Skip to content

parameters

parameters ¤

BinaryParameterOp ¤

Bases: ParameterOp, ABC

A symbolic parameter operator that represents a binary operation.

Source code in cirkit/symbolic/parameters.py
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
class BinaryParameterOp(ParameterOp, ABC):
    """A symbolic parameter operator that represents a binary operation."""

    def __init__(self, in_shape1: tuple[int, ...], in_shape2: tuple[int, ...]):
        """Initializes a symbolic binary parameter operator.

        Args:
            in_shape1: The shape of the first input.
            in_shape2: The shape of the second input.
        """
        super().__init__(in_shape1, in_shape2)

    @property
    def in_shape1(self) -> tuple[int, ...]:
        """Retrieves the shape of the first input.

        Returns:
            The shape of the first input.
        """
        return self._in_shapes[0]

    @property
    def in_shape2(self) -> tuple[int, ...]:
        """Retrieves the shape of the second input.

        Returns:
            The shape of the second input.
        """
        return self._in_shapes[1]

    @property
    def config(self) -> dict[str, Any]:
        return {"in_shape1": self.in_shape1, "in_shape2": self.in_shape2}

config property ¤

in_shape1 property ¤

Retrieves the shape of the first input.

Returns:

Type Description
tuple[int, ...]

The shape of the first input.

in_shape2 property ¤

Retrieves the shape of the second input.

Returns:

Type Description
tuple[int, ...]

The shape of the second input.

__init__(in_shape1, in_shape2) ¤

Initializes a symbolic binary parameter operator.

Parameters:

Name Type Description Default
in_shape1 tuple[int, ...]

The shape of the first input.

required
in_shape2 tuple[int, ...]

The shape of the second input.

required
Source code in cirkit/symbolic/parameters.py
222
223
224
225
226
227
228
229
def __init__(self, in_shape1: tuple[int, ...], in_shape2: tuple[int, ...]):
    """Initializes a symbolic binary parameter operator.

    Args:
        in_shape1: The shape of the first input.
        in_shape2: The shape of the second input.
    """
    super().__init__(in_shape1, in_shape2)

ClampParameter ¤

Bases: EntrywiseParameterOp

A symbolic parameter operator representing the element-wise clamping operator.

Source code in cirkit/symbolic/parameters.py
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
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
613
614
class ClampParameter(EntrywiseParameterOp):
    """A symbolic parameter operator representing the element-wise clamping operator."""

    def __init__(
        self,
        in_shape: tuple[int, ...],
        *,
        vmin: float | None = None,
        vmax: float | None = None,
    ):
        """Initializes a symbolic clamp parameter operator. At least one between
            the minimum and maximum value must be specified.

        Args:
            in_shape: The shape of the input.
            vmin: The minimum value to clamp to. If it is None, then clamping for
                the minimum value is not performed.
            vmax: The maximum value to clamp to. If it is None, then clamping for
                the maximum value is not performed.
        """
        assert vmin is not None or vmax is not None
        super().__init__(in_shape)
        self._vmin = vmin
        self._vmax = vmax

    @property
    def vmin(self) -> float | None:
        """Retrieves the minimum clamping value.

        Returns:
            The minimum clamping value.
        """
        return self._vmin

    @property
    def vmax(self) -> float | None:
        """Retrieves the maximum clamping value.

        Returns:
            The maximum clamping value.
        """
        return self._vmax

    @property
    def config(self) -> dict[str, Any]:
        config = super().config
        config["vmin"] = self.vmin
        config["vmax"] = self.vmax
        return config

config property ¤

vmax property ¤

Retrieves the maximum clamping value.

Returns:

Type Description
float | None

The maximum clamping value.

vmin property ¤

Retrieves the minimum clamping value.

Returns:

Type Description
float | None

The minimum clamping value.

__init__(in_shape, *, vmin=None, vmax=None) ¤

Initializes a symbolic clamp parameter operator. At least one between the minimum and maximum value must be specified.

Parameters:

Name Type Description Default
in_shape tuple[int, ...]

The shape of the input.

required
vmin float | None

The minimum value to clamp to. If it is None, then clamping for the minimum value is not performed.

None
vmax float | None

The maximum value to clamp to. If it is None, then clamping for the maximum value is not performed.

None
Source code in cirkit/symbolic/parameters.py
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
def __init__(
    self,
    in_shape: tuple[int, ...],
    *,
    vmin: float | None = None,
    vmax: float | None = None,
):
    """Initializes a symbolic clamp parameter operator. At least one between
        the minimum and maximum value must be specified.

    Args:
        in_shape: The shape of the input.
        vmin: The minimum value to clamp to. If it is None, then clamping for
            the minimum value is not performed.
        vmax: The maximum value to clamp to. If it is None, then clamping for
            the maximum value is not performed.
    """
    assert vmin is not None or vmax is not None
    super().__init__(in_shape)
    self._vmin = vmin
    self._vmax = vmax

ConjugateParameter ¤

Bases: EntrywiseParameterOp

A symbolic parameter operator representing the element-wise complex conjugation operation of its input.

Source code in cirkit/symbolic/parameters.py
617
618
619
620
class ConjugateParameter(EntrywiseParameterOp):
    """A symbolic parameter operator representing the element-wise complex conjugation
    operation of its input.
    """

ConstantParameter ¤

Bases: TensorParameter

A symbolic tensor parameter representing a constant tensor, i.e., a tensor that is not learnable.

Source code in cirkit/symbolic/parameters.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
class ConstantParameter(TensorParameter):
    """A symbolic tensor parameter representing a constant tensor, i.e.,
    a tensor that is not learnable.
    """

    def __init__(self, *shape: int, value: int | float | complex | np.number | np.ndarray = 0.0):
        """Initializes a constant symbolic parameter.

        Args:
            *shape: The shape of the parameter.
            value: The values stored in the parameter. It can be either a number or
                a Numpy array having the same shape of the given one.

        Raises:
            ValueError: If the given value is a Numpy array having a different shape
                than the given one.
        """
        if isinstance(value, np.ndarray) and value.shape != shape:
            raise ValueError("The shape of the Numpy array is not equal to the given shape")
        initializer = ConstantTensorInitializer(value)
        super().__init__(
            *shape,
            initializer=initializer,
            learnable=False,
            dtype=dtype_value(value),
        )
        self.value = value

    @property
    def config(self) -> dict[str, Any]:
        return {"shape": self.shape, "value": self.value}

config property ¤

value = value instance-attribute ¤

__init__(*shape, value=0.0) ¤

Initializes a constant symbolic parameter.

Parameters:

Name Type Description Default
*shape int

The shape of the parameter.

()
value int | float | complex | number | ndarray

The values stored in the parameter. It can be either a number or a Numpy array having the same shape of the given one.

0.0

Raises:

Type Description
ValueError

If the given value is a Numpy array having a different shape than the given one.

Source code in cirkit/symbolic/parameters.py
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
def __init__(self, *shape: int, value: int | float | complex | np.number | np.ndarray = 0.0):
    """Initializes a constant symbolic parameter.

    Args:
        *shape: The shape of the parameter.
        value: The values stored in the parameter. It can be either a number or
            a Numpy array having the same shape of the given one.

    Raises:
        ValueError: If the given value is a Numpy array having a different shape
            than the given one.
    """
    if isinstance(value, np.ndarray) and value.shape != shape:
        raise ValueError("The shape of the Numpy array is not equal to the given shape")
    initializer = ConstantTensorInitializer(value)
    super().__init__(
        *shape,
        initializer=initializer,
        learnable=False,
        dtype=dtype_value(value),
    )
    self.value = value

EntrywiseParameterOp ¤

Bases: UnaryParameterOp, ABC

A symbolic parameter operator that represents a unary function that is applied entrywise to the input parameter tensor.

Source code in cirkit/symbolic/parameters.py
254
255
256
257
258
259
260
261
class EntrywiseParameterOp(UnaryParameterOp, ABC):
    """A symbolic parameter operator that represents a unary function
    that is applied entrywise to the input parameter tensor.
    """

    @property
    def shape(self) -> tuple[int, ...]:
        return self.in_shape

shape property ¤

EntrywiseReduceParameterOp ¤

Bases: EntrywiseParameterOp, ABC

A symbolic parameter operator that represents a unary function that is applied entrywise to the input parameter tensor, and this unary function is obtained by reducing one input dimension.

Source code in cirkit/symbolic/parameters.py
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
class EntrywiseReduceParameterOp(EntrywiseParameterOp, ABC):
    """A symbolic parameter operator that represents a unary function
    that is applied entrywise to the input parameter tensor,
    and this unary function is obtained by reducing one input dimension.
    """

    def __init__(self, in_shape: tuple[int, ...], *, axis: int = -1):
        """Initializes an entrywise reduce parameter operator.

        Args:
            in_shape: The shape of the input.
            axis: The axis of the input being reduced.
        """
        super().__init__(in_shape)
        axis = axis if axis >= 0 else axis + len(in_shape)
        assert 0 <= axis < len(in_shape)
        self._axis = axis

    @property
    def axis(self) -> int:
        """Retrieves the axis of the input being reduced.

        Returns:
            The axis dimension.
        """
        return self._axis

    @property
    def config(self) -> dict[str, Any]:
        config = super().config
        config["axis"] = self.axis
        return config

axis property ¤

Retrieves the axis of the input being reduced.

Returns:

Type Description
int

The axis dimension.

config property ¤

__init__(in_shape, *, axis=-1) ¤

Initializes an entrywise reduce parameter operator.

Parameters:

Name Type Description Default
in_shape tuple[int, ...]

The shape of the input.

required
axis int

The axis of the input being reduced.

-1
Source code in cirkit/symbolic/parameters.py
306
307
308
309
310
311
312
313
314
315
316
def __init__(self, in_shape: tuple[int, ...], *, axis: int = -1):
    """Initializes an entrywise reduce parameter operator.

    Args:
        in_shape: The shape of the input.
        axis: The axis of the input being reduced.
    """
    super().__init__(in_shape)
    axis = axis if axis >= 0 else axis + len(in_shape)
    assert 0 <= axis < len(in_shape)
    self._axis = axis

ExpParameter ¤

Bases: EntrywiseParameterOp

A symbolic parameter operator representing the exponential of a parameter tensor.

Source code in cirkit/symbolic/parameters.py
496
497
class ExpParameter(EntrywiseParameterOp):
    """A symbolic parameter operator representing the exponential of a parameter tensor."""

GaussianProductLogPartition ¤

Bases: ParameterOp

A symbolic parameter operator computing the log partition function of the product of two Gaussians, given the means and standard deviations of the input Gaussians.

Source code in cirkit/symbolic/parameters.py
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
class GaussianProductLogPartition(ParameterOp):
    """A symbolic parameter operator computing the log partition function of the product of
    two Gaussians, given the means and standard deviations of the input Gaussians.
    """

    def __init__(
        self,
        in_mean1_shape: tuple[int, ...],
        in_stddev1_shape: tuple[int, ...],
        in_mean2_shape: tuple[int, ...],
        in_stddev2_shape: tuple[int, ...],
    ):
        """Initializes a symbolic Gaussian product log partition function,
            given the shape of the input means and standard deviations.

        Args:
            in_mean1_shape: The shape of the mean of the first univariate Gaussians.
            in_stddev1_shape: The shape of the standard deviations of the first
                univariate Gaussians.
            in_mean2_shape: The shape of the mean of the second univariate Gaussians.
            in_stddev2_shape: The shape of the standard deviations of the second
                univariate Gaussians.
        """
        assert in_mean1_shape == in_stddev1_shape
        assert in_mean2_shape == in_stddev2_shape
        super().__init__(in_mean1_shape, in_stddev1_shape, in_mean2_shape, in_stddev2_shape)

    @property
    def shape(self) -> tuple[int, ...]:
        return (self.in_shapes[0][0] * self.in_shapes[2][0],)

    @property
    def config(self) -> dict[str, Any]:
        return {
            "in_mean1_shape": self.in_shapes[0],
            "in_stddev1_shape": self.in_shapes[1],
            "in_mean2_shape": self.in_shapes[2],
            "in_stddev2_shape": self.in_shapes[3],
        }

config property ¤

shape property ¤

__init__(in_mean1_shape, in_stddev1_shape, in_mean2_shape, in_stddev2_shape) ¤

Initializes a symbolic Gaussian product log partition function, given the shape of the input means and standard deviations.

Parameters:

Name Type Description Default
in_mean1_shape tuple[int, ...]

The shape of the mean of the first univariate Gaussians.

required
in_stddev1_shape tuple[int, ...]

The shape of the standard deviations of the first univariate Gaussians.

required
in_mean2_shape tuple[int, ...]

The shape of the mean of the second univariate Gaussians.

required
in_stddev2_shape tuple[int, ...]

The shape of the standard deviations of the second univariate Gaussians.

required
Source code in cirkit/symbolic/parameters.py
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
def __init__(
    self,
    in_mean1_shape: tuple[int, ...],
    in_stddev1_shape: tuple[int, ...],
    in_mean2_shape: tuple[int, ...],
    in_stddev2_shape: tuple[int, ...],
):
    """Initializes a symbolic Gaussian product log partition function,
        given the shape of the input means and standard deviations.

    Args:
        in_mean1_shape: The shape of the mean of the first univariate Gaussians.
        in_stddev1_shape: The shape of the standard deviations of the first
            univariate Gaussians.
        in_mean2_shape: The shape of the mean of the second univariate Gaussians.
        in_stddev2_shape: The shape of the standard deviations of the second
            univariate Gaussians.
    """
    assert in_mean1_shape == in_stddev1_shape
    assert in_mean2_shape == in_stddev2_shape
    super().__init__(in_mean1_shape, in_stddev1_shape, in_mean2_shape, in_stddev2_shape)

GaussianProductMean ¤

Bases: ParameterOp

A symbolic parameter operator computing the mean of the product of two Gaussians, given the means and standard deviations of the input Gaussians. Note that we assume Gaussians being univariate.

Source code in cirkit/symbolic/parameters.py
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
class GaussianProductMean(ParameterOp):
    """A symbolic parameter operator computing the mean of the product of two Gaussians,
    given the means and standard deviations of the input Gaussians. Note that we assume
    Gaussians being univariate.
    """

    def __init__(
        self,
        in_mean1_shape: tuple[int, ...],
        in_stddev1_shape: tuple[int, ...],
        in_mean2_shape: tuple[int, ...],
        in_stddev2_shape: tuple[int, ...],
    ):
        """Initializes a symbolic Gaussian product mean, given the shape of the input means
            and standard deviations.

        Args:
            in_mean1_shape: The shape of the mean of the first univariate Gaussians.
            in_stddev1_shape: The shape of the standard deviations of the first
                univariate Gaussians.
            in_mean2_shape: The shape of the mean of the second univariate Gaussians.
            in_stddev2_shape: The shape of the standard deviations of the second
                univariate Gaussians.
        """
        assert in_mean1_shape == in_stddev1_shape
        assert in_mean2_shape == in_stddev2_shape
        super().__init__(in_mean1_shape, in_stddev1_shape, in_mean2_shape, in_stddev2_shape)

    @property
    def shape(self) -> tuple[int, ...]:
        return (self.in_shapes[0][0] * self.in_shapes[2][0],)

    @property
    def config(self) -> dict[str, Any]:
        return {
            "in_mean1_shape": self.in_shapes[0],
            "in_stddev1_shape": self.in_shapes[1],
            "in_mean2_shape": self.in_shapes[2],
            "in_stddev2_shape": self.in_shapes[3],
        }

config property ¤

shape property ¤

__init__(in_mean1_shape, in_stddev1_shape, in_mean2_shape, in_stddev2_shape) ¤

Initializes a symbolic Gaussian product mean, given the shape of the input means and standard deviations.

Parameters:

Name Type Description Default
in_mean1_shape tuple[int, ...]

The shape of the mean of the first univariate Gaussians.

required
in_stddev1_shape tuple[int, ...]

The shape of the standard deviations of the first univariate Gaussians.

required
in_mean2_shape tuple[int, ...]

The shape of the mean of the second univariate Gaussians.

required
in_stddev2_shape tuple[int, ...]

The shape of the standard deviations of the second univariate Gaussians.

required
Source code in cirkit/symbolic/parameters.py
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
def __init__(
    self,
    in_mean1_shape: tuple[int, ...],
    in_stddev1_shape: tuple[int, ...],
    in_mean2_shape: tuple[int, ...],
    in_stddev2_shape: tuple[int, ...],
):
    """Initializes a symbolic Gaussian product mean, given the shape of the input means
        and standard deviations.

    Args:
        in_mean1_shape: The shape of the mean of the first univariate Gaussians.
        in_stddev1_shape: The shape of the standard deviations of the first
            univariate Gaussians.
        in_mean2_shape: The shape of the mean of the second univariate Gaussians.
        in_stddev2_shape: The shape of the standard deviations of the second
            univariate Gaussians.
    """
    assert in_mean1_shape == in_stddev1_shape
    assert in_mean2_shape == in_stddev2_shape
    super().__init__(in_mean1_shape, in_stddev1_shape, in_mean2_shape, in_stddev2_shape)

GaussianProductStddev ¤

Bases: BinaryParameterOp

A symbolic parameter operator computing the standard deviation of the product of two Gaussians, given the standard deviations of the input Gaussians.

Source code in cirkit/symbolic/parameters.py
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
class GaussianProductStddev(BinaryParameterOp):
    """A symbolic parameter operator computing the standard deviation of the product of
    two Gaussians, given the standard deviations of the input Gaussians.
    """

    def __init__(self, in_stddev1_shape: tuple[int, ...], in_stddev2_shape: tuple[int, ...]):
        """Initializes a symbolic Gaussian product standard deviation,
            given the shape of the input standard deviations.

        Args:
            in_stddev1_shape: The shape of the standard deviations of the first
                univariate Gaussians.
            in_stddev2_shape: The shape of the standard deviations of the second
                univariate Gaussians.
        """
        super().__init__(in_stddev1_shape, in_stddev2_shape)

    @property
    def shape(self) -> tuple[int, ...]:
        return (self.in_shapes[0][0] * self.in_shapes[1][0],)

    @property
    def config(self) -> dict[str, Any]:
        return {"in_stddev1_shape": self.in_shapes[0], "in_stddev2_shape": self.in_shapes[1]}

config property ¤

shape property ¤

__init__(in_stddev1_shape, in_stddev2_shape) ¤

Initializes a symbolic Gaussian product standard deviation, given the shape of the input standard deviations.

Parameters:

Name Type Description Default
in_stddev1_shape tuple[int, ...]

The shape of the standard deviations of the first univariate Gaussians.

required
in_stddev2_shape tuple[int, ...]

The shape of the standard deviations of the second univariate Gaussians.

required
Source code in cirkit/symbolic/parameters.py
717
718
719
720
721
722
723
724
725
726
727
def __init__(self, in_stddev1_shape: tuple[int, ...], in_stddev2_shape: tuple[int, ...]):
    """Initializes a symbolic Gaussian product standard deviation,
        given the shape of the input standard deviations.

    Args:
        in_stddev1_shape: The shape of the standard deviations of the first
            univariate Gaussians.
        in_stddev2_shape: The shape of the standard deviations of the second
            univariate Gaussians.
    """
    super().__init__(in_stddev1_shape, in_stddev2_shape)

HadamardParameter ¤

Bases: BinaryParameterOp

A symbolic parameter operator representing the element-wise product of its inputs.

Source code in cirkit/symbolic/parameters.py
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
class HadamardParameter(BinaryParameterOp):
    """A symbolic parameter operator representing the element-wise product of its inputs."""

    def __init__(self, in_shape1: tuple[int, ...], in_shape2: tuple[int, ...]):
        """Initializes a symbolic Hadamard parameter operator.

        Args:
            in_shape1: The shape of the first input.
            in_shape2: The shape of the second input.
        """
        assert in_shape1 == in_shape2
        super().__init__(in_shape1, in_shape2)

    @property
    def shape(self) -> tuple[int, ...]:
        return self.in_shape1

shape property ¤

__init__(in_shape1, in_shape2) ¤

Initializes a symbolic Hadamard parameter operator.

Parameters:

Name Type Description Default
in_shape1 tuple[int, ...]

The shape of the first input.

required
in_shape2 tuple[int, ...]

The shape of the second input.

required
Source code in cirkit/symbolic/parameters.py
409
410
411
412
413
414
415
416
417
def __init__(self, in_shape1: tuple[int, ...], in_shape2: tuple[int, ...]):
    """Initializes a symbolic Hadamard parameter operator.

    Args:
        in_shape1: The shape of the first input.
        in_shape2: The shape of the second input.
    """
    assert in_shape1 == in_shape2
    super().__init__(in_shape1, in_shape2)

IndexParameter ¤

Bases: UnaryParameterOp

A symbolic parameter operator that indexes an input parameter tensor along one axis.

Source code in cirkit/symbolic/parameters.py
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
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
class IndexParameter(UnaryParameterOp):
    """A symbolic parameter operator that indexes an input parameter tensor
    along one axis.
    """

    def __init__(self, in_shape: tuple[int, ...], *, indices: list[int], axis: int = -1):
        """Initializes a symbolc index parameter.

        Args:
            in_shape: The shape of the input.
            indices: The indices to index.
            axis: The axis of the input tensor being indexed.
        """
        super().__init__(in_shape)
        axis = axis if axis >= 0 else axis + len(in_shape)
        assert 0 <= axis < len(in_shape)
        assert all(0 <= i < in_shape[axis] for i in indices)
        self._indices = indices
        self._axis = axis

    @property
    def indices(self) -> list[int]:
        """Retrieves the indices.

        Returns:
            The indices.
        """
        return self._indices

    @property
    def axis(self) -> int:
        """Retrieves the axis being indexed.

        Returns:
            The axis.
        """
        return self._axis

    @property
    def shape(self) -> tuple[int, ...]:
        return (
            *self.in_shape[: self.axis],
            len(self.indices),
            *self.in_shape[self.axis + 1 :],
        )

    @property
    def config(self) -> dict[str, Any]:
        config = super().config
        config["indices"] = self.indices
        config["axis"] = self.axis
        return config

axis property ¤

Retrieves the axis being indexed.

Returns:

Type Description
int

The axis.

config property ¤

indices property ¤

Retrieves the indices.

Returns:

Type Description
list[int]

The indices.

shape property ¤

__init__(in_shape, *, indices, axis=-1) ¤

Initializes a symbolc index parameter.

Parameters:

Name Type Description Default
in_shape tuple[int, ...]

The shape of the input.

required
indices list[int]

The indices to index.

required
axis int

The axis of the input tensor being indexed.

-1
Source code in cirkit/symbolic/parameters.py
339
340
341
342
343
344
345
346
347
348
349
350
351
352
def __init__(self, in_shape: tuple[int, ...], *, indices: list[int], axis: int = -1):
    """Initializes a symbolc index parameter.

    Args:
        in_shape: The shape of the input.
        indices: The indices to index.
        axis: The axis of the input tensor being indexed.
    """
    super().__init__(in_shape)
    axis = axis if axis >= 0 else axis + len(in_shape)
    assert 0 <= axis < len(in_shape)
    assert all(0 <= i < in_shape[axis] for i in indices)
    self._indices = indices
    self._axis = axis

KroneckerParameter ¤

Bases: BinaryParameterOp

A symbolic parameter operator representing the Kronecker product of its inputs.

Source code in cirkit/symbolic/parameters.py
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
class KroneckerParameter(BinaryParameterOp):
    """A symbolic parameter operator representing the Kronecker product of its inputs."""

    def __init__(self, in_shape1: tuple[int, ...], in_shape2: tuple[int, ...]):
        """Initializes a symbolic Kronecker parameter operator.

        Args:
            in_shape1: The shape of the first input.
            in_shape2: The shape of the second input.
        """
        assert len(in_shape1) == len(in_shape2)
        super().__init__(in_shape1, in_shape2)

    @cached_property
    def shape(self) -> tuple[int, ...]:
        return tuple(self.in_shape1[i] * self.in_shape2[i] for i in range(len(self.in_shape1)))

shape cached property ¤

__init__(in_shape1, in_shape2) ¤

Initializes a symbolic Kronecker parameter operator.

Parameters:

Name Type Description Default
in_shape1 tuple[int, ...]

The shape of the first input.

required
in_shape2 tuple[int, ...]

The shape of the second input.

required
Source code in cirkit/symbolic/parameters.py
427
428
429
430
431
432
433
434
435
def __init__(self, in_shape1: tuple[int, ...], in_shape2: tuple[int, ...]):
    """Initializes a symbolic Kronecker parameter operator.

    Args:
        in_shape1: The shape of the first input.
        in_shape2: The shape of the second input.
    """
    assert len(in_shape1) == len(in_shape2)
    super().__init__(in_shape1, in_shape2)

LogParameter ¤

Bases: EntrywiseParameterOp

A symbolic parameter operator representing the logarithm of a parameter tensor.

Source code in cirkit/symbolic/parameters.py
500
501
class LogParameter(EntrywiseParameterOp):
    """A symbolic parameter operator representing the logarithm of a parameter tensor."""

LogSoftmaxParameter ¤

Bases: EntrywiseReduceParameterOp

A symoblic parameter operator representing the application of the LogSoftmax function along one dimension.

Source code in cirkit/symbolic/parameters.py
641
642
643
644
class LogSoftmaxParameter(EntrywiseReduceParameterOp):
    """A symoblic parameter operator representing the application of the LogSoftmax function
    along one dimension.
    """

MixingWeightParameter ¤

Bases: UnaryParameterOp

The symbolic mixing weights parameter node, which takes as input a matrix \(\mathbf{V}\) of shape \((K, H)\), where \(K\) is the number of units and \(H\) is the arity of a SumLayer, and returns a matrix \(\mathbf{W}\) of shape \((K, K * H)\), where \(\mathbf{W}\) is the column-wise concatenation of matrices \(\{ \mathrm{diag}(\mathbf{v}_{:i}) \}_{i=1}^H\), \(\mathbf{v}_{:i}\) denotes the \(i\)-th column of $\mathbf{V} and \(\mathrm{diag}\) transforms a vector to a diagonal matrix.

This parameter node is used in mixing_weight_factory as to parameterize a sum layer encoding a weighted combination of its input vectors.

Source code in cirkit/symbolic/parameters.py
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
class MixingWeightParameter(UnaryParameterOp):
    r"""The symbolic mixing weights parameter node, which takes as input a matrix $\mathbf{V}$
    of shape $(K, H)$, where $K$ is the number of units and $H$ is the arity of a
    [SumLayer][cirkit.symbolic.layers.SumLayer], and returns a matrix $\mathbf{W}$ of shape
    $(K, K * H)$, where $\mathbf{W}$ is the column-wise concatenation of matrices
    $\{ \mathrm{diag}(\mathbf{v}_{:i}) \}_{i=1}^H$, $\mathbf{v}_{:i}$ denotes the $i$-th column
    of $\mathbf{V} and $\mathrm{diag}$ transforms a vector to a diagonal matrix.

    This parameter node is used in
    [mixing_weight_factory][cirkit.symbolic.parameters.mixing_weight_factory] as to parameterize
    a sum layer encoding a weighted combination of its input vectors.
    """

    def __init__(self, in_shape: tuple[int, ...]):
        if len(in_shape) != 2:
            raise ValueError(f"Expected shape (num_units, arity), but found {in_shape}")
        super().__init__(in_shape)

    @property
    def shape(self) -> tuple[int, ...]:
        return self.in_shape[0], self.in_shape[0] * self.in_shape[1]

shape property ¤

__init__(in_shape) ¤

Source code in cirkit/symbolic/parameters.py
660
661
662
663
def __init__(self, in_shape: tuple[int, ...]):
    if len(in_shape) != 2:
        raise ValueError(f"Expected shape (num_units, arity), but found {in_shape}")
    super().__init__(in_shape)

OuterParameterOp ¤

Bases: BinaryParameterOp

A symbolic parameter operator computing a function applied over all possible combinations of entries along one axis of the input tensors.

Source code in cirkit/symbolic/parameters.py
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
class OuterParameterOp(BinaryParameterOp):
    """A symbolic parameter operator computing a function applied over all possible combinations
    of entries along one axis of the input tensors.
    """

    def __init__(self, in_shape1: tuple[int, ...], in_shape2: tuple[int, ...], *, axis: int = -1):
        """Initializes a symbolic parameter outer operator.

        Args:
            in_shape1: The shape of the first input.
            in_shape2: The shape of the second input.
            axis: The axis of both inputs along which the function is applied.
        """
        assert len(in_shape1) == len(in_shape2)
        axis = axis if axis >= 0 else axis + len(in_shape1)
        assert 0 <= axis < len(in_shape1)
        assert in_shape1[:axis] == in_shape1[:axis]
        assert in_shape1[axis + 1 :] == in_shape1[axis + 1 :]
        super().__init__(in_shape1, in_shape2)
        self._axis = axis

    @property
    def axis(self) -> int:
        """Retrieves the axis.

        Returns:
            The axis.
        """
        return self._axis

    @property
    def shape(self) -> tuple[int, ...]:
        cross_dim = self.in_shape1[self.axis] * self.in_shape2[self.axis]
        return *self.in_shape1[: self.axis], cross_dim, *self.in_shape1[self.axis + 1 :]

    @property
    def config(self) -> dict[str, Any]:
        config = super().config
        config["axis"] = self.axis
        return config

axis property ¤

Retrieves the axis.

Returns:

Type Description
int

The axis.

config property ¤

shape property ¤

__init__(in_shape1, in_shape2, *, axis=-1) ¤

Initializes a symbolic parameter outer operator.

Parameters:

Name Type Description Default
in_shape1 tuple[int, ...]

The shape of the first input.

required
in_shape2 tuple[int, ...]

The shape of the second input.

required
axis int

The axis of both inputs along which the function is applied.

-1
Source code in cirkit/symbolic/parameters.py
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
def __init__(self, in_shape1: tuple[int, ...], in_shape2: tuple[int, ...], *, axis: int = -1):
    """Initializes a symbolic parameter outer operator.

    Args:
        in_shape1: The shape of the first input.
        in_shape2: The shape of the second input.
        axis: The axis of both inputs along which the function is applied.
    """
    assert len(in_shape1) == len(in_shape2)
    axis = axis if axis >= 0 else axis + len(in_shape1)
    assert 0 <= axis < len(in_shape1)
    assert in_shape1[:axis] == in_shape1[:axis]
    assert in_shape1[axis + 1 :] == in_shape1[axis + 1 :]
    super().__init__(in_shape1, in_shape2)
    self._axis = axis

OuterProductParameter ¤

Bases: OuterParameterOp

A symbolic parameter operator represeting the outer product of two parameter tensors along one axis.

Source code in cirkit/symbolic/parameters.py
484
485
486
487
class OuterProductParameter(OuterParameterOp):
    """A symbolic parameter operator represeting the outer product of two parameter tensors
    along one axis.
    """

OuterSumParameter ¤

Bases: OuterParameterOp

A symbolic parameter operator represeting the outer sum of two parameter tensors along one axis.

Source code in cirkit/symbolic/parameters.py
490
491
492
493
class OuterSumParameter(OuterParameterOp):
    """A symbolic parameter operator represeting the outer sum of two parameter tensors
    along one axis.
    """

Parameter ¤

Bases: RootedDiAcyclicGraph[ParameterNode]

The symbolic parameter computational graph. A symbolic parameter is a computational graph consisting of symbolic nodes, which represent how to compute a tensor parameter.

Source code in cirkit/symbolic/parameters.py
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
class Parameter(RootedDiAcyclicGraph[ParameterNode]):
    """The symbolic parameter computational graph. A symbolic parameter is a computational graph
    consisting of symbolic nodes, which represent how to compute a tensor parameter."""

    def __init__(
        self,
        nodes: Sequence[ParameterNode],
        in_nodes: Mapping[ParameterNode, Sequence[ParameterNode]],
        outputs: Sequence[ParameterNode],
    ):
        super().__init__(nodes, in_nodes, outputs)

        # Check the computational graph is consistent w.r.t.
        # the input and output shapes of each computational node
        for node in self.nodes:
            node_ins = self.node_inputs(node)
            if isinstance(node, ParameterInput):
                if len(node_ins):
                    raise ValueError(
                        f"{node}: found an input parameter node with {len(node_ins)} other inputs, "
                        "but expected none"
                    )
                continue
            assert isinstance(node, ParameterOp)
            if len(node.in_shapes) != len(node_ins):
                raise ValueError(
                    f"{node}: expected number of inputs {len(node.in_shapes)}, "
                    f"but found {len(node_ins)}"
                )
            node_ins_shapes = tuple(n.shape for n in node_ins)
            if node.in_shapes != node_ins_shapes:
                raise ValueError(
                    f"{node}: expected input shapes {node.in_shapes}, "
                    f"but found {node_ins_shapes}"
                )

    @property
    def shape(self) -> tuple[int, ...]:
        """Retrieves the shape of the output tensor.

        Returns:
            The shape of the output of the computational graph.
        """
        return self.output.shape

    @classmethod
    def from_input(cls, p: ParameterInput) -> "Parameter":
        """Constructs a parameter from a leaf symbolic node only.

        Args:
            p: The symbolic parameter input.

        Returns:
            A symbolic parameter encapsulating the given parameter input.
        """
        return Parameter([p], {}, [p])

    @classmethod
    def from_sequence(
        cls, p: Union[ParameterInput, "Parameter"], *ns: ParameterNode
    ) -> "Parameter":
        """Constructs a parameter from a composition of symbolic parameter nodes.

        Args:
            p: The entry point of the sequence, which can be either a symbolic parameter
                input or another symbolic parameter.
            *ns: A sequence of symbolic parameter nodes.

        Returns:
            A symbolic parameter that encodes the composition of the symbolic parameter nodes,
                starting from the given entry point of the sequence.
        """
        if isinstance(p, ParameterInput):
            p = Parameter.from_input(p)
        nodes = list(p.nodes) + list(ns)
        in_nodes = dict(p.nodes_inputs)
        for i, n in enumerate(ns):
            in_nodes[n] = [ns[i - 1]] if i - 1 >= 0 else [p.output]
        return Parameter(nodes, in_nodes, [ns[-1]])

    @classmethod
    def from_nary(cls, n: ParameterOp, *ps: Union[ParameterInput, "Parameter"]) -> "Parameter":
        """Constructs a parameter by using a parameter operation node and by specifying its inputs.

        Args:
            n: The parameter operation node.
            *ps: A sequence of symbolic parameter input nodes or parameters.

        Returns:
            A symbolic parameter that encodes the application of the given parameter operation node
                to the outputs given by the symbolic parameter input nodes or parameters.
        """
        p_graphs = tuple(
            Parameter.from_input(p) if isinstance(p, ParameterInput) else p for p in ps
        )
        p_nodes = list(chain.from_iterable(p.nodes for p in p_graphs)) + [n]
        in_nodes: dict[ParameterNode, Sequence[ParameterNode]] = dict(
            (k, v) for g in p_graphs for (k, v) in g.nodes_inputs.items()
        )
        in_nodes[n] = list(p.output for p in p_graphs)
        return Parameter(p_nodes, in_nodes, [n])

    @classmethod
    def from_unary(cls, n: UnaryParameterOp, p: Union[ParameterInput, "Parameter"]) -> "Parameter":
        """Constructs a parameter by using a unary parameter operation node and by specifying its
        inputs.

        Args:
            n: The unary parameter operation node.
            p: The symbolic parameter input node, or another parameter.

        Returns:
            A symbolic parameter that encodes the application of the given parameter operation
                node to the output given by the symbolic parameter input node or parameter.
        """
        return Parameter.from_sequence(p, n)

    @classmethod
    def from_binary(
        cls,
        n: BinaryParameterOp,
        p1: Union[ParameterInput, "Parameter"],
        p2: Union[ParameterInput, "Parameter"],
    ) -> "Parameter":
        """Constructs a parameter by using a binary parameter operation node and by specifying
        its inputs.

        Args:
            n: The binary parameter operation node.
            p1: The first symbolic parameter input node, or another parameter.
            p2: The second symbolic parameter input node, or another parameter.

        Returns:
            A symbolic parameter that encodes the application of the given parameter operation
                node to the two outputs given by the symbolic parameter inputs or parameters.
        """
        return Parameter.from_nary(n, p1, p2)

    def ref(self) -> "Parameter":
        """Constructs a shallow copy of the parameter, where the tensor parameters
            are replace with reference parameters to them.

        Returns:
            A shallow copy of the parameter nodes, with the exception that tensor parameter nodes
                are replaced with symbolic references to them.
        """

        # Build a new symbolic parameter's computational graph, where the parameter tensors
        # become references to the tensors of the 'self' parameter's computational graph.
        # All the other nodes are new objects.
        def _replace_ref_or_copy(n: ParameterNode) -> ParameterNode:
            return ReferenceParameter(n) if isinstance(n, TensorParameter) else copy(n)

        return self._process_nodes(_replace_ref_or_copy)

    def _process_nodes(self, process_fn: Callable[[ParameterNode], ParameterNode]) -> "Parameter":
        # Process all the nodes by following the topological ordering and using a function
        nodes, in_nodes, outputs = topologically_process_nodes(
            self.topological_ordering(), self.outputs, process_fn, incomings_fn=self.node_inputs
        )
        return Parameter(nodes, in_nodes, outputs)

    def __repr__(self) -> str:
        return f"{Parameter.__name__}(shape={self.shape})"

shape property ¤

Retrieves the shape of the output tensor.

Returns:

Type Description
tuple[int, ...]

The shape of the output of the computational graph.

__init__(nodes, in_nodes, outputs) ¤

Source code in cirkit/symbolic/parameters.py
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
def __init__(
    self,
    nodes: Sequence[ParameterNode],
    in_nodes: Mapping[ParameterNode, Sequence[ParameterNode]],
    outputs: Sequence[ParameterNode],
):
    super().__init__(nodes, in_nodes, outputs)

    # Check the computational graph is consistent w.r.t.
    # the input and output shapes of each computational node
    for node in self.nodes:
        node_ins = self.node_inputs(node)
        if isinstance(node, ParameterInput):
            if len(node_ins):
                raise ValueError(
                    f"{node}: found an input parameter node with {len(node_ins)} other inputs, "
                    "but expected none"
                )
            continue
        assert isinstance(node, ParameterOp)
        if len(node.in_shapes) != len(node_ins):
            raise ValueError(
                f"{node}: expected number of inputs {len(node.in_shapes)}, "
                f"but found {len(node_ins)}"
            )
        node_ins_shapes = tuple(n.shape for n in node_ins)
        if node.in_shapes != node_ins_shapes:
            raise ValueError(
                f"{node}: expected input shapes {node.in_shapes}, "
                f"but found {node_ins_shapes}"
            )

__repr__() ¤

Source code in cirkit/symbolic/parameters.py
989
990
def __repr__(self) -> str:
    return f"{Parameter.__name__}(shape={self.shape})"

from_binary(n, p1, p2) classmethod ¤

Constructs a parameter by using a binary parameter operation node and by specifying its inputs.

Parameters:

Name Type Description Default
n BinaryParameterOp

The binary parameter operation node.

required
p1 Union[ParameterInput, Parameter]

The first symbolic parameter input node, or another parameter.

required
p2 Union[ParameterInput, Parameter]

The second symbolic parameter input node, or another parameter.

required

Returns:

Type Description
Parameter

A symbolic parameter that encodes the application of the given parameter operation node to the two outputs given by the symbolic parameter inputs or parameters.

Source code in cirkit/symbolic/parameters.py
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
@classmethod
def from_binary(
    cls,
    n: BinaryParameterOp,
    p1: Union[ParameterInput, "Parameter"],
    p2: Union[ParameterInput, "Parameter"],
) -> "Parameter":
    """Constructs a parameter by using a binary parameter operation node and by specifying
    its inputs.

    Args:
        n: The binary parameter operation node.
        p1: The first symbolic parameter input node, or another parameter.
        p2: The second symbolic parameter input node, or another parameter.

    Returns:
        A symbolic parameter that encodes the application of the given parameter operation
            node to the two outputs given by the symbolic parameter inputs or parameters.
    """
    return Parameter.from_nary(n, p1, p2)

from_input(p) classmethod ¤

Constructs a parameter from a leaf symbolic node only.

Parameters:

Name Type Description Default
p ParameterInput

The symbolic parameter input.

required

Returns:

Type Description
Parameter

A symbolic parameter encapsulating the given parameter input.

Source code in cirkit/symbolic/parameters.py
872
873
874
875
876
877
878
879
880
881
882
@classmethod
def from_input(cls, p: ParameterInput) -> "Parameter":
    """Constructs a parameter from a leaf symbolic node only.

    Args:
        p: The symbolic parameter input.

    Returns:
        A symbolic parameter encapsulating the given parameter input.
    """
    return Parameter([p], {}, [p])

from_nary(n, *ps) classmethod ¤

Constructs a parameter by using a parameter operation node and by specifying its inputs.

Parameters:

Name Type Description Default
n ParameterOp

The parameter operation node.

required
*ps Union[ParameterInput, Parameter]

A sequence of symbolic parameter input nodes or parameters.

()

Returns:

Type Description
Parameter

A symbolic parameter that encodes the application of the given parameter operation node to the outputs given by the symbolic parameter input nodes or parameters.

Source code in cirkit/symbolic/parameters.py
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
@classmethod
def from_nary(cls, n: ParameterOp, *ps: Union[ParameterInput, "Parameter"]) -> "Parameter":
    """Constructs a parameter by using a parameter operation node and by specifying its inputs.

    Args:
        n: The parameter operation node.
        *ps: A sequence of symbolic parameter input nodes or parameters.

    Returns:
        A symbolic parameter that encodes the application of the given parameter operation node
            to the outputs given by the symbolic parameter input nodes or parameters.
    """
    p_graphs = tuple(
        Parameter.from_input(p) if isinstance(p, ParameterInput) else p for p in ps
    )
    p_nodes = list(chain.from_iterable(p.nodes for p in p_graphs)) + [n]
    in_nodes: dict[ParameterNode, Sequence[ParameterNode]] = dict(
        (k, v) for g in p_graphs for (k, v) in g.nodes_inputs.items()
    )
    in_nodes[n] = list(p.output for p in p_graphs)
    return Parameter(p_nodes, in_nodes, [n])

from_sequence(p, *ns) classmethod ¤

Constructs a parameter from a composition of symbolic parameter nodes.

Parameters:

Name Type Description Default
p Union[ParameterInput, Parameter]

The entry point of the sequence, which can be either a symbolic parameter input or another symbolic parameter.

required
*ns ParameterNode

A sequence of symbolic parameter nodes.

()

Returns:

Type Description
Parameter

A symbolic parameter that encodes the composition of the symbolic parameter nodes, starting from the given entry point of the sequence.

Source code in cirkit/symbolic/parameters.py
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
@classmethod
def from_sequence(
    cls, p: Union[ParameterInput, "Parameter"], *ns: ParameterNode
) -> "Parameter":
    """Constructs a parameter from a composition of symbolic parameter nodes.

    Args:
        p: The entry point of the sequence, which can be either a symbolic parameter
            input or another symbolic parameter.
        *ns: A sequence of symbolic parameter nodes.

    Returns:
        A symbolic parameter that encodes the composition of the symbolic parameter nodes,
            starting from the given entry point of the sequence.
    """
    if isinstance(p, ParameterInput):
        p = Parameter.from_input(p)
    nodes = list(p.nodes) + list(ns)
    in_nodes = dict(p.nodes_inputs)
    for i, n in enumerate(ns):
        in_nodes[n] = [ns[i - 1]] if i - 1 >= 0 else [p.output]
    return Parameter(nodes, in_nodes, [ns[-1]])

from_unary(n, p) classmethod ¤

Constructs a parameter by using a unary parameter operation node and by specifying its inputs.

Parameters:

Name Type Description Default
n UnaryParameterOp

The unary parameter operation node.

required
p Union[ParameterInput, Parameter]

The symbolic parameter input node, or another parameter.

required

Returns:

Type Description
Parameter

A symbolic parameter that encodes the application of the given parameter operation node to the output given by the symbolic parameter input node or parameter.

Source code in cirkit/symbolic/parameters.py
929
930
931
932
933
934
935
936
937
938
939
940
941
942
@classmethod
def from_unary(cls, n: UnaryParameterOp, p: Union[ParameterInput, "Parameter"]) -> "Parameter":
    """Constructs a parameter by using a unary parameter operation node and by specifying its
    inputs.

    Args:
        n: The unary parameter operation node.
        p: The symbolic parameter input node, or another parameter.

    Returns:
        A symbolic parameter that encodes the application of the given parameter operation
            node to the output given by the symbolic parameter input node or parameter.
    """
    return Parameter.from_sequence(p, n)

ref() ¤

Constructs a shallow copy of the parameter, where the tensor parameters are replace with reference parameters to them.

Returns:

Type Description
Parameter

A shallow copy of the parameter nodes, with the exception that tensor parameter nodes are replaced with symbolic references to them.

Source code in cirkit/symbolic/parameters.py
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
def ref(self) -> "Parameter":
    """Constructs a shallow copy of the parameter, where the tensor parameters
        are replace with reference parameters to them.

    Returns:
        A shallow copy of the parameter nodes, with the exception that tensor parameter nodes
            are replaced with symbolic references to them.
    """

    # Build a new symbolic parameter's computational graph, where the parameter tensors
    # become references to the tensors of the 'self' parameter's computational graph.
    # All the other nodes are new objects.
    def _replace_ref_or_copy(n: ParameterNode) -> ParameterNode:
        return ReferenceParameter(n) if isinstance(n, TensorParameter) else copy(n)

    return self._process_nodes(_replace_ref_or_copy)

ParameterFactory ¤

Bases: Protocol

A factory that constucts symbolic parameter given a shape.

Source code in cirkit/symbolic/parameters.py
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
class ParameterFactory(Protocol):
    """A factory that constucts symbolic parameter given a shape."""

    def __call__(self, shape: tuple[int, ...]) -> Parameter:
        """Constructs a symbolic parameter given the parameter shape.

        Args:
            shape: The shape.

        Returns:
            A parameter whose output shape is equal to the given shape.
        """

__call__(shape) ¤

Constructs a symbolic parameter given the parameter shape.

Parameters:

Name Type Description Default
shape tuple[int, ...]

The shape.

required

Returns:

Type Description
Parameter

A parameter whose output shape is equal to the given shape.

Source code in cirkit/symbolic/parameters.py
 996
 997
 998
 999
1000
1001
1002
1003
1004
def __call__(self, shape: tuple[int, ...]) -> Parameter:
    """Constructs a symbolic parameter given the parameter shape.

    Args:
        shape: The shape.

    Returns:
        A parameter whose output shape is equal to the given shape.
    """

ParameterInput ¤

Bases: ParameterNode, ABC

The abstract parameter input class. A parameter input is a parameter node in the computational graph that comptues parameter that does not have inputs. See Parameter for more details.

Source code in cirkit/symbolic/parameters.py
50
51
52
53
class ParameterInput(ParameterNode, ABC):
    """The abstract parameter input class. A parameter input is a parameter node in the
    computational graph that comptues parameter that does __not__ have inputs. See
    [Parameter][cirkit.symbolic.parameters.Parameter] for more details."""

ParameterNode ¤

Bases: ABC

The abstract parameter node class. A parameter node is a node in the computational graph that computes parameters. See Parameter for more details.

Source code in cirkit/symbolic/parameters.py
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
class ParameterNode(ABC):
    """The abstract parameter node class. A parameter node is a node in the computational
    graph that computes parameters. See [Parameter][cirkit.symbolic.parameters.Parameter]
    for more details."""

    def __copy__(self) -> "ParameterNode":
        """The shallow copy operation of a parameter node.

        Returns:
            The copy of the parameter node.
        """
        cls = self.__class__
        return cls(**self.config)

    @property
    @abstractmethod
    def shape(self) -> tuple[int, ...]:
        """Retrieves the shape of the output of the parameter node.

        Returns:
            The shape of the output.
        """

    @property
    @abstractmethod
    def config(self) -> dict[str, Any]:
        """Retrieves the configuration of the parameter node, i.e., a dictionary mapping
        hyperparameters of the parameter node to their values. The hyperparameter names must
        match the argument names in the ```__init__``` method.

        Returns:
            Dict[str, Any]: A dictionary from hyperparameter names to their value.
        """

config abstractmethod property ¤

Retrieves the configuration of the parameter node, i.e., a dictionary mapping hyperparameters of the parameter node to their values. The hyperparameter names must match the argument names in the __init__ method.

Returns:

Type Description
dict[str, Any]

Dict[str, Any]: A dictionary from hyperparameter names to their value.

shape abstractmethod property ¤

Retrieves the shape of the output of the parameter node.

Returns:

Type Description
tuple[int, ...]

The shape of the output.

__copy__() ¤

The shallow copy operation of a parameter node.

Returns:

Type Description
ParameterNode

The copy of the parameter node.

Source code in cirkit/symbolic/parameters.py
20
21
22
23
24
25
26
27
def __copy__(self) -> "ParameterNode":
    """The shallow copy operation of a parameter node.

    Returns:
        The copy of the parameter node.
    """
    cls = self.__class__
    return cls(**self.config)

ParameterOp ¤

Bases: ParameterNode, ABC

A symbolic parameter operator, i.e., an inner node of the symbolic parameter computational graph.

Source code in cirkit/symbolic/parameters.py
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
class ParameterOp(ParameterNode, ABC):
    """A symbolic parameter operator, i.e., an inner node of the symbolic parameter
    computational graph.
    """

    def __init__(self, *in_shapes: tuple[int, ...]):
        """Initializes a symbolic parameter operator.

        Args:
            *in_shapes: A sequence of the shapes of each input. The length of this
                sequence is the arity of the parameter operator.
        """
        self._in_shapes = in_shapes

    @property
    def in_shapes(self) -> tuple[tuple[int, ...], ...]:
        """Retrieves the shapes of the inputs to the parameter operator.

        Returns:
            A sequence of shapes, one for each input.
        """
        return self._in_shapes

in_shapes property ¤

Retrieves the shapes of the inputs to the parameter operator.

Returns:

Type Description
tuple[tuple[int, ...], ...]

A sequence of shapes, one for each input.

__init__(*in_shapes) ¤

Initializes a symbolic parameter operator.

Parameters:

Name Type Description Default
*in_shapes tuple[int, ...]

A sequence of the shapes of each input. The length of this sequence is the arity of the parameter operator.

()
Source code in cirkit/symbolic/parameters.py
175
176
177
178
179
180
181
182
def __init__(self, *in_shapes: tuple[int, ...]):
    """Initializes a symbolic parameter operator.

    Args:
        *in_shapes: A sequence of the shapes of each input. The length of this
            sequence is the arity of the parameter operator.
    """
    self._in_shapes = in_shapes

PolynomialDifferential ¤

Bases: UnaryParameterOp

A symbolic parameter operator representing the coefficients of a polynomial resulting from the differentiation of a polynomial.

Source code in cirkit/symbolic/parameters.py
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
class PolynomialDifferential(UnaryParameterOp):
    """A symbolic parameter operator representing the coefficients of a polynomial resulting
    from the differentiation of a polynomial.
    """

    def __init__(self, in_shape: tuple[int, ...], *, order: int = 1):
        """Initializes a symbolic polynomial differential coefficients.

        Args:
            in_shape: The shape of the coefficients of the input polynomial.
            order: The differentiation order.

        Raises:
            ValuerError: if the differentiation order is not a positive integer.
        """
        if order <= 0:
            raise ValueError("The order of differentiation must be positive.")
        super().__init__(in_shape)
        self.order = order

    @property
    def shape(self) -> tuple[int, ...]:
        # if dp1>order, i.e., deg>=order, then diff, else const 0.
        return (
            self.in_shape[0],
            self.in_shape[1] - self.order if self.in_shape[1] > self.order else 1,
        )

    @property
    def config(self) -> dict[str, Any]:
        config = super().config
        config["order"] = self.order
        return config

config property ¤

order = order instance-attribute ¤

shape property ¤

__init__(in_shape, *, order=1) ¤

Initializes a symbolic polynomial differential coefficients.

Parameters:

Name Type Description Default
in_shape tuple[int, ...]

The shape of the coefficients of the input polynomial.

required
order int

The differentiation order.

1

Raises:

Type Description
ValuerError

if the differentiation order is not a positive integer.

Source code in cirkit/symbolic/parameters.py
797
798
799
800
801
802
803
804
805
806
807
808
809
810
def __init__(self, in_shape: tuple[int, ...], *, order: int = 1):
    """Initializes a symbolic polynomial differential coefficients.

    Args:
        in_shape: The shape of the coefficients of the input polynomial.
        order: The differentiation order.

    Raises:
        ValuerError: if the differentiation order is not a positive integer.
    """
    if order <= 0:
        raise ValueError("The order of differentiation must be positive.")
    super().__init__(in_shape)
    self.order = order

PolynomialProduct ¤

Bases: BinaryParameterOp

A symbolic parameter operator representing the coefficients of a polynomial resulting from the product of two polynomial.

Source code in cirkit/symbolic/parameters.py
779
780
781
782
783
784
785
786
787
788
789
class PolynomialProduct(BinaryParameterOp):
    """A symbolic parameter operator representing the coefficients of a polynomial resulting
    from the product of two polynomial.
    """

    @property
    def shape(self) -> tuple[int, ...]:
        return (
            self.in_shape1[0] * self.in_shape2[0],  # dim Ko
            self.in_shape1[1] + self.in_shape2[1] - 1,  # dim deg+1
        )

shape property ¤

ReduceLSEParameter ¤

Bases: ReduceParameterOp

A symbolic parameter operator representing the LogSumExp reduction along one dimension.

Source code in cirkit/symbolic/parameters.py
631
632
class ReduceLSEParameter(ReduceParameterOp):
    """A symbolic parameter operator representing the LogSumExp reduction along one dimension."""

ReduceParameterOp ¤

Bases: UnaryParameterOp, ABC

A symbolic parameter operator that represents a unary function that is a reduction along one dimension of the input parameter tensor.

Source code in cirkit/symbolic/parameters.py
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
class ReduceParameterOp(UnaryParameterOp, ABC):
    """A symbolic parameter operator that represents a unary function
    that is a reduction along one dimension of the input parameter tensor.
    """

    def __init__(self, in_shape: tuple[int, ...], *, axis: int = -1):
        """Initializes a symbolic reduce parameter operator.

        Args:
            in_shape: The shape of the input.
            axis: The axis of the input being reduced.
        """
        axis = axis if axis >= 0 else axis + len(in_shape)
        super().__init__(in_shape)
        self._axis = axis

    @property
    def axis(self) -> int:
        """Retrieves the axis of the input being reduced.

        Returns:
            The axis dimension.
        """
        return self._axis

    @property
    def shape(self) -> tuple[int, ...]:
        return *self.in_shape[: self.axis], *self.in_shape[self.axis + 1 :]

    @property
    def config(self) -> dict[str, Any]:
        config = super().config
        config["axis"] = self.axis
        return config

axis property ¤

Retrieves the axis of the input being reduced.

Returns:

Type Description
int

The axis dimension.

config property ¤

shape property ¤

__init__(in_shape, *, axis=-1) ¤

Initializes a symbolic reduce parameter operator.

Parameters:

Name Type Description Default
in_shape tuple[int, ...]

The shape of the input.

required
axis int

The axis of the input being reduced.

-1
Source code in cirkit/symbolic/parameters.py
269
270
271
272
273
274
275
276
277
278
def __init__(self, in_shape: tuple[int, ...], *, axis: int = -1):
    """Initializes a symbolic reduce parameter operator.

    Args:
        in_shape: The shape of the input.
        axis: The axis of the input being reduced.
    """
    axis = axis if axis >= 0 else axis + len(in_shape)
    super().__init__(in_shape)
    self._axis = axis

ReduceProductParameter ¤

Bases: ReduceParameterOp

A symbolic parameter operator representing the product reduction along one dimension.

Source code in cirkit/symbolic/parameters.py
627
628
class ReduceProductParameter(ReduceParameterOp):
    """A symbolic parameter operator representing the product reduction along one dimension."""

ReduceSumParameter ¤

Bases: ReduceParameterOp

A symbolic parameter operator representing the sum reduction along one dimension.

Source code in cirkit/symbolic/parameters.py
623
624
class ReduceSumParameter(ReduceParameterOp):
    """A symbolic parameter operator representing the sum reduction along one dimension."""

ReferenceParameter ¤

Bases: ParameterInput

A symbolic reference parameter representing a symbolic link to a tensor parameter.

Source code in cirkit/symbolic/parameters.py
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
class ReferenceParameter(ParameterInput):
    """A symbolic reference parameter representing a symbolic link to a tensor parameter."""

    def __init__(self, parameter: TensorParameter):
        """Initializes a reference parameter.

        Args:
            parameter: The tensor parameter to point to.
        """
        super().__init__()
        self._parameter = parameter

    @property
    def shape(self) -> tuple[int, ...]:
        return self._parameter.shape

    @property
    def config(self) -> dict[str, Any]:
        return {"parameter": self._parameter}

    def deref(self) -> TensorParameter:
        """Dereference the pointer.

        Returns:
            The tensor paramter being pointed to.
        """
        return self._parameter

config property ¤

shape property ¤

__init__(parameter) ¤

Initializes a reference parameter.

Parameters:

Name Type Description Default
parameter TensorParameter

The tensor parameter to point to.

required
Source code in cirkit/symbolic/parameters.py
144
145
146
147
148
149
150
151
def __init__(self, parameter: TensorParameter):
    """Initializes a reference parameter.

    Args:
        parameter: The tensor parameter to point to.
    """
    super().__init__()
    self._parameter = parameter

deref() ¤

Dereference the pointer.

Returns:

Type Description
TensorParameter

The tensor paramter being pointed to.

Source code in cirkit/symbolic/parameters.py
161
162
163
164
165
166
167
def deref(self) -> TensorParameter:
    """Dereference the pointer.

    Returns:
        The tensor paramter being pointed to.
    """
    return self._parameter

ScaledSigmoidParameter ¤

Bases: EntrywiseParameterOp

A symbolic parameter operator representing the entry-wise application of the rescaled sigmoid function to a parameter tensor.

Source code in cirkit/symbolic/parameters.py
522
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
562
563
class ScaledSigmoidParameter(EntrywiseParameterOp):
    """A symbolic parameter operator representing the entry-wise application of
    the rescaled sigmoid function to a parameter tensor.
    """

    def __init__(self, in_shape: tuple[int, ...], vmin: float, vmax: float):
        """Initializes a symbolic scaled sigmoid parameter operator.

        Args:
            in_shape: The shape of the input.
            vmin: The minimum output value.
            vmax: The maximum output value
        """
        assert vmin < vmax
        super().__init__(in_shape)
        self._vmin = vmin
        self._vmax = vmax

    @property
    def vmin(self) -> float:
        """Retrieves the minimum output value.

        Returns:
            The minimum value.
        """
        return self._vmin

    @property
    def vmax(self) -> float:
        """Retrieves the minimum output value.

        Returns:
            The maximum value.
        """
        return self._vmax

    @property
    def config(self) -> dict[str, Any]:
        config = super().config
        config["vmin"] = self.vmin
        config["vmax"] = self.vmax
        return config

config property ¤

vmax property ¤

Retrieves the minimum output value.

Returns:

Type Description
float

The maximum value.

vmin property ¤

Retrieves the minimum output value.

Returns:

Type Description
float

The minimum value.

__init__(in_shape, vmin, vmax) ¤

Initializes a symbolic scaled sigmoid parameter operator.

Parameters:

Name Type Description Default
in_shape tuple[int, ...]

The shape of the input.

required
vmin float

The minimum output value.

required
vmax float

The maximum output value

required
Source code in cirkit/symbolic/parameters.py
527
528
529
530
531
532
533
534
535
536
537
538
def __init__(self, in_shape: tuple[int, ...], vmin: float, vmax: float):
    """Initializes a symbolic scaled sigmoid parameter operator.

    Args:
        in_shape: The shape of the input.
        vmin: The minimum output value.
        vmax: The maximum output value
    """
    assert vmin < vmax
    super().__init__(in_shape)
    self._vmin = vmin
    self._vmax = vmax

SigmoidParameter ¤

Bases: EntrywiseParameterOp

A symbolic parameter operator representing the entry-wise application of the sigmoid function to a parameter tensor.

Source code in cirkit/symbolic/parameters.py
516
517
518
519
class SigmoidParameter(EntrywiseParameterOp):
    """A symbolic parameter operator representing the entry-wise application of
    the sigmoid function to a parameter tensor.
    """

SoftmaxParameter ¤

Bases: EntrywiseReduceParameterOp

A symbolic parameter operator representing the application of the Softmax function along one dimension.

Source code in cirkit/symbolic/parameters.py
635
636
637
638
class SoftmaxParameter(EntrywiseReduceParameterOp):
    """A symbolic parameter operator representing the application of the Softmax function
    along one dimension.
    """

SoftplusParameter ¤

Bases: EntrywiseParameterOp

A symbolic parameter operator representing the entry-wise application of the softplus function to a parameter tensor.

Source code in cirkit/symbolic/parameters.py
510
511
512
513
class SoftplusParameter(EntrywiseParameterOp):
    """A symbolic parameter operator representing the entry-wise application of
    the softplus function to a parameter tensor.
    """

SquareParameter ¤

Bases: EntrywiseParameterOp

A symbolic parameter operator representing the entry-wise square of a parameter tensor.

Source code in cirkit/symbolic/parameters.py
504
505
506
507
class SquareParameter(EntrywiseParameterOp):
    """A symbolic parameter operator representing the entry-wise square of a parameter
    tensor.
    """

SumParameter ¤

Bases: BinaryParameterOp

A symbolic parameter operator representing the element-wise sum of its inputs.

Source code in cirkit/symbolic/parameters.py
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
class SumParameter(BinaryParameterOp):
    """A symbolic parameter operator representing the element-wise sum of its inputs."""

    def __init__(self, in_shape1: tuple[int, ...], in_shape2: tuple[int, ...]) -> None:
        """Initializes a symbolic sum parameter operator.

        Args:
            in_shape1: The shape of the first input.
            in_shape2: The shape of the second input.
        """
        assert in_shape1 == in_shape2
        super().__init__(in_shape1, in_shape2)

    @property
    def shape(self) -> tuple[int, ...]:
        return self.in_shape1

shape property ¤

__init__(in_shape1, in_shape2) ¤

Initializes a symbolic sum parameter operator.

Parameters:

Name Type Description Default
in_shape1 tuple[int, ...]

The shape of the first input.

required
in_shape2 tuple[int, ...]

The shape of the second input.

required
Source code in cirkit/symbolic/parameters.py
391
392
393
394
395
396
397
398
399
def __init__(self, in_shape1: tuple[int, ...], in_shape2: tuple[int, ...]) -> None:
    """Initializes a symbolic sum parameter operator.

    Args:
        in_shape1: The shape of the first input.
        in_shape2: The shape of the second input.
    """
    assert in_shape1 == in_shape2
    super().__init__(in_shape1, in_shape2)

TensorParameter ¤

Bases: ParameterInput

A symbolic tensor parameter is an object storing information about a dense tensor parameter, i.e., its shape, its initialization method, whether it is learnable (or if it is a constant tensor), and its data type. Note that the symbolic tensor parmater does not allocate any tensor, but only stores the mentioned information about it.

Source code in cirkit/symbolic/parameters.py
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
class TensorParameter(ParameterInput):
    """A symbolic tensor parameter is an object storing information about a dense
    tensor parameter, i.e., its shape, its initialization method, whether it is
    learnable (or if it is a constant tensor), and its data type. Note that the
    symbolic tensor parmater does __not__ allocate any tensor, but only stores
    the mentioned information about it."""

    def __init__(
        self,
        *shape: int,
        initializer: Initializer,
        learnable: bool = True,
        dtype: DataType = DataType.REAL,
    ):
        """Initializes a symbolic tensor parameter.

        Args:
            *shape: The shape of the tensor parameter.
            initializer: The initializer object.
            learnable: Whether the tensor parameter is learnable or not.
            dtype: The data type.

        Raises:
            ValueError: If the shape is empty or contains dimensions that are not positive.
            ValueError: If the initializer does not allow the parameter shape.
        """
        super().__init__()
        if len(shape) < 1 or any(d <= 0 for d in shape):
            raise ValueError(
                f"The shape {shape} must be non-empty and have positive dimension sizes"
            )
        if not initializer.allows_shape(shape):
            raise ValueError(f"The shape {shape} is not valid for the initializer {initializer}")
        self._shape = shape
        self.initializer = initializer
        self.learnable = learnable
        self.dtype = dtype

    @property
    def shape(self) -> tuple[int, ...]:
        return self._shape

    @property
    def config(self) -> dict[str, Any]:
        return {
            "shape": self.shape,
            "initializer": self.initializer,
            "learnable": self.learnable,
            "dtype": self.dtype,
        }

config property ¤

dtype = dtype instance-attribute ¤

initializer = initializer instance-attribute ¤

learnable = learnable instance-attribute ¤

shape property ¤

__init__(*shape, initializer, learnable=True, dtype=DataType.REAL) ¤

Initializes a symbolic tensor parameter.

Parameters:

Name Type Description Default
*shape int

The shape of the tensor parameter.

()
initializer Initializer

The initializer object.

required
learnable bool

Whether the tensor parameter is learnable or not.

True
dtype DataType

The data type.

REAL

Raises:

Type Description
ValueError

If the shape is empty or contains dimensions that are not positive.

ValueError

If the initializer does not allow the parameter shape.

Source code in cirkit/symbolic/parameters.py
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
def __init__(
    self,
    *shape: int,
    initializer: Initializer,
    learnable: bool = True,
    dtype: DataType = DataType.REAL,
):
    """Initializes a symbolic tensor parameter.

    Args:
        *shape: The shape of the tensor parameter.
        initializer: The initializer object.
        learnable: Whether the tensor parameter is learnable or not.
        dtype: The data type.

    Raises:
        ValueError: If the shape is empty or contains dimensions that are not positive.
        ValueError: If the initializer does not allow the parameter shape.
    """
    super().__init__()
    if len(shape) < 1 or any(d <= 0 for d in shape):
        raise ValueError(
            f"The shape {shape} must be non-empty and have positive dimension sizes"
        )
    if not initializer.allows_shape(shape):
        raise ValueError(f"The shape {shape} is not valid for the initializer {initializer}")
    self._shape = shape
    self.initializer = initializer
    self.learnable = learnable
    self.dtype = dtype

UnaryParameterOp ¤

Bases: ParameterOp, ABC

A symbolic parameter operator that represents a unary operation.

Source code in cirkit/symbolic/parameters.py
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
class UnaryParameterOp(ParameterOp, ABC):
    """A symbolic parameter operator that represents a unary operation."""

    def __init__(self, in_shape: tuple[int, ...]):
        """Initializes a symbolic unary parameter operator.

        Args:
            in_shape: The shape of the input.
        """
        super().__init__(in_shape)

    @property
    def in_shape(self) -> tuple[int, ...]:
        """Retrieves the shape of the input.

        Returns:
            The shape of the input.
        """
        return self._in_shapes[0]

    @property
    def config(self) -> dict[str, Any]:
        return {"in_shape": self.in_shape}

config property ¤

in_shape property ¤

Retrieves the shape of the input.

Returns:

Type Description
tuple[int, ...]

The shape of the input.

__init__(in_shape) ¤

Initializes a symbolic unary parameter operator.

Parameters:

Name Type Description Default
in_shape tuple[int, ...]

The shape of the input.

required
Source code in cirkit/symbolic/parameters.py
197
198
199
200
201
202
203
def __init__(self, in_shape: tuple[int, ...]):
    """Initializes a symbolic unary parameter operator.

    Args:
        in_shape: The shape of the input.
    """
    super().__init__(in_shape)

mixing_weight_factory(shape, *, param_factory) ¤

Construct the parameters of a sum layer with arity > 1 such that it encodes a linear combination of the input vectors it receives. A sum layer with this semantics is also referred to as "mixing layer" in some papers (see references below). A mixing layer is parameterized by a parameter matrix \(\mathbf{W}\in\bbR^{K\times H}\), where \(K\) is the number of sum units, and H is the number of input vectors; and it computes \(\sum_{i=1}^H \mathbf{w}_{:i} \mathbf{x}_i\). This function firstly constructs \(\mathbf{W}\) given a parameter factory, and then reshapes it into a \(K\times KH\) parameter matrix for a sum layer that mimics a mixing layer.

References
  • R. Peharz et al. (2020), Einsum Networks: Fast and Scalable Learning of Tractable Probabilistic Circuits
  • Loconte et al. (2024), What is the Relationship between Tensor Factorizations and Circuits (and How Can We Exploit it)?

Parameters:

Name Type Description Default
shape tuple[int, ...]

The shape of the parameter. It must be (num_units, arity * num_units), where num_units is the number of sum units or, equivalently the size of the input vectors, and arity is the number of them.

required
param_factory ParameterFactory

The parameter factory used to construct the mixing weights of shape (num_units, arity).

required

Returns:

Name Type Description
Parameter Parameter

A symbolic parameter.

Raises:

Type Description
ValueError

If the given shape is not of the form (num_units, arity * num_units).

Source code in cirkit/symbolic/parameters.py
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
def mixing_weight_factory(shape: tuple[int, ...], *, param_factory: ParameterFactory) -> Parameter:
    r"""Construct the parameters of a [sum layer][cirkit.symbolic.layers.SumLayer] with
    arity > 1 such that it encodes a linear combination of the input vectors it receives.
    A sum layer with this semantics is also referred to as "mixing layer" in some papers
    (see references below).
    A mixing layer is parameterized by a parameter matrix $\mathbf{W}\in\bbR^{K\times H}$,
    where $K$ is the number of sum units, and H is the number of input vectors; and it computes
    $\sum_{i=1}^H \mathbf{w}_{:i} \mathbf{x}_i$. This function firstly constructs $\mathbf{W}$ given
    a parameter factory, and then reshapes it into a $K\times KH$ parameter matrix for a sum layer
    that mimics a mixing layer.

    References:
        * R. Peharz et al. (2020), Einsum Networks: Fast and Scalable Learning of
            Tractable Probabilistic Circuits
        * Loconte et al. (2024), What is the Relationship between Tensor Factorizations
            and Circuits (and How Can We Exploit it)?

    Args:
        shape: The shape of the parameter. It must be (num_units, arity * num_units), where
            num_units is the number of sum units or, equivalently the size of the input vectors,
            and arity is the number of them.
        param_factory: The parameter factory used to construct the mixing weights of shape
            (num_units, arity).

    Returns:
        Parameter: A symbolic parameter.

    Raises:
        ValueError: If the given shape is not of the form (num_units, arity * num_units).
    """
    if len(shape) != 2 or shape[1] % shape[0]:
        raise ValueError(f"Expected shape (num_units, arity * num_units), but found {shape}")
    num_units = shape[0]
    arity = shape[1] // num_units
    mixing_weights_shape = num_units, arity
    return Parameter.from_unary(
        MixingWeightParameter(mixing_weights_shape), param_factory(mixing_weights_shape)
    )