Skip to content

Declare what a project's numbers are written in, and convert on entry - #161

Merged
sotashimozono merged 1 commit into
mainfrom
feat/conventions
Sep 15, 2026
Merged

sotashimozono merged 1 commit into
mainfrom
feat/conventions

Conversation

@sotashimozono

Copy link
Copy Markdown
Member

VariableKey pins WHICH quantity and WHERE. It does not pin how the number is written, so relations/entanglement.jl's header

Entropies here are in NATS.

is prose that nothing reads. An app counting bits hands its entropies straight to a relation written in nats.

What this adds

Three parts, kept separate because different people declare them:

verb who declares it says
canonical_convention(Q) the owner of Q what the relations here are written in
conventions(...) the project what ITS numbers are written in
bag(cs, pairs...) nobody converts on entry

bag is the only door, so a relation never sees the project's convention and there is no call that skips the conversion.

cs = conventions(AbstractEntanglementMeasure => Bits)
bag(cs, entanglement_entropy(1, 2) => 1.75)     # stored as 1.75 * log(2), in nats

The axis is a type, not an entry in a list

A new convention is a Convention subtype plus a convert_convention method, with nothing to change in this package. test/core/test_conventions.jl proves it with a quantity, an axis and a conversion all defined outside src/.

Which quantities declare the shipped axis

LogBase, with Nats and Bits. Twelve of the sixteen entanglement measures, selected by whether the definition in this package contains a logarithm:

canonical_convention
Nats VonNeumann, FermionicEE, Renyi, MutualInformation, ConditionalEntropy, RelativeEntropy, MeasurementEntropy, MarkovEntropy, TripartiteInformation, TopologicalEE, LogNegativity, Page
nothing Tsallis, Concurrence, Tangle, ThreeTangle

The four have no logarithm to take a base of. TsallisEntropy is (1 - Tr ρ^q)/(q - 1); the other three are a wavefunction amplitude and its squares. That is why the declaration is per quantity and a supertype sweep skips them rather than claiming a base they do not have, and why naming one of them concretely is an error.

What it changes

region_report's maximum-entropy bound at local_dim = 2, two qubits, ceiling 2 bits and 2 ln 2 = 1.386 nats:

S undeclared declared Bits
1.75, legal in bits FAIL, slack -0.3637 pass, slack +0.1733
2.50, over the ceiling in bits too FAIL, slack -1.1137 FAIL, slack -0.3466

Row 1 is a false alarm today. Row 2 is the control: declaring the convention does not make an impossible entropy pass.

Mutation: replacing the LogBase conversion with return v fails 4 assertions across 3 testsets, including both rows.

Additive (git diff -- src/ | grep -E "^-[^-]" is empty), so 0.7.14 -> 0.7.15.

🤖 Generated with Claude Code

A VariableKey pins WHICH quantity and WHERE. It does not pin how the number is
written, so relations/entanglement.jl's "Entropies here are in NATS" is prose
that nothing reads, and an app counting bits hands its entropies straight to a
relation written in nats.

Three parts, kept separate because different people declare them:
canonical_convention(Q) says what the relations here are written in,
conventions(...) says what a project's values are written in, and bag(cs, ...)
converts between them on entry, so a relation never sees the project's
convention and there is no call that skips the conversion.

The axis is a type, not an entry in a list: a new convention is a subtype plus a
convert_convention method, with nothing to change in this package. The test
proves that with a quantity, an axis and a conversion all defined outside src/.

Shipped axis: LogBase, with Nats and Bits. Twelve of the sixteen entanglement
measures declare it, selected by whether the definition in this package contains
a logarithm:

| canonical_convention | |
|---|---|
| Nats | VonNeumann, FermionicEE, Renyi, MutualInformation, ConditionalEntropy, RelativeEntropy, MeasurementEntropy, MarkovEntropy, TripartiteInformation, TopologicalEE, LogNegativity, Page |
| nothing | Tsallis, Concurrence, Tangle, ThreeTangle |

The four have no logarithm to take a base of (Tsallis is (1 - Tr p^q)/(q - 1),
and the other three are wavefunction amplitudes and their squares), which is why
the declaration is per quantity rather than by supertype.

What it changes, on region_report's maximum-entropy bound at local_dim = 2, two
qubits, ceiling 2 bits and 2 ln 2 = 1.386 nats:

| S | undeclared | declared Bits |
|---|---|---|
| 1.75, legal in bits | FAIL, slack -0.3637 | pass, slack +0.1733 |
| 2.50, over in bits too | FAIL, slack -1.1137 | FAIL, slack -0.3466 |

The second row is the control: declaring the convention does not make an
impossible entropy pass.

Mutation: replacing the LogBase conversion with `return v` fails 4 assertions
across 3 testsets, including both rows above.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

📚 Docs preview: https://qatlashub.github.io/AbstractQAtlas.jl/previews/PR161/

(updates on each push to this PR)

@codecov

codecov Bot commented Sep 15, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.67442% with 1 line in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/core/conventions.jl 97.29% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@sotashimozono
sotashimozono merged commit 8cb2eb3 into main Sep 15, 2026
26 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant