Skip to content

Add a phase subcommand (print the phase of a Pauli product) #11

Description

@PengPengUSTC

Add a phase subcommand (print the phase of a Pauli product)

Background

qsym-rs is a deliberately small symbolic Pauli-algebra engine and qsym CLI (see docs/design/qsym-rs.md). A PauliString carries an overall phase: u8 — the exponent k in i^k (0..=3, surfaced as +/+i/-/-i by PauliString::sign). This phase is the central quantity of symbolic Pauli algebra: it is the i^k that makes X·Y = iZ, and it accumulates element-wise in PauliString::mul (src/lib.rs).

The CLI exposes the product's full signed form via qsym mul XY II+iZI, but there is no script-friendly way to ask for only the phase exponent. A script that needs the phase of a product must parse the human-readable sign token out of mul's output and map +/+i/-/-i back to 0/1/2/3 itself. This is the exact gap that weight filled for the Pauli weight and len (#9) fills for the site count — a bare-integer, arithmetic-ready subcommand for a quantity the engine already computes.

Task

Add a new phase subcommand: qsym phase <A> <B>.

It takes two equal-length Pauli strings (the same shape as mul and commute), multiplies them, and prints only the resulting phase exponent as a decimal integer in 0..=3 followed by a newline. On a parse failure or a length mismatch, reuse the existing CLI error path: non-zero exit and error: ... on stderr.

This should be a CLI-only change in src/main.rs: add a Phase { a: String, b: String } variant to Cmd and a match arm that calls parse_pair(&a, &b)? (the shared length-mismatch guard), then pa.mul(&pb).phase, printing that integer. Do not change src/lib.rs.

Verification

  1. cargo run -q -- phase XY II → stdout is exactly 1, exit code 0. (X·Y = iZ at site 0, I·I = I at site 1 → phase 1.)
  2. Distinguishing fixture: cargo run -q -- phase YX ZZ → stdout is exactly 3. (Y·X = -iZ at site 0 → phase 3; a different value than example 1, so a hardcoded answer fails.)
  3. Second value: cargo run -q -- phase XY YZ → stdout is exactly 2. (X·Y = iZ → phase 1 at site 0, Y·Z = iX → phase 1 at site 1; 1+1 = 2 mod 4.)
  4. Negative control (bad input): cargo run -q -- phase XQZ II → exits non-zero and stderr contains error: not a Pauli letter. This proves the command parses via the normal path rather than skipping validation.
  5. Negative control (length mismatch): cargo run -q -- phase XY III → exits non-zero and stderr contains error: length mismatch. This proves it reuses the parse_pair guard shared with mul/commute.
  6. Regression check: cargo run -q -- mul XY II still prints exactly +iZI, and cargo run -q -- weight XIZ still prints exactly 2. No existing behavior changes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions