Skip to content

emc()

Calculate effective measure complexity E and its range profile. E captures organization and correlations across different ranges of a sequence. Use it alongside h to study the balance between new information and the context connecting it.

emc(seq, partitions=1, alphabet=None, log_base=None,
    max_block_size=-1, jobs=0) -> tuple[float, list[float]]

Parameters

Parameter Default Behavior
seq required A supported sequence input, converted to bytes.
partitions 1 Accepted; has no effect.
alphabet None Does not change E or select its logarithm base.
log_base None Normalization base. Omitted: observed byte alphabet size, with a minimum of two. Pass 2 for base-two units. Values zero and one are treated as two.
max_block_size -1 Largest examined range in bytes. A positive M includes ranges 1 through M; zero or a negative value selects the limit automatically from the input length.
jobs 0 Accepted; has no effect. Native workers use Rayon configuration.

See parameter types and errors for integer ranges and errors. max_block_size=None is not accepted: omit the argument or use a nonpositive integer for automatic selection.

Return value

Returns (value, summands):

Item Type Meaning
value float E: final level of the fitted range profile.
summands list[float] Nonnegative increases between successive fitted levels, in range order. Their sum is E.

For an explicit positive limit M, len(summands) is M. summands[l - 1] is the increase from fitted level l - 1 to level l, starting from level zero. A cumulative sum reconstructs the nondecreasing profile.

Calculate E and inspect its profile

import math
from itertools import accumulate
import lzcomplexity as lz

sequence = b"00010111" * 256
E, increments = lz.emc(sequence, log_base=2, max_block_size=8)
profile = list(accumulate(increments))

assert E == 3.2105712890625
assert len(increments) == 8
assert all(term >= 0 for term in increments)
assert math.isclose(sum(increments), E, abs_tol=1e-12)
assert profile[-1] == E

The profile shows where the fitted result increases as longer ranges are included. A zero increment means that the fitted profile is flat at that step.

Choose a maximum range

Choose ranges according to the patterns represented by the bytes. For one byte per sampled state, sixteen bytes correspond to sixteen consecutive observations. For UTF-8 text, bytes and characters can have different lengths.

Keep sequence length, encoding, logarithm base and maximum range the same when comparing samples. An explicit cap also makes the amount of work predictable. A longer maximum range does not guarantee a larger final E: changing the included ranges can change the fitted profile.

Inspect an automatically selected limit through the complete result:

import lzcomplexity as lz

result = lz.lz76(b"00010111" * 256, log_base=2)
selected_range = result["emc"]["max_block_size"]
assert selected_range == len(result["emc"]["summands"])

lz76() also exposes multi_information, the first-range contrast before the fitted profile. Use lz76() when those fields are needed together with h and the factorization.

Reproducibility and short inputs

The same input bytes and parameters give the same E and increments. Worker scheduling does not change the result. E can depend on the symbol encoding and alignment, so keep preprocessing consistent and retain the settings.

Constant inputs return E zero. Inputs of ten bytes or fewer also return zero with this calculation. Empty and one-byte inputs produce zero increments; an explicit positive cap still determines their list length. Use longer sequences when exploring E and its profile.

Related: effective measure complexity, reproducibility, h().