Continuous Morphisms¶
Continuous mappings between topological spaces.
morphisms
¶
Continuous morphisms: Markov kernels on continuous and mixed spaces.
A ContinuousMorphism represents a conditional probability distribution p(y | x) where x and y may live in either discrete (FinSet) or continuous (ContinuousSpace) spaces. The morphism is defined by two operations:
log_prob(x, y) — log-density/probability of y given x
rsample(x) — reparameterized samples from p(· | x)
Composition uses ancestral sampling:
(g . f)(x, z) = integral f(x, y) g(y, z) dy
~ E_{y~f(x,.)}[g(y, z)]
This module provides:
ContinuousMorphism — abstract base with >> and @ operators
SampledComposition — f >> g via ancestral sampling
ProductContinuousMorphism — f @ g (independent product)
DiscreteAsContinuous — wrap a discrete Morphism as continuous
Convention for input shapes
- Discrete domain (SetObject): x is LongTensor of shape (batch,)
- Continuous domain (ContinuousSpace): x is FloatTensor of shape (batch, dim)
- Discrete codomain: y is LongTensor of shape (batch,)
- Continuous codomain: y is FloatTensor of shape (batch, dim)
ContinuousMorphism
¶
ContinuousMorphism(domain: AnySpace, codomain: AnySpace)
Bases: Module, ABC
Abstract base for morphisms involving continuous spaces.
Subclasses must implement log_prob and rsample. The
composition operator >> and product operator @ are
provided and dispatch to SampledComposition and
ProductContinuousMorphism respectively.
Unlike discrete Morphism (which materializes a full tensor), ContinuousMorphism is defined operationally: it can evaluate log-densities and generate reparameterized samples.
| PARAMETER | DESCRIPTION |
|---|---|
domain
|
Source space.
TYPE:
|
codomain
|
Target space.
TYPE:
|
Source code in src/quivers/continuous/morphisms.py
67 68 69 70 | |
log_prob
abstractmethod
¶
log_prob(x: Tensor, y: Tensor) -> Tensor
Log-probability (density) of y given x.
| PARAMETER | DESCRIPTION |
|---|---|
x
|
Inputs. Shape (batch,) for discrete domain or (batch, domain_dim) for continuous domain.
TYPE:
|
y
|
Outputs. Shape (batch,) for discrete codomain or (batch, codomain_dim) for continuous codomain.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Tensor
|
Log-probabilities/densities. Shape (batch,). |
Source code in src/quivers/continuous/morphisms.py
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | |
rsample
abstractmethod
¶
rsample(x: Tensor, sample_shape: Size = Size()) -> Tensor
Reparameterized samples from p(. | x).
Gradients flow through the returned samples back to the parameters of this morphism (and to x if the domain is continuous).
| PARAMETER | DESCRIPTION |
|---|---|
x
|
Inputs. Shape (batch,) or (batch, domain_dim).
TYPE:
|
sample_shape
|
Additional leading sample dimensions.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Tensor
|
Samples. Shape (sample_shape, batch, codomain_dim) for continuous codomain, or (sample_shape, batch) for discrete. |
Source code in src/quivers/continuous/morphisms.py
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | |
sample
¶
sample(x: Tensor, sample_shape: Size = Size()) -> Tensor
Non-reparameterized samples (no gradient through samples).
| PARAMETER | DESCRIPTION |
|---|---|
x
|
Inputs.
TYPE:
|
sample_shape
|
Additional leading sample dimensions.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Tensor
|
Samples (detached from computation graph). |
Source code in src/quivers/continuous/morphisms.py
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | |
__rshift__
¶
__rshift__(other: object) -> ContinuousMorphism
Composition via ancestral sampling: self >> other.
Source code in src/quivers/continuous/morphisms.py
147 148 149 150 151 152 153 154 155 | |
__rrshift__
¶
__rrshift__(other: object) -> ContinuousMorphism
Handle discrete_morphism >> continuous_morphism.
Source code in src/quivers/continuous/morphisms.py
157 158 159 160 161 162 163 | |
__matmul__
¶
__matmul__(other: object) -> ProductContinuousMorphism
Independent product: self @ other.
Source code in src/quivers/continuous/morphisms.py
165 166 167 168 169 170 171 172 173 | |
SampledComposition
¶
SampledComposition(left: ContinuousMorphism, right: ContinuousMorphism, n_intermediate: int = 100)
Bases: ContinuousMorphism
Composition of morphisms via ancestral sampling.
Given f: X -> Y and g: Y -> Z, the composition g . f satisfies:
(g . f)(x, z) = integral f(x, y) g(y, z) dy
This integral is computed: - Exactly (finite sum) when Y is discrete. - Approximately (Monte Carlo) when Y is continuous.
For rsample: draw y ~ f(x, .), then draw z ~ g(y, .). For log_prob: sum/average g(z | y_i) weighted by f(y_i | x).
| PARAMETER | DESCRIPTION |
|---|---|
left
|
First morphism (applied first).
TYPE:
|
right
|
Second morphism (applied second).
TYPE:
|
n_intermediate
|
Number of Monte Carlo samples for continuous intermediate spaces. Ignored when the intermediate space is discrete.
TYPE:
|
Source code in src/quivers/continuous/morphisms.py
287 288 289 290 291 292 293 294 295 296 | |
rsample
¶
rsample(x: Tensor, sample_shape: Size = Size()) -> Tensor
Ancestral sampling: y ~ f(x, .), then z ~ g(y, .).
| PARAMETER | DESCRIPTION |
|---|---|
x
|
Inputs to the composition.
TYPE:
|
sample_shape
|
Additional sample dimensions.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Tensor
|
Samples from the composed morphism. |
Source code in src/quivers/continuous/morphisms.py
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 | |
log_prob
¶
log_prob(x: Tensor, y: Tensor) -> Tensor
Log-probability of y given x through the composition.
When the intermediate space is discrete, computes the exact marginalization. When continuous, uses Monte Carlo estimation.
| PARAMETER | DESCRIPTION |
|---|---|
x
|
Inputs. Shape (batch,) or (batch, dom_dim).
TYPE:
|
y
|
Outputs. Shape (batch,) or (batch, cod_dim).
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Tensor
|
Log-probabilities. Shape (batch,). |
Source code in src/quivers/continuous/morphisms.py
337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 | |
ProductContinuousMorphism
¶
ProductContinuousMorphism(left: ContinuousMorphism, right: ContinuousMorphism)
Bases: ContinuousMorphism
Independent product of two continuous morphisms.
Given f: A -> B and g: C -> D, produces f @ g: (A, C) -> (B, D) where p_{f@g}((y,z) | (x,w)) = f(y | x) * g(z | w).
Domain inputs are concatenated: (x, w) as a single vector. Codomain outputs are concatenated: (y, z) as a single vector. For discrete components, indices are embedded as 1-d floats.
| PARAMETER | DESCRIPTION |
|---|---|
left
|
Left factor morphism.
TYPE:
|
right
|
Right factor morphism.
TYPE:
|
Source code in src/quivers/continuous/morphisms.py
428 429 430 431 432 433 434 435 436 437 | |
FanOutMorphism
¶
FanOutMorphism(components: list[ContinuousMorphism])
Bases: ContinuousMorphism
Fan-out morphism: copy input to N morphisms, concatenate outputs.
Given f_1: A -> B_1, f_2: A -> B_2, ..., f_N: A -> B_N, produces fan(f_1, ..., f_N): A -> B_1 * B_2 * ... * B_N where the input A is copied to all N morphisms.
Unlike the tensor product (f @ g), which takes a product domain (A * C), fan-out feeds the same input to all morphisms. This implements the diagonal morphism Delta: A -> A^N followed by the product f_1 @ f_2 @ ... @ f_N.
| PARAMETER | DESCRIPTION |
|---|---|
components
|
The morphisms to fan out to. All must share the same domain.
TYPE:
|
Source code in src/quivers/continuous/morphisms.py
493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 | |
rsample
¶
rsample(x: Tensor, sample_shape: Size = Size()) -> Tensor
Sample from all components and concatenate outputs.
| PARAMETER | DESCRIPTION |
|---|---|
x
|
Input tensor (broadcast to all components).
TYPE:
|
sample_shape
|
Additional leading sample dimensions.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Tensor
|
Concatenated outputs from all components. |
Source code in src/quivers/continuous/morphisms.py
511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 | |
log_prob
¶
log_prob(x: Tensor, y: Tensor) -> Tensor
Log-probability: sum of component log-probs.
| PARAMETER | DESCRIPTION |
|---|---|
x
|
Input (same for all components).
TYPE:
|
y
|
Concatenated output values.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Tensor
|
Sum of log-probabilities. Shape |
Source code in src/quivers/continuous/morphisms.py
536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 | |
DiscreteAsContinuous
¶
DiscreteAsContinuous(inner: object)
Bases: ContinuousMorphism
Wrap a discrete Morphism as a ContinuousMorphism.
Enables composition between discrete and continuous morphisms via the >> operator. The wrapped morphism's tensor is used for both log_prob evaluation and sampling.
Note
Sampling from a discrete distribution is NOT reparameterizable. Gradients do not flow through the discrete samples back to the left morphism's parameters. Use score function estimators (REINFORCE) if gradients through discrete choices are needed.
| PARAMETER | DESCRIPTION |
|---|---|
inner
|
The discrete morphism to wrap.
TYPE:
|
Source code in src/quivers/continuous/morphisms.py
583 584 585 586 587 588 589 590 | |
log_prob
¶
log_prob(x: Tensor, y: Tensor) -> Tensor
Log-probability from the discrete tensor.
| PARAMETER | DESCRIPTION |
|---|---|
x
|
Domain indices. Shape (batch,).
TYPE:
|
y
|
Codomain indices. Shape (batch,).
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Tensor
|
Log-probabilities. Shape (batch,). |
Source code in src/quivers/continuous/morphisms.py
592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 | |
rsample
¶
rsample(x: Tensor, sample_shape: Size = Size()) -> Tensor
Sample from the categorical distribution defined by the tensor.
Note: not reparameterizable. Gradients do not flow through the returned samples.
| PARAMETER | DESCRIPTION |
|---|---|
x
|
Domain indices. Shape (batch,).
TYPE:
|
sample_shape
|
Additional sample dimensions.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Tensor
|
Sampled codomain indices. Shape (*sample_shape, batch). |
Source code in src/quivers/continuous/morphisms.py
611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 | |