Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -597,12 +597,18 @@ sparse-autoencoder dictionaries report *graded* within-cluster similarity
and **sub-cluster structure** that flat block tiers cannot express.
[`examples/larql-polysemantic-hierarchical.q.orca.md`](examples/larql-polysemantic-hierarchical.q.orca.md)
lifts the encoding to **bond-dimension-2 matrix product states** via a
`Ry(q0,α); CNOT(q0,q1); Ry(q1,β); CNOT(q1,q2); Ry(q2,γ)` staircase. The
12 concepts are organized as a two-level hierarchy — 3 super-groups
(`animals`, `fruits`, `vehicles`) × 2 sub-clusters × 2 concepts — and the
Gram matrix splits into **four** ordered tiers: self 1.000 /
sub-cluster-mate 0.882 / super-group-sibling [0.47, 0.54] / cross-group
[0.12, 0.25].
`Ry(q0,α); CNOT(q0,q1); Ry(q1,α+β); CNOT(q1,q2); Ry(q2,β+γ)` staircase
with **cross-coupled angle expressions** — the q1 and q2 rotations bind
linear combinations of the bound parameters rather than single
parameters. The cross-coupling is what produces a non-factorized Gram:
the bare staircase `Ry(q0,α)·CNOT·Ry(q1,β)·CNOT·Ry(q2,γ)·|000>`
*factorizes* as `∏_k cos((θ_{i,k} − θ_{j,k})/2)` across qubits despite
having Schmidt rank 2 — a surprising mathematical fact documented in the
`fix-mps-encoding-non-factorizing` change. The 12 concepts are organized
as a two-level hierarchy — 3 super-groups (`animals`, `fruits`,
`vehicles`) × 2 sub-clusters × 2 concepts — and the Gram matrix splits
into **four** ordered tiers: self 1.000 / sub-cluster-mate 0.882 /
super-group-sibling {0.335, 0.593, 0.753} / cross-group [0.000, 0.178].

The optional `q_orca.compiler.concept_gram_mps.compute_concept_gram_mps(machine)`
helper produces the Gram matrix for machines following the CNOT-staircase
Expand Down
64 changes: 38 additions & 26 deletions demos/larql_polysemantic_hierarchical/demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,22 @@
4-tier) Gram signatures.

Topology: 3 super-groups × 2 sub-clusters × 2 concepts = 12 concepts on a
3-qubit register. Each concept is encoded as the bond-2 MPS

|c_i> = Ry(q0, α_i) CNOT(q0, q1) Ry(q1, β_i) CNOT(q1, q2) Ry(q2, γ_i) |000>

with α ∈ {0, 2π/3, 4π/3} (super-group), β ∈ {-0.75, +0.75} (sub-cluster),
and γ ∈ {-0.35, +0.35} (concept). This produces analytic
`|<c_i|c_j>|²` tiers — self 1.0, sub-cluster-mate 0.882, super-group-
sibling [0.47, 0.54], cross-group [0.12, 0.25] — distinct from the
flat-block clusters demo's three uniform tiers.
3-qubit register. Each concept is encoded as the *cross-coupled* bond-2
MPS

|c_i> = Ry(q0, α_i) CNOT(q0, q1) Ry(q1, α_i + β_i) CNOT(q1, q2) Ry(q2, β_i + γ_i) |000>

with α ∈ {0, 2π/3, 4π/3} (super-group), β ∈ {-0.5, +0.5} (sub-cluster),
and γ ∈ {-0.35, +0.35} (concept). The q1 and q2 rotations bind linear-
combination angles (`α + β`, `β + γ`) — the cross-coupling is what makes
the Gram non-factorized. The bare staircase (single-parameter Ry on each
qubit) factorizes as `∏_k cos((θ_{i,k} − θ_{j,k})/2)` despite Schmidt rank
2 — a known counter-example documented in the
`fix-mps-encoding-non-factorizing` design note. The cross-coupled
encoding produces analytic `|<c_i|c_j>|²` tiers — self 1.000, sub-
cluster-mate 0.882 (uniform), super-group-sibling {0.335, 0.593, 0.753},
cross-group [0.000, 0.178] — distinct from the flat-block clusters
demo's three uniform tiers.

Usage:
pip install q-orca[quantum]
Expand Down Expand Up @@ -75,21 +82,21 @@ def banner(title: str) -> None:


def heatmap_tier(value: float) -> str:
"""4-tier ASCII heatmap: '#' ≥ 0.7, 'o' ∈ [0.3, 0.7), '.' ∈ [0.1, 0.3), blank < 0.1."""
"""4-tier ASCII heatmap: '#' ≥ 0.7, 'o' ∈ [0.3, 0.7), '.' ∈ [0.05, 0.3), blank < 0.05."""
v = abs(value)
if v >= 0.7:
return "#"
if v >= 0.3:
return "o"
if v >= 0.1:
if v >= 0.05:
return "."
return " "


def print_gram_heatmap(gram: np.ndarray) -> None:
"""Print |gram|² as a 4-tier 12×12 ASCII heatmap with hierarchy labels."""
gsq = np.abs(gram) ** 2
print(" |gram[i,j]|² (# ≥ 0.7, o ∈ [0.3, 0.7), . ∈ [0.1, 0.3), blank < 0.1)")
print(" |gram[i,j]|² (# ≥ 0.7, o ∈ [0.3, 0.7), . ∈ [0.05, 0.3), blank < 0.05)")
print(" ", "".join(f"{i:>3}" for i in range(12)))
for i in range(12):
row = "".join(f" {heatmap_tier(gsq[i, j])}" for j in range(12))
Expand All @@ -100,23 +107,23 @@ def print_gram_heatmap(gram: np.ndarray) -> None:
def build_query_circuit(prepare_angles: tuple, query_angles: tuple):
"""Build a prepare(feature) + query(concept) circuit on 3 qubits.

Mirrors the .q.orca.md effect strings exactly:
prepare: Ry(q0, a); CNOT(q0,q1); Ry(q1, b); CNOT(q1,q2); Ry(q2, c)
query: Ry(q2,-c); CNOT(q1,q2); Ry(q1,-b); CNOT(q0,q1); Ry(q0,-a)
Mirrors the .q.orca.md effect strings exactly (cross-coupled bond-2):
prepare: Ry(q0, a); CNOT(q0,q1); Ry(q1, a+b); CNOT(q1,q2); Ry(q2, b+c)
query: Ry(q2,-(b+c)); CNOT(q1,q2); Ry(q1,-(a+b)); CNOT(q0,q1); Ry(q0,-a)
"""
from qiskit import QuantumCircuit

qc = QuantumCircuit(3, 3)
a, b, c = prepare_angles
qc.ry(a, 0)
qc.cx(0, 1)
qc.ry(b, 1)
qc.ry(a + b, 1)
qc.cx(1, 2)
qc.ry(c, 2)
qc.ry(b + c, 2)
a2, b2, c2 = query_angles
qc.ry(-c2, 2)
qc.ry(-(b2 + c2), 2)
qc.cx(1, 2)
qc.ry(-b2, 1)
qc.ry(-(a2 + b2), 1)
qc.cx(0, 1)
qc.ry(-a2, 0)
qc.measure(range(3), range(3))
Expand Down Expand Up @@ -221,11 +228,11 @@ def main() -> None:
)
print(
f" super-group-sib |<c_i|c_j>|² : min={min(super_sib):.4f} "
f"max={max(super_sib):.4f} (n={len(super_sib)}; analytic [0.47, 0.54])"
f"max={max(super_sib):.4f} (n={len(super_sib)}; analytic {{0.335, 0.593, 0.753}})"
)
print(
f" cross-group |<c_i|c_j>|² : min={min(cross):.4f} "
f"max={max(cross):.4f} (n={len(cross)}; analytic [0.12, 0.25])"
f"max={max(cross):.4f} (n={len(cross)}; analytic [0.000, 0.178])"
)

# 4. Per-concept polysemy column (|f> = |dog>)
Expand Down Expand Up @@ -276,13 +283,18 @@ def main() -> None:
print(" tiers : 1.000 / 0.720 / ≲ 0.09")
print(" (self / cluster-mate / cross-cluster — three flat tiers)")
print()
print(" rung-1 (this demo, MPS bond-2 CNOT staircase):")
print(" |c_i> = Ry(q0,α) CNOT(q0,q1) Ry(q1,β) CNOT(q1,q2) Ry(q2,γ) |000>")
print(" tiers : 1.000 / 0.882 / [0.47, 0.54] / [0.12, 0.25]")
print(" rung-1 (this demo, cross-coupled bond-2 MPS):")
print(" |c_i> = Ry(q0,α) CNOT(q0,q1) Ry(q1,α+β) CNOT(q1,q2) Ry(q2,β+γ) |000>")
print(" tiers : 1.000 / 0.882 / {0.335, 0.593, 0.753} / [0.000, 0.178]")
print(" (self / sub-mate / super-sib / cross-group — four ordered tiers)")
print()
print(" The CNOT staircase entangles adjacent qubits, lifting the")
print(" block diagonal of rung-0 into a graded two-level hierarchy.")
print(" The bond-2 CNOT staircase is a *prerequisite* for this hierarchy")
print(" (it gives the register an entangled MPS structure), but it is not")
print(" sufficient on its own — the bare staircase Ry(q0,α)·CNOT·Ry(q1,β)·")
print(" CNOT·Ry(q2,γ)·|000> has a Gram identical to rung-0's product-state")
print(" Gram despite Schmidt rank 2. The cross-coupled angle structure")
print(" (α+β on q1, β+γ on q2) is what breaks the factorization and")
print(" produces the graded four-tier hierarchy.")

raise SystemExit(0 if passed else 1)

Expand Down
38 changes: 34 additions & 4 deletions docs/research/polysemantic-encoding-beyond-product-states.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,25 @@ per-axis independent. The moment you leave, that factorization
dies. Inner products become contractions, amplitudes become
correlated, and the analytic helper needs more machinery.

> **Caveat: Schmidt rank > 1 ≠ non-factorized overlap.** "Leaving
> the product-state manifold" is *necessary* for non-factorized
> overlap but *not sufficient*. The bare Ry-CNOT staircase
> `Ry(q0,α)·CNOT·Ry(q1,β)·CNOT·Ry(q2,γ)·|000>` produces a state
> with Schmidt rank 2 across both bipartitions (it is genuinely
> entangled), yet its Gram still factorizes as
> `∏_k cos((θ_{i,k} − θ_{j,k})/2)` — exactly the rung-0 inner-
> product map. Entanglement of the *state* and factorization of
> the *inner-product map* are independent properties; the latter
> depends on whether each angle parameter affects only one
> qubit's amplitude (factorizes) or leaks across qubits
> (doesn't). The bare staircase happens to keep each parameter
> on its primary qubit, so the leak is zero. The fix used by the
> canonical rung-1 example below is to bind *linear combinations*
> of the angle parameters to the q1 and q2 rotations (e.g.,
> `Ry(q1, α + β)`, `Ry(q2, β + γ)`), forcing each parameter to
> leak into more than one qubit's amplitude. Detailed proof in
> `openspec/changes/fix-mps-encoding-non-factorizing/design.md`.

### The unification analogy

The transition from product states to entangled states maps cleanly
Expand Down Expand Up @@ -161,9 +180,10 @@ more expressive than rung 0, but still polynomial in all parameters.

#### Rung 1 — MPS with bond dimension 2

- **Effect**: `Ry(qs[0], a); CNOT(qs[0], qs[1]); Ry(qs[1], b); CNOT(qs[1], qs[2]); Ry(qs[2], c)`
- **Effect (canonical, cross-coupled)**: `Ry(qs[0], a); CNOT(qs[0], qs[1]); Ry(qs[1], a + b); CNOT(qs[1], qs[2]); Ry(qs[2], b + c)`
- **Parameters per concept**: `n` (same as rung 0, but they now
couple)
couple — and **must couple across qubits** for the Gram to
leave the rung-0 factorized form)
- **Overlap**: `O(n · χ⁶)` transfer-matrix contraction at χ=2 —
polynomial, closed-form-ish
- **Capacity at clean tiers**: `N = O(n³)` by available hierarchy
Expand All @@ -173,8 +193,18 @@ more expressive than rung 0, but still polynomial in all parameters.
- **What it cannot**: non-local correlations across the qubit line,
arbitrary 2-designs
- **Q-orca surface**: already-parsed gates (CNOT, Ry), multi-gate
effect string, same parametric-expansion path as rung 0
- **Proposed in**: `openspec/changes/add-mps-concept-encoding/`
effect string, linear-combination angle expressions, same
parametric-expansion path as rung 0
- **Note on the bare staircase.** The single-parameter variant
`Ry(qs[0], a); CNOT(qs[0], qs[1]); Ry(qs[1], b); CNOT(qs[1], qs[2]); Ry(qs[2], c)`
*factorizes* as `∏_k cos((θ_{i,k} − θ_{j,k})/2)` — its Gram is
identical to rung 0's despite the state having Schmidt rank 2
(see caveat box above). The cross-coupled-by-sum variant breaks
the factorization while staying within the bond-2 MPS family.
Both variants are accepted by `compute_concept_gram_mps`; the
canonical hierarchical example uses the cross-coupled variant.
- **Shipped in**: `examples/larql-polysemantic-hierarchical.q.orca.md`
(post-`fix-mps-encoding-non-factorizing`)

#### Rung 2 — hardware-efficient ansatz, depth L

Expand Down
Loading
Loading