
    ph"                         S r SSKrSSKJrJrJrJr  SSKJ	r	  SS jr
SS jrS rS	 rS
 rS rS rS rS rS rS rS rS rS rS rS rS rg)z#
Methods for validating arguments.
    N   )	Directionconfigconvert
exceptions)is_state_by_statec                     [         R                  [         R                  /nU(       a  UR                  [         R                  5        X;  a  [        SR                  U5      5      eg)zValidate that the given direction is one of the allowed constants.

If ``allow_bi`` is ``True`` then ``Direction.BIDIRECTIONAL`` is
acceptable.
z`direction` must be one of {}T)r   CAUSEEFFECTappendBIDIRECTIONAL
ValueErrorformat)	directionallow_bivalids      H/home/james-whalen/.local/lib/python3.13/site-packages/pyphi/validate.pyr   r      sM     __i../EY,,-8??FGG    c                    Sn[         R                  " U 5      n U R                  S   nU R                  S:X  a  U R                  S   SU-  :X  a  U R                  S   U:X  dE  U R                  S   U R                  S   :X  d%  [	        SR                  U R                  U5      5      eU R                  S   U R                  S   :X  a  U(       a  [        U 5        g	U R                  US-   :X  aQ  U R                  [        S/U-  U/-   5      :w  a.  [	        SR                  U R                  S/U-  U/-   X25      5      e g	[	        SR                  U5      5      e)
zValidate a TPM.

The TPM can be in

    * 2-dimensional state-by-state form,
    * 2-dimensional state-by-node form, or
    * multidimensional state-by-node form.
zjSee the documentation on TPM conventions and the `pyphi.Network` object for more information on TPM forms.   r   r   zInvalid shape for 2-D TPM: {}
For a state-by-node TPM, there must be 2^N rows and N columns, where N is the number of nodes. State-by-state TPM must be square. {}z`Invalid shape for multidimensional state-by-node TPM: {}
The shape should be {} for {} nodes. {}zAInvalid TPM: Must be either 2-dimensional or multidimensional. {}T)nparrayshapendimr   r   conditionally_independenttuple)tpmcheck_independencesee_tpm_docsNs       r   r   r   !   sI   	4 
 ((3-C		"A
xx1}1A%#))A,!*;11- VCII|4	6 6
 99Q<399Q<',>%c*  
a!e	99qcAgm,,::@&IIaA3;AB B -  %' 	'r   c                 b   [         R                  " U 5      n [        U 5      (       a+  [        R                  " [        R
                  " U 5      5      nO*[        R
                  " [        R                  " U 5      5      n[         R                  " X-
  S5      (       d  [        R                  " S5      eg)z3Validate that the TPM is conditionally independent.g        zrTPM is not conditionally independent.
See the conditional independence example in the documentation for more info.T)	r   r   r   r   state_by_node2state_by_statestate_by_state2state_by_nodeallcloser   ConditionallyDependentError)r   there_and_back_agains     r   r   r   I   s    
((3-C&CC005 7  'CC005 7;;2S9944 	 r   c                 4   U R                   S:X  a  gU R                  S:w  a  [        S5      eU R                  S   U R                  S   :w  a  [        S5      e[        R
                  " [        R                  " U S:H  U S:H  5      5      (       d  [        S5      eg)z'Validate the given connectivity matrix.r   Tr   z*Connectivity matrix must be 2-dimensional.r   z#Connectivity matrix must be square.z4Connectivity matrix must contain only binary values.)sizer   r   r   r   all
logical_or)cms    r   connectivity_matrixr-   Z   s     
ww!|	ww!|EFF	xx{bhhqk!>??66"--aq122 # $ 	$r   c                     [        U 5      [        U5      :w  a  [        SR                  X5      5      e[        U 5      [        [        U 5      5      :w  a  [        SR                  U 5      5      eg)z-Validate that there is a label for each node.z%Labels {0} must label every node {1}.zLabels {0} must be unique.N)lenr   r   set)node_labelsnode_indicess     r   r1   r1   i   sg    
;3|,,@GG' ( 	( ;3s;/005<<[IJJ 1r   c                     [        U R                   5        [        U R                  5        U R                  R                  S   U R                  :w  a  [        S5      eg)z?Validate a |Network|.

Checks the TPM and connectivity matrix.
r   zOConnectivity matrix must be NxN, where N is the number of nodes in the network.T)r   r-   r,   r   r)   r   )ns    r   networkr5   s   sH    
 Jttzz!} ; < 	<r   c                 F    SSK Jn  [        X5      (       d  [        S5      eg)z*Validate that the argument is a |Network|.r   )Networkz@Input must be a Network (perhaps you passed a Subsystem instead?N) r7   
isinstancer   )r5   r7   s     r   
is_networkr:      s'    g''NP 	P (r   c                 H    [        S U  5       5      (       d  [        S5      eg)z2Check that the state contains only zeros and ones.c              3   *   #    U  H	  oS ;   v   M     g7f))r   r   N ).0r4   s     r   	<genexpr>node_states.<locals>.<genexpr>   s     *EqF{Es   z:Invalid state: states must consist of only zeros and ones.N)r*   r   )states    r   node_statesrB      s*    *E***HJ 	J +r   c                 j    [        U 5      U:w  a$  [        SR                  [        U 5      U5      5      eg)z'Check that the state is the given size.zrInvalid state: there must be one entry per node in the network; this state has {} entries, but there are {} nodes.T)r/   r   r   )rA   r)   s     r   state_lengthrD      s7    
5zT //5vc%j$/GI 	I r   c                 J   U R                   SU R                  4   nU[        R                  " U R                  5      -
  n[        R
                  " [        R                  " SU:  US:  5      R                  S5      5      (       d   [        R                  " U R                  5      eg)zEReturn whether a state can be reached according to the network's TPM..r   r   N)r   r2   r   r   proper_stateanylogical_andr*   r   StateUnreachableErrorrA   )	subsystemr   tests      r   state_reachablerL      s}     --Y333
4C)0011D66"..dD1H599"=>>..y?? ?r   c                 X    U R                   U:w  a  [        SR                  X5      5      eg)z/Check that the cut is for only the given nodes.z,{} nodes are not equal to subsystem nodes {}N)indicesr   r   )cutr2   s     r   rO   rO      s/    
{{l" $fS79 	9 #r   c                     [        U R                  5        [        U R                  U R                  5        [        R
                  (       a  [        U 5        g)z3Validate a |Subsystem|.

Checks its state and cut.
T)rB   rA   rO   cut_indicesr   VALIDATE_SUBSYSTEM_STATESrL   )ss    r   rJ   rJ      s6    
 q}}''r   c                 P    U S::  d  [        U [        5      (       a  [        S5      eg)z%Validate a macro temporal time scale.r   z%time scale must be a positive integerN)r9   floatr   )
time_scales    r   rV   rV      s&    Q*Z77@AA 8r   c                     [        5       nU  H<  nU H3  nX1;   a  [        SR                  U5      5      eUR                  U5        M5     M>     g)z<Validate a partition - used by blackboxes and coarse grains.zDMicro-element {} may not be partitioned into multiple macro-elementsN)r0   r   r   add)	partitionnodespartnodes       r   rY   rY      sJ    EED} %%+VD\3 3 IIdO  r   c                    [        U R                   5        [        U R                   5      [        U R                  5      :w  a  [        S5      e[	        U R                   U R                  5       HU  u  p[        [        [        U5      S-   5      5      [        US   US   -   5      :w  d  M=  [        SR                  X5      5      e   g)z!Validate a macro coarse-graining.z0output and state groupings must be the same sizer   r   zKelements in output grouping {0} do not match elements in state grouping {1}N)rY   r/   groupingr   zipr0   ranger   )coarse_grainr[   groups      r   ra   ra      s    l$$%
<!!"c,*?*?&@@KLL<11<3H3HIuSY]#$E!HuQx,?(@@  >>Df!%?./ /	 Jr   c                 t   [        [        U R                  5      5      U R                  :w  a$  [        SR	                  U R                  5      5      e[        U R
                  5        U R
                   HC  n[        U5      [        U R                  5      -  (       a  M+  [        SR	                  U5      5      e   g)zValidate a macro blackboxing.z!Output indices {} must be orderedz0Every blackbox must have an output - {} does notN)r   sortedoutput_indicesr   r   rY   r0   )blackboxr[   s     r   rf   rf      s    VH++,-1H1HH<CC##% & 	& h  !""4y3x66777BII  #r   c                    ^ U c  gU R                    Hy  n[        U5      [        U R                  5      -  mUc  [        T5      S:  a  [	        S5      eU(       d  MJ  [        U4S jUR                    5       5      (       a  Mp  [	        S5      e   g)zPValidate that a coarse-graining properly combines the outputs of a
blackboxing.
Nr   zCA blackboxing with multiple outputs per box must be coarse-grained.c              3   F   >#    U  H  nTR                  U5      v   M     g 7f)N)issubset)r>   r[   outputss     r   r?   ,blackbox_and_coarse_grain.<locals>.<genexpr>   s'      %I1G &-%5%5d%;%;1Gs   !zgMultiple outputs from a blackbox must be partitioned into the same macro-element of the coarse-graining)rY   r0   re   r/   r   rG   )rf   ra   boxrj   s      @r   blackbox_and_coarse_grainrm      s     !!c(S!8!899CL1$4"# # L %I1=1G1G%I "I "I@A A "r   )F)T)__doc__numpyr   r8   r   r   r   r   r   r   r   r   r-   r1   r5   r:   rB   rD   rL   rO   rJ   rV   rY   ra   rf   rm   r=   r   r   <module>rp      st   
  4 4 "
 %P"K
PJ@9	B	/ Ar   