Transformations¶
Change-of-base transformations between algebras: pointwise algebra
homomorphisms, shape-aware morphism transformations, and the sequences
compose_trans builds from them. Each is consumed by
Morphism.change_base.
algebra_morphisms
¶
Algebra homomorphisms and change-of-base for V-enriched morphisms.
A morphism in quivers.core.morphisms is V-enriched: its
codomain is :math:\mathrm{Hom}_V(A, B) for the active algebra
V. Two morphisms over different algebras (V and W)
do not directly compose — Morphism.__rshift__ raises
incompatible algebras. The standard categorical way to
bridge them is a algebra homomorphism (a lax monoidal poset
functor) :math:\varphi : V \to W mediating the change of
base. There is then a 2-functor
:math:(-) \otimes_\varphi W : V\text{-}\mathbf{Cat} \to W\text{-}\mathbf{Cat}
that base-changes objects and an induced natural transformation
on morphisms.
This module ships:
-
AlgebraHomomorphism— the abstract base. A homomorphism carries a source algebra, a target algebra, and a functionapply(t : Tensor) -> Tensorthat maps a tensor whose entries live in the source's lattice to a tensor whose entries live in the target's lattice. Subclasses implementapplyfor a specific pair. -
Embedding— the inclusion of a sub-algebra into a super-algebra (e.g.Boolean ↪ ProductFuzzyAlgebra). -
Expectation— Markov-to-ProductFuzzyAlgebra (softmax↦ fuzzy membership). -
LogProb— ProductFuzzyAlgebra-to-LogProb (log(p)). -
MaxPlus— ProductFuzzyAlgebra-to-Viterbi (max-plus tropical lift). -
Threshold— ProductFuzzyAlgebra-to-Boolean (discretize at a threshold). -
MaterialImplication— ProductFuzzyAlgebra-to-Godel (Heyting implication semantics). -
IdentityHom— a no-op homomorphism from an algebra to itself, useful as the unit of homomorphism composition. -
A registry
HOMOMORPHISM_REGISTRYkeyed by(source.name, target.name)so the compiler / user code can look up the canonical homomorphism between two algebras.
The categorical denotation of f.change_base(φ) for
f : A → B in V is the V-Cat morphism
φ ∘ f : A → B in W with tensor
φ.apply(f.tensor) and lattice values in W. Composition then
proceeds in W using W's tensor / join operations.
This module is intentionally backend-agnostic: every homomorphism's
apply operates on a torch.Tensor without touching
PyTorch's autograd or module infrastructure, so a future numpy /
JAX backend can replace the runtime without touching the
categorical hierarchy.
AlgebraHomomorphism
¶
Bases: ABC
A lax monoidal poset functor between two algebras.
Concretely, a homomorphism :math:\varphi : V \to W
satisfies:
φ(a ⊗_V b) ≤ φ(a) ⊗_W φ(b)(lax with respect to the monoidal tensor).φ(⋁_i a_i) ≤ ⋁_i φ(a_i)(lax with respect to joins).φ(I_V) ≤ I_W(lax with respect to the monoidal unit).
The "lax" qualifier allows for embeddings that preserve order but compress structure (a threshold is lax but not strict). Strictness is not required for change-of-base to be categorically valid; only the order-preservation is.
apply
abstractmethod
¶
Map a tensor with entries in source.L to a tensor
with entries in target.L.
The shape is preserved; only the per-entry lattice changes.
IdentityHom
¶
IdentityHom(q: Algebra)
Bases: AlgebraHomomorphism
The identity homomorphism id_V : V → V.
Useful as the unit of composition; f.change_base(IdentityHom(V))
leaves the morphism in V unchanged.
Source code in src/quivers/core/algebra_morphisms.py
Embedding
¶
Bases: AlgebraHomomorphism
The inclusion of a sub-algebra into a super-algebra.
The canonical example is Boolean ↪ ProductFuzzyAlgebra: a
boolean tensor with entries in {0, 1} embeds as a
product-fuzzy tensor with entries in [0, 1] whose support
is the boolean's truth assignment.
Embeddings preserve every algebra operation up to the embedding inclusion; they are strict homomorphisms.
Source code in src/quivers/core/algebra_morphisms.py
Expectation
¶
Bases: AlgebraHomomorphism
Markov → ProductFuzzyAlgebra via softmax to fuzzy membership.
A Markov kernel k : A → B has rows that sum to 1 (a
probability distribution over B per a∈A). Reading the
per-entry probability as a fuzzy membership of (a, b)
in the relation gives a ProductFuzzyAlgebra morphism.
Categorically this is the change of base induced by the
Δ natural transformation that erases the normalisation
constraint — the resulting fuzzy morphism is no longer
row-stochastic but its entries still lie in [0, 1].
Source code in src/quivers/core/algebra_morphisms.py
LogProb
¶
Bases: AlgebraHomomorphism
ProductFuzzyAlgebra → LogProb via log.
Maps entries in (0, 1] to (-∞, 0] for
log-space computation. Entries that are exactly 0 in the
source go to -inf. In practice the input is clamped to
[ε, 1] first to avoid numerical blow-up.
Source code in src/quivers/core/algebra_morphisms.py
MaxPlus
¶
Bases: AlgebraHomomorphism
ProductFuzzyAlgebra → MaxPlus via log.
The max-plus tropical algebra on the reals has tensor =
addition and join = max. A ProductFuzzyAlgebra morphism transports
via log so the product t-norm becomes addition in
log-space; subsequent joins (which were noisy-OR in
ProductFuzzyAlgebra) get replaced by max in Viterbi-style
Viterbi-MAP aggregations.
The two ProductFuzzyAlgebra → log-target homomorphisms are different
category-theoretically — LogProb carries the join
structure to logsumexp, MaxPlus carries it to
max-plus — even though they share the same per-entry mapping
log.
Source code in src/quivers/core/algebra_morphisms.py
Threshold
¶
Bases: AlgebraHomomorphism
ProductFuzzyAlgebra → Boolean via thresholding.
Entries above tau map to True; entries at or below
tau map to False. This is a lax homomorphism: it
preserves order (a ≤ b ⟹ threshold(a) ≤ threshold(b)) but
compresses information (every value in (tau, 1] collapses to
True).
| PARAMETER | DESCRIPTION |
|---|---|
tau
|
Threshold value in [0, 1].
TYPE:
|
Source code in src/quivers/core/algebra_morphisms.py
MaterialImplication
¶
Bases: AlgebraHomomorphism
ProductFuzzyAlgebra → Godel via a * b + (1 - a) reading.
Reads each ProductFuzzyAlgebra entry p as a probability that
the implication p → q holds — the Heyting-implication-
style transport that respects the Godel algebra's monoid.
The mapping is entry ↦ entry-preserving on the entry value
but changes the composition semantics downstream: subsequent
>> in the Godel algebra uses min / Godel-implication, not
product / noisy-OR.
Source code in src/quivers/core/algebra_morphisms.py
ProbabilityClamp
¶
Bases: AlgebraHomomorphism
Real → Probability via clamping to the unit interval.
Coerces a real-valued tensor into a probability tensor by
clamping entries to [0, 1]. Lax — destroys information
outside the unit interval — but preserves the entry-wise
order on the survivors.
Source code in src/quivers/core/algebra_morphisms.py
CountingFromReal
¶
Bases: AlgebraHomomorphism
Real → Counting via floor-and-clamp-to-non-negative.
Coerces a real-valued tensor into a non-negative integer
counting tensor by flooring and clamping at zero.
Information-destroying; inverse is CountingToReal.
Source code in src/quivers/core/algebra_morphisms.py
ProbabilityToReal
¶
Bases: AlgebraHomomorphism
Probability → Real (sub-algebra inclusion).
Entries already lie in [0, 1] ⊂ ℝ; the inclusion is
strict (preserves every operation).
Source code in src/quivers/core/algebra_morphisms.py
CountingToReal
¶
Bases: AlgebraHomomorphism
Counting → Real (sub-algebra inclusion).
Non-negative integers embed canonically in the reals; this is the strict inclusion homomorphism.
Source code in src/quivers/core/algebra_morphisms.py
threshold
¶
threshold(tau: float = 0.5) -> Threshold
Build a Threshold homomorphism at the given threshold value.
| PARAMETER | DESCRIPTION |
|---|---|
tau
|
The threshold; entries strictly above it map to true.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Threshold
|
The ProductFuzzy-to-Boolean homomorphism at |
Source code in src/quivers/core/algebra_morphisms.py
embedding
¶
Build an Embedding homomorphism, a sub-algebra inclusion.
| PARAMETER | DESCRIPTION |
|---|---|
source
|
The sub-algebra.
TYPE:
|
target
|
The super-algebra that
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Embedding
|
The inclusion |
Source code in src/quivers/core/algebra_morphisms.py
lookup_homomorphism
¶
lookup_homomorphism(source: Algebra, target: Algebra) -> AlgebraHomomorphism | None
Look up the canonical homomorphism source → target.
Identity is always available: algebras of one type yield
IdentityHom(source).
| PARAMETER | DESCRIPTION |
|---|---|
source
|
The algebra to map from.
TYPE:
|
target
|
The algebra to map to.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
AlgebraHomomorphism or None
|
The registered bridge from |
Source code in src/quivers/core/algebra_morphisms.py
morphism_transformations
¶
Functorial change-of-base for non-pointwise morphism transformations.
A quivers.core.algebra_morphisms.AlgebraHomomorphism
acts pointwise on tensor entries (log, threshold, max-plus
lift). That handles a useful but narrow class of change-of-base
moves. The broader class — functors V-Cat -> W-Cat whose
action on a morphism's tensor is shape-aware rather than
strictly pointwise — covers softmax-style normalizations,
Bayes-inversion under a prior, L1 / L2 / spectral row
normalizations, top-k truncation, and Sinkhorn balancing.
This module ships the abstract base
MorphismTransformation and four concrete subclasses
(Softmax, L1Normalize, L2Normalize, BayesInvert) that cover the
common practical needs. Morphism.change_base accepts either a
AlgebraHomomorphism (pointwise) or a MorphismTransformation
(shape-aware) and dispatches accordingly.
Categorically, a MorphismTransformation is a (possibly lax)
2-functor between V-Cat and W-Cat that need not factor through a
algebra homomorphism on tensor entries — the action operates on
whole rows / columns / matrices, and may carry parameter data
(BayesInvert carries a prior).
MorphismTransformation
¶
Bases: ABC
A shape-aware change-of-base transformation.
Concrete subclasses act on a morphism's whole tensor (not
entry-by-entry), optionally consuming an explicit axis
specification or external parameters (e.g. a prior). The
source algebra is the domain of the action; the
target algebra is the resulting morphism's algebra.
The base contract is:
morphism :: V-Cat(A, B) --> V-Cat(A', B')
where (A', B') is determined by the transformation
(often the same as (A, B) for normalizations; swapped
for Bayes inversion).
apply
abstractmethod
¶
Transform morphism.tensor into a tensor over the target
algebra.
| PARAMETER | DESCRIPTION |
|---|---|
tensor
|
The morphism's tensor at the current algebra.
TYPE:
|
morphism
|
The full morphism, exposed so the transformation can consult domain / codomain shape and pick the right axis.
TYPE:
|
Source code in src/quivers/core/morphism_transformations.py
Softmax
¶
Softmax(axis_object: SetObject, source: Algebra = PRODUCT_FUZZY)
Bases: MorphismTransformation
Softmax-normalize along an axis, producing a Markov-style kernel.
Maps a ProductFuzzyAlgebra (or Real) tensor to a row-stochastic
Markov kernel by applying softmax along the axis indexed by
axis_object. The output's entries lie in (0, 1) and
sum to 1 along that axis.
| PARAMETER | DESCRIPTION |
|---|---|
axis_object
|
The object whose axis the softmax is taken over.
TYPE:
|
source
|
The morphism's algebra before softmax. Default
TYPE:
|
Source code in src/quivers/core/morphism_transformations.py
L1Normalize
¶
Bases: MorphismTransformation
L1-normalize along an axis: divide each entry by the row sum.
Maps a non-negative real tensor to one whose entries sum to 1 along the given axis. The output is row-stochastic on that axis; semantically identical to a Markov kernel.
| PARAMETER | DESCRIPTION |
|---|---|
axis_object
|
The object whose axis is normalized.
TYPE:
|
source
|
Default |
Source code in src/quivers/core/morphism_transformations.py
L2Normalize
¶
Bases: MorphismTransformation
L2-normalize along an axis: divide each entry by the row norm.
Maps a real-valued tensor to one whose entries lie on the unit L2 sphere along the given axis. The result is still in the source algebra (Real), with rows rescaled to unit length.
| PARAMETER | DESCRIPTION |
|---|---|
axis_object
|
The object whose axis is normalized.
TYPE:
|
source
|
Default |
Source code in src/quivers/core/morphism_transformations.py
BayesInvert
¶
BayesInvert(prior: Tensor)
Bases: MorphismTransformation
Bayes-invert a Markov kernel under a prior.
Given a Markov kernel f : A -> B and a prior
pi : 1 -> A, the Bayes-inverse f^{-1}_pi : B -> A is
the kernel satisfying
f^{-1}_pi(a | b) = f(b | a) * pi(a) / sum_a' f(b | a') * pi(a')
Mathematically this is the disintegration of the joint distribution along the second margin. The domain and codomain swap roles in the result.
| PARAMETER | DESCRIPTION |
|---|---|
prior
|
Prior probabilities over the source's first object.
Shape
TYPE:
|
Source code in src/quivers/core/morphism_transformations.py
softmax
¶
Build a Softmax transformation along axis_object.
| PARAMETER | DESCRIPTION |
|---|---|
axis_object
|
The object whose axis the softmax is taken over.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Softmax
|
The ProductFuzzy-to-Markov transformation. |
Source code in src/quivers/core/morphism_transformations.py
l1_normalize
¶
l1_normalize(axis_object: SetObject) -> L1Normalize
Build an L1Normalize transformation along axis_object.
| PARAMETER | DESCRIPTION |
|---|---|
axis_object
|
The object whose axis is normalized.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
L1Normalize
|
The Real-to-Markov transformation. |
Source code in src/quivers/core/morphism_transformations.py
l2_normalize
¶
l2_normalize(axis_object: SetObject) -> L2Normalize
Build an L2Normalize transformation along axis_object.
| PARAMETER | DESCRIPTION |
|---|---|
axis_object
|
The object whose axis is normalized.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
L2Normalize
|
The Real-to-Real transformation. |
Source code in src/quivers/core/morphism_transformations.py
bayes_invert
¶
bayes_invert(prior) -> BayesInvert
Build a BayesInvert transformation from a prior.
prior may be a 1-D torch.Tensor (used directly)
or any object that exposes a .tensor attribute (the
morphism convention used throughout the V-Cat layer). Duck
typing on .tensor avoids a circular import between
quivers.core.morphisms and this module. The morphism
form is what the DSL feeds in when the user writes
change_base(bayes_invert(prior_morph)).
| PARAMETER | DESCRIPTION |
|---|---|
prior
|
The prior over the kernel's domain, as a tensor or as a
morphism whose |
| RETURNS | DESCRIPTION |
|---|---|
BayesInvert
|
The Bayes-inversion transformation under |
| RAISES | DESCRIPTION |
|---|---|
TypeError
|
If |
ValueError
|
If |
Source code in src/quivers/core/morphism_transformations.py
trans
¶
First-class transformation composition.
A transformation in quivers is either a
quivers.core.algebra_morphisms.AlgebraHomomorphism
(pointwise, lax monoidal) or a
quivers.core.morphism_transformations.MorphismTransformation
(shape-aware). Both expose a source and target algebra
and an apply that consumes a morphism's tensor.
This module gives them a composition operation: compose_trans(t1, t2, ...)
returns a TransSeq value that applies the steps in order
when handed to Morphism.change_base. Adjacent target
and source are type-checked at compose time. Nested
TransSeq are flattened so the resulting steps tuple is
always a single flat sequence of base transformations.
This is the Python-side surface for the DSL's t1 >>> t2
operator: in the .qvr surface,
let pipe = softmax(B) >>> expectation builds the same value
that compose_trans(softmax(B), EXPECTATION) builds here.
TransSeq
¶
TransSeq(steps: tuple[TransValue, ...])
Sequence of transformations applied left-to-right.
Constructed by compose_trans; consumed by
Morphism.change_base. Each adjacent target /
source boundary in steps is verified at
construction time, so apply does not have to
revalidate.
A TransSeq itself exposes the same source / target
/ name interface as a single transformation, so it can be
fed into further compose_trans calls and the nesting
is flattened.
Source code in src/quivers/core/trans.py
compose_trans
¶
compose_trans(*steps: TransValue | TransSeq) -> TransSeq
Compose two or more transformations into a single sequence.
Each argument is either a base transformation (a
AlgebraHomomorphism or MorphismTransformation) or
another TransSeq whose steps are inlined. The
resulting sequence is flat; nested compositions never appear
in TransSeq.steps.
| PARAMETER | DESCRIPTION |
|---|---|
*steps
|
Two or more transformations.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
TransSeq
|
The composed sequence with |
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
If fewer than two steps are supplied. |
TypeError
|
If two adjacent steps' target / source algebras differ. |
Source code in src/quivers/core/trans.py
The homomorphism singletons, their registry, and the TransValue
alias are documented on the core overview.