pub trait Quotient<G: LieGroup<V>, H: LieGroup<V>, V: Vector>: Point {
// Required methods
fn new(g: G) -> Self;
fn lift(&self) -> G;
fn embed(h: H) -> G;
// Provided methods
fn quotient_identity() -> Self { ... }
fn quotient_compose(&self, other: &Self) -> Self { ... }
fn quotient_inverse(&self) -> Self { ... }
fn quotient_identity_exp(v: V) -> Self { ... }
fn quotient_identity_log(p: &Self) -> Option<V> { ... }
fn check_new_respects_coset(g: G, h: H) -> bool
where Self: PartialEq { ... }
}Expand description
A quotient of a Lie group by a central subgroup.
The space of all values of a type Q: Quotient<G, H, V> is interpreted
as the quotient group G/H — the set of cosets gH, with the group
operation inherited from G. This requires H to be central in G
(so the quotient is well-defined and the cosets gH and Hg coincide),
which in particular makes H automatically normal.
§The lift/canonical pattern
Rather than representing a coset abstractly, Quotient requires a
concrete representation via two operations:
-
Quotient::newmaps a valueg: Gto theQuotientvalue representing its cosetgH. It must satisfycanonical(g) == canonical(h.compose(g))for everyh: H(acting ongviaG’s own composition) — i.e. it must not distinguish between elements of the same coset. Beyond that one algebraic requirement,canonicalis free to be any deterministic, even discontinuous, choice function; it need not be smooth or continuous, since it carries no geometric content of its own. ForS³ / {±1} → SO(3),canonicalis a sign comparison on the real component; for(R\{0}, ×) / {±1} → (R⁺, ×), it is|x|. -
Quotient::liftrecovers some representativeg: Gof the coset, satisfyingcanonical(self.lift()) == selffor everyself: Q. Which representative is returned is unspecified beyond that round-trip property — only one of possibly several valid choices needs to be produced.
All group structure on Q — composition, inverse, the exponential map
at the identity — is defined generically in terms of G’s own structure
by lifting, operating in G, and re-applying canonical:
a.compose(b) = canonical(a.lift().compose(&b.lift())). This works
because all the differential structure lives in G, which is already
known to be smooth; canonical is purely a bookkeeping step applied
after the smooth operation completes, never a smoothness-bearing
operation in its own right. The map G → G/H being a covering map (a
local diffeomorphism) is what makes G/H itself a smooth manifold, even
though canonical — being a global choice of representative — is
typically forced to be discontinuous somewhere, an unavoidable
topological obstruction rather than evidence that canonical was chosen
poorly.
§Why H must be central
Centrality (h.compose(g) == g.compose(h) for all g: G, h: H) is
what makes left cosets and right cosets coincide, which is what makes
G/H a group rather than merely a set of cosets with no induced
operation. Sphere<0, V> — {1, -1} under the relevant composition —
is central in every Sphere<N, V> for N ∈ {0, 1, 3} precisely
because -1 commutes with everything (it is, after all, just a scalar
multiple of the identity), which is what makes S³/{±1} → SO(3) and
(R\{0}, ×)/{±1} → (R⁺, ×) both legitimate instances of this trait.
Required Methods§
Sourcefn lift(&self) -> G
fn lift(&self) -> G
Recovers a representative of self’s coset, satisfying
new(self.lift()) == self.
This is not merely “some” representative: lift must return the
one nearest the identity, in the sense that identity_log’s
result (built from lift, see quotient_identity_log) reports
the same norm as Metric::distance from the identity. A lift
that satisfies new(self.lift()) == self without also being
nearest will still pass every Quotient/Group/LieGroup
axiom test — those are satisfied by any valid representative
choice — but will silently produce a geometrically wrong
identity_log, and hence a wrong Chart/ExpMap/Metric for
the whole type. This is exactly what test_riemannian!’s
chart_metric_compatibility catches: it is the test that
certifies lift chose correctly, not a separate property to
verify independently.
Provided Methods§
fn quotient_identity() -> Self
fn quotient_compose(&self, other: &Self) -> Self
fn quotient_inverse(&self) -> Self
fn quotient_identity_exp(v: V) -> Self
fn quotient_identity_log(p: &Self) -> Option<V>
Sourcefn check_new_respects_coset(g: G, h: H) -> boolwhere
Self: PartialEq,
fn check_new_respects_coset(g: G, h: H) -> boolwhere
Self: PartialEq,
The sole independent Quotient axiom: new must not distinguish elements of the same coset. Everything else (group structure, differential structure) follows from this plus the inherited LieGroup axioms.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".