Skip to content

Add a kron subcommand (tensor-concatenate two Pauli strings) #3

Description

@GiggleLiu

Add a kron subcommand (tensor-concatenate two Pauli strings)

Background

qsym-rs is a deliberately small symbolic Pauli-algebra engine and qsym CLI — the worked example
in QudeLeap's beginner-training "how to develop" lab (see docs/design/qsym-rs.md for the full
roadmap this issue is one part of). Its engine (crate qsym_rs, src/lib.rs) represents a "Pauli
string" as PauliString { ops: Vec<Pauli>, phase: u8 }, one Pauli (I/X/Y/Z) per qubit,
with phase the exponent k in i^k (0..=3, printed as +/+i/-/-i).

The engine's existing mul and the commutes predicate both require equal-length operands
(they assert it), because multiplying or comparing Pauli strings is site-by-site. But a common
operation on independent subsystems is the tensor product (): laying two Pauli strings over
disjoint qubits, side by side, into one longer string over the combined register. For example,
an X on qubit 0 tensored with ZZ on qubits 1–2 is the 3-qubit operator XZZ. Unlike mul,
tensoring must accept operands of different lengths — that is the whole point. There is no
engine method or CLI surface for it today.

Task

Two additive changes, mirroring the existing commute/mul patterns:

  1. Engine (src/lib.rs): add pub fn kron(&self, other: &PauliString) -> PauliString that
    concatenates the operators (self.ops followed by other.ops) and combines the phase as
    (self.phase + other.phase) % 4 — the same phase-composition rule mul already uses. Crucially,
    kron must not assert or require equal lengths (it concatenates; it does not multiply
    site-by-site). Do not change mul, commutes, parse, or the field layout.
  2. CLI (src/main.rs): add a Kron { a: String, b: String } variant to Cmd and a match arm.
    Parse both operands the same way the other subcommands do (a bad Pauli letter still exits
    non-zero with an error: ... message), but — unlike mul/commutedo not reject a length
    mismatch; pass both to kron and print the result via Display. (Concretely: call
    PauliString::parse on each operand directly rather than going through the shared parse_pair
    guard, which rejects unequal lengths.)

Verification

Run each command with cargo run -q --, trimming trailing newlines before comparing stdout:

  1. cargo run -q -- kron X ZZ → stdout is exactly +XZZ, exit code 0. (Length-1 tensored with
    length-2 gives a length-3 string; both operands parse with phase 0, so the combined phase is
    0+.)
  2. cargo run -q -- kron IY XZ → stdout is exactly +IYXZ, exit code 0 (a length-2 ⊗ length-2
    concatenation, in order).
  3. Negative control (the whole point of kron): cargo run -q -- kron X ZZ succeeds where
    the equal-length commands reject the same shapes — confirm cargo run -q -- mul X ZZ exits
    non-zero with error: length mismatch, while kron X ZZ exits 0. If your kron reused
    parse_pair's equal-length guard (or the engine's assert_eq!), it would reject or panic here
    instead of returning +XZZ.
  4. Engine unit test (phase composition, which the CLI can't reach — parse always yields phase
    0):
    add a #[test] to tests/engine.rs asserting that
    PauliString { ops: vec![Pauli::X], phase: 1 }.kron(&PauliString { ops: vec![Pauli::Z], phase: 2 })
    displays as -iXZ (ops = [X, Z], phase (1 + 2) % 4 = 3-i). Run cargo test / make check → the new test passes alongside the existing suite.
  5. Regression check: cargo run -q -- mul XZ ZX still prints exactly +YY — confirms this
    addition is purely additive and the existing Mul arm and parse_pair guard are untouched.

Checks 1+2 require the real concatenation and order; check 3 requires kron to not reuse the
equal-length guard (a stub that did would fail it); check 4 requires the phase actually to combine,
not be hardcoded to 0.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions