probabilistic_model.probabilistic_circuit.jax
=============================================

.. py:module:: probabilistic_model.probabilistic_circuit.jax


Submodules
----------

.. toctree::
   :maxdepth: 1

   /autoapi/probabilistic_model/probabilistic_circuit/jax/coupling_circuit/index
   /autoapi/probabilistic_model/probabilistic_circuit/jax/discrete_layer/index
   /autoapi/probabilistic_model/probabilistic_circuit/jax/gaussian_layer/index
   /autoapi/probabilistic_model/probabilistic_circuit/jax/inner_layer/index
   /autoapi/probabilistic_model/probabilistic_circuit/jax/input_layer/index
   /autoapi/probabilistic_model/probabilistic_circuit/jax/probabilistic_circuit/index
   /autoapi/probabilistic_model/probabilistic_circuit/jax/uniform_layer/index
   /autoapi/probabilistic_model/probabilistic_circuit/jax/utils/index


Classes
-------

.. autoapisummary::

   probabilistic_model.probabilistic_circuit.jax.SumUnit
   probabilistic_model.probabilistic_circuit.jax.ProductUnit
   probabilistic_model.probabilistic_circuit.jax.Unit
   probabilistic_model.probabilistic_circuit.jax.NXProbabilisticCircuit
   probabilistic_model.probabilistic_circuit.jax.Layer
   probabilistic_model.probabilistic_circuit.jax.InnerLayer
   probabilistic_model.probabilistic_circuit.jax.InputLayer
   probabilistic_model.probabilistic_circuit.jax.SumLayer
   probabilistic_model.probabilistic_circuit.jax.SparseSumLayer
   probabilistic_model.probabilistic_circuit.jax.DenseSumLayer
   probabilistic_model.probabilistic_circuit.jax.ProductLayer
   probabilistic_model.probabilistic_circuit.jax.NXConverterLayer
   probabilistic_model.probabilistic_circuit.jax.InputLayer
   probabilistic_model.probabilistic_circuit.jax.NXConverterLayer
   probabilistic_model.probabilistic_circuit.jax.Unit
   probabilistic_model.probabilistic_circuit.jax.NXProbabilisticCircuit
   probabilistic_model.probabilistic_circuit.jax.UnivariateContinuousLeaf
   probabilistic_model.probabilistic_circuit.jax.DiracDeltaDistribution
   probabilistic_model.probabilistic_circuit.jax.ContinuousLayer
   probabilistic_model.probabilistic_circuit.jax.ContinuousLayerWithFiniteSupport
   probabilistic_model.probabilistic_circuit.jax.DiracDeltaLayer
   probabilistic_model.probabilistic_circuit.jax.NXConverterLayer
   probabilistic_model.probabilistic_circuit.jax.ContinuousLayerWithFiniteSupport
   probabilistic_model.probabilistic_circuit.jax.Unit
   probabilistic_model.probabilistic_circuit.jax.NXProbabilisticCircuit
   probabilistic_model.probabilistic_circuit.jax.UnivariateContinuousLeaf
   probabilistic_model.probabilistic_circuit.jax.UniformDistribution
   probabilistic_model.probabilistic_circuit.jax.UniformLayer


Functions
---------

.. autoapisummary::

   probabilistic_model.probabilistic_circuit.jax.timeit_print
   probabilistic_model.probabilistic_circuit.jax.copy_bcoo
   probabilistic_model.probabilistic_circuit.jax.copy_bcsr
   probabilistic_model.probabilistic_circuit.jax.simple_interval_to_open_array
   probabilistic_model.probabilistic_circuit.jax.create_bcoo_indices_from_row_lengths
   probabilistic_model.probabilistic_circuit.jax.create_bcoo_indices_from_row_lengths_np
   probabilistic_model.probabilistic_circuit.jax.create_bcsr_indices_from_row_lengths
   probabilistic_model.probabilistic_circuit.jax.embed_sparse_array_in_nan_array
   probabilistic_model.probabilistic_circuit.jax.sample_from_sparse_probabilities_csc
   probabilistic_model.probabilistic_circuit.jax.remove_rows_and_cols_where_all
   probabilistic_model.probabilistic_circuit.jax.shrink_index_array
   probabilistic_model.probabilistic_circuit.jax.sparse_remove_rows_and_cols_where_all
   probabilistic_model.probabilistic_circuit.jax.copy_bcoo
   probabilistic_model.probabilistic_circuit.jax.inverse_class_of
   probabilistic_model.probabilistic_circuit.jax.simple_interval_to_open_array


Package Contents
----------------

.. py:function:: timeit_print(func)

.. py:function:: copy_bcoo(x: jax.experimental.sparse.BCOO) -> jax.experimental.sparse.BCOO

.. py:function:: copy_bcsr(x: jax.experimental.sparse.BCSR) -> jax.experimental.sparse.BCSR

.. py:function:: simple_interval_to_open_array(interval: random_events.interval.SimpleInterval) -> jax.numpy.array

.. py:function:: create_bcoo_indices_from_row_lengths(row_lengths: numpy.array) -> numpy.array

   Create the indices of a BCOO array with the given row lengths.

   The shape of the indices is (2, sum(row_lengths)).
   The shape of the sparse tensor that the indices describe should be (len(row_lengths), max(row_lengths)).

   Example::

       >>> row_lengths = jnp.array([2, 3])
       >>> create_bcoo_indices_from_row_lengths(row_lengths)
           [[0 0]
            [0 1]
            [1 0]
            [1 1]
            [1 2]]

   :param row_lengths: The row lengths.
   :return: The indices of the sparse tensor


.. py:function:: create_bcoo_indices_from_row_lengths_np(row_lengths: numpy.array) -> numpy.array

   Create the indices of a BCOO array with the given row lengths.

   The shape of the indices is (2, sum(row_lengths)).
   The shape of the sparse tensor that the indices describe should be (len(row_lengths), max(row_lengths)).

   Example::

       >>> row_lengths = jnp.array([2, 3])
       >>> create_bcoo_indices_from_row_lengths(row_lengths)
           [[0 0]
            [0 1]
            [1 0]
            [1 1]
            [1 2]]

   :param row_lengths: The row lengths.
   :return: The indices of the sparse tensor


.. py:function:: create_bcsr_indices_from_row_lengths(row_lengths: jax.Array) -> typing_extensions.Tuple[jax.Array, jax.Array]

   Create the column indices and indent pointer of bcsr array with the given row lengths.

   The shape of the sparse tensor that the indices describe should be (len(row_lengths), max(row_lengths)).

   Example::

       >>> row_lengths = jnp.array([2, 3])
       >>> create_bcsr_indices_from_row_lengths(row_lengths)
       (Array([0, 1, 0, 1, 2], dtype=int32), Array([0, 2, 5], dtype=int32))

   :param row_lengths: The row lengths.
   :return: The indices of the sparse tensor


.. py:function:: embed_sparse_array_in_nan_array(sparse_array: jax.experimental.sparse.BCOO) -> jax.Array

.. py:function:: sample_from_sparse_probabilities_csc(probabilities: scipy.sparse.csr_array, amount: numpy.array) -> scipy.sparse.csc_array

   Sample from a sparse array of probabilities.
   Each row in the sparse array encodes a categorical probability distribution.

   :param probabilities: The sparse array of probabilities.
   :param amount: The amount of samples to draw from each row.
   :return: The samples that are drawn for each state in the probabilities indicies.


.. py:function:: remove_rows_and_cols_where_all(array: jax.Array, value: float) -> jax.Array

   Remove rows and columns from an array where all elements are equal to a given value.

   :param array: The tensor to remove rows and columns from.
   :param value: The value to remove.
   :return: The tensor without the rows and columns.

   Example::


       >>> a = jnp.array([[1, 0, 3], [0, 0, 0], [7, 0, 9]])
       >>> remove_rows_and_cols_where_all(a, 0)
       array([[1, 3], [7, 9]])


.. py:function:: shrink_index_array(index_array: jax.Array) -> jax.Array

   Shrink an index array to only contain successive indices.

   Example::

       >>> shrink_index_array(jnp.array([[0, 3], [1, 0], [4, 1]]))
           [[0 2]
            [1 0]
            [2 1]]
   :param index_array: The index tensor to shrink.
   :return: The shrunken index tensor.


.. py:function:: sparse_remove_rows_and_cols_where_all(array: jax.experimental.sparse.BCOO, value: float) -> jax.experimental.sparse.BCOO

   Remove rows and columns from a sparse tensor where all elements are equal to a given value.

   Example::
       >>> array = BCOO.fromdense(jnp.array([[1, 0, 3], [0, 0, 0], [7, 0, 9]]))
       >>> sparse_remove_rows_and_cols_where_all(array, 0).todense()
           [[1 3]
            [7 9]]

   :param array: The sparse tensor to remove rows and columns from.
   :param value: The value to remove.
   :return: The tensor without the unnecessary rows and columns.


.. py:function:: copy_bcoo(x: jax.experimental.sparse.BCOO) -> jax.experimental.sparse.BCOO

.. py:class:: SumUnit

   Bases: :py:obj:`InnerUnit`


   Class for inner units


   .. py:attribute:: _latent_variable
      :type:  typing_extensions.Optional[random_events.variable.Symbolic]
      :value: None


      The latent variable of this unit.
      This has to be here due to the rvalue/lvalue problem in random events.

      TODO remove this when RE is fixed



   .. py:method:: __repr__()


   .. py:attribute:: __hash__


   .. py:property:: representation
      :type: str



   .. py:property:: drawio_label
      :type: str


      The label of the object as a drawio compatible string.



   .. py:property:: log_weighted_subcircuits
      :type: typing_extensions.List[typing_extensions.Tuple[float, Unit]]


      :return: The weighted subcircuits of this unit.



   .. py:property:: variables
      :type: sortedcontainers.SortedSet



   .. py:property:: latent_variable
      :type: random_events.variable.Symbolic



   .. py:method:: forward(*args, **kwargs)


   .. py:method:: log_forward(*args, **kwargs)


   .. py:attribute:: moment


   .. py:method:: log_forward_conditioning(*args, **kwargs)


   .. py:method:: support()

      Calculate the support of this unit.



   .. py:property:: log_weights
      :type: numpy.array


      :return: The log_weights of the subcircuits.



   .. py:method:: sample(*args, **kwargs) -> numpy.array

      Draw samples from the circuit.

      For sampling, a node gets requested a number of samples from all his parents.
      The parents write into the `result_of_current_query` attribute a tuple describing the beginning index of the
      sampling and how many samples are requested.



   .. py:method:: _from_json(data: typing_extensions.Dict[str, typing_extensions.Any]) -> typing_extensions.Self
      :classmethod:


      Create a variable from a json dict.
      This method is called from the from_json method after the correct subclass is determined and should be
      overwritten by the respective subclass.

      :param data: The json dict
      :return: The deserialized object



   .. py:method:: mount_with_interaction_terms(other: typing_extensions.Self, interaction_model: probabilistic_model.probabilistic_model.ProbabilisticModel)

      Create a distribution that factorizes as follows:

      .. math::
          p(self.latent\_variable) \cdot p(self.variables | self.latent\_variable) \cdot
          p(other.latent\_variable | self.latent\_variable) \cdot p(other.variables | other.latent\_variable)

      where `self.latent_variable` and `other.latent_variable` are the results of the latent variable interpretation
      of mixture models.

      :param other: The other distribution to mount at this distribution children level.
      :param interaction_model: The interaction probabilities between both latent variables



   .. py:method:: mount_from_bayesian_network(other: SumUnit)

      Mount a distribution from tge `to_probabilistic_circuit` method in bayesian networks.
      The distribution is mounted as follows:


      :param other: The other distribution to mount at this distribution children level.
      :return:



   .. py:method:: simplify()

      Simplify the circuit by removing nodes and redirected edges that have no impact in-place.
      Essentially, this method transforms the circuit into an alternating order of sum and product units.

      :return: The simplified circuit.



   .. py:method:: normalize()

      Normalize the log_weights of the subcircuits such that they sum up to 1 inplace.



   .. py:method:: is_deterministic() -> bool

      :return: If this unit is deterministic or not.



   .. py:method:: log_mode()


   .. py:method:: subcircuit_index_of_samples(samples: numpy.array) -> numpy.array

      :return: the index of the subcircuit where p(sample) > 0 and None if p(sample) = 0 for all subcircuits.



.. py:class:: ProductUnit

   Bases: :py:obj:`InnerUnit`


   Decomposable Product Units for Probabilistic Circuits


   .. py:attribute:: representation
      :value: '×'



   .. py:attribute:: __hash__


   .. py:property:: drawio_label
      :type: str


      The label of the object as a drawio compatible string.



   .. py:method:: __repr__()


   .. py:method:: forward(*args, **kwargs)


   .. py:method:: log_forward(*args, **kwargs)


   .. py:attribute:: moment


   .. py:property:: variables
      :type: sortedcontainers.SortedSet



   .. py:method:: support()

      Calculate the support of this unit.



   .. py:method:: is_decomposable()


   .. py:method:: log_mode()


   .. py:method:: __copy__()


   .. py:method:: simplify()

      Simplify the circuit by removing nodes and redirected edges that have no impact in-place.
      Essentially, this method transforms the circuit into an alternating order of sum and product units.

      :return: The simplified circuit.



   .. py:method:: sample(*args, **kwargs)

      Draw samples from the circuit.

      For sampling, a node gets requested a number of samples from all his parents.
      The parents write into the `result_of_current_query` attribute a tuple describing the beginning index of the
      sampling and how many samples are requested.



.. py:class:: Unit

   Bases: :py:obj:`random_events.utils.SubclassJSONSerializer`, :py:obj:`probabilistic_model.interfaces.drawio.drawio.DrawIOInterface`, :py:obj:`abc.ABC`


   Class for all units of a probabilistic circuit.

   This class should not be used by users directly.
   Use :class:`ProbabilisticCircuit` as interface to users.


   .. py:attribute:: probabilistic_circuit
      :type:  typing_extensions.Optional[ProbabilisticCircuit]
      :value: None


      The circuit this component is part of. 



   .. py:attribute:: result_of_current_query
      :type:  typing_extensions.Any
      :value: None


      The result of the current query. 



   .. py:attribute:: index
      :type:  typing_extensions.Optional[int]
      :value: None


      The index of the node in the graph of its circuit.



   .. py:method:: __post_init__()


   .. py:property:: subcircuits
      :type: typing_extensions.List[Unit]


      :return: The subcircuits of this unit.



   .. py:property:: parents
      :type: typing_extensions.List[InnerUnit]


      :return: The parents of this unit.



   .. py:method:: support()
      :abstractmethod:


      Calculate the support of this unit.



   .. py:property:: is_leaf
      :abstractmethod:


      :return: If this unit is a leaf unit.



   .. py:property:: variables
      :type: sortedcontainers.SortedSet

      :abstractmethod:



   .. py:property:: leaves
      :type: typing_extensions.List[LeafUnit]


      :return: The leaves of the circuit that are descendants of this node.



   .. py:method:: update_variables(new_variables: random_events.product_algebra.VariableMap)

      Update the variables of this unit and its descendants.

      :param new_variables: A map that maps the variables that should be replaced to their new variable.



   .. py:method:: connect_incoming_edges_to(other: Unit)

      Connect all incoming edges to this unit to another unit.

      :param other: The other unit to connect the incoming edges to.



   .. py:method:: filter_variable_map_by_self(variable_map: random_events.product_algebra.VariableMap)

      Filter a variable map by the variables of this unit.

      :param variable_map: The map to filter
      :return: The map filtered by the variables of this unit.



   .. py:property:: impossible_condition_result
      :type: typing_extensions.Tuple[typing_extensions.Optional[Unit], float]


      :return: The result of an impossible truncated query.



   .. py:method:: log_mode()
      :abstractmethod:



   .. py:method:: __hash__()


   .. py:method:: copy_without_graph()


   .. py:method:: empty_copy() -> typing_extensions.Self

      Creat a copy of this circuit without any subcircuits. Only the parameters should be copied.
      This is used whenever a new circuit has to be created during inference.

      :return: A copy of this circuit without any subcircuits that is not in this units graph.



   .. py:method:: simplify()
      :abstractmethod:


      Simplify the circuit by removing nodes and redirected edges that have no impact in-place.
      Essentially, this method transforms the circuit into an alternating order of sum and product units.

      :return: The simplified circuit.



   .. py:method:: sample(*args, **kwargs)
      :abstractmethod:


      Draw samples from the circuit.

      For sampling, a node gets requested a number of samples from all his parents.
      The parents write into the `result_of_current_query` attribute a tuple describing the beginning index of the
      sampling and how many samples are requested.



   .. py:method:: marginal(*args, **kwargs) -> typing_extensions.Optional[typing_extensions.Self]
      :abstractmethod:


      Remove nodes that are not part of the marginal distribution.



   .. py:method:: moment(*args, **kwargs)
      :abstractmethod:



   .. py:property:: drawio_style
      :type: typing_extensions.Dict[str, typing_extensions.Any]


      The style of the object.



.. py:class:: NXProbabilisticCircuit

   Bases: :py:obj:`probabilistic_model.probabilistic_model.ProbabilisticModel`, :py:obj:`random_events.utils.SubclassJSONSerializer`


   Probabilistic Circuits as a directed, rooted, acyclic graph.

   The nodes of the graph are the units of the circuit.
   The edges of the graph indicate how the units are connected.
   The outgoing edges of a sum unit contain the log-log_weights of the subcircuits.


   .. py:attribute:: graph
      :type:  rustworkx.PyDAG[Unit]

      The graph to check connectivity from.



   .. py:method:: __len__()

      Return the number of nodes in the graph.

      :return: The number of nodes in the graph.



   .. py:method:: __iter__()

      Return an iterator over the nodes in the graph.

      :return: An iterator over the nodes in the graph.



   .. py:method:: from_other(other: typing_extensions.Self) -> typing_extensions.Self
      :classmethod:



   .. py:property:: variables
      :type: sortedcontainers.SortedSet


      :return: The variables of the model.



   .. py:property:: variable_to_index_map
      :type: typing_extensions.Dict[random_events.variable.Variable, int]



   .. py:property:: layers
      :type: typing_extensions.List[typing_extensions.List[Unit]]



   .. py:property:: leaves
      :type: typing_extensions.List[LeafUnit]



   .. py:method:: is_valid() -> bool

      Check if this graph is:

      - acyclic
      - connected

      :return: True if the graph is valid, False otherwise.



   .. py:method:: add_node(node: Unit)


   .. py:method:: add_nodes_from(units: typing_extensions.Iterable[Unit])


   .. py:method:: add_edge(parent: Unit, child: Unit, log_weight: typing_extensions.Optional[float] = None)


   .. py:method:: add_edges_from(edges: typing_extensions.Iterable[typing_extensions.Union[typing_extensions.Tuple[Unit, Unit], typing_extensions.Tuple[Unit, Unit, float]]])


   .. py:method:: successors(unit: Unit) -> typing_extensions.List[Unit]


   .. py:method:: descendants(unit: Unit) -> random_events.set.Set[Unit]


   .. py:method:: predecessors(unit: Unit) -> typing_extensions.List[InnerUnit]


   .. py:method:: remove_node(unit: Unit)


   .. py:method:: remove_nodes_from(units: typing_extensions.Iterable[Unit])


   .. py:method:: remove_edge(parent: Unit, child: Unit)


   .. py:method:: remove_edges_from(edges: typing_extensions.Iterable[typing_extensions.Tuple[Unit, Unit]])


   .. py:method:: in_edges(unit: Unit) -> typing_extensions.List[typing_extensions.Tuple[Unit, Unit, typing_extensions.Optional[float]]]


   .. py:method:: add_from_subgraph(subgraph: rustworkx.PyDAG[Unit]) -> typing_extensions.Dict[int, Unit]

      Add nodes and edges from a subgraph to this circuit.

      :param subgraph: The subgraph to add nodes from.
      :return: A dictionary mapping the node indices in the subgraph to the new units in this circuit.



   .. py:method:: nodes() -> typing_extensions.List[Unit]

      Return an iterator over the nodes.

      :return: An iterator over the nodes.



   .. py:method:: edges() -> typing_extensions.List[typing_extensions.Tuple[Unit, Unit, typing_extensions.Optional[float]]]


   .. py:method:: in_degree(unit: Unit)


   .. py:method:: has_edge(parent: Unit, child: Unit) -> bool


   .. py:property:: root
      :type: Unit


      The root of the circuit is the node with in-degree 0.
      This is the output node, that will perform the final computation.

      :return: The root of the circuit.



   .. py:method:: log_likelihood(events: numpy.array) -> numpy.array

      Calculate the log-likelihood of an event.

      Check the documentation of `likelihood` for more information.

      :param events: The full evidence event with shape (#events, #variables)
      :return: The log-likelihood of the event with shape (#events).



   .. py:method:: cdf(events: numpy.array) -> numpy.array

      Calculate the cumulative distribution function of an event-array.

      The event belongs to the class of full evidence queries.

      ..Note:: The cdf only exists if all variables are continuous or integers.

      :param events: The array of full evidence events.
                     The shape of the array has to be (n, len(self.variables)).
      :return: The cumulative distribution function of the event as an array of shape (n,).



   .. py:method:: probability_of_simple_event(event: random_events.product_algebra.SimpleEvent) -> float

      Calculate the probability of a simple event.

      The event belongs to the class of marginal queries.

      .. Note:: You can read more about queries of this class in Definition 11 in :cite:p:`choi2020probabilistic`
          or watch the `video tutorial <https://youtu.be/2RAG5-L9R70?si=8aEGIqmoDTiUR2u6&t=1089>`_.
          :cite:p:`youtube2020probabilistic`

      :param event: The event.
      :return: The probability of the event.



   .. py:method:: log_mode(check_determinism: bool = True) -> typing_extensions.Tuple[random_events.product_algebra.Event, float]

      Calculate the mode of the model.

      Check the documentation of `mode` for more information.

      :return: The mode and its log-likelihood.



   .. py:method:: remove_unreachable_nodes(root: Unit)

      Remove all nodes that are not reachable from the root.



   .. py:method:: log_truncated_of_simple_event_in_place(simple_event: random_events.product_algebra.SimpleEvent) -> typing_extensions.Tuple[typing_extensions.Optional[typing_extensions.Self], float]

      Construct the truncated circuit from a simple event.

      :param simple_event: The simple event to condition on.
      :return: The truncated circuit and the log-probability of the event



   .. py:method:: log_truncated_in_place(event: random_events.product_algebra.Event) -> typing_extensions.Tuple[typing_extensions.Optional[typing_extensions.Self], float]

      Efficiently compute the truncated for an Event, batching as much as possible.



   .. py:method:: log_truncated(event: random_events.product_algebra.Event) -> typing_extensions.Tuple[typing_extensions.Optional[typing_extensions.Self], float]

      Calculate the truncated distribution P(*| event) and the probability of the event.

      Check the documentation of `truncated` for more information.

      :param event: The event to condition on.
      :return: The truncated distribution and the log-probability of the event.



   .. py:method:: marginal_in_place(variables: typing_extensions.Iterable[random_events.variable.Variable]) -> typing_extensions.Optional[typing_extensions.Self]


   .. py:method:: log_conditional_in_place(point: typing_extensions.Dict[random_events.variable.Variable, typing_extensions.Any]) -> typing_extensions.Tuple[typing_extensions.Optional[typing_extensions.Self], float]


   .. py:method:: log_conditional(point: typing_extensions.Dict[random_events.variable.Variable, typing_extensions.Any]) -> typing_extensions.Tuple[typing_extensions.Optional[typing_extensions.Self], float]

      Calculate the truncated distribution P(*| point) and the probability of the event.
      Check the documentation of `conditional` for more information.

      :param point: A partial point to calculate the truncated distribution on.
      :return: The truncated distribution and the log-probability of the point.



   .. py:method:: marginal(variables: typing_extensions.Iterable[random_events.variable.Variable]) -> typing_extensions.Optional[typing_extensions.Self]

      Calculate the marginal distribution of a set of variables.

      :param variables: The variables to calculate the marginal distribution on.
      :return: The marginal distribution over the variables.



   .. py:method:: sample(amount: int) -> numpy.array

      Sample from the model.

      :param amount: The number of samples to draw.
      :return: The samples.



   .. py:method:: moment(order: probabilistic_model.probabilistic_model.OrderType, center: probabilistic_model.probabilistic_model.CenterType) -> probabilistic_model.probabilistic_model.MomentType

      Calculate the (centralized) moment of the distribution.

      .. math::

          \int_{-\infty}^{\infty} (x - center)^{order} pdf(x) dx

      .. Note:: You can read more about queries of this class in Definition 22 in :cite:p:`choi2020probabilistic`_.
          :cite:p:`youtube2020probabilistic`


      :param order: The orders of the moment as a variable map for every continuous and integer variable.
      :param center: The center of the moment as a variable map for every continuous and integer variable.
      :return: The moments of the variables in `order`.



   .. py:method:: simplify() -> typing_extensions.Self

      Simplify the circuit inplace.



   .. py:property:: support
      :type: random_events.product_algebra.Event


      :return: The support of the model.



   .. py:method:: is_decomposable() -> bool

      Check if the whole circuit is decomposed.

      A circuit is decomposed if all its product units are decomposed.

      :return: if the whole circuit is decomposed



   .. py:method:: __eq__(other: typing_extensions.Self)
      :abstractmethod:



   .. py:method:: empty_copy() -> typing_extensions.Self

      Create a copy of this circuit without any nodes.
      Only the parameters should be copied.
      This is used whenever a new circuit has to be created during inference.

      :return: A copy of this circuit without any subcircuits that is not in this units graph.



   .. py:method:: __deepcopy__(memo=None) -> typing_extensions.Self

      Deep copy of the circuit.

      :param memo: A dictionary that is used to keep track of objects that have already been copied.
      :return: A deep copy of the circuit.



   .. py:method:: to_json() -> typing_extensions.Dict[str, typing_extensions.Any]


   .. py:method:: parameters_from_json(data: typing_extensions.Dict[str, typing_extensions.Any]) -> typing_extensions.Self
      :classmethod:



   .. py:method:: _from_json(data: typing_extensions.Dict[str, typing_extensions.Any]) -> typing_extensions.Self
      :classmethod:


      Create a variable from a json dict.
      This method is called from the from_json method after the correct subclass is determined and should be
      overwritten by the respective subclass.

      :param data: The json dict
      :return: The deserialized object



   .. py:method:: update_variables(new_variables: random_events.product_algebra.VariableMap)

      Update the variables of this unit and its descendants.

      :param new_variables: The new variables to set.



   .. py:method:: is_deterministic() -> bool

      :return: Whether, this circuit is deterministic or not.



   .. py:method:: normalize()

      Normalize every sum node of this circuit in-place.



   .. py:method:: add_edges_and_nodes_from_circuit(other: typing_extensions.Self)

      Add all edges and nodes from another circuit to this circuit.

      :param other: The other circuit to add.



   .. py:method:: add_weighted_edges_from(ebunch_to_add, weight='log_weight', **attr)


   .. py:method:: subgraph_of(node: Unit) -> typing_extensions.Self

      Create a subgraph with a node as root.

      :param node: The root of the subgraph.
      :return: The subgraph.



   .. py:method:: fill_node_colors(node_colors: typing_extensions.Dict[Unit, str])

      Fill the node colors for the structure plot.

      :param node_colors: The node colors to fill.



   .. py:method:: bfs_layout(scale: float = 1.0, align: PlotAlignment = PlotAlignment.VERTICAL) -> typing_extensions.Dict[int, numpy.array]

      Generate a bfs layout for this circuit.

      :return: A dict mapping the node indices to 2d coordinates.



   .. py:method:: plot_structure(node_colors: typing_extensions.Optional[typing_extensions.Dict[Unit, str]] = None, variable_name_offset=0.2, plot_inference=False, inference_representation: typing_extensions.Callable = lambda node: str(node.result_of_current_query), inference_result_offset: float = -0.25)

      Plot the structure of the circuit using matplotlib.

      :param node_colors: Optionally specified colors of the node.
      If nodes are not specified in the dictionary, they will be black.
      :param node_size: The size of the nodes
      :param variable_name_offset: The offset to the right of the variable names.
      :param plot_inference: If the results of the inference should be plotted.
      :param inference_representation: The representation of the inference results as a function from node to string.
      :param inference_result_offset: The vertical offset of the inference results.



   .. py:method:: nodes_weights() -> dict

      :return: dict with keys as nodes and values as list of all the log_weights for the node.



   .. py:method:: replace_discrete_distribution_with_deterministic_sum()

      splits the distribution into sum unit with all the discrete possibilities as leaf.



   .. py:method:: translate(translation: typing_extensions.Dict[random_events.variable.Variable, float])

      Translate the model in-place.
      Translation is done by adding the translation to the variable location influencing values.
      The translation can be viewed as what happens
      when you shift the numeric variables of the model by a constant vector.

      :param translation: The variable value pairs to translate the model by.



   .. py:method:: scale(scale: typing_extensions.Dict[random_events.variable.Variable, float])

      Scale the model in-place.
      Scaling is done by multiplying the variable location influencing values.
      The scaling can be viewed as what happens
      when you multiply the numeric variables of the model by a constant vector.

      :param scaling: The variable value pairs to scale the model by.



   .. py:method:: mount(other: Unit) -> typing_extensions.Dict[int, Unit]

      Mount another unit including its descendants. There will be no edge from `self` to `other`.
      This will also remove the nodes in other and their descendants from their circuit.

      :param other: The other unit to mount.



   .. py:method:: __repr__()


.. py:function:: inverse_class_of(clazz: typing_extensions.Type[probabilistic_model.probabilistic_circuit.rx.probabilistic_circuit.Unit]) -> typing_extensions.Type[Layer]

.. py:class:: Layer

   Bases: :py:obj:`equinox.Module`, :py:obj:`random_events.utils.SubclassJSONSerializer`, :py:obj:`abc.ABC`


   Abstract class for Layers of a layered circuit.

   Layers have the same scope (set of variables) for every node in them.


   .. py:attribute:: _variables
      :type:  typing_extensions.Optional[jax.numpy.array]

      The variable indices of the layer.



   .. py:property:: variables
      :type: jax.Array

      :abstractmethod:



   .. py:method:: set_variables(value: jax.Array)
      :abstractmethod:



   .. py:method:: log_likelihood_of_nodes_single(x: jax.numpy.array) -> jax.numpy.array
      :abstractmethod:


      Calculate the log-likelihood of the distribution.

      :param x: The input vector.
      :return: The log-likelihood of every node in the layer for x.



   .. py:method:: log_likelihood_of_nodes(x: jax.numpy.array) -> jax.numpy.array

      Vectorized version of :meth:`log_likelihood_of_nodes_single`



   .. py:method:: validate()
      :abstractmethod:


      Validate the parameters and their layouts.



   .. py:property:: number_of_nodes
      :type: int

      :abstractmethod:


      :return: The number of nodes in the layer.



   .. py:method:: all_layers() -> typing_extensions.List[Layer]

      :return: A list of all layers in the circuit.



   .. py:method:: all_layers_with_depth(depth: int = 0) -> typing_extensions.List[typing_extensions.Tuple[int, Layer]]

      :return: A list of tuples of all layers in the circuit with their depth.



   .. py:method:: __deepcopy__(memo=None) -> Layer
      :abstractmethod:


      Create a deep copy of the layer.

      :param memo: A dictionary that is used to keep track of objects that have already been copied.



   .. py:method:: nx_classes() -> typing_extensions.Tuple[typing_extensions.Type, Ellipsis]
      :classmethod:


      :return: The tuple of matching classes of the layer in the probabilistic_model.probabilistic_circuit.rx package.



   .. py:method:: to_nx(variables: sortedcontainers.SortedSet[random_events.variable.Variable], result: probabilistic_model.probabilistic_circuit.rx.probabilistic_circuit.ProbabilisticCircuit, progress_bar: typing_extensions.Optional[tqdm.tqdm] = None) -> typing_extensions.List[probabilistic_model.probabilistic_circuit.rx.probabilistic_circuit.Unit]
      :abstractmethod:


      Convert the layer to a networkx circuit.
      For every node in this circuit, a corresponding node in the networkx circuit
      is created.
      The nodes all belong to the same circuit.

      :param variables: The variables of the circuit.
      :param result: The resulting circuit to write into
      :param progress_bar: A progress bar to show the progress.

      :return: The nodes of the networkx circuit.



   .. py:method:: create_layers_from_nodes(nodes: typing_extensions.List[probabilistic_model.probabilistic_circuit.rx.probabilistic_circuit.Unit], child_layers: typing_extensions.List[NXConverterLayer], progress_bar: bool = True) -> typing_extensions.List[NXConverterLayer]
      :staticmethod:


      Create a layer from a list of nodes.



   .. py:method:: create_layer_from_nodes_with_same_type_and_scope(nodes: typing_extensions.List[probabilistic_model.probabilistic_circuit.rx.probabilistic_circuit.Unit], child_layers: typing_extensions.List[NXConverterLayer], progress_bar: bool = True) -> NXConverterLayer
      :classmethod:

      :abstractmethod:


      Create a layer from a list of nodes with the same type and scope.



   .. py:method:: partition() -> typing_extensions.Tuple[typing_extensions.Any, typing_extensions.Any]

      Partition the layer into the parameters and the static structure.

      :return: A tuple containing the parameters and the static structure as pytrees.



   .. py:property:: number_of_trainable_parameters

      :return: The trainable parameters of the layer and all child layers.



   .. py:property:: number_of_components
      :type: int


      :return: The number of components (leaves + edges) of the entire circuit



.. py:class:: InnerLayer(child_layers: typing_extensions.List[Layer])

   Bases: :py:obj:`Layer`, :py:obj:`abc.ABC`


   Abstract Base Class for inner layers


   .. py:attribute:: child_layers
      :type:  typing_extensions.List[Layer]

      The child layers of this layer.



   .. py:method:: set_variables(value: jax.numpy.array)


   .. py:method:: reset_variables()


   .. py:method:: all_layers() -> typing_extensions.List[Layer]

      :return: A list of all layers in the circuit.



   .. py:method:: all_layers_with_depth(depth: int = 0) -> typing_extensions.List[typing_extensions.Tuple[int, Layer]]

      :return: A list of tuples of all layers in the circuit with their depth.



   .. py:method:: to_json() -> typing_extensions.Dict[str, typing_extensions.Any]


.. py:class:: InputLayer(variable: int)

   Bases: :py:obj:`Layer`, :py:obj:`abc.ABC`


   Abstract base class for univariate input units.

   Input layers contain only one type of distribution such that the vectorization of the log likelihood
   calculation works without bottleneck statements like if/else or loops.


   .. py:attribute:: _variables

      The variable indices of the layer.



   .. py:property:: variables
      :type: jax.Array



   .. py:method:: set_variables(value: jax.Array)


   .. py:method:: to_json() -> typing_extensions.Dict[str, typing_extensions.Any]


   .. py:property:: variable


.. py:class:: SumLayer(child_layers: typing_extensions.List[Layer], log_weights: typing_extensions.List[typing_extensions.Union[jax.array, jax.experimental.sparse.BCOO]])

   Bases: :py:obj:`InnerLayer`, :py:obj:`abc.ABC`


   Abstract Base Class for inner layers


   .. py:attribute:: log_weights
      :type:  typing_extensions.List[typing_extensions.Union[jax.array, jax.experimental.sparse.BCOO]]


   .. py:attribute:: child_layers
      :type:  typing_extensions.Union[typing_extensions.List[[ProductLayer]], typing_extensions.List[InputLayer]]

      The child layers of this layer.



   .. py:method:: validate()

      Validate the parameters and their layouts.



   .. py:property:: log_weighted_child_layers
      :type: typing_extensions.Iterator[typing_extensions.Tuple[jax.experimental.sparse.BCOO, Layer]]


      :returns: Yields log log_weights and the child layers zipped together.



   .. py:property:: variables
      :type: jax.Array



   .. py:property:: number_of_nodes
      :type: int


      :return: The number of nodes in the layer.



.. py:class:: SparseSumLayer(child_layers: typing_extensions.List[Layer], log_weights: typing_extensions.List[typing_extensions.Union[jax.array, jax.experimental.sparse.BCOO]])

   Bases: :py:obj:`SumLayer`


   Abstract Base Class for inner layers


   .. py:attribute:: log_weights
      :type:  typing_extensions.List[jax.experimental.sparse.BCOO]


   .. py:method:: nx_classes() -> typing_extensions.Tuple[typing_extensions.Type, Ellipsis]
      :classmethod:


      :return: The tuple of matching classes of the layer in the probabilistic_model.probabilistic_circuit.rx package.



   .. py:property:: number_of_components
      :type: int


      :return: The number of components (leaves + edges) of the entire circuit



   .. py:property:: concatenated_log_weights
      :type: jax.experimental.sparse.BCOO


      :return: The concatenated log_weights of the child layers for each node.



   .. py:property:: log_normalization_constants
      :type: jax.Array



   .. py:property:: normalized_weights

      :return: The normalized log_weights of the child layers for each node.



   .. py:method:: log_likelihood_of_nodes_single(x: jax.Array) -> jax.Array

      Calculate the log-likelihood of the distribution.

      :param x: The input vector.
      :return: The log-likelihood of every node in the layer for x.



   .. py:method:: __deepcopy__(memo=None)

      Create a deep copy of the layer.

      :param memo: A dictionary that is used to keep track of objects that have already been copied.



   .. py:method:: to_json() -> typing_extensions.Dict[str, typing_extensions.Any]


   .. py:method:: _from_json(data: typing_extensions.Dict[str, typing_extensions.Any]) -> typing_extensions.Self
      :classmethod:


      Create a variable from a json dict.
      This method is called from the from_json method after the correct subclass is determined and should be
      overwritten by the respective subclass.

      :param data: The json dict
      :return: The deserialized object



   .. py:method:: create_layer_from_nodes_with_same_type_and_scope(nodes: typing_extensions.List[probabilistic_model.probabilistic_circuit.rx.probabilistic_circuit.SumUnit], child_layers: typing_extensions.List[NXConverterLayer], progress_bar: bool = True) -> NXConverterLayer
      :classmethod:


      Create a layer from a list of nodes with the same type and scope.



   .. py:method:: to_nx(variables: sortedcontainers.SortedSet[random_events.variable.Variable], result: probabilistic_model.probabilistic_circuit.rx.probabilistic_circuit.ProbabilisticCircuit, progress_bar: typing_extensions.Optional[tqdm.tqdm] = None) -> typing_extensions.List[probabilistic_model.probabilistic_circuit.rx.probabilistic_circuit.Unit]

      Convert the layer to a networkx circuit.
      For every node in this circuit, a corresponding node in the networkx circuit
      is created.
      The nodes all belong to the same circuit.

      :param variables: The variables of the circuit.
      :param result: The resulting circuit to write into
      :param progress_bar: A progress bar to show the progress.

      :return: The nodes of the networkx circuit.



.. py:class:: DenseSumLayer(child_layers: typing_extensions.List[Layer], log_weights: typing_extensions.List[typing_extensions.Union[jax.array, jax.experimental.sparse.BCOO]])

   Bases: :py:obj:`SumLayer`


   Abstract Base Class for inner layers


   .. py:attribute:: log_weights
      :type:  typing_extensions.List[jax.numpy.array]


   .. py:attribute:: child_layers
      :type:  typing_extensions.Union[typing_extensions.List[[ProductLayer]], typing_extensions.List[InputLayer]]

      The child layers of this layer.



   .. py:method:: create_layer_from_nodes_with_same_type_and_scope(nodes: typing_extensions.List[probabilistic_model.probabilistic_circuit.rx.probabilistic_circuit.Unit], child_layers: typing_extensions.List[NXConverterLayer], progress_bar: bool = True) -> NXConverterLayer
      :classmethod:

      :abstractmethod:


      Create a layer from a list of nodes with the same type and scope.



   .. py:property:: number_of_components
      :type: int


      :return: The number of components (leaves + edges) of the entire circuit



   .. py:method:: nx_classes() -> typing_extensions.Tuple[typing_extensions.Type, Ellipsis]
      :classmethod:


      :return: The tuple of matching classes of the layer in the probabilistic_model.probabilistic_circuit.rx package.



   .. py:property:: concatenated_log_weights
      :type: jax.numpy.array


      :return: The concatenated log_weights of the child layers for each node.



   .. py:property:: log_normalization_constants
      :type: jax.Array



   .. py:property:: normalized_weights

      :return: The normalized log_weights of the child layers for each node.



   .. py:method:: log_likelihood_of_nodes_single(x: jax.Array) -> jax.Array

      Calculate the log-likelihood of the distribution.

      :param x: The input vector.
      :return: The log-likelihood of every node in the layer for x.



   .. py:method:: __deepcopy__(memo=None)

      Create a deep copy of the layer.

      :param memo: A dictionary that is used to keep track of objects that have already been copied.



   .. py:method:: to_json() -> typing_extensions.Dict[str, typing_extensions.Any]


   .. py:method:: _from_json(data: typing_extensions.Dict[str, typing_extensions.Any]) -> typing_extensions.Self
      :classmethod:


      Create a variable from a json dict.
      This method is called from the from_json method after the correct subclass is determined and should be
      overwritten by the respective subclass.

      :param data: The json dict
      :return: The deserialized object



   .. py:method:: to_nx(variables: sortedcontainers.SortedSet[random_events.variable.Variable], result: probabilistic_model.probabilistic_circuit.rx.probabilistic_circuit.ProbabilisticCircuit, progress_bar: typing_extensions.Optional[tqdm.tqdm] = None) -> typing_extensions.List[probabilistic_model.probabilistic_circuit.rx.probabilistic_circuit.Unit]

      Convert the layer to a networkx circuit.
      For every node in this circuit, a corresponding node in the networkx circuit
      is created.
      The nodes all belong to the same circuit.

      :param variables: The variables of the circuit.
      :param result: The resulting circuit to write into
      :param progress_bar: A progress bar to show the progress.

      :return: The nodes of the networkx circuit.



.. py:class:: ProductLayer(child_layers: typing_extensions.List[Layer], edges: jax.experimental.sparse.BCOO)

   Bases: :py:obj:`InnerLayer`


   A layer that represents the product of multiple other units.


   .. py:attribute:: child_layers
      :type:  typing_extensions.List[typing_extensions.Union[SparseSumLayer, InputLayer]]

      The child of a product layer is a list that contains groups sum units with the same scope or groups of input
      units with the same scope.



   .. py:attribute:: edges
      :type:  jaxtyping.Int[jax.experimental.sparse.BCOO, len(child_layers), number_of_nodes]

      The edges consist of a sparse matrix containing integers.
      The first dimension describes the edges for each child layer.
      The second dimension describes the edges for each node in the child layer.
      The integers are interpreted in such a way that n-th value represents a edge (n, edges[n]).

      Nodes in the child layer can be mapped to by multiple nodes in this layer.

      The shape is (#child_layers, #nodes).



   .. py:method:: validate()

      Validate the parameters and their layouts.



   .. py:property:: number_of_nodes
      :type: int


      :return: The number of nodes in the layer.



   .. py:method:: nx_classes() -> typing_extensions.Tuple[typing_extensions.Type, Ellipsis]
      :classmethod:


      :return: The tuple of matching classes of the layer in the probabilistic_model.probabilistic_circuit.rx package.



   .. py:property:: number_of_components
      :type: int


      :return: The number of components (leaves + edges) of the entire circuit



   .. py:method:: variables() -> jax.Array


   .. py:method:: log_likelihood_of_nodes_single(x: jax.Array) -> jax.Array

      Calculate the log-likelihood of the distribution.

      :param x: The input vector.
      :return: The log-likelihood of every node in the layer for x.



   .. py:method:: __deepcopy__(memo=None)

      Create a deep copy of the layer.

      :param memo: A dictionary that is used to keep track of objects that have already been copied.



   .. py:method:: to_json() -> typing_extensions.Dict[str, typing_extensions.Any]


   .. py:method:: _from_json(data: typing_extensions.Dict[str, typing_extensions.Any]) -> typing_extensions.Self
      :classmethod:


      Create a variable from a json dict.
      This method is called from the from_json method after the correct subclass is determined and should be
      overwritten by the respective subclass.

      :param data: The json dict
      :return: The deserialized object



   .. py:method:: create_layer_from_nodes_with_same_type_and_scope(nodes: typing_extensions.List[probabilistic_model.probabilistic_circuit.rx.probabilistic_circuit.Unit], child_layers: typing_extensions.List[NXConverterLayer], progress_bar: bool = True) -> NXConverterLayer
      :classmethod:


      Create a layer from a list of nodes with the same type and scope.



   .. py:method:: to_nx(variables: sortedcontainers.SortedSet[random_events.variable.Variable], result: probabilistic_model.probabilistic_circuit.rx.probabilistic_circuit.ProbabilisticCircuit, progress_bar: typing_extensions.Optional[tqdm.tqdm] = None) -> typing_extensions.List[probabilistic_model.probabilistic_circuit.rx.probabilistic_circuit.Unit]

      Convert the layer to a networkx circuit.
      For every node in this circuit, a corresponding node in the networkx circuit
      is created.
      The nodes all belong to the same circuit.

      :param variables: The variables of the circuit.
      :param result: The resulting circuit to write into
      :param progress_bar: A progress bar to show the progress.

      :return: The nodes of the networkx circuit.



.. py:class:: NXConverterLayer

   Class used for conversion from a probabilistic circuit in networkx to a layered circuit in jax.


   .. py:attribute:: layer
      :type:  Layer


   .. py:attribute:: nodes
      :type:  typing_extensions.List[probabilistic_model.probabilistic_circuit.rx.probabilistic_circuit.Unit]


   .. py:attribute:: hash_remap
      :type:  typing_extensions.Dict[int, int]


.. py:class:: InputLayer(variable: int)

   Bases: :py:obj:`Layer`, :py:obj:`abc.ABC`


   Abstract base class for univariate input units.

   Input layers contain only one type of distribution such that the vectorization of the log likelihood
   calculation works without bottleneck statements like if/else or loops.


   .. py:attribute:: _variables

      The variable indices of the layer.



   .. py:property:: variables
      :type: jax.Array



   .. py:method:: set_variables(value: jax.Array)


   .. py:method:: to_json() -> typing_extensions.Dict[str, typing_extensions.Any]


   .. py:property:: variable


.. py:class:: NXConverterLayer

   Class used for conversion from a probabilistic circuit in networkx to a layered circuit in jax.


   .. py:attribute:: layer
      :type:  Layer


   .. py:attribute:: nodes
      :type:  typing_extensions.List[probabilistic_model.probabilistic_circuit.rx.probabilistic_circuit.Unit]


   .. py:attribute:: hash_remap
      :type:  typing_extensions.Dict[int, int]


.. py:class:: Unit

   Bases: :py:obj:`random_events.utils.SubclassJSONSerializer`, :py:obj:`probabilistic_model.interfaces.drawio.drawio.DrawIOInterface`, :py:obj:`abc.ABC`


   Class for all units of a probabilistic circuit.

   This class should not be used by users directly.
   Use :class:`ProbabilisticCircuit` as interface to users.


   .. py:attribute:: probabilistic_circuit
      :type:  typing_extensions.Optional[ProbabilisticCircuit]
      :value: None


      The circuit this component is part of. 



   .. py:attribute:: result_of_current_query
      :type:  typing_extensions.Any
      :value: None


      The result of the current query. 



   .. py:attribute:: index
      :type:  typing_extensions.Optional[int]
      :value: None


      The index of the node in the graph of its circuit.



   .. py:method:: __post_init__()


   .. py:property:: subcircuits
      :type: typing_extensions.List[Unit]


      :return: The subcircuits of this unit.



   .. py:property:: parents
      :type: typing_extensions.List[InnerUnit]


      :return: The parents of this unit.



   .. py:method:: support()
      :abstractmethod:


      Calculate the support of this unit.



   .. py:property:: is_leaf
      :abstractmethod:


      :return: If this unit is a leaf unit.



   .. py:property:: variables
      :type: sortedcontainers.SortedSet

      :abstractmethod:



   .. py:property:: leaves
      :type: typing_extensions.List[LeafUnit]


      :return: The leaves of the circuit that are descendants of this node.



   .. py:method:: update_variables(new_variables: random_events.product_algebra.VariableMap)

      Update the variables of this unit and its descendants.

      :param new_variables: A map that maps the variables that should be replaced to their new variable.



   .. py:method:: connect_incoming_edges_to(other: Unit)

      Connect all incoming edges to this unit to another unit.

      :param other: The other unit to connect the incoming edges to.



   .. py:method:: filter_variable_map_by_self(variable_map: random_events.product_algebra.VariableMap)

      Filter a variable map by the variables of this unit.

      :param variable_map: The map to filter
      :return: The map filtered by the variables of this unit.



   .. py:property:: impossible_condition_result
      :type: typing_extensions.Tuple[typing_extensions.Optional[Unit], float]


      :return: The result of an impossible truncated query.



   .. py:method:: log_mode()
      :abstractmethod:



   .. py:method:: __hash__()


   .. py:method:: copy_without_graph()


   .. py:method:: empty_copy() -> typing_extensions.Self

      Creat a copy of this circuit without any subcircuits. Only the parameters should be copied.
      This is used whenever a new circuit has to be created during inference.

      :return: A copy of this circuit without any subcircuits that is not in this units graph.



   .. py:method:: simplify()
      :abstractmethod:


      Simplify the circuit by removing nodes and redirected edges that have no impact in-place.
      Essentially, this method transforms the circuit into an alternating order of sum and product units.

      :return: The simplified circuit.



   .. py:method:: sample(*args, **kwargs)
      :abstractmethod:


      Draw samples from the circuit.

      For sampling, a node gets requested a number of samples from all his parents.
      The parents write into the `result_of_current_query` attribute a tuple describing the beginning index of the
      sampling and how many samples are requested.



   .. py:method:: marginal(*args, **kwargs) -> typing_extensions.Optional[typing_extensions.Self]
      :abstractmethod:


      Remove nodes that are not part of the marginal distribution.



   .. py:method:: moment(*args, **kwargs)
      :abstractmethod:



   .. py:property:: drawio_style
      :type: typing_extensions.Dict[str, typing_extensions.Any]


      The style of the object.



.. py:class:: NXProbabilisticCircuit

   Bases: :py:obj:`probabilistic_model.probabilistic_model.ProbabilisticModel`, :py:obj:`random_events.utils.SubclassJSONSerializer`


   Probabilistic Circuits as a directed, rooted, acyclic graph.

   The nodes of the graph are the units of the circuit.
   The edges of the graph indicate how the units are connected.
   The outgoing edges of a sum unit contain the log-log_weights of the subcircuits.


   .. py:attribute:: graph
      :type:  rustworkx.PyDAG[Unit]

      The graph to check connectivity from.



   .. py:method:: __len__()

      Return the number of nodes in the graph.

      :return: The number of nodes in the graph.



   .. py:method:: __iter__()

      Return an iterator over the nodes in the graph.

      :return: An iterator over the nodes in the graph.



   .. py:method:: from_other(other: typing_extensions.Self) -> typing_extensions.Self
      :classmethod:



   .. py:property:: variables
      :type: sortedcontainers.SortedSet


      :return: The variables of the model.



   .. py:property:: variable_to_index_map
      :type: typing_extensions.Dict[random_events.variable.Variable, int]



   .. py:property:: layers
      :type: typing_extensions.List[typing_extensions.List[Unit]]



   .. py:property:: leaves
      :type: typing_extensions.List[LeafUnit]



   .. py:method:: is_valid() -> bool

      Check if this graph is:

      - acyclic
      - connected

      :return: True if the graph is valid, False otherwise.



   .. py:method:: add_node(node: Unit)


   .. py:method:: add_nodes_from(units: typing_extensions.Iterable[Unit])


   .. py:method:: add_edge(parent: Unit, child: Unit, log_weight: typing_extensions.Optional[float] = None)


   .. py:method:: add_edges_from(edges: typing_extensions.Iterable[typing_extensions.Union[typing_extensions.Tuple[Unit, Unit], typing_extensions.Tuple[Unit, Unit, float]]])


   .. py:method:: successors(unit: Unit) -> typing_extensions.List[Unit]


   .. py:method:: descendants(unit: Unit) -> random_events.set.Set[Unit]


   .. py:method:: predecessors(unit: Unit) -> typing_extensions.List[InnerUnit]


   .. py:method:: remove_node(unit: Unit)


   .. py:method:: remove_nodes_from(units: typing_extensions.Iterable[Unit])


   .. py:method:: remove_edge(parent: Unit, child: Unit)


   .. py:method:: remove_edges_from(edges: typing_extensions.Iterable[typing_extensions.Tuple[Unit, Unit]])


   .. py:method:: in_edges(unit: Unit) -> typing_extensions.List[typing_extensions.Tuple[Unit, Unit, typing_extensions.Optional[float]]]


   .. py:method:: add_from_subgraph(subgraph: rustworkx.PyDAG[Unit]) -> typing_extensions.Dict[int, Unit]

      Add nodes and edges from a subgraph to this circuit.

      :param subgraph: The subgraph to add nodes from.
      :return: A dictionary mapping the node indices in the subgraph to the new units in this circuit.



   .. py:method:: nodes() -> typing_extensions.List[Unit]

      Return an iterator over the nodes.

      :return: An iterator over the nodes.



   .. py:method:: edges() -> typing_extensions.List[typing_extensions.Tuple[Unit, Unit, typing_extensions.Optional[float]]]


   .. py:method:: in_degree(unit: Unit)


   .. py:method:: has_edge(parent: Unit, child: Unit) -> bool


   .. py:property:: root
      :type: Unit


      The root of the circuit is the node with in-degree 0.
      This is the output node, that will perform the final computation.

      :return: The root of the circuit.



   .. py:method:: log_likelihood(events: numpy.array) -> numpy.array

      Calculate the log-likelihood of an event.

      Check the documentation of `likelihood` for more information.

      :param events: The full evidence event with shape (#events, #variables)
      :return: The log-likelihood of the event with shape (#events).



   .. py:method:: cdf(events: numpy.array) -> numpy.array

      Calculate the cumulative distribution function of an event-array.

      The event belongs to the class of full evidence queries.

      ..Note:: The cdf only exists if all variables are continuous or integers.

      :param events: The array of full evidence events.
                     The shape of the array has to be (n, len(self.variables)).
      :return: The cumulative distribution function of the event as an array of shape (n,).



   .. py:method:: probability_of_simple_event(event: random_events.product_algebra.SimpleEvent) -> float

      Calculate the probability of a simple event.

      The event belongs to the class of marginal queries.

      .. Note:: You can read more about queries of this class in Definition 11 in :cite:p:`choi2020probabilistic`
          or watch the `video tutorial <https://youtu.be/2RAG5-L9R70?si=8aEGIqmoDTiUR2u6&t=1089>`_.
          :cite:p:`youtube2020probabilistic`

      :param event: The event.
      :return: The probability of the event.



   .. py:method:: log_mode(check_determinism: bool = True) -> typing_extensions.Tuple[random_events.product_algebra.Event, float]

      Calculate the mode of the model.

      Check the documentation of `mode` for more information.

      :return: The mode and its log-likelihood.



   .. py:method:: remove_unreachable_nodes(root: Unit)

      Remove all nodes that are not reachable from the root.



   .. py:method:: log_truncated_of_simple_event_in_place(simple_event: random_events.product_algebra.SimpleEvent) -> typing_extensions.Tuple[typing_extensions.Optional[typing_extensions.Self], float]

      Construct the truncated circuit from a simple event.

      :param simple_event: The simple event to condition on.
      :return: The truncated circuit and the log-probability of the event



   .. py:method:: log_truncated_in_place(event: random_events.product_algebra.Event) -> typing_extensions.Tuple[typing_extensions.Optional[typing_extensions.Self], float]

      Efficiently compute the truncated for an Event, batching as much as possible.



   .. py:method:: log_truncated(event: random_events.product_algebra.Event) -> typing_extensions.Tuple[typing_extensions.Optional[typing_extensions.Self], float]

      Calculate the truncated distribution P(*| event) and the probability of the event.

      Check the documentation of `truncated` for more information.

      :param event: The event to condition on.
      :return: The truncated distribution and the log-probability of the event.



   .. py:method:: marginal_in_place(variables: typing_extensions.Iterable[random_events.variable.Variable]) -> typing_extensions.Optional[typing_extensions.Self]


   .. py:method:: log_conditional_in_place(point: typing_extensions.Dict[random_events.variable.Variable, typing_extensions.Any]) -> typing_extensions.Tuple[typing_extensions.Optional[typing_extensions.Self], float]


   .. py:method:: log_conditional(point: typing_extensions.Dict[random_events.variable.Variable, typing_extensions.Any]) -> typing_extensions.Tuple[typing_extensions.Optional[typing_extensions.Self], float]

      Calculate the truncated distribution P(*| point) and the probability of the event.
      Check the documentation of `conditional` for more information.

      :param point: A partial point to calculate the truncated distribution on.
      :return: The truncated distribution and the log-probability of the point.



   .. py:method:: marginal(variables: typing_extensions.Iterable[random_events.variable.Variable]) -> typing_extensions.Optional[typing_extensions.Self]

      Calculate the marginal distribution of a set of variables.

      :param variables: The variables to calculate the marginal distribution on.
      :return: The marginal distribution over the variables.



   .. py:method:: sample(amount: int) -> numpy.array

      Sample from the model.

      :param amount: The number of samples to draw.
      :return: The samples.



   .. py:method:: moment(order: probabilistic_model.probabilistic_model.OrderType, center: probabilistic_model.probabilistic_model.CenterType) -> probabilistic_model.probabilistic_model.MomentType

      Calculate the (centralized) moment of the distribution.

      .. math::

          \int_{-\infty}^{\infty} (x - center)^{order} pdf(x) dx

      .. Note:: You can read more about queries of this class in Definition 22 in :cite:p:`choi2020probabilistic`_.
          :cite:p:`youtube2020probabilistic`


      :param order: The orders of the moment as a variable map for every continuous and integer variable.
      :param center: The center of the moment as a variable map for every continuous and integer variable.
      :return: The moments of the variables in `order`.



   .. py:method:: simplify() -> typing_extensions.Self

      Simplify the circuit inplace.



   .. py:property:: support
      :type: random_events.product_algebra.Event


      :return: The support of the model.



   .. py:method:: is_decomposable() -> bool

      Check if the whole circuit is decomposed.

      A circuit is decomposed if all its product units are decomposed.

      :return: if the whole circuit is decomposed



   .. py:method:: __eq__(other: typing_extensions.Self)
      :abstractmethod:



   .. py:method:: empty_copy() -> typing_extensions.Self

      Create a copy of this circuit without any nodes.
      Only the parameters should be copied.
      This is used whenever a new circuit has to be created during inference.

      :return: A copy of this circuit without any subcircuits that is not in this units graph.



   .. py:method:: __deepcopy__(memo=None) -> typing_extensions.Self

      Deep copy of the circuit.

      :param memo: A dictionary that is used to keep track of objects that have already been copied.
      :return: A deep copy of the circuit.



   .. py:method:: to_json() -> typing_extensions.Dict[str, typing_extensions.Any]


   .. py:method:: parameters_from_json(data: typing_extensions.Dict[str, typing_extensions.Any]) -> typing_extensions.Self
      :classmethod:



   .. py:method:: _from_json(data: typing_extensions.Dict[str, typing_extensions.Any]) -> typing_extensions.Self
      :classmethod:


      Create a variable from a json dict.
      This method is called from the from_json method after the correct subclass is determined and should be
      overwritten by the respective subclass.

      :param data: The json dict
      :return: The deserialized object



   .. py:method:: update_variables(new_variables: random_events.product_algebra.VariableMap)

      Update the variables of this unit and its descendants.

      :param new_variables: The new variables to set.



   .. py:method:: is_deterministic() -> bool

      :return: Whether, this circuit is deterministic or not.



   .. py:method:: normalize()

      Normalize every sum node of this circuit in-place.



   .. py:method:: add_edges_and_nodes_from_circuit(other: typing_extensions.Self)

      Add all edges and nodes from another circuit to this circuit.

      :param other: The other circuit to add.



   .. py:method:: add_weighted_edges_from(ebunch_to_add, weight='log_weight', **attr)


   .. py:method:: subgraph_of(node: Unit) -> typing_extensions.Self

      Create a subgraph with a node as root.

      :param node: The root of the subgraph.
      :return: The subgraph.



   .. py:method:: fill_node_colors(node_colors: typing_extensions.Dict[Unit, str])

      Fill the node colors for the structure plot.

      :param node_colors: The node colors to fill.



   .. py:method:: bfs_layout(scale: float = 1.0, align: PlotAlignment = PlotAlignment.VERTICAL) -> typing_extensions.Dict[int, numpy.array]

      Generate a bfs layout for this circuit.

      :return: A dict mapping the node indices to 2d coordinates.



   .. py:method:: plot_structure(node_colors: typing_extensions.Optional[typing_extensions.Dict[Unit, str]] = None, variable_name_offset=0.2, plot_inference=False, inference_representation: typing_extensions.Callable = lambda node: str(node.result_of_current_query), inference_result_offset: float = -0.25)

      Plot the structure of the circuit using matplotlib.

      :param node_colors: Optionally specified colors of the node.
      If nodes are not specified in the dictionary, they will be black.
      :param node_size: The size of the nodes
      :param variable_name_offset: The offset to the right of the variable names.
      :param plot_inference: If the results of the inference should be plotted.
      :param inference_representation: The representation of the inference results as a function from node to string.
      :param inference_result_offset: The vertical offset of the inference results.



   .. py:method:: nodes_weights() -> dict

      :return: dict with keys as nodes and values as list of all the log_weights for the node.



   .. py:method:: replace_discrete_distribution_with_deterministic_sum()

      splits the distribution into sum unit with all the discrete possibilities as leaf.



   .. py:method:: translate(translation: typing_extensions.Dict[random_events.variable.Variable, float])

      Translate the model in-place.
      Translation is done by adding the translation to the variable location influencing values.
      The translation can be viewed as what happens
      when you shift the numeric variables of the model by a constant vector.

      :param translation: The variable value pairs to translate the model by.



   .. py:method:: scale(scale: typing_extensions.Dict[random_events.variable.Variable, float])

      Scale the model in-place.
      Scaling is done by multiplying the variable location influencing values.
      The scaling can be viewed as what happens
      when you multiply the numeric variables of the model by a constant vector.

      :param scaling: The variable value pairs to scale the model by.



   .. py:method:: mount(other: Unit) -> typing_extensions.Dict[int, Unit]

      Mount another unit including its descendants. There will be no edge from `self` to `other`.
      This will also remove the nodes in other and their descendants from their circuit.

      :param other: The other unit to mount.



   .. py:method:: __repr__()


.. py:class:: UnivariateContinuousLeaf

   Bases: :py:obj:`UnivariateLeaf`


   Class for Leaf units.


   .. py:attribute:: distribution
      :type:  typing_extensions.Optional[probabilistic_model.distributions.ContinuousDistribution]

      The distribution contained in this leaf unit.



   .. py:attribute:: __hash__


   .. py:method:: log_truncated_of_simple_event_in_place(event: random_events.product_algebra.SimpleEvent)


   .. py:method:: univariate_log_truncated_of_simple_event_in_place(event: random_events.interval.Interval)

      Condition this distribution on a simple event in-place but use sum units to create conditions on composite
      intervals.
      :param event: The simple event to condition on.



.. py:class:: DiracDeltaDistribution(variable: random_events.variable.Continuous, location: float, density_cap: float = np.inf, tolerance: float = 1e-06)

   Bases: :py:obj:`ContinuousDistribution`


   Class for Dirac delta distributions.
   The Dirac measure is used whenever evidence is given as a singleton instance.

   https://en.wikipedia.org/wiki/Dirac_delta_function


   .. py:attribute:: variable
      :type:  random_events.variable.Continuous


   .. py:attribute:: location
      :type:  float

      The location of the Dirac delta distribution.



   .. py:attribute:: density_cap
      :type:  float

      The density cap of the Dirac delta distribution.
      This value will be used to replace infinity in likelihood.



   .. py:attribute:: tolerance
      :type:  float
      :value: 1e-06


      The tolerance of deviations of the `location` of the Dirac delta distribution.
      This is used during calculations to take precision problems into account.



   .. py:method:: log_likelihood(events: numpy.array) -> numpy.array

      Calculate the log-likelihood of an event.

      Check the documentation of `likelihood` for more information.

      :param events: The full evidence event with shape (#events, #variables)
      :return: The log-likelihood of the event with shape (#events).



   .. py:method:: cdf(x: numpy.array) -> numpy.array

      Calculate the cumulative distribution function at x.
      :param x: The data
      :return: The cumulative distribution function at x



   .. py:property:: abbreviated_symbol
      :type: str



   .. py:property:: univariate_support
      :type: random_events.variable.Interval


      :return: The univariate support of the distribution. This is not an Event.



   .. py:method:: log_conditional_from_simple_interval(interval: random_events.variable.SimpleInterval) -> typing_extensions.Tuple[typing_extensions.Self, float]

      Calculate the truncated distribution given a simple interval.

      :param interval: The simple interval
      :return: The truncated distribution and the log-probability of the interval.



   .. py:method:: probability_of_simple_event(event: random_events.product_algebra.SimpleEvent) -> float

      Calculate the probability of a simple event.

      The event belongs to the class of marginal queries.

      .. Note:: You can read more about queries of this class in Definition 11 in :cite:p:`choi2020probabilistic`
          or watch the `video tutorial <https://youtu.be/2RAG5-L9R70?si=8aEGIqmoDTiUR2u6&t=1089>`_.
          :cite:p:`youtube2020probabilistic`

      :param event: The event.
      :return: The probability of the event.



   .. py:method:: univariate_log_mode() -> typing_extensions.Tuple[random_events.variable.AbstractCompositeSet, float]

      :return: The univariate mode of the distribution and its log-likelihood. The mode is not an Event.



   .. py:method:: sample(amount: int) -> numpy.array

      Sample from the model.

      :param amount: The number of samples to draw.
      :return: The samples.



   .. py:method:: moment(order: probabilistic_model.probabilistic_model.OrderType, center: probabilistic_model.probabilistic_model.CenterType) -> probabilistic_model.probabilistic_model.MomentType

      Calculate the (centralized) moment of the distribution.

      .. math::

          \int_{-\infty}^{\infty} (x - center)^{order} pdf(x) dx

      .. Note:: You can read more about queries of this class in Definition 22 in :cite:p:`choi2020probabilistic`_.
          :cite:p:`youtube2020probabilistic`


      :param order: The orders of the moment as a variable map for every continuous and integer variable.
      :param center: The center of the moment as a variable map for every continuous and integer variable.
      :return: The moments of the variables in `order`.



   .. py:method:: __eq__(other)


   .. py:method:: __hash__()


   .. py:property:: representation

      The symbol used to represent this distribution.



   .. py:method:: __repr__()


   .. py:method:: __copy__()


   .. py:method:: __deepcopy__(memo=None)


   .. py:method:: to_json() -> typing_extensions.Dict[str, typing_extensions.Any]


   .. py:method:: _from_json(data: typing_extensions.Dict[str, typing_extensions.Any]) -> typing_extensions.Self
      :classmethod:


      Create a variable from a json dict.
      This method is called from the from_json method after the correct subclass is determined and should be
      overwritten by the respective subclass.

      :param data: The json dict
      :return: The deserialized object



   .. py:method:: plot(**kwargs) -> typing_extensions.List

      Generate traces that can be plotted with plotly.

      :param number_of_samples: The number of samples to draw.
      :param surface: If True, plot the model as a surface plot.
      :param mode: If True, plot the mode of the model.
      :return: The traces.



   .. py:method:: translate(translation: random_events.product_algebra.VariableMap[random_events.variable.Variable, float])

      Translate the model in-place.
      Translation is done by adding the translation to the variable location influencing values.
      The translation can be viewed as what happens
      when you shift the numeric variables of the model by a constant vector.

      :param translation: The variable value pairs to translate the model by.



   .. py:method:: scale(scaling: random_events.product_algebra.VariableMap[random_events.variable.Variable, float])

      Scale the model in-place.
      Scaling is done by multiplying the variable location influencing values.
      The scaling can be viewed as what happens
      when you multiply the numeric variables of the model by a constant vector.

      :param scaling: The variable value pairs to scale the model by.



.. py:class:: ContinuousLayer(variable: int)

   Bases: :py:obj:`probabilistic_model.probabilistic_circuit.jax.inner_layer.InputLayer`, :py:obj:`abc.ABC`


   Abstract base class for continuous univariate input units.


.. py:class:: ContinuousLayerWithFiniteSupport(variable: int, interval: jax.Array)

   Bases: :py:obj:`ContinuousLayer`, :py:obj:`abc.ABC`


   Abstract class for continuous univariate input units with finite support.


   .. py:attribute:: interval
      :type:  jax.Array

      The interval of the distribution as a array of shape (num_nodes, 2).
      The first column contains the lower bounds and the second column the upper bounds.
      The intervals are treated as open intervals (>/< comparator).



   .. py:property:: lower
      :type: jax.Array



   .. py:property:: upper
      :type: jax.Array



   .. py:method:: left_included_condition(x: jax.Array) -> jax.Array

      Check if x is included in the left bound of the intervals.
      :param x: The data
      :return: A boolean array of shape (#x, #nodes)



   .. py:method:: right_included_condition(x: jax.Array) -> jax.Array

      Check if x is included in the right bound of the intervals.
      :param x: The data
      :return: A boolean array of shape (#x, #nodes)



   .. py:method:: included_condition(x: jax.Array) -> jax.Array

      Check if x is included in the interval.
      :param x: The data
      :return: A boolean array of shape (#x, #nodes)



   .. py:method:: to_json() -> Dict[str, Any]


   .. py:method:: __deepcopy__(memo=None)

      Create a deep copy of the layer.

      :param memo: A dictionary that is used to keep track of objects that have already been copied.



.. py:class:: DiracDeltaLayer(variable_index, location, density_cap)

   Bases: :py:obj:`ContinuousLayer`


   A layer that represents Dirac delta distributions over a single variable.


   .. py:attribute:: location
      :type:  jax.Array

      The locations of the Dirac delta distributions.



   .. py:attribute:: density_cap
      :type:  jax.Array

      The density caps of the Dirac delta distributions.
      This value will be used to replace infinity in likelihoods.



   .. py:method:: validate()

      Validate the parameters and their layouts.



   .. py:property:: number_of_nodes

      :return: The number of nodes in the layer.



   .. py:method:: log_likelihood_of_nodes(x: jax.Array) -> jax.Array

      Vectorized version of :meth:`log_likelihood_of_nodes_single`



   .. py:method:: log_likelihood_of_nodes_single(x: jax.Array) -> jax.Array

      Calculate the log-likelihood of the distribution.

      :param x: The input vector.
      :return: The log-likelihood of every node in the layer for x.



   .. py:method:: nx_classes() -> typing_extensions.Tuple[typing_extensions.Type, Ellipsis]
      :classmethod:


      :return: The tuple of matching classes of the layer in the probabilistic_model.probabilistic_circuit.rx package.



   .. py:method:: create_layer_from_nodes_with_same_type_and_scope(nodes: List[probabilistic_model.probabilistic_circuit.rx.probabilistic_circuit.UnivariateContinuousLeaf], child_layers: List[probabilistic_model.probabilistic_circuit.jax.inner_layer.NXConverterLayer], progress_bar: bool = True) -> probabilistic_model.probabilistic_circuit.jax.inner_layer.NXConverterLayer
      :classmethod:


      Create a layer from a list of nodes with the same type and scope.



   .. py:method:: to_json() -> Dict[str, Any]


   .. py:method:: _from_json(data: Dict[str, Any]) -> typing_extensions.Self
      :classmethod:


      Create a variable from a json dict.
      This method is called from the from_json method after the correct subclass is determined and should be
      overwritten by the respective subclass.

      :param data: The json dict
      :return: The deserialized object



   .. py:method:: to_nx(variables: sortedcontainers.SortedSet[random_events.variable.Variable], result: probabilistic_model.probabilistic_circuit.rx.probabilistic_circuit.ProbabilisticCircuit, progress_bar: typing_extensions.Optional[tqdm.tqdm] = None) -> List[probabilistic_model.probabilistic_circuit.rx.probabilistic_circuit.Unit]

      Convert the layer to a networkx circuit.
      For every node in this circuit, a corresponding node in the networkx circuit
      is created.
      The nodes all belong to the same circuit.

      :param variables: The variables of the circuit.
      :param result: The resulting circuit to write into
      :param progress_bar: A progress bar to show the progress.

      :return: The nodes of the networkx circuit.



.. py:class:: NXConverterLayer

   Class used for conversion from a probabilistic circuit in networkx to a layered circuit in jax.


   .. py:attribute:: layer
      :type:  Layer


   .. py:attribute:: nodes
      :type:  typing_extensions.List[probabilistic_model.probabilistic_circuit.rx.probabilistic_circuit.Unit]


   .. py:attribute:: hash_remap
      :type:  typing_extensions.Dict[int, int]


.. py:class:: ContinuousLayerWithFiniteSupport(variable: int, interval: jax.Array)

   Bases: :py:obj:`ContinuousLayer`, :py:obj:`abc.ABC`


   Abstract class for continuous univariate input units with finite support.


   .. py:attribute:: interval
      :type:  jax.Array

      The interval of the distribution as a array of shape (num_nodes, 2).
      The first column contains the lower bounds and the second column the upper bounds.
      The intervals are treated as open intervals (>/< comparator).



   .. py:property:: lower
      :type: jax.Array



   .. py:property:: upper
      :type: jax.Array



   .. py:method:: left_included_condition(x: jax.Array) -> jax.Array

      Check if x is included in the left bound of the intervals.
      :param x: The data
      :return: A boolean array of shape (#x, #nodes)



   .. py:method:: right_included_condition(x: jax.Array) -> jax.Array

      Check if x is included in the right bound of the intervals.
      :param x: The data
      :return: A boolean array of shape (#x, #nodes)



   .. py:method:: included_condition(x: jax.Array) -> jax.Array

      Check if x is included in the interval.
      :param x: The data
      :return: A boolean array of shape (#x, #nodes)



   .. py:method:: to_json() -> Dict[str, Any]


   .. py:method:: __deepcopy__(memo=None)

      Create a deep copy of the layer.

      :param memo: A dictionary that is used to keep track of objects that have already been copied.



.. py:function:: simple_interval_to_open_array(interval: random_events.interval.SimpleInterval) -> jax.numpy.array

.. py:class:: Unit

   Bases: :py:obj:`random_events.utils.SubclassJSONSerializer`, :py:obj:`probabilistic_model.interfaces.drawio.drawio.DrawIOInterface`, :py:obj:`abc.ABC`


   Class for all units of a probabilistic circuit.

   This class should not be used by users directly.
   Use :class:`ProbabilisticCircuit` as interface to users.


   .. py:attribute:: probabilistic_circuit
      :type:  typing_extensions.Optional[ProbabilisticCircuit]
      :value: None


      The circuit this component is part of. 



   .. py:attribute:: result_of_current_query
      :type:  typing_extensions.Any
      :value: None


      The result of the current query. 



   .. py:attribute:: index
      :type:  typing_extensions.Optional[int]
      :value: None


      The index of the node in the graph of its circuit.



   .. py:method:: __post_init__()


   .. py:property:: subcircuits
      :type: typing_extensions.List[Unit]


      :return: The subcircuits of this unit.



   .. py:property:: parents
      :type: typing_extensions.List[InnerUnit]


      :return: The parents of this unit.



   .. py:method:: support()
      :abstractmethod:


      Calculate the support of this unit.



   .. py:property:: is_leaf
      :abstractmethod:


      :return: If this unit is a leaf unit.



   .. py:property:: variables
      :type: sortedcontainers.SortedSet

      :abstractmethod:



   .. py:property:: leaves
      :type: typing_extensions.List[LeafUnit]


      :return: The leaves of the circuit that are descendants of this node.



   .. py:method:: update_variables(new_variables: random_events.product_algebra.VariableMap)

      Update the variables of this unit and its descendants.

      :param new_variables: A map that maps the variables that should be replaced to their new variable.



   .. py:method:: connect_incoming_edges_to(other: Unit)

      Connect all incoming edges to this unit to another unit.

      :param other: The other unit to connect the incoming edges to.



   .. py:method:: filter_variable_map_by_self(variable_map: random_events.product_algebra.VariableMap)

      Filter a variable map by the variables of this unit.

      :param variable_map: The map to filter
      :return: The map filtered by the variables of this unit.



   .. py:property:: impossible_condition_result
      :type: typing_extensions.Tuple[typing_extensions.Optional[Unit], float]


      :return: The result of an impossible truncated query.



   .. py:method:: log_mode()
      :abstractmethod:



   .. py:method:: __hash__()


   .. py:method:: copy_without_graph()


   .. py:method:: empty_copy() -> typing_extensions.Self

      Creat a copy of this circuit without any subcircuits. Only the parameters should be copied.
      This is used whenever a new circuit has to be created during inference.

      :return: A copy of this circuit without any subcircuits that is not in this units graph.



   .. py:method:: simplify()
      :abstractmethod:


      Simplify the circuit by removing nodes and redirected edges that have no impact in-place.
      Essentially, this method transforms the circuit into an alternating order of sum and product units.

      :return: The simplified circuit.



   .. py:method:: sample(*args, **kwargs)
      :abstractmethod:


      Draw samples from the circuit.

      For sampling, a node gets requested a number of samples from all his parents.
      The parents write into the `result_of_current_query` attribute a tuple describing the beginning index of the
      sampling and how many samples are requested.



   .. py:method:: marginal(*args, **kwargs) -> typing_extensions.Optional[typing_extensions.Self]
      :abstractmethod:


      Remove nodes that are not part of the marginal distribution.



   .. py:method:: moment(*args, **kwargs)
      :abstractmethod:



   .. py:property:: drawio_style
      :type: typing_extensions.Dict[str, typing_extensions.Any]


      The style of the object.



.. py:class:: NXProbabilisticCircuit

   Bases: :py:obj:`probabilistic_model.probabilistic_model.ProbabilisticModel`, :py:obj:`random_events.utils.SubclassJSONSerializer`


   Probabilistic Circuits as a directed, rooted, acyclic graph.

   The nodes of the graph are the units of the circuit.
   The edges of the graph indicate how the units are connected.
   The outgoing edges of a sum unit contain the log-log_weights of the subcircuits.


   .. py:attribute:: graph
      :type:  rustworkx.PyDAG[Unit]

      The graph to check connectivity from.



   .. py:method:: __len__()

      Return the number of nodes in the graph.

      :return: The number of nodes in the graph.



   .. py:method:: __iter__()

      Return an iterator over the nodes in the graph.

      :return: An iterator over the nodes in the graph.



   .. py:method:: from_other(other: typing_extensions.Self) -> typing_extensions.Self
      :classmethod:



   .. py:property:: variables
      :type: sortedcontainers.SortedSet


      :return: The variables of the model.



   .. py:property:: variable_to_index_map
      :type: typing_extensions.Dict[random_events.variable.Variable, int]



   .. py:property:: layers
      :type: typing_extensions.List[typing_extensions.List[Unit]]



   .. py:property:: leaves
      :type: typing_extensions.List[LeafUnit]



   .. py:method:: is_valid() -> bool

      Check if this graph is:

      - acyclic
      - connected

      :return: True if the graph is valid, False otherwise.



   .. py:method:: add_node(node: Unit)


   .. py:method:: add_nodes_from(units: typing_extensions.Iterable[Unit])


   .. py:method:: add_edge(parent: Unit, child: Unit, log_weight: typing_extensions.Optional[float] = None)


   .. py:method:: add_edges_from(edges: typing_extensions.Iterable[typing_extensions.Union[typing_extensions.Tuple[Unit, Unit], typing_extensions.Tuple[Unit, Unit, float]]])


   .. py:method:: successors(unit: Unit) -> typing_extensions.List[Unit]


   .. py:method:: descendants(unit: Unit) -> random_events.set.Set[Unit]


   .. py:method:: predecessors(unit: Unit) -> typing_extensions.List[InnerUnit]


   .. py:method:: remove_node(unit: Unit)


   .. py:method:: remove_nodes_from(units: typing_extensions.Iterable[Unit])


   .. py:method:: remove_edge(parent: Unit, child: Unit)


   .. py:method:: remove_edges_from(edges: typing_extensions.Iterable[typing_extensions.Tuple[Unit, Unit]])


   .. py:method:: in_edges(unit: Unit) -> typing_extensions.List[typing_extensions.Tuple[Unit, Unit, typing_extensions.Optional[float]]]


   .. py:method:: add_from_subgraph(subgraph: rustworkx.PyDAG[Unit]) -> typing_extensions.Dict[int, Unit]

      Add nodes and edges from a subgraph to this circuit.

      :param subgraph: The subgraph to add nodes from.
      :return: A dictionary mapping the node indices in the subgraph to the new units in this circuit.



   .. py:method:: nodes() -> typing_extensions.List[Unit]

      Return an iterator over the nodes.

      :return: An iterator over the nodes.



   .. py:method:: edges() -> typing_extensions.List[typing_extensions.Tuple[Unit, Unit, typing_extensions.Optional[float]]]


   .. py:method:: in_degree(unit: Unit)


   .. py:method:: has_edge(parent: Unit, child: Unit) -> bool


   .. py:property:: root
      :type: Unit


      The root of the circuit is the node with in-degree 0.
      This is the output node, that will perform the final computation.

      :return: The root of the circuit.



   .. py:method:: log_likelihood(events: numpy.array) -> numpy.array

      Calculate the log-likelihood of an event.

      Check the documentation of `likelihood` for more information.

      :param events: The full evidence event with shape (#events, #variables)
      :return: The log-likelihood of the event with shape (#events).



   .. py:method:: cdf(events: numpy.array) -> numpy.array

      Calculate the cumulative distribution function of an event-array.

      The event belongs to the class of full evidence queries.

      ..Note:: The cdf only exists if all variables are continuous or integers.

      :param events: The array of full evidence events.
                     The shape of the array has to be (n, len(self.variables)).
      :return: The cumulative distribution function of the event as an array of shape (n,).



   .. py:method:: probability_of_simple_event(event: random_events.product_algebra.SimpleEvent) -> float

      Calculate the probability of a simple event.

      The event belongs to the class of marginal queries.

      .. Note:: You can read more about queries of this class in Definition 11 in :cite:p:`choi2020probabilistic`
          or watch the `video tutorial <https://youtu.be/2RAG5-L9R70?si=8aEGIqmoDTiUR2u6&t=1089>`_.
          :cite:p:`youtube2020probabilistic`

      :param event: The event.
      :return: The probability of the event.



   .. py:method:: log_mode(check_determinism: bool = True) -> typing_extensions.Tuple[random_events.product_algebra.Event, float]

      Calculate the mode of the model.

      Check the documentation of `mode` for more information.

      :return: The mode and its log-likelihood.



   .. py:method:: remove_unreachable_nodes(root: Unit)

      Remove all nodes that are not reachable from the root.



   .. py:method:: log_truncated_of_simple_event_in_place(simple_event: random_events.product_algebra.SimpleEvent) -> typing_extensions.Tuple[typing_extensions.Optional[typing_extensions.Self], float]

      Construct the truncated circuit from a simple event.

      :param simple_event: The simple event to condition on.
      :return: The truncated circuit and the log-probability of the event



   .. py:method:: log_truncated_in_place(event: random_events.product_algebra.Event) -> typing_extensions.Tuple[typing_extensions.Optional[typing_extensions.Self], float]

      Efficiently compute the truncated for an Event, batching as much as possible.



   .. py:method:: log_truncated(event: random_events.product_algebra.Event) -> typing_extensions.Tuple[typing_extensions.Optional[typing_extensions.Self], float]

      Calculate the truncated distribution P(*| event) and the probability of the event.

      Check the documentation of `truncated` for more information.

      :param event: The event to condition on.
      :return: The truncated distribution and the log-probability of the event.



   .. py:method:: marginal_in_place(variables: typing_extensions.Iterable[random_events.variable.Variable]) -> typing_extensions.Optional[typing_extensions.Self]


   .. py:method:: log_conditional_in_place(point: typing_extensions.Dict[random_events.variable.Variable, typing_extensions.Any]) -> typing_extensions.Tuple[typing_extensions.Optional[typing_extensions.Self], float]


   .. py:method:: log_conditional(point: typing_extensions.Dict[random_events.variable.Variable, typing_extensions.Any]) -> typing_extensions.Tuple[typing_extensions.Optional[typing_extensions.Self], float]

      Calculate the truncated distribution P(*| point) and the probability of the event.
      Check the documentation of `conditional` for more information.

      :param point: A partial point to calculate the truncated distribution on.
      :return: The truncated distribution and the log-probability of the point.



   .. py:method:: marginal(variables: typing_extensions.Iterable[random_events.variable.Variable]) -> typing_extensions.Optional[typing_extensions.Self]

      Calculate the marginal distribution of a set of variables.

      :param variables: The variables to calculate the marginal distribution on.
      :return: The marginal distribution over the variables.



   .. py:method:: sample(amount: int) -> numpy.array

      Sample from the model.

      :param amount: The number of samples to draw.
      :return: The samples.



   .. py:method:: moment(order: probabilistic_model.probabilistic_model.OrderType, center: probabilistic_model.probabilistic_model.CenterType) -> probabilistic_model.probabilistic_model.MomentType

      Calculate the (centralized) moment of the distribution.

      .. math::

          \int_{-\infty}^{\infty} (x - center)^{order} pdf(x) dx

      .. Note:: You can read more about queries of this class in Definition 22 in :cite:p:`choi2020probabilistic`_.
          :cite:p:`youtube2020probabilistic`


      :param order: The orders of the moment as a variable map for every continuous and integer variable.
      :param center: The center of the moment as a variable map for every continuous and integer variable.
      :return: The moments of the variables in `order`.



   .. py:method:: simplify() -> typing_extensions.Self

      Simplify the circuit inplace.



   .. py:property:: support
      :type: random_events.product_algebra.Event


      :return: The support of the model.



   .. py:method:: is_decomposable() -> bool

      Check if the whole circuit is decomposed.

      A circuit is decomposed if all its product units are decomposed.

      :return: if the whole circuit is decomposed



   .. py:method:: __eq__(other: typing_extensions.Self)
      :abstractmethod:



   .. py:method:: empty_copy() -> typing_extensions.Self

      Create a copy of this circuit without any nodes.
      Only the parameters should be copied.
      This is used whenever a new circuit has to be created during inference.

      :return: A copy of this circuit without any subcircuits that is not in this units graph.



   .. py:method:: __deepcopy__(memo=None) -> typing_extensions.Self

      Deep copy of the circuit.

      :param memo: A dictionary that is used to keep track of objects that have already been copied.
      :return: A deep copy of the circuit.



   .. py:method:: to_json() -> typing_extensions.Dict[str, typing_extensions.Any]


   .. py:method:: parameters_from_json(data: typing_extensions.Dict[str, typing_extensions.Any]) -> typing_extensions.Self
      :classmethod:



   .. py:method:: _from_json(data: typing_extensions.Dict[str, typing_extensions.Any]) -> typing_extensions.Self
      :classmethod:


      Create a variable from a json dict.
      This method is called from the from_json method after the correct subclass is determined and should be
      overwritten by the respective subclass.

      :param data: The json dict
      :return: The deserialized object



   .. py:method:: update_variables(new_variables: random_events.product_algebra.VariableMap)

      Update the variables of this unit and its descendants.

      :param new_variables: The new variables to set.



   .. py:method:: is_deterministic() -> bool

      :return: Whether, this circuit is deterministic or not.



   .. py:method:: normalize()

      Normalize every sum node of this circuit in-place.



   .. py:method:: add_edges_and_nodes_from_circuit(other: typing_extensions.Self)

      Add all edges and nodes from another circuit to this circuit.

      :param other: The other circuit to add.



   .. py:method:: add_weighted_edges_from(ebunch_to_add, weight='log_weight', **attr)


   .. py:method:: subgraph_of(node: Unit) -> typing_extensions.Self

      Create a subgraph with a node as root.

      :param node: The root of the subgraph.
      :return: The subgraph.



   .. py:method:: fill_node_colors(node_colors: typing_extensions.Dict[Unit, str])

      Fill the node colors for the structure plot.

      :param node_colors: The node colors to fill.



   .. py:method:: bfs_layout(scale: float = 1.0, align: PlotAlignment = PlotAlignment.VERTICAL) -> typing_extensions.Dict[int, numpy.array]

      Generate a bfs layout for this circuit.

      :return: A dict mapping the node indices to 2d coordinates.



   .. py:method:: plot_structure(node_colors: typing_extensions.Optional[typing_extensions.Dict[Unit, str]] = None, variable_name_offset=0.2, plot_inference=False, inference_representation: typing_extensions.Callable = lambda node: str(node.result_of_current_query), inference_result_offset: float = -0.25)

      Plot the structure of the circuit using matplotlib.

      :param node_colors: Optionally specified colors of the node.
      If nodes are not specified in the dictionary, they will be black.
      :param node_size: The size of the nodes
      :param variable_name_offset: The offset to the right of the variable names.
      :param plot_inference: If the results of the inference should be plotted.
      :param inference_representation: The representation of the inference results as a function from node to string.
      :param inference_result_offset: The vertical offset of the inference results.



   .. py:method:: nodes_weights() -> dict

      :return: dict with keys as nodes and values as list of all the log_weights for the node.



   .. py:method:: replace_discrete_distribution_with_deterministic_sum()

      splits the distribution into sum unit with all the discrete possibilities as leaf.



   .. py:method:: translate(translation: typing_extensions.Dict[random_events.variable.Variable, float])

      Translate the model in-place.
      Translation is done by adding the translation to the variable location influencing values.
      The translation can be viewed as what happens
      when you shift the numeric variables of the model by a constant vector.

      :param translation: The variable value pairs to translate the model by.



   .. py:method:: scale(scale: typing_extensions.Dict[random_events.variable.Variable, float])

      Scale the model in-place.
      Scaling is done by multiplying the variable location influencing values.
      The scaling can be viewed as what happens
      when you multiply the numeric variables of the model by a constant vector.

      :param scaling: The variable value pairs to scale the model by.



   .. py:method:: mount(other: Unit) -> typing_extensions.Dict[int, Unit]

      Mount another unit including its descendants. There will be no edge from `self` to `other`.
      This will also remove the nodes in other and their descendants from their circuit.

      :param other: The other unit to mount.



   .. py:method:: __repr__()


.. py:class:: UnivariateContinuousLeaf

   Bases: :py:obj:`UnivariateLeaf`


   Class for Leaf units.


   .. py:attribute:: distribution
      :type:  typing_extensions.Optional[probabilistic_model.distributions.ContinuousDistribution]

      The distribution contained in this leaf unit.



   .. py:attribute:: __hash__


   .. py:method:: log_truncated_of_simple_event_in_place(event: random_events.product_algebra.SimpleEvent)


   .. py:method:: univariate_log_truncated_of_simple_event_in_place(event: random_events.interval.Interval)

      Condition this distribution on a simple event in-place but use sum units to create conditions on composite
      intervals.
      :param event: The simple event to condition on.



.. py:class:: UniformDistribution(variable: probabilistic_model.distributions.distributions.Continuous, interval: probabilistic_model.distributions.distributions.SimpleInterval)

   Bases: :py:obj:`probabilistic_model.distributions.distributions.ContinuousDistributionWithFiniteSupport`


   Class for uniform distributions over the half-open interval [lower, upper).


   .. py:attribute:: variable


   .. py:attribute:: interval

      The interval of the distribution.



   .. py:method:: log_likelihood_without_bounds_check(x: probabilistic_model.distributions.distributions.np.array) -> probabilistic_model.distributions.distributions.np.array

      Evaluate the logarithmic likelihood function at `x` without checking the inclusion into the interval.
      :param x: x where p(x) > 0
      :return: log(p(x))



   .. py:method:: cdf(x: probabilistic_model.distributions.distributions.np.array) -> probabilistic_model.distributions.distributions.np.array

      Calculate the cumulative distribution function at x.
      :param x: The data
      :return: The cumulative distribution function at x



   .. py:method:: univariate_log_mode() -> probabilistic_model.distributions.distributions.Tuple[probabilistic_model.distributions.distributions.AbstractCompositeSet, float]

      :return: The univariate mode of the distribution and its log-likelihood. The mode is not an Event.



   .. py:method:: log_conditional_from_simple_interval(interval: probabilistic_model.distributions.distributions.SimpleInterval) -> probabilistic_model.distributions.distributions.Tuple[probabilistic_model.distributions.distributions.Self, float]

      Calculate the truncated distribution given a simple interval.

      :param interval: The simple interval
      :return: The truncated distribution and the log-probability of the interval.



   .. py:method:: sample(amount: int) -> probabilistic_model.distributions.distributions.np.array

      Sample from the model.

      :param amount: The number of samples to draw.
      :return: The samples.



   .. py:method:: pdf_value() -> float

      Calculate the density of the uniform distribution.



   .. py:method:: log_pdf_value() -> float

      Calculate the log-density of the uniform distribution.



   .. py:method:: moment(order: probabilistic_model.distributions.distributions.OrderType, center: probabilistic_model.distributions.distributions.CenterType) -> probabilistic_model.distributions.distributions.MomentType

      Calculate the (centralized) moment of the distribution.

      .. math::

          \int_{-\infty}^{\infty} (x - center)^{order} pdf(x) dx

      .. Note:: You can read more about queries of this class in Definition 22 in :cite:p:`choi2020probabilistic`_.
          :cite:p:`youtube2020probabilistic`


      :param order: The orders of the moment as a variable map for every continuous and integer variable.
      :param center: The center of the moment as a variable map for every continuous and integer variable.
      :return: The moments of the variables in `order`.



   .. py:method:: __eq__(other)


   .. py:property:: drawio_label

      The label of the object as a drawio compatible string.



   .. py:property:: representation

      The symbol used to represent this distribution.



   .. py:property:: abbreviated_symbol
      :type: str



   .. py:method:: __repr__()


   .. py:property:: image


   .. py:method:: __copy__()


   .. py:method:: __deepcopy__(memo=None)


   .. py:method:: to_json() -> probabilistic_model.distributions.distributions.Dict[str, probabilistic_model.distributions.distributions.Any]


   .. py:method:: _from_json(data: probabilistic_model.distributions.distributions.Dict[str, probabilistic_model.distributions.distributions.Any]) -> probabilistic_model.distributions.distributions.Self
      :classmethod:


      Create a variable from a json dict.
      This method is called from the from_json method after the correct subclass is determined and should be
      overwritten by the respective subclass.

      :param data: The json dict
      :return: The deserialized object



   .. py:method:: x_axis_points_for_plotly() -> probabilistic_model.distributions.distributions.List[probabilistic_model.distributions.distributions.Union[None, float]]


   .. py:method:: pdf_trace() -> probabilistic_model.distributions.distributions.go.Scatter


   .. py:method:: cdf_trace() -> probabilistic_model.distributions.distributions.go.Scatter


   .. py:method:: plot(**kwargs) -> probabilistic_model.distributions.distributions.List

      Generate traces that can be plotted with plotly.

      :param number_of_samples: The number of samples to draw.
      :param surface: If True, plot the model as a surface plot.
      :param mode: If True, plot the mode of the model.
      :return: The traces.



   .. py:method:: __hash__()


.. py:class:: UniformLayer(variable: int, interval: jax.Array)

   Bases: :py:obj:`probabilistic_model.probabilistic_circuit.jax.input_layer.ContinuousLayerWithFiniteSupport`


   A layer that represents uniform distributions over a single variable.


   .. py:method:: nx_classes() -> typing_extensions.Tuple[typing_extensions.Type, Ellipsis]
      :classmethod:


      :return: The tuple of matching classes of the layer in the probabilistic_model.probabilistic_circuit.rx package.



   .. py:method:: validate()

      Validate the parameters and their layouts.



   .. py:property:: number_of_nodes
      :type: int


      :return: The number of nodes in the layer.



   .. py:method:: log_pdf_value() -> jax.numpy.array

      Calculate the log-density of the uniform distribution.



   .. py:method:: log_likelihood_of_nodes_single(x: jax.numpy.array) -> jax.numpy.array

      Calculate the log-likelihood of the distribution.

      :param x: The input vector.
      :return: The log-likelihood of every node in the layer for x.



   .. py:method:: log_likelihood_of_nodes(x: jax.numpy.array) -> jax.numpy.array

      Vectorized version of :meth:`log_likelihood_of_nodes_single`



   .. py:method:: create_layer_from_nodes_with_same_type_and_scope(nodes: List[probabilistic_model.probabilistic_circuit.rx.probabilistic_circuit.UnivariateContinuousLeaf], child_layers: List[probabilistic_model.probabilistic_circuit.jax.inner_layer.NXConverterLayer], progress_bar: bool = True) -> probabilistic_model.probabilistic_circuit.jax.inner_layer.NXConverterLayer
      :classmethod:


      Create a layer from a list of nodes with the same type and scope.



   .. py:method:: _from_json(data: Dict[str, Any]) -> typing_extensions.Self
      :classmethod:


      Create a variable from a json dict.
      This method is called from the from_json method after the correct subclass is determined and should be
      overwritten by the respective subclass.

      :param data: The json dict
      :return: The deserialized object



   .. py:method:: to_nx(variables: sortedcontainers.SortedSet[random_events.variable.Variable], result: probabilistic_model.probabilistic_circuit.rx.probabilistic_circuit.ProbabilisticCircuit, progress_bar: Optional[tqdm.tqdm] = None) -> List[probabilistic_model.probabilistic_circuit.rx.probabilistic_circuit.Unit]

      Convert the layer to a networkx circuit.
      For every node in this circuit, a corresponding node in the networkx circuit
      is created.
      The nodes all belong to the same circuit.

      :param variables: The variables of the circuit.
      :param result: The resulting circuit to write into
      :param progress_bar: A progress bar to show the progress.

      :return: The nodes of the networkx circuit.



