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
68 69 70 71 | |
support
property
¶
support: Constraint
The support constraint of the distribution this morphism samples
from, in the form of a torch.distributions.constraints.Constraint.
Used by variational guides (quivers.inference.AutoNormalGuide,
quivers.inference.AutoDeltaGuide) to determine the
correct bijector that maps an unconstrained variational
approximation back to the constrained support of the prior, so
that samples used to evaluate the prior's log_prob lie inside
its support (avoiding Expected value to be within the support
of the distribution errors).
Subclasses representing a constrained distribution family
(HalfNormal, Beta, Uniform, Dirichlet,
LogitNormal, Wishart, …) should override this property
to return the appropriate constraint. The default is
torch.distributions.constraints.real, which is correct
for unconstrained families like Normal and discrete
codomains (where the guide skips the site anyway).
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
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | |
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
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | |
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
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 | |
__rshift__
¶
__rshift__(other: object) -> ContinuousMorphism
Composition via ancestral sampling: self >> other.
Source code in src/quivers/continuous/morphisms.py
171 172 173 174 175 176 177 178 179 | |
__rrshift__
¶
__rrshift__(other: object) -> ContinuousMorphism
Handle discrete_morphism >> continuous_morphism.
Source code in src/quivers/continuous/morphisms.py
181 182 183 184 185 186 187 | |
__matmul__
¶
__matmul__(other: object) -> ProductContinuousMorphism
Independent product: self @ other.
Source code in src/quivers/continuous/morphisms.py
189 190 191 192 193 194 195 196 197 | |
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
313 314 315 316 317 318 319 320 321 322 | |
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
324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 | |
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
363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 | |
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
454 455 456 457 458 459 460 461 462 463 | |
FanOutMorphism
¶
FanOutMorphism(components: list)
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
523 524 525 526 527 528 529 530 531 532 533 534 535 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 561 | |
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
563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 | |
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
588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 | |
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
635 636 637 638 639 640 641 642 | |
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
644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 | |
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
663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 | |