Operations¶
Structural operations for combining, splitting, and factorizing features in probabilistic circuits.
Cat¶
Concatenates multiple modules along the feature or channel dimension.
- class spflow.modules.ops.Cat(inputs, dim=-1)[source]¶
Bases:
Module- log_likelihood(data, cache=None)[source]¶
Compute log likelihood by concatenating input log-likelihoods.
Split¶
Abstract base class for feature splitting operations.
- class spflow.modules.ops.split.Split(inputs, dim=1, num_splits=2)[source]¶
Bases:
Module,ABCAbstract base class for tensor splitting operations.
Splits input tensors along specified dimensions. Concrete implementations must provide feature_to_scope property.
- inputs¶
Single input module to split.
- Type:
nn.ModuleList
- scope¶
Variable scope inherited from input.
- Type:
Scope
- get_out_shapes(event_shape)[source]¶
Get output shapes for each split based on input event shape.
- Parameters:
event_shape – Shape of the input event tensor.
- Returns:
List of tuples representing output shapes for each split.
- marginalize(marg_rvs, prune=True, cache=None)[source]¶
Marginalize out specified random variables.
- Parameters:
- Return type:
None|Module- Returns:
Marginalized module or None if fully marginalized.
- abstractmethod merge_split_indices(*split_indices)[source]¶
Merge per-split channel indices back to original feature layout.
This method takes channel indices for each split and combines them into indices matching the original (unsplit) feature layout. Used by parent modules (like EinsumLayer) during sampling.
SplitMode¶
Factory class for creating split configurations.
- class spflow.modules.ops.split.SplitMode(split_type, num_splits=2, indices=None)[source]¶
Bases:
objectConfiguration for split operations.
Factory class for creating split configurations. Use the class methods to create split configurations that can be passed to modules.
Example
>>> layer = EinsumLayer(inputs=leaf, num_repetitions=3, out_channels=10, split_mode=SplitMode.interleaved(num_splits=3)) >>> layer = LinsumLayer(inputs=leaf, out_channels=10, split_mode=SplitMode.consecutive(num_splits=2)) >>> layer = LinsumLayer(inputs=leaf, out_channels=10, split_mode=SplitMode.by_index(indices=[[0,1], [2,3]]))
- classmethod by_index(indices)[source]¶
Create a split configuration with explicit feature indices.
Splits features according to specified indices. Each inner list contains the feature indices for that split.
Example
>>> SplitMode.by_index([[0, 1, 4], [2, 3, 5, 6, 7]]) SplitMode.by_index(indices=[[0, 1, 4], [2, 3, 5, 6, 7]])
- classmethod consecutive(num_splits=2)[source]¶
Create a consecutive split configuration.
Splits features into consecutive chunks: [0,1,2,3] -> [0,1], [2,3].
- classmethod interleaved(num_splits=2)[source]¶
Create an interleaved split configuration.
Splits features using modulo: [0,1,2,3] -> [0,2], [1,3].
SplitConsecutive¶
Splits features into consecutive halves (or n parts).
- class spflow.modules.ops.SplitConsecutive(inputs, dim=1, num_splits=2)[source]¶
Bases:
SplitSplit operation using consecutive feature distribution.
Splits features into consecutive chunks: feature i goes to split i // (num_features / num_splits).
Example
With num_splits=2: [0,1,2,3] -> [0,1], [2,3] With num_splits=3: [0,1,2,3,4,5] -> [0,1], [2,3], [4,5]
- merge_split_indices(*split_indices)[source]¶
Merge split indices back to original layout (consecutive).
SplitConsecutive splits features consecutively: [0,1,2,3] -> [0,1], [2,3]. So we concatenate: left_indices, right_indices.
- Return type:
SplitInterleaved¶
Splits features in alternating fashion.
- class spflow.modules.ops.SplitInterleaved(inputs, dim=1, num_splits=2)[source]¶
Bases:
SplitSplit operation using interleaved feature distribution.
Distributes features using modulo arithmetic: feature i goes to split i % num_splits. Optimized for common cases (2 and 3 splits).
Example
With num_splits=2: [0,1,2,3] -> [0,2], [1,3] With num_splits=3: [0,1,2,3,4,5] -> [0,3], [1,4], [2,5]
- split_masks¶
Boolean masks for each split.
- Type:
list[Tensor]
- merge_split_indices(*split_indices)[source]¶
Merge split indices back to original layout (interleaved).
SplitInterleaved splits features by modulo: [0,1,2,3] -> [0,2], [1,3]. So we interleave: [left[0], right[0], left[1], right[1], …].
- Return type:
SplitByIndex¶
Splits features according to user-specified indices.
- class spflow.modules.ops.SplitByIndex(inputs, indices=None, dim=1)[source]¶
Bases:
SplitSplit operation using explicit feature indices.
Allows full control over which features go into which split by specifying exact indices for each split.
Example
With indices=[[0, 1, 4], [2, 3, 5, 6, 7]]: features are split into group 1: [0, 1, 4] and group 2: [2, 3, 5, 6, 7]
- indices¶
List of lists specifying feature indices for each split.
- inverse_indices¶
Tensor mapping original positions to split outputs.
- __init__(inputs, indices=None, dim=1)[source]¶
Initialize index-based split operation.
- Parameters:
inputs (
Module) – Input module to split.indices (
Optional[Sequence[Sequence[int]]]) – List of lists specifying feature indices for each split. Each inner list contains the feature indices for that split. All features must be covered exactly once (no overlap, no gaps).dim (
int) – Dimension along which to split (0=batch, 1=feature, 2=channel).
- Raises:
ValueError – If indices are invalid (overlap, gaps, out of bounds).
- merge_split_indices(*split_indices)[source]¶
Merge split indices back to original layout.
Takes channel indices for each split and combines them into indices matching the original (unsplit) feature layout.
- merge_split_tensors(*split_tensors)[source]¶
Merge split feature tensors back to original layout.
- Return type: