Categorical Structures¶
Functors¶
A functor \(F: \mathcal{C} \to \mathcal{D}\) between \(\mathcal{V}\)-enriched categories maps objects to objects and morphisms to morphisms, preserving composition and identity.
In quivers, Functor is an abstract base class with three abstract methods:
map_object(obj): the object map \(F_\text{obj}: \text{Ob}(\mathcal{C}) \to \text{Ob}(\mathcal{D})\)map_morphism(morph): the morphism map, returning aFunctorMorphismmap_tensor(tensor, algebra): the tensor-level action
Concrete subclasses ship with the library:
from quivers.categorical.functors import IdentityFunctor, ComposedFunctor, FreeMonoidFunctor
from quivers.core.objects import FinSet
from quivers.core.morphisms import morphism
X = FinSet(name="X", cardinality=3)
Y = FinSet(name="Y", cardinality=4)
# Identity endofunctor
I = IdentityFunctor()
assert I.map_object(X) == X
# Free monoid functor on FinSet
F = FreeMonoidFunctor(max_length=3)
FX = F.map_object(X) # FreeMonoid(generators=X, max_length=3)
f = morphism(X, Y)
Ff = F.map_morphism(f) # FunctorMorphism with domain F(X), codomain F(Y)
# Composition of functors
FF = ComposedFunctor(F, F) # F ∘ F applied as outer ∘ inner
To define your own functor, subclass Functor and implement the three abstract methods.
Natural Transformations¶
A natural transformation \(\alpha: F \Rightarrow G\) between functors \(F, G: \mathcal{C} \to \mathcal{D}\) is a family of morphisms \(\{\alpha_X: F(X) \to G(X)\}\) indexed by objects of \(\mathcal{C}\), such that the naturality square commutes:
NaturalTransformation is an ABC; use ComponentwiseNT to construct one from a callable that produces each component:
from quivers.categorical.functors import IdentityFunctor, FreeMonoidFunctor
from quivers.categorical.natural_transformations import ComponentwiseNT
from quivers.categorical.adjunctions import FreeForgetfulAdjunction
from quivers.core.objects import FinSet
from quivers.core.morphisms import morphism
X = FinSet(name="X", cardinality=3)
Y = FinSet(name="Y", cardinality=4)
F = IdentityFunctor()
G = FreeMonoidFunctor(max_length=3)
# unit η: Id ⇒ Free (length-1 embedding) reuses the adjunction's unit
adj = FreeForgetfulAdjunction(max_length=3)
eta = ComponentwiseNT(F, G, adj.unit_component)
# verify naturality on a chosen morphism
f = morphism(X, Y)
assert eta.verify_naturality(f)
Adjunctions¶
An adjunction \(F \dashv G\) is a pair of functors with morphisms \(\eta: \text{id}_\mathcal{C} \Rightarrow GF\) (unit) and \(\varepsilon: FG \Rightarrow \text{id}_\mathcal{D}\) (counit) satisfying triangle identities.
The free-forgetful adjunction \(\text{Free} \dashv \text{Forget}\) is shipped as FreeForgetfulAdjunction:
from quivers.categorical.adjunctions import FreeForgetfulAdjunction
from quivers.core.objects import FinSet, FreeMonoid
A = FinSet(name="A", cardinality=5)
adjunction = FreeForgetfulAdjunction(max_length=3)
# Left and right functors
F = adjunction.left # FreeMonoidFunctor
U = adjunction.right # ForgetfulFunctor
# Monad image T(A) = U(F(A)) is the free monoid on A
T_A = U.map_object(F.map_object(A))
assert isinstance(T_A, FreeMonoid)
# Unit and counit components
eta_A = adjunction.unit_component(A) # A → A*
eps_A = adjunction.counit_component(A) # A* → A
# Triangle identities
assert adjunction.verify_triangle_right(A)
Monoidal Structures¶
A monoidal category \((\mathcal{C}, \otimes, I)\) has:
- A bifunctor \(\otimes: \mathcal{C} \times \mathcal{C} \to \mathcal{C}\) (the product)
- A unit object \(I\)
- Natural associativity, left identity, right identity (with coherence)
Cartesian Monoidal¶
The standard monoidal structure on finite sets. CartesianMonoidal exposes the object-level product, the unit (terminal object), and the coherence morphisms associator, left_unitor, right_unitor, braiding:
from quivers.categorical.monoidal import CartesianMonoidal
from quivers.core.objects import FinSet, Unit
monoidal = CartesianMonoidal()
X = FinSet(name="X", cardinality=3)
Y = FinSet(name="Y", cardinality=4)
# product on objects
XY = monoidal.product(X, Y)
assert XY == X * Y
assert monoidal.unit == Unit
# coherence morphisms
swap = monoidal.braiding(X, Y) # X × Y → Y × X
assoc = monoidal.associator(X, Y, X) # (X×Y)×X → X×(Y×X)
Morphism-level tensor product is provided directly on Morphism via the @ operator:
f = morphism(X, Y)
g = morphism(X, Y)
fg = f @ g # ProductMorphism: X×X → Y×Y
Coproduct Monoidal¶
Coproduct as the monoidal operation:
from quivers.categorical.monoidal import CoproductMonoidal
from quivers.core.objects import FinSet
monoidal = CoproductMonoidal()
X = FinSet(name="X", cardinality=3)
Y = FinSet(name="Y", cardinality=4)
XY = monoidal.product(X, Y)
assert XY == X + Y
The unit here is the initial object (empty set), exposed as EMPTY from quivers.categorical.monoidal.
Base Change¶
Change the enriching algebra without changing the structure of morphisms. BaseChange is an ABC; concrete instances are BoolToFuzzy and FuzzyToBool:
from quivers.categorical.base_change import BoolToFuzzy, FuzzyToBool
from quivers.core.algebras import BOOLEAN, PRODUCT_FUZZY
from quivers.core.objects import FinSet
from quivers.core.morphisms import morphism
X = FinSet(name="X", cardinality=3)
Y = FinSet(name="Y", cardinality=4)
# fuzzy → boolean via thresholding
fuzzy_morph = morphism(X, Y, algebra=PRODUCT_FUZZY)
to_bool = FuzzyToBool(threshold=0.5)
bool_morph = to_bool.apply_to_morphism(fuzzy_morph)
assert bool_morph.algebra == BOOLEAN
assert bool_morph.domain == fuzzy_morph.domain
assert bool_morph.codomain == fuzzy_morph.codomain
# boolean → fuzzy via inclusion
to_fuzzy = BoolToFuzzy()
fuzzy_again = to_fuzzy.apply_to_morphism(bool_morph)
Traced Monoidal Structure¶
A traced monoidal category adds a trace operator:
This is useful for feedback and recursive definitions. The free function trace wraps a CartesianTrace:
from quivers.categorical.traced import trace
from quivers.core.objects import FinSet
from quivers.core.morphisms import morphism
X = FinSet(name="X", cardinality=2)
Y = FinSet(name="Y", cardinality=3)
Z = FinSet(name="Z", cardinality=4)
# f: (Y × X) → (Z × X)
f = morphism(Y * X, Z * X)
# Trace over X: returns A → B with the feedback loop closed
traced_f = trace(f, feedback=X, domain=Y, codomain=Z)
assert traced_f.domain == Y
assert traced_f.codomain == Z
The trace contracts the matching \(X\) wire, leaving the external domain \(Y\) and codomain \(Z\).
Summary¶
| Structure | Concept | Syntax |
|---|---|---|
| Functor | Object and morphism map | F: C → D |
| Natural Transform | Family of morphisms | α: F ⇒ G |
| Adjunction | Inverse functors up to natural isos | F ⊣ G |
| Monoidal | Product with coherence | (C, ⊗, I) |
| Base Change | Enrichment transformation | FuzzyToBool().apply_to_morphism(f) |
| Traced | Feedback/iteration | trace(f, feedback=X, domain=Y, codomain=Z) |