Profunctors

Profunctors (bimodules) in enriched categories.

profunctors

Profunctors (bimodules) for V-enriched categories.

A V-profunctor R: A ↛ B is a V-valued functor A^op ⊗ B → V, represented as a tensor of shape (A.shape, B.shape). Every morphism in a V-enriched category is canonically a profunctor.

Profunctor composition uses the coend formula:

(R ; S)(a, c) = ∫^b R(a, b) ⊗ S(b, c)

which is exactly V-enriched composition. This module makes the profunctor structure explicit and provides composition via the coend from ends_coends.py.

This module provides:

Profunctor — explicit profunctor with contravariant/covariant structure

Profunctor

Profunctor(contra: SetObject, co: SetObject, tensor: Tensor, quantale: Quantale | None = None)

A V-profunctor R: A ↛ B.

Wraps a tensor of shape (A.shape, B.shape) with explicit contravariant (A) and covariant (B) objects.

PARAMETER DESCRIPTION
contra

The contravariant (domain/source) object A.

TYPE: SetObject

co

The covariant (codomain/target) object B.

TYPE: SetObject

tensor

The profunctor's tensor of shape (A.shape, B.shape).

TYPE: Tensor

quantale

The enrichment algebra. Defaults to PRODUCT_FUZZY.

TYPE: Quantale or None DEFAULT: None

Source code in src/quivers/enriched/profunctors.py
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
def __init__(
    self,
    contra: SetObject,
    co: SetObject,
    tensor: torch.Tensor,
    quantale: Quantale | None = None,
) -> None:
    self._contra = contra
    self._co = co
    self._tensor = tensor
    self._quantale = quantale if quantale is not None else PRODUCT_FUZZY

    expected_shape = (*contra.shape, *co.shape)

    if tensor.shape != expected_shape:
        raise ValueError(
            f"tensor shape {tensor.shape} does not match expected "
            f"{expected_shape} from contra={contra!r}, co={co!r}"
        )

contra property

contra: SetObject

The contravariant (source) object.

co property

The covariant (target) object.

tensor property

tensor: Tensor

The profunctor tensor.

quantale property

quantale: Quantale

The enrichment algebra.

from_morphism classmethod

from_morphism(morph: Morphism) -> Profunctor

View a morphism as a profunctor (Yoneda embedding).

PARAMETER DESCRIPTION
morph

A morphism R: A → B.

TYPE: Morphism

RETURNS DESCRIPTION
Profunctor

The profunctor R: A ↛ B with the same tensor.

Source code in src/quivers/enriched/profunctors.py
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
@classmethod
def from_morphism(cls, morph: Morphism) -> Profunctor:
    """View a morphism as a profunctor (Yoneda embedding).

    Parameters
    ----------
    morph : Morphism
        A morphism R: A → B.

    Returns
    -------
    Profunctor
        The profunctor R: A ↛ B with the same tensor.
    """
    return cls(
        contra=morph.domain,
        co=morph.codomain,
        tensor=morph.tensor,
        quantale=morph.quantale,
    )

compose

compose(other: Profunctor) -> Profunctor

Profunctor composition via coend.

(R ; S)(a, c) = ∫^b R(a, b) ⊗ S(b, c)

This is equivalent to V-enriched composition via the quantale's compose method.

PARAMETER DESCRIPTION
other

Right profunctor S: B ↛ C.

TYPE: Profunctor

RETURNS DESCRIPTION
Profunctor

Composed profunctor R ; S: A ↛ C.

Source code in src/quivers/enriched/profunctors.py
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
def compose(self, other: Profunctor) -> Profunctor:
    """Profunctor composition via coend.

    (R ; S)(a, c) = ∫^b R(a, b) ⊗ S(b, c)

    This is equivalent to V-enriched composition via the
    quantale's compose method.

    Parameters
    ----------
    other : Profunctor
        Right profunctor S: B ↛ C.

    Returns
    -------
    Profunctor
        Composed profunctor R ; S: A ↛ C.
    """
    if self._co != other._contra:
        raise TypeError(
            f"cannot compose: R's covariant object {self._co!r} "
            f"!= S's contravariant object {other._contra!r}"
        )

    # use quantale.compose which is exactly the coend formula
    n_contract = self._co.ndim
    result_tensor = self._quantale.compose(self._tensor, other._tensor, n_contract)

    return Profunctor(
        contra=self._contra,
        co=other._co,
        tensor=result_tensor,
        quantale=self._quantale,
    )

to_morphism

to_morphism() -> ObservedMorphism

Convert back to a morphism (same tensor, different framing).

RETURNS DESCRIPTION
ObservedMorphism

A morphism with domain=contra, codomain=co.

Source code in src/quivers/enriched/profunctors.py
143
144
145
146
147
148
149
150
151
152
153
154
155
156
def to_morphism(self) -> ObservedMorphism:
    """Convert back to a morphism (same tensor, different framing).

    Returns
    -------
    ObservedMorphism
        A morphism with domain=contra, codomain=co.
    """
    return observed(
        self._contra,
        self._co,
        self._tensor,
        quantale=self._quantale,
    )