mirror of
https://github.com/saymrwulf/autoresearch-quantum.git
synced 2026-05-14 20:37:51 +00:00
Quality fixes: - Add deprecation warnings to 5 silent no-op legacy wrappers in assess.py - Remove dead code in tracker.py score_by_section (unused first loop) - Remove unused variable in assess.py _check_order - Fix .gitignore: add progress JSONs, checkpoints, .coverage, .DS_Store, LaTeX aux - Fix "all three plans" → "all four plans" in learning_objectives.md - Add teaching/ package to README project tree - Add compendium to README paper tree Testing: - Add 43 unit tests for teaching/assess.py and tracker.py (quiz, predict_choice, reflect, order, checkpoint_summary, legacy wrapper deprecation warnings, tracker scoring, persistence, mastery calculation) - Add notebook execution test suite (nbclient): all 11 notebooks execute without errors in a fresh kernel, structural validation (valid JSON, has code cells, has assessments, section parameters, learning objectives document) - Overall test count: 185 passing (was 107), coverage: 85% (was ~25% in tests) Toolchain: - Add pytest-cov, ruff, nbclient, nbformat to dev dependencies - Add ruff config (E, F, W, I, UP, B, SIM rules) - Add coverage config with term-missing output - Fix all ruff lint issues across src/ and tests/ (import sorting, unused imports) - Fix Plan D notebook paths (configs/rungs → ../../configs/rungs) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
103 lines
3.7 KiB
Python
103 lines
3.7 KiB
Python
"""Tests for codes.four_two_two — all seed and encoder styles."""
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
from qiskit import QuantumCircuit
|
|
from qiskit.quantum_info import Statevector
|
|
|
|
from autoresearch_quantum.codes.four_two_two import (
|
|
STABILIZERS,
|
|
apply_magic_seed,
|
|
build_encoder,
|
|
build_preparation_circuit,
|
|
)
|
|
|
|
# ── apply_magic_seed ─────────────────────────────────────────────────────────
|
|
|
|
def test_magic_seed_h_p() -> None:
|
|
qc = QuantumCircuit(1)
|
|
apply_magic_seed(qc, 0, "h_p")
|
|
sv = Statevector.from_instruction(qc)
|
|
assert abs(sv.probabilities().sum() - 1.0) < 1e-9
|
|
|
|
|
|
def test_magic_seed_ry_rz() -> None:
|
|
qc = QuantumCircuit(1)
|
|
apply_magic_seed(qc, 0, "ry_rz")
|
|
sv = Statevector.from_instruction(qc)
|
|
assert abs(sv.probabilities().sum() - 1.0) < 1e-9
|
|
|
|
|
|
def test_magic_seed_u_magic() -> None:
|
|
qc = QuantumCircuit(1)
|
|
apply_magic_seed(qc, 0, "u_magic")
|
|
sv = Statevector.from_instruction(qc)
|
|
assert abs(sv.probabilities().sum() - 1.0) < 1e-9
|
|
|
|
|
|
def test_magic_seed_all_styles_equivalent() -> None:
|
|
"""All seed styles should produce the same single-qubit state (up to global phase)."""
|
|
states = []
|
|
for style in ["h_p", "ry_rz", "u_magic"]:
|
|
qc = QuantumCircuit(1)
|
|
apply_magic_seed(qc, 0, style)
|
|
states.append(Statevector.from_instruction(qc))
|
|
# Check fidelity between pairs
|
|
from qiskit.quantum_info import state_fidelity
|
|
for i in range(len(states)):
|
|
for j in range(i + 1, len(states)):
|
|
fid = state_fidelity(states[i], states[j])
|
|
assert fid == pytest.approx(1.0, abs=1e-6), (
|
|
f"Seed styles produced different states: fidelity={fid}"
|
|
)
|
|
|
|
|
|
def test_magic_seed_unsupported_raises() -> None:
|
|
qc = QuantumCircuit(1)
|
|
with pytest.raises(ValueError, match="Unsupported seed style"):
|
|
apply_magic_seed(qc, 0, "unknown_style")
|
|
|
|
|
|
# ── build_encoder ────────────────────────────────────────────────────────────
|
|
|
|
def test_encoder_cx_chain() -> None:
|
|
enc = build_encoder("cx_chain")
|
|
assert enc.num_qubits == 4
|
|
|
|
|
|
def test_encoder_cz_compiled() -> None:
|
|
enc = build_encoder("cz_compiled")
|
|
assert enc.num_qubits == 4
|
|
|
|
|
|
def test_encoder_styles_equivalent() -> None:
|
|
"""Both encoder styles should produce equivalent encoded states."""
|
|
from qiskit.quantum_info import state_fidelity
|
|
sv_cx = Statevector.from_instruction(build_preparation_circuit("h_p", "cx_chain"))
|
|
sv_cz = Statevector.from_instruction(build_preparation_circuit("h_p", "cz_compiled"))
|
|
fid = state_fidelity(sv_cx, sv_cz)
|
|
assert fid == pytest.approx(1.0, abs=1e-6)
|
|
|
|
|
|
def test_encoder_unsupported_raises() -> None:
|
|
with pytest.raises(ValueError, match="Unsupported encoder style"):
|
|
build_encoder("unknown_encoder")
|
|
|
|
|
|
# ── Stabilizer checks for all style combos ───────────────────────────────────
|
|
|
|
@pytest.mark.parametrize("seed,encoder", [
|
|
("h_p", "cx_chain"),
|
|
("h_p", "cz_compiled"),
|
|
("ry_rz", "cx_chain"),
|
|
("ry_rz", "cz_compiled"),
|
|
("u_magic", "cx_chain"),
|
|
("u_magic", "cz_compiled"),
|
|
])
|
|
def test_all_style_combos_satisfy_stabilizers(seed: str, encoder: str) -> None:
|
|
state = Statevector.from_instruction(build_preparation_circuit(seed, encoder))
|
|
for name, stab in STABILIZERS.items():
|
|
exp = state.expectation_value(stab)
|
|
assert abs(exp - 1.0) < 1e-6, (
|
|
f"Stabilizer {name} failed for seed={seed}, encoder={encoder}: exp={exp}"
|
|
)
|