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().