
    ph%              	       B   S r SSKrSSKJr  SSKrSSKJrJr  SSKJ	r	J
r
   " S S	5      r " S
 S\5      r " S S\5      r " S S\5      r " S S\5      r " S S\R                   " SSS/5      5      r " S S\R$                  5      r " S S\5      r " S S\5      rg)z3Objects that represent partitions of sets of nodes.    N)chain   )cmpfmt   )connectivityutilsc                   V    \ rS rSrSr\S 5       rS r\S 5       rS r	S r
S rS	 rS
rg)_CutBase   zBase class for all unidirectional system cuts.

Concrete cut classes must implement a ``cut_matrix`` method and an
``indices`` property. See ``Cut`` for a concrete example.
c                     [         ezIndices of this cut.NotImplementedErrorselfs    K/home/james-whalen/.local/lib/python3.13/site-packages/pyphi/models/cuts.pyindices_CutBase.indices   s
     "!    c                     [         e)a  Return the cut matrix for this cut.

The cut matrix is a square matrix representing  connections severed
by the cut: if the connection from node `a` to node `b` is cut,
`cut_matrix[a, b]` is `1`; otherwise it is `0`.

Args:
   n (int): The size of the network.
r   r   ns     r   
cut_matrix_CutBase.cut_matrix   s
     "!r   c                     g)zDIs this cut a null cut?

All concrete cuts should return ``False``.
F r   s    r   is_null_CutBase.is_null(   s     r   c                     [         R                  " U R                  UR                  S   5      5      R	                  [
        5      nX-  $ )zReturn a modified connectivity matrix with all connections that are
severed by this cut removed.

Args:
    cm (np.ndarray): A connectivity matrix.
r   )nplogical_notr   shapeastypeint)r   cminverses      r   	apply_cut_CutBase.apply_cut0   s6     ..!!=>EEcJ|r   c                     [        U R                  5      S-   nU R                  U5      [        R                  " X5         R                  5       $ )zCheck if this cut severs any connections from ``a`` to ``b``.

Args:
    a (tuple[int]): A set of nodes.
    b (tuple[int]): A set of nodes.
r   )maxr   r   r!   ix_any)r   abr   s       r   cuts_connections_CutBase.cuts_connections;   s<     !q!"&&,/3355r   c                 $    U R                  X5      $ )zCheck if this cut splits a mechanism.

Args:
    mechanism (tuple[int]): The mechanism in question.

Returns:
    bool: ``True`` if `mechanism` has elements on both sides of the
    cut; ``False`` otherwise.
)r0   r   	mechanisms     r   splits_mechanism_CutBase.splits_mechanismE   s     $$Y::r   c              #      #    [         R                  " U R                  SS9 H  nU R                  U5      (       d  M  Uv   M!     g7f)zpReturn all mechanisms with elements on both sides of this cut.

Yields:
    tuple[int]: The next cut mechanism.
T)nonemptyN)r	   powersetr   r5   r3   s     r   all_cut_mechanisms_CutBase.all_cut_mechanismsQ   s7      tDI$$Y// Es
   7A	Ar   N)__name__
__module____qualname____firstlineno____doc__propertyr   r   r   r(   r0   r5   r:   __static_attributes__r   r   r   r   r      sH     " "
"  	6
; r   r   c                       \ rS rSrSrSS jr\S 5       r\S 5       rS r	S r
S	 rS
 r\R                  S 5       rS rSrg)NullCut\   zThe cut that does nothing.Nc                     Xl         X l        g N_indicesnode_labels)r   r   rJ   s      r   __init__NullCut.__init___   s    &r   c                     g)z/This is the only cut where ``is_null == True``.Tr   r   s    r   r   NullCut.is_nullc   s     r   c                     U R                   $ )zIndices of the cut.)rI   r   s    r   r   NullCut.indicesh   s     }}r   c                 0    [         R                  " X45      $ )zReturn a matrix of zeros.)r!   zerosr   s     r   r   NullCut.cut_matrixm   s    xxr   c                     SU R                   0$ Nr   r   r   s    r   to_jsonNullCut.to_jsonq   s    4<<((r   c                 2    [         R                  " U S/5      $ rU   r   	make_reprr   s    r   __repr__NullCut.__repr__t   s    }}TI;//r   c                 8    SR                  U R                  5      $ )NzNullCut({}))formatr   r   s    r   __str__NullCut.__str__w   s    ##DLL11r   c                 4    U R                   UR                   :H  $ rG   rV   r   others     r   __eq__NullCut.__eq__z   s    ||u}},,r   c                 ,    [        U R                  5      $ rG   )hashr   r   s    r   __hash__NullCut.__hash__~   s    DLL!!r   rH   rG   )r<   r=   r>   r?   r@   rK   rA   r   r   r   rW   r\   r`   r   sametypere   ri   rB   r   r   r   rD   rD   \   sc    $'     )02 	\\- -"r   rD   c                   x    \ rS rSrSrSrSS jr\S 5       rS r	\
R                  S 5       rS	 rS
 rS rS rSrg)Cut   a  Represents a unidirectional cut.

Attributes:
    from_nodes (tuple[int]): Connections from this group of nodes to those
        in ``to_nodes`` are from_nodes.
    to_nodes (tuple[int]): Connections to this group of nodes from those in
        ``from_nodes`` are from_nodes.

from_nodesto_nodesrJ   Nc                 (    Xl         X l        X0l        g rG   ro   )r   rp   rq   rJ   s       r   rK   Cut.__init__   s    $ &r   c                 j    [        [        [        U R                  U R                  -   5      5      5      $ r   )tuplesortedsetrp   rq   r   s    r   r   Cut.indices   s&     VC$-- ?@ABBr   c                 X    [         R                  " XR                  U R                  5      $ )a3  Compute the cut matrix for this cut.

The cut matrix is a square matrix which represents connections severed
by the cut.

Args:
   n (int): The size of the network.

Example:
    >>> cut = Cut((1,), (2,))
    >>> cut.cut_matrix(3)
    array([[0., 0., 0.],
           [0., 0., 1.],
           [0., 0., 0.]])
)r   relevant_connectionsrp   rq   r   s     r   r   Cut.cut_matrix   s&      00OO15@ 	@r   c                 t    U R                   UR                   :H  =(       a    U R                  UR                  :H  $ rG   rp   rq   rc   s     r   re   
Cut.__eq__   s.    5#3#33 0/	1r   c                 D    [        U R                  U R                  45      $ rG   )rh   rp   rq   r   s    r   ri   Cut.__hash__   s    T__dmm455r   c                 4    [         R                  " U SS/5      $ )Nrp   rq   rZ   r   s    r   r\   Cut.__repr__   s    }}TL*#=>>r   c                 .    [         R                  " U 5      $ rG   )r   fmt_cutr   s    r   r`   Cut.__str__   s    {{4  r   c                 4    U R                   U R                  S.$ )*Return a JSON-serializable representation.r}   r}   r   s    r   rW   Cut.to_json   s    "oo4==IIr   )rp   rJ   rq   rG   )r<   r=   r>   r?   r@   	__slots__rK   rA   r   r   r   rk   re   ri   r\   r`   rW   rB   r   r   r   rm   rm      s\     :I'
 C C@& 	\\1 16?!Jr   rm   c                   t    \ rS rSrSrSS jr\S 5       rS r\	R                  S 5       rS rS	 rS
 rS rSrg)KCut   zAA cut that severs all connections between parts of a K-partition.Nc                 (    Xl         X l        X0l        g rG   )	direction	partitionrJ   )r   r   r   rJ   s       r   rK   KCut.__init__   s    ""&r   c                     U R                   R                  U R                   R                  :X  d   eU R                   R                  $ rG   )r   r4   purviewr   s    r   r   KCut.indices   s4    ~~''4>>+A+AAAA~~'''r   c                 D   [         R                  " X45      nU R                   Hx  nU R                  R	                  UR
                  UR                  5      u  pE[        [        U R                  5      [        U5      -
  5      nSU[         R                  " XF5      '   Mz     U$ )z7The matrix of connections that are severed by this cut.r   )r!   rR   r   r   orderr4   r   ru   rw   r   r,   )r   r   r&   partfrom_toexternals          r   r   KCut.cut_matrix   sv    XXqfNND,,T^^T\\JIES.R89H*+Brvve&'	 # 	r   c                 t    U R                   UR                   :H  =(       a    U R                  UR                  :H  $ rG   )r   r   rc   s     r   re   KCut.__eq__   s,    %//1 2%//1	3r   c                 D    [        U R                  U R                  45      $ rG   )rh   r   r   r   s    r   ri   KCut.__hash__   s    T^^T^^455r   c                 4    [         R                  " U SS/5      $ )Nr   r   rZ   r   s    r   r\   KCut.__repr__   s    }}TK#=>>r   c                 .    [         R                  " U 5      $ rG   )r   fmt_kcutr   s    r   r`   KCut.__str__   s    ||D!!r   c                 4    U R                   U R                  S.$ )Nr   r   r   r   s    r   rW   KCut.to_json   s    !^^$..IIr   )r   rJ   r   rG   )r<   r=   r>   r?   r@   rK   rA   r   r   r   rk   re   ri   r\   r`   rW   rB   r   r   r   r   r      sP    K'
 ( (
 	\\3 36?"Jr   r   c                   (    \ rS rSrSr\S 5       rSrg)	ActualCut   z%Represents an cut for a |Transition|.c                     [        [        [        U R                  R                  U R                  R
                  -   5      5      5      $ rG   )ru   rv   rw   r   r4   r   r   s    r   r   ActualCut.indices   s;    VC 8 8 $ 6 6!7 8 9 : 	:r   r   N)r<   r=   r>   r?   r@   rA   r   rB   r   r   r   r   r      s    /: :r   r   c                   "    \ rS rSrSrSrS rSrg)Part   u  Represents one part of a |Bipartition|.

Attributes:
    mechanism (tuple[int]): The nodes in the mechanism for this part.
    purview (tuple[int]): The nodes in the mechanism for this part.

Example:
    When calculating |small_phi| of a 3-node subsystem, we partition the
    system in the following way::

        mechanism:  A,C    B
                    ─── ✕ ───
          purview:   B    A,C

    This class represents one term in the above product.
r   c                 4    U R                   U R                  S.$ )r   r4   r   r   r   s    r   rW   Part.to_json  s    !^^EEr   N)r<   r=   r>   r?   r@   r   rW   rB   r   r   r   r   r      s    " IFr   r   r4   r   c                       \ rS rSrSrSS/rSS.S jrS rS	 rS
 r	S r
S rS r\S 5       r\S 5       rS rS r\S 5       rSrg)
KPartitioni  z.A partition with an arbitrary number of parts.partsrJ   N)rJ   c                    X l         Xl        g rG   )r   rJ   )r   rJ   r   s      r   rK   KPartition.__init__  s    
&r   c                 ,    [        U R                  5      $ rG   )lenr   r   s    r   __len__KPartition.__len__  s    4::r   c                      U R                   U   $ rG   )r   )r   indexs     r   __getitem__KPartition.__getitem__  s    zz%  r   c                 j    [        U[        5      (       d  [        $ U R                  UR                  :H  $ rG   )
isinstancer   NotImplementedr   rc   s     r   re   KPartition.__eq__  s(    %,,!!zzU[[((r   c                 ,    [        U R                  5      $ rG   )rh   r   r   s    r   ri   KPartition.__hash__!  s    DJJr   c                 .    [         R                  " U 5      $ rG   )r   fmt_partitionr   s    r   r`   KPartition.__str__$  s      &&r   c                 4    [         R                  " U SS/5      $ )Nr   rJ   rZ   r   s    r   r\   KPartition.__repr__'  s    }}TG]#;<<r   c                 `    [        [        [        R                  " S U  5       5      5      5      $ )z8tuple[int]: The nodes of the mechanism in the partition.c              3   8   #    U  H  oR                   v   M     g 7frG   )r4   .0r   s     r   	<genexpr>'KPartition.mechanism.<locals>.<genexpr>.  s     @444   ru   rv   r   from_iterabler   s    r   r4   KPartition.mechanism*  s/     V@4@@B C 	Cr   c                 `    [        [        [        R                  " S U  5       5      5      5      $ )z6tuple[int]: The nodes of the purview in the partition.c              3   8   #    U  H  oR                   v   M     g 7frG   )r   r   s     r   r   %KPartition.purview.<locals>.<genexpr>4  s     >r   r   r   s    r   r   KPartition.purview0  s/     V>>>@ A 	Ar   c                 J    [        U 5      " [        U 5      SU R                  06$ )z.Normalize the order of parts in the partition.rJ   )typerv   rJ   r   s    r   	normalizeKPartition.normalize6  s     Dz6$<FT5E5EFFr   c                     S[        U 5      0$ Nr   )listr   s    r   rW   KPartition.to_json:  s    d$$r   c                     U " US   6 $ r   r   clsdcts     r   	from_jsonKPartition.from_json=  s    CL!!r   )rJ   r   )r<   r=   r>   r?   r@   r   rK   r   r   re   ri   r`   r\   rA   r4   r   r   rW   classmethodr   rB   r   r   r   r   r     s    8-(I+/ '!)
 '= C C
 A A
G% " "r   r   c                   F    \ rS rSrSr\R                  rS r\S 5       r	Sr
g)BipartitioniB  zA bipartition of a mechanism and purview.

Attributes:
    part0 (Part): The first part of the partition.
    part1 (Part): The second part of the partition.
c                     U S   U S   S.$ )r   r   r   )part0part1r   r   s    r   rW   Bipartition.to_jsonL  s    a4733r   c                      U " US   US   5      $ )Nr   r   r   r   s     r   r   Bipartition.from_jsonP  s    3w<W..r   r   N)r<   r=   r>   r?   r@   r   r   rW   r   r   rB   r   r   r   r   r   B  s-     $$I4 / /r   r   c                   0    \ rS rSrSr\R                  rSrg)TripartitioniU  zA partition with three parts.r   N)r<   r=   r>   r?   r@   r   r   rB   r   r   r   r   r   U  s    '$$Ir   r   )r@   collections	itertoolsr   numpyr!    r   r   r   r	   r   rD   rm   r   r   
namedtupler   Sequencer   r   r   r   r   r   <module>r      s   
 :     "I  I X#"h #"L:J( :Jz)J8 )JX: :F;!!&;	*BC F22"%% 2"j/* /&%: %r   