
    ph>                        S r SSKrSSKrSSKJrJrJrJrJr  SSK	J
r
JrJrJrJrJrJrJr  SSKJrJrJr  SSKJr  SS	KJr  SS
KJr  \R6                  " \5      r " S S\5      r\  S!S j5       rS r S r! " S S\5      r"S"S jr#S r$\RJ                  " S/S9\S 5       5       r&S r'\RP                  " \&5      S 5       r)S r* " S S5      r+S"S jr,S"S jr- " S S\R\                  5      r/S  r0g)#z5
Functions for computing subsystem-level properties.
    N   )	Directionconfigconnectivitymemoryutils)CauseEffectStructureConceptCutKCutSystemIrreducibilityAnalysis	_null_siacmpfmt)directed_bipartitiondirected_bipartition_of_onemip_partitions)time_annotated   )ces_distance)	MapReducec                   H    \ rS rSrSrSr\S 5       rS r\	S 5       r
S rSrg	)
ComputeCauseEffectStructure   z.Engine for computing a |CauseEffectStructure|.zComputing conceptsc                      U R                   S   $ )Nr   )contextselfs    Q/home/james-whalen/.local/lib/python3.13/site-packages/pyphi/compute/subsystem.py	subsystem%ComputeCauseEffectStructure.subsystem   s    ||A    c                     / $ N )r   argss     r   empty_result(ComputeCauseEffectStructure.empty_result#   s    	r"   c                 8    UR                  U UUUS9nSUl        U$ )zUCompute a |Concept| for a mechanism, in this |Subsystem| with the
provided purviews.
)purviewscause_purviewseffect_purviewsN)conceptr    )	mechanismr    r*   r+   r,   r-   s         r   compute#ComputeCauseEffectStructure.compute&   s4     ##I-53A4C $ E !r"   c                 j    UR                   S:  a"  U R                  Ul        UR                  U5        U$ )zKSave all concepts with non-zero |small_phi| to the
|CauseEffectStructure|.
r   )phir    append)r   new_conceptconceptss      r   process_result*ComputeCauseEffectStructure.process_result6   s-     ??Q$(NNK!OOK(r"   r%   N)__name__
__module____qualname____firstlineno____doc__descriptionpropertyr    r'   staticmethodr/   r6   __static_attributes__r%   r"   r   r   r      s<    8 'K   r"   r   c                     USL a  [         R                  " U R                  SS9n[        XUX45      n[	        UR                  U=(       d    [        R                  5      U S9$ )a  Return the conceptual structure of this subsystem, optionally restricted
to concepts with the mechanisms and purviews given in keyword arguments.

If you don't need the full |CauseEffectStructure|, restricting the possible
mechanisms and purviews can make this function much faster.

Args:
    subsystem (Subsystem): The subsystem for which to determine the
        |CauseEffectStructure|.

Keyword Args:
    mechanisms (tuple[tuple[int]]): Restrict possible mechanisms to those
        in this list.
    purviews (tuple[tuple[int]]): Same as in |Subsystem.concept()|.
    cause_purviews (tuple[tuple[int]]): Same as in |Subsystem.concept()|.
    effect_purviews (tuple[tuple[int]]): Same as in |Subsystem.concept()|.
    parallel (bool): Whether to compute concepts in parallel. If ``True``,
        overrides :data:`config.PARALLEL_CONCEPT_EVALUATION`.

Returns:
    CauseEffectStructure: A tuple of every |Concept| in the cause-effect
    structure.
FT)nonemptyr    )r   powersetnode_indicesr   r	   runr   PARALLEL_CONCEPT_EVALUATION)r    
mechanismsr*   r+   r,   parallelengines          r   cesrK   A   sc    4 U^^I$:$:TJ
()7JF  

8 ,N+1+M+M!O*35 5r"   c                 p    [        [        U 5      [        SU S95      n[        U[        R
                  5      $ )zReturn the conceptual information for a |Subsystem|.

This is the distance from the subsystem's |CauseEffectStructure| to the
null concept.
r%   rC   )r   rK   r	   roundr   	PRECISION)r    cis     r   conceptual_inforP   f   s2     
c)n*2C
EBV%%&&r"   c                 \   [         R                  SU5        U R                  U5      n[        R                  (       a  UR
                  nO+[        UR
                  [        UR                  5      -   5      n[        X45      n[         R                  SU5        [        X%5      n[        UUUU US9$ )ap  Compute the system irreducibility for a given cut.

Args:
    uncut_subsystem (Subsystem): The subsystem without the cut applied.
    cut (Cut): The cut to evaluate.
    unpartitioned_ces (CauseEffectStructure): The cause-effect structure of
        the uncut subsystem.

Returns:
    SystemIrreducibilityAnalysis: The |SystemIrreducibilityAnalysis| for
    that cut.
zEvaluating %s...zFinished evaluating %s.)r2   rK   partitioned_cesr    cut_subsystem)logdebug	apply_cutr   &ASSUME_CUTS_CANNOT_CREATE_NEW_CONCEPTSrH   setlistcut_mechanismsrK   r   r   )uncut_subsystemcutunpartitioned_cesrS   rH   rR   phi_s          r   evaluate_cutr_   q   s     II #&#--c2M44&11
 ((--./0
 -4OII'-);D''!#% %r"   c                   j    \ rS rSrSrSR                  \R                  5      rS r	\
S 5       rS rSrg)	ComputeSystemIrreducibility   z3Computation engine for system-level irreducibility.zEvaluating {} cutsc                 (    [        U[        S5      S9$ )zLBegin with a |SIA| with infinite |big_phi|; all actual SIAs will
have less.
infr2   )r   float)r   r    r]   s      r   r'   (ComputeSystemIrreducibility.empty_result   s     e55r"   c                     [        XU5      $ )zEvaluate a cut.)r_   )r\   r    r]   s      r   r/   #ComputeSystemIrreducibility.compute   s     I,=>>r"   c                 F    UR                   S:X  a	  SU l        U$ X:  a  U$ U$ )zECheck if the new SIA has smaller |big_phi| than the standing
result.
r   T)r2   done)r   new_siamin_sias      r   r6   *ComputeSystemIrreducibility.process_result   s,     ;;!DINNr"   )rk   N)r8   r9   r:   r;   r<   formatr   BIG_PHIr=   r'   r?   r/   r6   r@   r%   r"   r   ra   ra      s9    = '--ckk:K6 ? ?r"   ra   c                     [         R                  (       a  [        U 5      nO
[        U SS9nU Vs/ s H  n[	        US   US   U5      PM     sn$ s  snf )zReturn all |big_phi| cuts for the given nodes.

This value changes based on :const:`config.CUT_ONE_APPROXIMATION`.

Args:
    nodes (tuple[int]): The node indices to partition.
Returns:
    list[Cut]: All unidirectional partitions.
T)
nontrivialr   r   )r   CUT_ONE_APPROXIMATIONr   r   r   )nodesnode_labelsbipartitionsbipartitions       r   sia_bipartitionsrx      s]     ##259 ,EdC  ,-+ AA<+- - -s   Ac                 2    [        U [        R                  S9$ )zParallelize the unpartitioned |CauseEffectStructure| if parallelizing
cuts, since we have free processors because we're not computing any cuts
yet.
)rI   )rK   r   PARALLEL_CUT_EVALUATIONrC   s    r   _cesr{      s    
 y6#A#ABBr"   r    )ignorec                    [         R                  SU5        U(       d!  [         R                  SU5        [        U5      $ [        R                  " UR
                  UR                  5      (       d!  [         R                  SU5        [        U5      $ [        UR                  5      S:X  a  UR
                  UR                     UR                     (       d!  [         R                  SU5        [        U5      $ [        R                  (       d!  [         R                  SU5        [        U5      $ [         R                  S5        [        U5      nU(       d   [         R                  S5        [        U5      $ [         R                  S	5        [        UR                  5      S:X  a-  [        UR                  UR                  UR                  5      /nO [        UR                  UR                  5      n[!        X1U5      nUR#                  [        R$                  5      n[        R&                  (       a%  [         R                  S
5        UR)                  5         [         R                  SU5        U$ )aO  Return the minimal information partition of a subsystem.

Args:
    subsystem (Subsystem): The candidate set of nodes.

Returns:
    SystemIrreducibilityAnalysis: A nested structure containing all the
    data from the intermediate calculations. The top level contains the
    basic irreducibility information for the given subsystem.
z"Calculating big-phi data for %s...z6Subsystem %s is empty; returning null SIA immediately.z=%s is not strongly connected; returning null SIA immediately.r   zXSingle micro nodes %s without selfloops cannot have phi; returning null SIA immediately.zUSingle micro nodes %s with selfloops cannot have phi; returning null SIA immediately.z-Finding unpartitioned CauseEffectStructure...zIEmpty unpartitioned CauseEffectStructure; returning null SIA immediately.z)Found unpartitioned CauseEffectStructure.zClearing subsystem caches.z)Finished calculating big-phi data for %s.)rT   infor   r   	is_strongcmrE   lencut_indicesr   *SINGLE_MICRO_NODES_WITH_SELFLOOPS_HAVE_PHIrU   r{   r   cut_node_labelsrx   ra   rF   rz   *CLEAR_SUBSYSTEM_CACHES_AFTER_COMPUTING_SIAclear_caches)	cache_keyr    r]   cutsrJ   results         r   _siar      s    HH19=   !*	,##!!),,	0F0FGG  !*	,##
 9  !Q&||I223I4J4JKHH <=FHY''BBHH <=FHY'' II=>Y $ 	% ##II9: 9  !Q&I))9+@+@--/ 0  	 5 5 ) 9 9; )*,FZZ667F88		./ HH8)DMr"   c                     [        U 5      [        R                  [        R                  [        R                  [        R
                  [        R                  [        R                  [        R                  4$ )zThe cache key of the subsystem.

This includes the native hash of the subsystem and all configuration values
which change the results of ``sia``.
)	hashr   rW   rs   MEASURErN   VALIDATE_SUBSYSTEM_STATESr   PARTITION_TYPErC   s    r   _sia_cache_keyr   )  sR     	Y55$$((99	 	r"   c                 j    [         R                  S:X  a  [        U 5      $ [        [	        U 5      U 5      $ )NCONCEPT_STYLE)r   SYSTEM_CUTSsia_concept_styler   r   rC   s    r   siar   ?  s-    _, ++y)955r"   c                 ,    [        U 5      R                  $ )z*Return the |big_phi| value of a subsystem.)r   r2   rC   s    r   r2   r2   G  s    y>r"   c                   h    \ rS rSrSrSS jrS rS rS r\	S 5       r
\	S	 5       r  SS
 jrS rSrg)ConceptStyleSystemiL  zSA functional replacement for ``Subsystem`` implementing concept-style
system cuts.
Nc                 T    Xl         X l        X0l        UR                  U5      U l        g r$   )r    	directionr\   rV   
cut_system)r   r    r   r\   s       r   __init__ConceptStyleSystem.__init__Q  s#    ""#--c2r"   c                 D    [        U R                  U R                  U5      $ r$   )r   r    r   )r   r\   s     r   rV   ConceptStyleSystem.apply_cutW  s    !$..$..#FFr"   c                 d    SU R                   ;   a  [        U R                  U5      $ [        U5      e)z5Pass attribute access through to the basic subsystem.r    )__dict__getattrr    AttributeErrorr   names     r   __getattr__ConceptStyleSystem.__getattr__Z  s,    
 $--'4>>400T""r"   c                 ,    [        U R                  5      $ r$   )r   r    r   s    r   __len__ConceptStyleSystem.__len__c  s    4>>""r"   c                     [         R                  U R                  [         R                  U R                  0U R
                     $ r$   )r   CAUSEr   EFFECTr    r   r   s    r   cause_systemConceptStyleSystem.cause_systemf  s8     OOT__dnn
 .. 	r"   c                     [         R                  U R                  [         R                  U R                  0U R
                     $ r$   )r   r   r    r   r   r   r   s    r   effect_system ConceptStyleSystem.effect_systemm  s8     OOT^^doo
 .. 	r"   c                     U R                   R                  X=(       d    US9nU R                  R                  X=(       d    US9n[	        XUU S9$ )zJCompute a concept, using the appropriate system for each side of the
cut.
)r*   )r.   causeeffectr    )r   micr   mier
   )r   r.   r*   r+   r,   r   r   s          r   r-   ConceptStyleSystem.conceptt  sb    
 !!%%!;8 & > ##''!<H ( ? !%' 	'r"   c                 8    SR                  U R                  5      $ )NzConceptStyleSystem{})ro   rE   r   s    r   __str__ConceptStyleSystem.__str__  s    %,,T->->??r"   )r\   r   r   r    r$   )FFF)r8   r9   r:   r;   r<   r   rV   r   r   r>   r   r   r-   r   r@   r%   r"   r   r   r   L  sY    3G##     AF %'@r"   r   c              #   L   #    [        X5       H  n[        XU5      v   M     g7f)z5Generator over all concept-syle cuts for these nodes.N)r   r   )r   rE   ru   	partitions       r   concept_cutsr     s"     #L?	955 @s   "$c                     Uc  [        U 5      n[        X5      n[        XR                  U R                  5      n[        XCU5      nUR                  [        R                  5      $ )zcCalculate a concept-style SystemIrreducibilityAnalysisCause or
SystemIrreducibilityAnalysisEffect.
)	r{   r   r   r   ru   ra   rF   r   rz   )r    r   r]   c_systemr   rJ   s         r   directional_siar     s]       O!)7H	#7#79N9NOD ))+F::f4455r"   c                   R    \ rS rSrSrS r\S 5       rS rS r	S/r
S rS	 rS
 rSrg)(SystemIrreducibilityAnalysisConceptStylei  z<Represents a |SIA| computed using concept-style system cuts.c                     Xl         X l        g r$   	sia_cause
sia_effect)r   r   r   s      r   r   1SystemIrreducibilityAnalysisConceptStyle.__init__  s    "$r"   c                 B    [        U R                  U R                  S S9$ )Nc                     U R                   $ r$   re   )ms    r   <lambda>BSystemIrreducibilityAnalysisConceptStyle.min_sia.<locals>.<lambda>  s    !%%r"   )key)minr   r   r   s    r   rm   0SystemIrreducibilityAnalysisConceptStyle.min_sia  s    4>>4??HHr"   c                     SU R                   ;   a&  SU R                   ;   a  [        U R                  U5      $ [        U5      e)z1Pass attribute access through to the minimal SIA.r   r   )r   r   rm   r   r   s     r   r   4SystemIrreducibilityAnalysisConceptStyle.__getattr__  s5    4==(\T]]-J4<<..T""r"   c                 2    [         R                  " XS/5      $ )Nr2   )r   
general_eq)r   others     r   __eq__/SystemIrreducibilityAnalysisConceptStyle.__eq__  s    ~~dE733r"   networkc                 D    U R                   [        U R                  5      /$ r$   )r2   r   r    r   s    r   order_by1SystemIrreducibilityAnalysisConceptStyle.order_by  s    #dnn-..r"   c                 ,    [        U R                  5      $ r$   )reprrm   r   s    r   __repr__1SystemIrreducibilityAnalysisConceptStyle.__repr__  s    DLL!!r"   c                 ,    [        U R                  5      $ r$   )strrm   r   s    r   r   0SystemIrreducibilityAnalysisConceptStyle.__str__  s    4<<  r"   r   N)r8   r9   r:   r;   r<   r   r>   rm   r   r   unorderable_unless_eqr   r   r   r@   r%   r"   r   r   r     sC    F% I I#4 'K/"!r"   r   c                     [        U 5      n[        U [        R                  U5      n[        U [        R                  U5      n[        X#5      $ )z4Compute a concept-style SystemIrreducibilityAnalysis)r{   r   r   r   r   r   )r    r]   r   r   s       r   r   r     sE    Y	9?? 13I I,<,<!24J 4IJJr"   )FFFFFr$   )1r<   	functoolslogging r   r   r   r   r   modelsr	   r
   r   r   r   r   r   r   r   r   r   r   r   distancer   rI   r   	getLoggerr8   rT   r   rK   rP   r_   ra   rx   r{   cacher   r   wrapsr   r2   r   r   r   	Orderabler   r   r%   r"   r   <module>r      s  
   = =I I I) ) " "  !%) %P DI(-!5 !5H'%%P) >-(C k]#N  $Nf, 6 6
7@ 7@t66$!s}} !B	Kr"   