
    ph|                     (   S r SSKrSSKJr  SSKJr  SSK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JrJrJrJrJrJrJrJr  SSKJr  SS	K J!r!  \RD                  " \#5      r$S
 r " S S5      r%  SS jr&\
RN                  4S jr(S r)\
RN                  4S jr*S r+\
RN                  4S jr, " S S\RZ                  R\                  5      r/S r0\
RN                  4S jr1\
RN                  4S jr2S r3 S S jr4 S S jr5 S S jr6S r7 S!S jr8 S!S jr9g)"a^  
Methods for computing actual causation of subsystems and mechanisms.

If you use this module, please cite the following papers:

    Albantakis L, Marshall W, Hoel E, Tononi G (2019).
    What Caused What? A quantitative Account of Actual Causation Using
    Dynamical Causal Networks.
    *Entropy*, 21 (5), pp. 459.
    `<https://doi.org/10.3390/e21050459>`_

    Mayner WGP, Marshall W, Albantakis L, Findlay G, Marchman R, Tononi G. (2018).
    PyPhi: A toolbox for integrated information theory.
    *PLOS Computational Biology* 14(7): e1006343.
    `<https://doi.org/10.1371/journal.pcbi.1006343>`_
    N)chain)log2   )	Directioncomputeconfigconnectivity	constants
exceptionsutilsvalidate)Account"AcRepertoireIrreducibilityAnalysisAcSystemIrreducibilityAnalysis	ActualCut
CausalLinkDirectedAccountEventNullCut_null_ac_ria_null_ac_siafmt)mip_partitions)	Subsystemc                 H    [        [        U 5      [        R                  5      $ )zRounded version of ``log2``.)round_log2r   	PRECISION)xs    F/home/james-whalen/.local/lib/python3.13/site-packages/pyphi/actual.pyr   r   (   s    q6++,,    c                      \ rS rSrSr S&S jrS rS 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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'S jr!S'S  jr"  S(S! jr#S'S" jr$S'S# jr%S$ r&S%r'g))
Transition-   a  A state transition between two sets of nodes in a network.

A |Transition| is implemented with two |Subsystem| objects: one
representing the system at time |t-1| used to compute effect coefficients,
and another representing the system at time |t| which is used to compute
cause coefficients. These subsystems are accessed with the
``effect_system`` and ``cause_system`` attributes, and are mapped to the
causal directions via the ``system`` attribute.

Args:
    network (Network): The network the subsystem belongs to.
    before_state (tuple[int]): The state of the network at
        time |t-1|.
    after_state (tuple[int]): The state of the network at
        time |t|.
    cause_indices (tuple[int] or tuple[str]): Indices of nodes in the cause
        system. (TODO: clarify)
    effect_indices (tuple[int] or tuple[str]): Indices of nodes in the
        effect system. (TODO: clarify)

Keyword Args:
    noise_background (bool): If ``True``, background conditions are
        noised instead of frozen.

Attributes:
    node_indices (tuple[int]): The indices of the nodes in the system.
    network (Network): The network the system belongs to.
    before_state (tuple[int]): The state of the network at time |t-1|.
    after_state (tuple[int]): The state of the network at time |t|.
    effect_system (Subsystem): The system in ``before_state`` used to
        compute effect repertoires and coefficients.
    cause_system (Subsystem): The system in ``after_state`` used to compute
        cause repertoires and coefficients.
    cause_system (Subsystem):
    system (dict): A dictionary mapping causal directions to the system
        used to compute repertoires in that direction.
    cut (ActualCut): The cut that has been applied to this transition.

.. note::
    During initialization, both the cause and effect systems are
    conditioned on ``before_state`` as the background state. After
    conditioning the ``effect_system`` is then properly reset to
    ``after_state``.
Nc           	         Xl         X l        X0l        U R                  R                  nU" U5      U l        U" U5      U l        U" XE-   5      U l        Ub  UO[        U R                  U R                  5      U l	        U(       a  Sn	O3[        [        [        UR                  5      [        U5      -
  5      5      n	[        R                  " SS9   [        XU R                  U R                  U	S9U l        [        XU R                  U R                  U	S9U l        S S S 5        X0R"                  l        U R"                  R&                   H  n
X:R(                     U
l        M     [*        R,                  " U R"                  5        [.        R0                  U R"                  [.        R2                  U R                   0U l        g ! , (       d  f       N= f)N F)VALIDATE_SUBSYSTEM_STATES)_external_indices)networkbefore_stateafter_statenode_labelscoerce_to_indicescause_indiceseffect_indicesnode_indicesr   cuttuplesortedsetr   overrider   effect_systemcause_systemstatenodesindexr   state_reachabler   CAUSEEFFECTsystem)selfr)   r*   r+   r.   r/   r1   noise_backgroundr-   external_indicesnodes              r    __init__Transition.__init__[   s    (& ,,>>.}=/?-m.LM?C !2!2D4D4DE 	   "  %VG(()C,>>&@  A __u=!*7+/+<+<dhh=M"OD !*'*.*;*;TXX<L!ND > #.%%++D$ZZ0DJ , 	  !2!23
 OOT..d00
) >=s   AF<<
G
c                 .    [         R                  " U 5      $ N)r   fmt_transitionr?   s    r    __repr__Transition.__repr__   s    !!$''r!   c                     [        U 5      $ rF   )reprrH   s    r    __str__Transition.__str__   s    Dzr!   c                 t   U R                   UR                   :H  =(       a    U R                  UR                  :H  =(       ay    U R                  UR                  :H  =(       aY    U R                  UR                  :H  =(       a9    U R                  UR                  :H  =(       a    U R
                  UR
                  :H  $ rF   )r.   r/   r*   r+   r)   r1   )r?   others     r    __eq__Transition.__eq__   s    %"5"55 "5#7#77"!3!33"  1 11" LLEMM)	"
 HH		!	
r!   c                     [        U R                  U R                  U R                  U R                  U R
                  U R                  45      $ rF   )hashr.   r/   r*   r+   r)   r1   rH   s    r    __hash__Transition.__hash__   sB    T'')<)<&&(8(8$,,XX   	 r!   c                 ,    [        U R                  5      $ rF   )lenr0   rH   s    r    __len__Transition.__len__   s    4$$%%r!   c                     [        U 5      S:  $ )Nr   )rX   rH   s    r    __bool__Transition.__bool__   s    4y1}r!   c                 .    U R                   R                  $ rF   )r)   r,   rH   s    r    r,   Transition.node_labels   s    ||'''r!   c                     U R                   U R                  U R                  U R                  U R                  U R
                  S.$ )z*Return a JSON-serializable representation.r)   r*   r+   r.   r/   r1   ra   rH   s    r    to_jsonTransition.to_json   s@     || --++!//"1188
 	
r!   c                     [        U R                  U R                  U R                  U R                  U R
                  U5      $ )z(Return a cut version of this transition.)r#   r)   r*   r+   r.   r/   )r?   r1   s     r    	apply_cutTransition.apply_cut   s:    $,,(9(94;K;K,,d.A.A3H 	Hr!   c                 B    U R                  [        R                  X5      $ )zReturn the cause repertoire.)
repertoirer   r<   r?   	mechanismpurviews      r    cause_repertoireTransition.cause_repertoire   s    y	CCr!   c                 B    U R                  [        R                  X5      $ )zReturn the effect repertoire.)rh   r   r=   ri   s      r    effect_repertoireTransition.effect_repertoire   s    y//DDr!   c                 &    U R                  SU5      $ )z;Return the unconstrained cause repertoire of the occurence.r&   )rl   r?   rk   s     r    unconstrained_cause_repertoire)Transition.unconstrained_cause_repertoire   s    $$R11r!   c                 &    U R                  SU5      $ )z<Return the unconstrained effect repertoire of the occurence.r&   )ro   rr   s     r    unconstrained_effect_repertoire*Transition.unconstrained_effect_repertoire   s    %%b'22r!   c                    U R                   U   nUR                  n[        U5      R                  U R	                  U5      5      (       d/  [        SR                  [        R                  " X55      X5      5      e[        U5      R                  U R                  U5      5      (       d/  [        SR                  [        R                  " X%5      X5      5      eUR                  XU5      $ )zReturn the cause or effect repertoire function based on a direction.

Args:
    direction (str): The temporal direction, specifiying the cause or
        effect repertoire.
z{} is not a {} purview in {}z{} is no a {} mechanism in {})r>   r,   r4   issubsetpurview_indices
ValueErrorformatr   fmt_mechanismmechanism_indicesrh   )r?   	directionrj   rk   r>   r,   s         r    rh   Transition.repertoire   s     Y'((7|$$T%9%9)%DEE;BB!!'7J K K 9~&&t'='=i'HII<CC!!)99L M M   w??r!   c                 j   ^ U R                  U5      n[        U4S j[        U5       5       5      nX%   $ )a6  Compute the probability of the purview in its current state given
the repertoire.

Collapses the dimensions of the repertoire that correspond to the
purview nodes onto their state. All other dimension are already
singular and thus receive 0 as the conditioning index.

Returns:
    float: A single probabilty.
c              3   <   >#    U  H  u  pUT;   a  UOS v   M     g7f)r   Nr&   ).0rB   
node_staterk   s      r    	<genexpr>/Transition.state_probability.<locals>.<genexpr>   s'      H.F*$ %)GOj:.F   )purview_stater2   	enumerate)r?   r   rh   rk   r   r:   s      `  r    state_probabilityTransition.state_probability   s=     **95 H.7.FH H  r!   c                 J    U R                  XU5      nU R                  XU5      $ )zXProbability that the purview is in it's current state given the
state of the mechanism.
)rh   r   )r?   r   rj   rk   rh   s        r    probabilityTransition.probability   s'     __Y7C
%%iWEEr!   c                 (    U R                  USU5      $ )z)Unconstrained probability of the purview.r&   )r   )r?   r   rk   s      r    unconstrained_probability$Transition.unconstrained_probability   s    	2w77r!   c                 t    [         R                  U R                  [         R                  U R                  0U   $ )zThe state of the purview when we are computing coefficients in
``direction``.

For example, if we are computing the cause coefficient of a mechanism
in ``after_state``, the direction is``CAUSE`` and the ``purview_state``
is ``before_state``.
)r   r<   r*   r=   r+   r?   r   s     r    r   Transition.purview_state  s8     OOT..d..
  	r!   c                 4    U R                   U   R                  $ )zIThe state of the mechanism when computing coefficients in
``direction``.
)r>   r8   r   s     r    mechanism_stateTransition.mechanism_state  s     {{9%+++r!   c                 t    [         R                  U R                  [         R                  U R                  0U   $ )z-The indices of nodes in the mechanism system.)r   r<   r/   r=   r.   r   s     r    r~   Transition.mechanism_indices  s8     OOT00d00
  	r!   c                 t    [         R                  U R                  [         R                  U R                  0U   $ )z+The indices of nodes in the purview system.)r   r<   r.   r=   r/   r   s     r    rz   Transition.purview_indices  s8     OOT//d11
  	r!   c                 \    [        U R                  XU5      U R                  X5      -  5      $ rF   )r   r   r   )r?   r   rj   rk   s       r    _ratioTransition._ratio$  s4    D$$Y7C229FG H 	Hr!   c                 B    U R                  [        R                  X5      $ )z7The cause ratio of the ``purview`` given ``mechanism``.)r   r   r<   ri   s      r    cause_ratioTransition.cause_ratio(  s    {{9??I??r!   c                 B    U R                  [        R                  X5      $ )z8The effect ratio of the ``purview`` given ``mechanism``.)r   r   r=   ri   s      r    effect_ratioTransition.effect_ratio,  s    {{9++Y@@r!   c                 B    U R                   U   nUR                  X5      $ )zACompute the repertoire over the partition in the given direction.)r>   partitioned_repertoire)r?   r   	partitionr>   s       r    r   !Transition.partitioned_repertoire0  s!    Y',,YBBr!   c                 \    U R                  X5      nU R                  XUR                  5      $ )zLCompute the probability of the mechanism over the purview in
the partition.
)r   r   rk   )r?   r   r   rh   s       r    partitioned_probability"Transition.partitioned_probability5  s-     00F
%%iY=N=NOOr!   c                    [        S5      nU R                  XU5      n[        X#U R                  5       H  nU R	                  X5      n[        Xh-  5      n	[        R                  " U	S5      (       d  U	S:  a3  U(       d,  [        U R                  U5      UUUUUUU R                  SS9	s  $ [        U5      [        U	5      -
  [        R                  :  d  M  U	n[        U R                  U5      UUUUUUU R                  US9	n
M     W
$ )a  Find the ratio minimum information partition for a mechanism
over a purview.

Args:
    direction (str): |CAUSE| or |EFFECT|
    mechanism (tuple[int]): A mechanism.
    purview (tuple[int]): A purview.

Keyword Args:
    allow_neg (boolean): If true, ``alpha`` is allowed to be negative.
        Otherwise, negative values of ``alpha`` will be treated as if
        they were 0.

Returns:
    AcRepertoireIrreducibilityAnalysis: The irreducibility analysis for
    the mechanism.
infr   g        )	r8   r   rj   rk   r   r   r   r,   alpha)floatr   r   r,   r   r   r   eqr   r   absr
   EPSILON)r?   r   rj   rk   	allow_neg	alpha_minr   r   r   r   acrias              r    find_mipTransition.find_mip@  s   $ %L	&&yWE'	D<L<LMI&*&B&B'&#>?E xxq!!eai	9..y9''#' +,C $ 0 0
 
 IU+y/@/@@!	:..y9''#' +,C $ 0 0#
- NB r!   c                     U R                   U   nUR                  XU5       Vs/ s H5  n[        U5      R                  U R	                  U5      5      (       d  M3  UPM7     sn$ s  snf )a'  Return all purviews that could belong to the |MIC|/|MIE|.

Filters out trivially-reducible purviews.

Args:
    direction (str): Either |CAUSE| or |EFFECT|.
    mechanism (tuple[int]): The mechanism of interest.

Keyword Args:
    purviews (tuple[int]): Optional subset of purviews of interest.
)r>   potential_purviewsr4   ry   rz   )r?   r   rj   purviewsr>   rk   s         r    r   Transition.potential_purviews{  sh     Y'#)#<#<h$0
$07|$$T%9%9)%DE  $0
 	
 
s   2A#A#c                    ^ ^^^ T R                  TTU5      nU(       d  [        T R                  T5      TTS5      nO[        UUUU 4S jU 5       5      n[	        U5      $ )a)  Return the maximally irreducible cause or effect ratio for a
mechanism.

Args:
    direction (str): The temporal direction, specifying cause or
        effect.
    mechanism (tuple[int]): The mechanism to be tested for
        irreducibility.

Keyword Args:
    purviews (tuple[int]): Optionally restrict the possible purviews
        to a subset of the subsystem. This may be useful for _e.g._
        finding only concepts that are "about" a certain subset of
        nodes.

Returns:
    CausalLink: The maximally-irreducible actual cause or effect.
Nc              3   L   >#    U  H  nTR                  TTUT5      v   M     g 7frF   )r   )r   rk   r   r   rj   r?   s     r    r   .Transition.find_causal_link.<locals>.<genexpr>  s/      3)1g --	9g(13 3)1s   !$)r   r   r   maxr   )r?   r   rj   r   r   max_rias   ``` ` r    find_causal_linkTransition.find_causal_link  sb    ( **9iJ "4#7#7	#B#,i?G  3)13 3G
 '""r!   c                 B    U R                  [        R                  X5      $ )z'Return the actual cause of a mechanism.)r   r   r<   r?   rj   r   s      r    find_actual_causeTransition.find_actual_cause  s    $$Y__iJJr!   c                 B    U R                  [        R                  X5      $ )z(Return the actual effect of a mechanism.)r   r   r=   r   s      r    find_actual_effectTransition.find_actual_effect  s    $$Y%5%5yKKr!   c                 &    U R                   " U0 UD6$ )z8Backwards-compatible alias for :func:`find_causal_link`.)r   )r?   argskwargss      r    	find_miceTransition.find_mice  s    $$d5f55r!   )
r+   r*   r.   r7   r1   r/   r6   r)   r0   r>   )NFF)FF)(__name__
__module____qualname____firstlineno____doc__rC   rI   rM   rQ   rU   rY   r\   propertyr,   rb   re   rl   ro   rs   rv   rh   r   r   r   r   r   r~   rz   r   r   r   r   r   r   r   r   r   r   r   __static_attributes__r&   r!   r    r#   r#   -   s    +\ =B6
p(
 
& ( (	
H
DE23@(!"F8,H@AC
P6v
* ?D#(!#FKL6r!   r#   c           
          USL a$  [         R                  " U R                  U5      SS9nU Vs/ s H  nU R                  XUUS9PM     nn[	        [        SU5      5      $ s  snf )z?Return the set of all |CausalLinks| of the specified direction.FTnonempty)r   r   N)r   powersetr~   r   r   filter)
transitionr   
mechanismsr   r   rj   linkss          r    directed_accountr     s~     U^^J$@$@$K-13

 $% $I 	##I8.7 	$ 	9# 
 % 6$.//%s   A c                     U[         R                  :w  a  [        X5      $ [        [        U [         R                  5      [        U [         R
                  5      -   5      $ )zReturn the set of all causal links for a |Transition|.

Args:
    transition (Transition): The transition of interest.

Keyword Args:
    direction (Direction): By default the account contains actual causes
        and actual effects.
)r   BIDIRECTIONALr   r   r<   r=   )r   r   s     r    accountr     sP     I+++
66#J	@#J	0@0@AB C Cr!   c                     [        U  Vs/ s H  o"R                  PM     sn5      [        U Vs/ s H  o"R                  PM     sn5      -
  $ s  snf s  snf )zReturn the distance between two accounts. Here that is just the
difference in sum(alpha)

Args:
    A1 (Account): The first account.
    A2 (Account): The second account

Returns:
    float: The distance between the two accounts.
)sumr   )A1A2actions      r    account_distancer     sF     B/B&B/0B/B&B/01 2//s
   AA
c           	          U R                  U5      n[        XC5      n[        R                  SU5        [	        X%5      n[        [        U[        R                  5      UUUU US9$ )z:Find the |AcSystemIrreducibilityAnalysis| for a given cut.zFinished evaluating %s.)r   r   r   partitioned_accountr   r1   )	re   r   logdebugr   r   r   r   r   )r   r1   unpartitioned_accountr   cut_transitionr   r   s          r    _evaluate_cutr     se      ))#.N!.<II'-2HE)E6++,%/ r!   c              #   *  #    U R                   R                  nU[        R                  L a  [	        5       n[        [        U [        R                  5      [        U [        R                  5      5       HD  n[        R                  " UR                  U5      5      nXS;  d  M/  UR                  U5        Uv   MF     gU R                  U5      nU R                  U5      n[        XgU R                   5       H  n[#        XU R                   5      v   M     g7f)z(A list of possible cuts to a transition.N)r)   sizer   r   r4   r   	_get_cutsr<   r=   r   np_hashable
cut_matrixaddr~   rz   r   r,   r   )	r   r   nyieldedr1   cmrj   rk   r   s	            r    r   r     s     AI+++%:y?":y/?/?@BC""3>>!#45B B	B 00;	,,Y7'	(2(>(>@II*2H2HII@s   BD!A2Dc                    [         R                  " USS9  [        R                  SU 5        U (       d!  [        R                  SU 5        [	        X5      $ [
        R                  " U R                  R                  U R                  5      (       d!  [        R                  SU 5        [	        X5      $ [        R                  S5        [        X5      n[        R                  S5        U(       d   [        R                  S5        [	        X5      $ [        X5      n[        X0X5      nUR                  5       n[        R                  S	U 5        [        R                  S
U5        U$ )af  Return the minimal information partition of a transition in a specific
direction.

Args:
    transition (Transition): The candidate system.

Returns:
    AcSystemIrreducibilityAnalysis: A nested structure containing all the
    data from the intermediate calculations. The top level contains the
    basic irreducibility information for the given subsystem.
T)allow_bizCalculating big-alpha for %s...z7Transition %s is empty; returning null SIA immediately.zD%s is not strongly/weakly connected; returning null SIA immediately.z Finding unpartitioned account...zFound unpartitioned account.z?Empty unpartitioned account; returning null AC SIA immediately.z,Finished calculating big-ac-phi data for %s.RESULT: 
%s)r   r   r   infor   r	   is_weakr)   r   r0   r   r   r   ComputeACSystemIrreducibilityrun_sequential)r   r   r   cutsengineresults         r    siar  !  s    y40HH.
;  !+	-J22
 2 2 5 5 * 7 79 9  !+	-J22II01#J:II,-    	!J22Z+D*)<F""$FHH;ZHIInf%Mr!   c                   8    \ rS rSrSrSrS r\S 5       rS r	Sr
g)	r   iM  zComputation engine for AC SIAs.zEvaluating AC cutsc                 (    [        X[        S5      S9$ )Nr   )r   )r   r   )r?   r   r   r   s       r    empty_result*ComputeACSystemIrreducibility.empty_resultS  s    JuFFr!   c                     [        XX25      $ rF   )r   )r1   r   r   r   s       r    r   %ComputeACSystemIrreducibility.computeV  s    Z.COOr!   c                 4    U(       d	  SU l         U$ X:  a  U$ U$ )NTdone)r?   new_siamin_sias      r    process_result,ComputeACSystemIrreducibility.process_resultZ  s!    DINNr!   r  N)r   r   r   r   r   descriptionr  staticmethodr   r  r   r&   r!   r    r   r   M  s-    ) 'KG P P	r!   r   c           	   #     #    [         R                  " [         R                  " U R                  S5      S:  5      S   n[         R                  " [         R                  " U R                  S5      S:  5      S   n[        R
                  " USS9 H/  n[        R
                  " USS9 H  n [        XUXV5      v   M     M1     g! [        R                   a     M3  f = f7f)zEReturn a generator of all **possible** transitions of a network.
    r   r   Tr   N)	npwherer   r   r   r   r#   r   StateUnreachableError)r)   r*   r+   possible_causespossible_effectscause_subseteffect_subsets          r    transitionsr  l  s      hhrvvgjj!4q89!<Oxxwzz1 5 9:1=F"^^,<tLM !-> > M G
 33 s*   B'C*C9	CCCCCc                    ^ [         R                  " U 5        U4S j[        XU5       5       n[        [	        [        SU5      SS95      $ )z7Return a tuple of all irreducible nexus of the network.c              3   <   >#    U  H  n[        UT5      v   M     g 7frF   )r  )r   r   r   s     r    r   nexus.<locals>.<genexpr>  s"      =; ,6C
I&&;r   NT)reverse)r   
is_networkr  r2   r3   r   )r)   r*   r+   r   siass      ` r    nexusr"    sB      ={;=DtT*D9::r!   c                 "   [         R                  " U 5        [        R                  S5        [	        XX#5      nU(       a  [        U5      nO[        XUSS5      n[        XS5      n[        R                  S5        [        R                  SU5        U$ )z'Return the causal nexus of the network.zCalculating causal nexus...r&   z"Finished calculating causal nexus.r   )	r   r   r   r   r"  r   r#   r   r   )r)   r*   r+   r   r  null_transitions         r    causal_nexusr%    st      HH*+7+AFV$;B8o9HH12IInf%Mr!   c           	      r   / n/ nSnSnU  H  nUR                   [        R                  :X  aM  UR                  SR	                  [        UR                  S5      5      UR                  X5R                  /5        Mn  UR                   [        R                  :X  aM  UR                  SR	                  [        UR                  S5      5      UR                  XER                  /5        M  [        R                   " UR                   5        M     [        [        U5      5       Vs/ s H  nX   X%   4PM     nnU$ s  snf )z%Format a true |CauseEffectStructure|.z<--z-->z{0:.4f}   )r   r   r<   appendr|   r   r   rj   rk   r=   r   rangerX   )tc
cause_list	next_listcauseeffectevent	true_lists          r    nice_true_cesr1    s   JIEF??ioo-y//ekk10EF$}}F G__	 0 00i..uU[[!/DE#oov}}F G u/  $C
O464U #Y%564  66s   D4c                 x    [         R                  S5        [        XX#U5      n[        U[        R
                  US9$ )NzCalculating true causes ...r   )r   r   r#   r   r   r<   )r)   previous_statecurrent_stater9   r   r   s         r    _actual_causesr6    s5    HH*+u>J J	JOOr!   c                 x    [         R                  S5        [        XX#U5      n[        U[        R
                  US9$ )NzCalculating true effects ...r3  )r   r   r#   r   r   r=   )r)   r5  
next_stater9   r   r   s         r    _actual_effectsr9    s7    HH+,GJuMJI$$= =r!   c                    ^^^	 [        XUXE5      m[        XUXE5      m[        S T 5       5      [        S T 5       5      -  m	T	(       d  gU	4S jnU" T5      mU" T5      m[        UU4S j[	        T	5       5       5      $ )zCFind all events (mechanisms with actual causes and actual effects).c              3   8   #    U  H  oR                   v   M     g 7frF   rj   r   cs     r    r   events.<locals>.<genexpr>  s     @-Q[[-   c              3   8   #    U  H  oR                   v   M     g 7frF   r<  r=  s     r    r   r?    s     A.Q[[.r@  r&   c                 n   > U  Vs0 s H"  nUR                   T;   d  M  UR                   U_M$     sn$ s  snf )zlFilter out unidirectional occurences and return a dictionary keyed
by the mechanism of the cause or effect.
r<  )actual_causes_or_effectsoactual_mechanismss     r    r:   events.<locals>.index  sB     )A 5(@1;;"33 Q(@ 5 	5 5s   22c              3   H   >#    U  H  n[        TU   TU   5      v   M     g 7frF   )r   )r   mactual_causesactual_effectss     r    r   r?    s,      53Q }Q'):;;3s   ")r6  r9  r4   r2   r3   )
r)   r4  r5  r8  r9   r   r:   rI  rJ  rE  s
          @@@r    eventsrK    s     #7M#(6M$WZ%*8N@-@@A.AAB 5 -(M>*N 5 !235 5 5r!   c                    U R                   nU R                  nU R                  n[        X1XRU5      nU(       d  [        R                  S5        g[        U Vs/ s H  owR                  PM     snU Vs/ s H  owR                  PM     sn-   5      n[        R                  S5        [        R                  SU5        U$ s  snf s  snf )a  Set of all sets of elements that have true causes and true effects.

.. note::
    Since the true |CauseEffectStructure| is always about the full system,
    the background conditions don't matter and the subsystem should be
    conditioned on the current state.
z%Finished calculating, no echo events.Nz!Finished calculating true events.r   )
r)   r0   r8   rK  r   r   r2   actual_causeactual_effectr   )		subsystemr4  r8  r)   r9   r8   _eventsr/  r  s	            r    true_cesrQ    s     G""EOOEWeGG89G<G5&&G<5<=WE''W=> ?FHH01IInf%M ==s   B>3C
c                     U(       a  UR                   R                  nO6U(       a  UnO,[        R                  " X5      nUR                   R                  n[	        XX#U5      $ )aq  Return all mechanisms that have true causes and true effects within the
complex.

Args:
    network (Network): The network to analyze.
    previous_state (tuple[int]): The state of the network at ``t - 1``.
    current_state (tuple[int]): The state of the network at ``t``.
    next_state (tuple[int]): The state of the network at ``t + 1``.

Keyword Args:
    indices (tuple[int]): The indices of the major complex.
    major_complex (AcSystemIrreducibilityAnalysis): The major complex. If
        ``major_complex`` is given then ``indices`` is ignored.

Returns:
    tuple[Event]: List of true events in the major complex.
)rO  r0   r   major_complexrK  )r)   r4  r5  r8  indicesrS  r9   s          r    true_eventsrU    sP    * ''44	--gE''44'=eLLr!   c           	         U(       a  UR                   R                  nO6U(       a  UnO,[        R                  " X5      nUR                   R                  n[	        [
        R                  " USS95      nU R                  n[        XX#XS9$ )a  Set of all mechanisms that are in the major complex but which have true
causes and effects within the entire network.

Args:
    network (Network): The network to analyze.
    previous_state (tuple[int]): The state of the network at ``t - 1``.
    current_state (tuple[int]): The state of the network at ``t``.
    next_state (tuple[int]): The state of the network at ``t + 1``.

Keyword Args:
    indices (tuple[int]): The indices of the major complex.
    major_complex (AcSystemIrreducibilityAnalysis): The major complex. If
        ``major_complex`` is given then ``indices`` is ignored.

Returns:
    tuple(actions): List of extrinsic events in the major complex.
Tr   r3  )rO  r0   r   rS  listr   r   rK  )	r)   r4  r5  r8  rT  rS  mc_nodesr   	all_nodess	            r    extrinsic_eventsrZ    su    &  **77	--gE **77ennX=>J$$I'=4 4r!   )FFFr   )NN):r   logging	itertoolsr   mathr   r   numpyr   r   r   r   r	   r
   r   r   r   modelsr   r   r   r   r   r   r   r   r   r   r   r   r   rO  r   	getLoggerr   r   r#   r   r   r   r   r   r   r  parallel	MapReducer   r  r"  r%  r1  r6  r9  rK  rQ  rU  rZ  r&   r!   r    <module>rd     s-  
"         ( ( ( ( &  !-
P6 P6p HM$0 #,"9"9 C,2  &33&J* (55 )XG$4$4$>$> >( ++; %220, $P  %= 5:6 -1MB 264r!   