Recursive exclusion: how complexes divide a substrate#
Download this page as a Jupyter notebook
The exclusion postulate says that candidate systems sharing units cannot both exist: among overlapping candidates, only one specifies its cause–effect structure. PyPhi applies the postulate recursively (Marshall et al., 2023): candidates are walked in descending order of system integrated information \(\varphi_s\), each accepted complex claims its units, and a candidate excluded by an accepted complex no longer exists, so it cannot exclude anything else in turn.
This recursion has a consequence worth stating explicitly: a complex can coexist with an overlapping candidate of higher \(\varphi_s\), as long as that candidate was itself excluded by some other complex. This tutorial builds a small substrate where that happens, finds its complexes, and reads the exclusion records and selection margins that document who beat whom.
import numpy as np
import pyphi
pyphi.config.progress_bars = False
A chain of decaying couplings#
Four units A, B, C, D in a chain, with reciprocal coupling strengths that decay along it: A–B couple strongly (0.6), B–C moderately (0.3), C–D weakly (0.15). Each unit’s probability of turning on is a baseline 0.05, plus 0.05 times its own state, plus the coupled inputs.
n = 4
weights = np.zeros((n, n))
weights[0, 1] = weights[1, 0] = 0.6
weights[1, 2] = weights[2, 1] = 0.3
weights[2, 3] = weights[3, 2] = 0.15
for i in range(n):
weights[i, i] = 0.05
tpm = np.zeros((2**n, n))
for row in range(2**n):
state = np.array([(row >> k) & 1 for k in range(n)])
tpm[row] = 0.05 + weights @ state
substrate = pyphi.Substrate(tpm, node_labels=("A", "B", "C", "D"))
state = (0, 0, 0, 0)
By construction the \(\varphi_s\) landscape is a chain: \(\{A,B\} > \{B,C\} > \{C,D\}\), with \(\{B,C\}\) overlapping both of its neighbors.
Finding the complexes#
found = substrate.complexes(state)
for complex_ in found:
print(complex_.node_indices, float(complex_.phi))
(0, 1) 0.14800116288755374
(2, 3) 0.03710393588291759
Both \(\{A,B\}\) and \(\{C,D\}\) are complexes. A non-recursive reading of exclusion would reject \(\{C,D\}\): it overlaps \(\{B,C\}\), which has higher \(\varphi_s\). But \(\{B,C\}\) overlaps \(\{A,B\}\), which has higher \(\varphi_s\) still — so \(\{B,C\}\) is excluded first, and once excluded it does not exist and has no standing to exclude \(\{C,D\}\). The recursion carves the substrate from the top down, and \(\{C,D\}\) is the maximum among the candidates that remain.
Excluded candidates with higher φₛ#
Each complex records the overlapping candidates excluded in its favor:
from pyphi import numerics
cd = found[1]
phi = float(cd.phi)
for record in sorted(cd.excluded, key=lambda r: -r.phi):
beaten = record.phi < phi or numerics.eq(record.phi, phi)
print(f"{record.node_indices} φₛ={record.phi:.4f} [{'beaten' if beaten else 'excluded earlier'}]")
(1, 2) φₛ=0.1041 [excluded earlier]
(0, 1, 2) φₛ=0.1000 [excluded earlier]
(0, 1, 2, 3) φₛ=0.0564 [excluded earlier]
(1, 2, 3) φₛ=0.0546 [excluded earlier]
(2,) φₛ=0.0227 [beaten]
(3,) φₛ=0.0208 [beaten]
\(\{C,D\}\)’s records contain candidates with higher \(\varphi_s\) than \(\{C,D\}\) itself — \(\{B,C\}\) among them. They have more integrated information than the complex, and were excluded by a different complex before this one was accepted. They document the recursion at work: they were never rivals that \(\{C,D\}\) had to beat.
Selection margins#
How decisively did each complex win? The exclusion_margin of a
Complex reports the \(\varphi_s\) gap to the
best overlapping rival the complex actually beat — candidates excluded
earlier by another complex do not enter the margin:
for complex_ in found:
print(
complex_.node_indices,
f"φₛ={float(complex_.phi):.4f}",
f"margin={complex_.exclusion_margin:.4f}",
)
(0, 1) φₛ=0.1480 margin=0.0439
(2, 3) φₛ=0.0371 margin=0.0144
\(\{A,B\}\) beat its strongest overlapping rival, \(\{B,C\}\), by about
\(0.04\). \(\{C,D\}\)
beat only the singletons \(\{C\}\) and \(\{D\}\), and its margin measures the
gap to the best of them. A margin of zero (equivalently,
complex_.effectively_tied) would mean an overlapping rival tied at the
configured precision and the selection was decided by criteria beyond
\(\varphi_s\); see
Control tie-breaking for how ties are resolved.
References#
Marshall W, et al. (2023). System integrated information. Entropy 25(2):334, Algorithm A1.
Albantakis L et al. (2023). Integrated information theory (IIT) 4.0. PLoS Computational Biology 19(10):e1011465 (the exclusion postulate).