Skip to content

pgms

pgms ¤

from_hmm(ordering, input_factory, weight_factory=None, num_channels=1, num_units=1, num_classes=1) ¤

Construct a symbolic circuit mimicking a hidden markov model (HMM) of a given variable ordering. Product Layers are of type HadamardLayer, and sum layers are of type SumLayer.

Parameters:

Name Type Description Default
ordering Sequence[int]

The input order of variables of the HMM.

required
input_factory InputLayerFactory

A factory that builds input layers.

required
weight_factory ParameterFactory | None

The factory to construct the weight of sum layers. It can be None, or a parameter factory, i.e., a map from a shape to a symbolic parameter.

None
num_channels int

The number of channels for each variable.

1
num_units int

The number of sum units per sum layer.

1
num_classes int

The number of output classes.

1

Returns:

Name Type Description
Circuit Circuit

A symbolic circuit.

Raises:

Type Description
ValueError

order must consists of consistent numbers, starting from 0.

Source code in cirkit/templates/pgms.py
10
11
12
13
14
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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
def from_hmm(
    ordering: Sequence[int],
    input_factory: InputLayerFactory,
    weight_factory: ParameterFactory | None = None,
    num_channels: int = 1,
    num_units: int = 1,
    num_classes: int = 1,
) -> Circuit:
    """Construct a symbolic circuit mimicking a hidden markov model (HMM) of
      a given variable ordering. Product Layers are of type
      [HadamardLayer][cirkit.symbolic.layers.HadamardLayer], and sum layers are of type
      [SumLayer][cirkit.symbolic.layers.SumLayer].

    Args:
        ordering: The input order of variables of the HMM.
        input_factory: A factory that builds input layers.
        weight_factory: The factory to construct the weight of sum layers. It can be None,
            or a parameter factory, i.e., a map from a shape to a symbolic parameter.
        num_channels: The number of channels for each variable.
        num_units: The number of sum units per sum layer.
        num_classes: The number of output classes.

    Returns:
        Circuit: A symbolic circuit.

    Raises:
        ValueError: order must consists of consistent numbers, starting from 0.
    """
    if max(ordering) != len(ordering) - 1 or min(ordering):
        raise ValueError("The 'ordering' of variables is not valid")

    layers: list[Layer] = []
    in_layers: dict[Layer, list[Layer]] = {}

    input_sl = input_factory(Scope([ordering[0]]), num_units, num_channels)
    layers.append(input_sl)
    sum_sl = SumLayer(num_units, num_units, weight_factory=weight_factory)
    layers.append(sum_sl)
    in_layers[sum_sl] = [input_sl]

    # Loop over the number of variables
    for i in range(1, len(ordering)):
        last_dense = layers[-1]

        input_sl = input_factory(Scope([ordering[i]]), num_units, num_channels)
        layers.append(input_sl)
        prod_sl = HadamardLayer(num_units, 2)
        layers.append(prod_sl)
        in_layers[prod_sl] = [last_dense, input_sl]

        num_units_out = num_units if i != len(ordering) - 1 else num_classes
        sum_sl = SumLayer(
            num_units,
            num_units_out,
            weight_factory=weight_factory,
        )
        layers.append(sum_sl)
        in_layers[sum_sl] = [prod_sl]

    return Circuit(num_channels, layers, in_layers, [layers[-1]])