Macro units and grains#

A substrate’s cause–effect power need not be maximal at the grain of its smallest parts. Grouping micro units into coarser macro units, and reading their state over a window of several micro updates, can raise a system’s integrated information \(\varphi_s\) by orders of magnitude. IIT takes this seriously: the units that actually exist for a substrate are the ones — at whichever spatial grouping and temporal window — that maximize \(\varphi_s\), its intrinsic units (Marshall et al., 2026). This page covers what a macro unit is, the criteria a candidate unit must satisfy, and how candidates at different grains compete in a single exclusion cascade. It maps each notion onto the types in pyphi.macro; for a worked walkthrough see the intrinsic-units tutorial, and for running and bounding the search see Search across grains.

Units at a grain#

A macro unit is a coarser unit built from finer ones. Formally it is a tuple of its direct constituents, an update grain, and a mapping — the core of the unit tuple of Eq. 12 (Marshall et al., 2026): the constituents \(V\) are the finer units it is composed of; the update grain \(\tau'\) is the number of micro updates over which those constituents are read; and the mapping \(g'\) is a truth table that assigns a binary macro state to each joint sequence-state of the constituents over the window (Eq. 14),

\[ g' : \Omega^{\tau'}_{V} \to \{0, 1\}. \]

At update grain 1 the mapping reads a single joint state of the constituents. At grain \(\tau' > 1\) it reads a sequence of \(\tau'\) successive constituent states, so the macro state depends on the trajectory, not only on the final micro state.

Two mapping families cover the common cases. A coarse-graining groups the constituents’ joint states by their ON-count: the macro unit is ON exactly for a chosen set of counts, at update grain 1. A blackboxing reads out a designated subset of output constituents at the final update of the window, and admits any update grain. These are the two families the default search enumerates; the full space is every non-constant mapping. A unit with \(|V|\) constituents at update grain \(\tau'\) has \(2^{\,2^{\tau'|V|}} - 2\) non-constant mappings (Marshall et al., 2026, in the text after Eq. 14). A mapping and its complement describe the same unit with its two macro state labels swapped, so PyPhi counts mappings up to complementation, which halves that number to

\[ 2^{\,2^{\tau'|V|} - 1} - 1 . \]

The count grows doubly exponentially in \(\tau'|V|\), which is why the search enumerates the two mapping families by default and bounds the exhaustive alternative.

Macro units stack into a hierarchy. A unit’s constituents may themselves be macro units (meso units), so that its mapping composes with theirs down to the micro units at the bottom (Marshall et al., 2026, Eq. 15; Fig. 3E). Building a unit directly on micro constituents leaves more mappings to choose from than building it on meso constituents, whose mappings are already fixed; which construction wins is decided, like everything else, by whichever maximizes \(\varphi_s\). Because each level contributes its own update grain, the grains multiply down the hierarchy: a search that allows update grains up to max_update_grain over max_depth levels reads each unit over a window of up to max_update_grain ** max_depth micro updates, which is exactly the length of micro history such a search requires.

In PyPhi a macro unit is a MacroUnit with attributes constituents, update_grain, and mapping. The two families are built by coarse_grain() (from ON-count classes) and blackbox() (from output constituents, at any grain); micro_unit() is the trivial identity unit over a single micro index, the base of the hierarchy.

The intrinsic-unit criteria#

To exist as one unit, a candidate’s constituent system — the constituents evaluated over the full universe, with everything else held as background — must satisfy the same postulates a complex does. Two criteria capture this (Marshall et al., 2026, Eqs. 16–17). First, the constituent system must be integrated: its own system integrated information is positive,

\[ \varphi_s(v^{J}) > 0 \qquad \text{(Eq. 16).} \]

Second, it must be maximally irreducible within its footprint: no competing system that could be built from the same micro units and background may match or beat it,

\[ \varphi_s(v^{J}) > \varphi_s(v') \quad \text{for every competitor } v' \qquad \text{(Eq. 17).} \]

Both criteria are properties of the pair (constituents, background) alone. A candidate’s mapping and update grain do not enter either inequality, so all variants of one decomposition — whatever their mappings and update grains — share a single verdict. The grain is chosen later, by the exclusion competition, not here.

judge_candidate() applies both inequalities to a candidate’s \(\varphi_s\) and its evaluated competitor set and returns a UnitVerdict. The verdict’s reason is a Reason: VALID when both criteria hold, NOT_INTEGRATED when the constituent system has \(\varphi_s = 0\) and so fails the integration criterion of Eq. 16, and NOT_MAXIMAL or TIED when a competitor beats or ties it under Eq. 17. Micro units are exempt — they are the base case of the recursion, and count as units even when their own \(\varphi_s\) is zero.

Exclusion across grains#

Many candidate units, at many grains, can each be integrated. They cannot all exist over the same substrate: the exclusion postulate requires a definite set of units (Albantakis et al., 2023). IIT resolves the competition by keeping, among overlapping candidates, only the one whose system integrated information is maximal, and this applies across grains — a micro candidate system and a macro candidate system over the same micro units are rivals, not separate answers (Marshall et al., 2026, Eq. 20).

The procedure is recursive (Albantakis et al., 2023, Eqs. 24–26; Marshall et al., 2023, Algorithm A1): the candidate with maximal \(\varphi_s\) is accepted as a complex, every candidate overlapping it is excluded, and the search repeats on what remains until the substrate is exhausted. The papers state this over one substrate at one grain; across grains they state the criterion, that two candidates overlap when they share micro units (Marshall et al., 2026, Eq. 20). PyPhi puts the two together as one cascade over micro footprints, so candidates at every grain compete on the same basis. Each candidate’s footprint is the set of micro units it ultimately covers; the cascade walks candidates in descending \(\varphi_s\), accepts the maximal one, drops every remaining candidate whose footprint overlaps it, and continues on what is left. Because an excluded candidate is removed from the search, it has no standing to exclude anything else in turn. A complex can therefore coexist with an overlapping candidate of higher \(\varphi_s\), when that candidate was excluded earlier by a different complex. Ties within a tier escalate to the composition measure Φ, and a tier that still ties fails exclusion outright: none of its members becomes a complex, and their units remain available to lower-\(\varphi_s\) candidates further down.

This cascade is the same pyphi.condensation machinery the micro complex search uses; the macro search feeds it candidate systems at every grain. It returns a ComplexesResult whose winners are Complex objects. Each winner reports an exclusion_margin — the \(\varphi_s\) gap to the best overlapping rival it beat — and records the candidates excluded in its favor, including any with higher \(\varphi_s\) that an earlier complex had already excluded; those do not enter the margin. A margin of zero means a rival tied at the configured precision, so the selection was decided by criteria beyond \(\varphi_s\). For how the recursion resolves overlapping candidates step by step, see the recursive-exclusion tutorial; for reading margins and controlling how ties are broken, see Control tie-breaking.

From theory to the library#

Notion

Type or function

A macro unit: constituents, update grain, mapping (Eqs. 12, 14)

MacroUnit

Coarse-graining and blackboxing mapping families

coarse_grain(), blackbox()

The trivial micro unit

micro_unit()

A system of macro units, evaluated by the IIT pipeline

MacroSystem

The intrinsic-unit criteria (Eqs. 16–17)

judge_candidate(), UnitVerdict, Reason

The recursive exclusion cascade (Eq. 20)

pyphi.condensation

The bounded search across grains

pyphi.macro.complexes(), pyphi.analyze(substrate, state, grains=...)

The search bounds and their cost estimate

SearchBounds, SearchEstimate

The search result: complexes, ties, and evaluation records

ComplexesResult

References#

  • Marshall W, Findlay G, Albantakis L, Tononi G (2026). Intrinsic units: identifying a system’s causal grain. Neuroscience of Consciousness 2026(1): niag013. https://doi.org/10.1093/nc/niag013

  • Albantakis L, Barbosa L, Findlay G, Grasso M, et al. (2023). Integrated information theory (IIT) 4.0. PLOS Computational Biology 19(10): e1011465.

  • Marshall W, Grasso M, Mayner WGP, Tononi G, Albantakis L (2023). System integrated information. Entropy 25(2): 334.