
    ph\                         S r SSKrSSKrSSKJr  SSKJrJr  SSK	J
r
  SSKJrJr  \R                   " S S	5      5       rSS
 jrS rg)zl
Represents a node in a network. Each node has a unique index, its position in
the network's list of nodes.
    N   )utils)get_inputs_from_cmget_outputs_from_cm)
NodeLabels)marginalize_outtpm_indicesc                       \ rS rSrSrS r\S 5       r\S 5       r\S 5       r	\S 5       r
\S 5       rS	 rS
 rS rS rS rS rS rSrg)Node   a  A node in a subsystem.

Args:
    tpm (np.ndarray): The TPM of the subsystem.
    cm (np.ndarray): The CM of the subsystem.
    index (int): The node's index in the network.
    state (int): The state of this node.
    node_labels (|NodeLabels|): Labels for these nodes.

Attributes:
    tpm (np.ndarray): The node TPM is an array with shape ``(2,)*(n + 1)``,
        where ``n`` is the size of the |Network|. The first ``n``
        dimensions correspond to each node in the system. Dimensions
        corresponding to nodes that provide input to this node are of size
        2, while those that do not correspond to inputs are of size 1, so
        that the TPM has |2^m x 2| elements where |m| is the number of
        inputs. The last dimension corresponds to the state of the node in
        the next timestep, so that ``node.tpm[..., 0]`` gives probabilities
        that the node will be 'OFF' and ``node.tpm[..., 1]`` gives
        probabilities that the node will be 'ON'.
c                 T   X0l         X@l        XPl        [        [	        U R                   U5      5      U l        [        [        U R                   U5      5      U l        USU R                   4   n[        [        U5      5      U R
                  -
  n[        Xv5      nSU-
  n[        R                  " X/SS9U l        [        R                  " U R                  5        [!        U[        R"                  " U R                  5      U R                  U R
                  U R                  45      U l        g )N.r   )axis)indexstatenode_labels	frozensetr   _inputsr   _outputssetr	   r   npstacktpmr   np_immutablehashnp_hash_hash)	selfr   cmr   r   r   tpm_on
non_inputstpm_offs	            D/home/james-whalen/.local/lib/python3.13/site-packages/pyphi/node.py__init__Node.__init__-   s     
 
 ' !!3DJJ!CD!"5djj""EF S$**_% S)*T\\9
 4 f* 88W-B7 	488$ 5%--"94::<<8 9
    c                      U R                   S   $ )z=The TPM of this node containing only the 'OFF' probabilities.).r   r   r   s    r#   r"   Node.tpm_off^        xxr&   c                      U R                   S   $ )z<The TPM of this node containing only the 'ON' probabilities.).r   r(   r)   s    r#   r    Node.tpm_onc   r+   r&   c                     U R                   $ )z/The set of nodes with connections to this node.)r   r)   s    r#   inputsNode.inputsh   s     ||r&   c                     U R                   $ )z.The set of nodes this node has connections to.)r   r)   s    r#   outputsNode.outputsm   s     }}r&   c                 4    U R                   U R                     $ )z The textual label for this node.)r   r   r)   s    r#   label
Node.labelr   s     

++r&   c                     U R                   $ N)r5   r)   s    r#   __repr__Node.__repr__w       zzr&   c                 "    U R                  5       $ r8   )r9   r)   s    r#   __str__Node.__str__z   s    }}r&   c                 X   U R                   UR                   :H  =(       a    [        R                  " U R                  UR                  5      =(       aY    U R                  UR                  :H  =(       a9    U R
                  UR
                  :H  =(       a    U R                  UR                  :H  $ )a/  Return whether this node equals the other object.

Two nodes are equal if they belong to the same subsystem and have the
same index (their TPMs must be the same in that case, so this method
doesn't need to check TPM equality).

Labels are for display only, so two equal nodes may have different
labels.
)r   r   array_equalr   r   r/   r2   r   others     r#   __eq__Node.__eq__}   sw     

ekk) .txx3.

ekk). u||+. -		/r&   c                 .    U R                  U5      (       + $ r8   )rC   rA   s     r#   __ne__Node.__ne__   s    ;;u%%%r&   c                 4    U R                   UR                   :  $ r8   r   rA   s     r#   __lt__Node.__lt__   s    zzEKK''r&   c                     U R                   $ r8   )r   r)   s    r#   __hash__Node.__hash__   r;   r&   c                     U R                   $ )z*Return a JSON-serializable representation.rI   r)   s    r#   to_jsonNode.to_json   s    zzr&   )r   r   r   r   r   r   r   N)__name__
__module____qualname____firstlineno____doc__r$   propertyr"   r    r/   r2   r5   r9   r=   rC   rF   rJ   rM   rP   __static_attributes__ r&   r#   r   r      s    ,/9b             , ,/ &(r&   r   c                    ^ ^^ Tc  [        SU5      m[        R                  " X25      n[        UUU 4S j[	        X55       5       5      $ )aq  Generate |Node| objects for a subsystem.

Args:
    tpm (np.ndarray): The system's TPM
    cm (np.ndarray): The corresponding CM.
    network_state (tuple): The state of the network.
    indices (tuple[int]): Indices to generate nodes for.

Keyword Args:
    node_labels (|NodeLabels|): Textual labels for each node.

Returns:
    tuple[Node]: The nodes of the system.
Nc              3   D   >#    U  H  u  p[        TTXT5      v   M     g 7fr8   )r   ).0r   r   r   r   r   s      r#   	<genexpr>!generate_nodes.<locals>.<genexpr>   s(      ?%=\U c2u[99%=s    )r   r   state_oftuplezip)r   r   network_stateindicesr   
node_states   ``  ` r#   generate_nodesre      sD      w/7J ?%(%=? ? ?r&   c                 v    [         R                  " U R                   Vs/ s H  nSPM     sn5      nX -  $ s  snf )a
  Broadcast a node TPM over the full network.

This is different from broadcasting the TPM of a full system since the last
dimension (containing the state of the node) contains only the probability
of *this* node being on, rather than the probabilities for each node.
   )r   onesshape)r   nodeucs      r#   expand_node_tpmrl      s1     
		*	!	*	+B8O +s   6r8   )rV   	functoolsnumpyr    r   connectivityr   r   labelsr   r   r   r	   total_orderingr   re   rl   rY   r&   r#   <module>rs      sK   

    A  - C C CL?0r&   