Skip to content

Fix Python stubs' docstrings. - #168

Open
Juan M. Bello-Rivas (jmbr) wants to merge 22 commits into
mainfrom
fix/pyi-docstrings
Open

Juan M. Bello-Rivas (jmbr) wants to merge 22 commits into
mainfrom
fix/pyi-docstrings

Conversation

@jmbr

@jmbr Juan M. Bello-Rivas (jmbr) commented Aug 19, 2026

Copy link
Copy Markdown
Member

Fixes #167 and other unreported issues. See individual commits for a breakdown.

Perhaps the best solution would be to maintain the docstrings solely from the Rust side and extract them programmatically but that belongs in a different PR.

Some of the problems have to do with panics on the Rust side, those deserve deeper scrutiny.

  • docs(binar): describe BitMatrix resize behavior
  • docs(paulimer): correct Clifford generator ordering
  • docs(paulimer): clarify controlled-Pauli semantics
  • docs(paulimer): correct Pauli phase convention
  • docs(paulimer): correct permutation direction
  • docs(paulimer): correct default Clifford support
  • docs(paulimer): correct simulation capacity contracts
  • docs(paulimer): describe OutcomeSpecific sign parity
  • docs(paulimer): clarify zero-outcome simulation
  • docs(paulimer): correct simulation protocol membership
  • docs(paulimer): correct simulation qubit count
  • docs(paulimer): clarify random bit counts
  • docs(paulimer): mark all_commute as a promise
  • docs(paulimer): include phases in PauliGroup size
  • docs(paulimer): correct weighted distribution contract
  • docs(paulimer): qualify correlated fault coupling
  • docs(paulimer): document FaultySimulation hint dependency
  • docs(binar): correct inverse exceptions
  • docs(binar): describe rows as a list
  • docs(binar): use Python matrix multiplication syntax
  • docs(paulimer): remove unsupported opcode guidance
  • docs(python): correct native repr examples

Juan M. Bello-Rivas and others added 22 commits August 19, 2026 07:51
Claim: BitMatrix.reshape changes the matrix dimensions while preserving in-bounds coordinates, zero-filling new entries, and dropping truncated entries; it does not require the element count to remain constant.

Source: binar/bindings/python/src/py_bitmatrix.rs calls BitMatrix::resize, whose contract is documented in binar/src/matrix/bitmatrix.rs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Claim: CliffordUnitary.from_preimages and from_images consume alternating X/Z entries for each qubit.

Source: paulimer/src/clifford/generic_algos.rs::clifford_from_preimages takes two consecutive entries as X_i and Z_i; clifford_from_images delegates to it before inversion.

Validation: The existing one-qubit binding tests pass [Z, X] for a Hadamard, consistent with alternating order.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Claim: A generalized controlled-Pauli uses commuting Paulis, is symmetric in them, and applies either Pauli on the -1 eigenspace of the other.

Source: paulimer/src/clifford/generic_algos.rs::clifford_left_mul_eq_controlled_pauli requires commuting inputs; paulimer/tests/clifford_test.rs::controlled_pauli_via_pauli_exp_test gives the symmetric decomposition.

Validation: For the standard eigenvalue factor (1 + c + t - c*t)/2, c=+1 gives identity and c=-1 gives t.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Claim: The exposed exponent is the modulo-4 exponent in i**exponent * X^a Z^b, while phase is the coefficient in tensor-product I/X/Y/Z form.

Source: paulimer/src/pauli/generic.rs defines PauliUnitary as i^k * X^a tensor Z^b; py_dense_pauli.rs and py_sparse_pauli.rs remove the Y contribution when computing phase.

Validation: DensePauli("Y") exposes exponent 1 and phase 1, which contradicts the previous exp(i*pi*exponent/4) description.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Claim: permutation[i] identifies the source copied into destination i within the supplied support, rather than the destination of source i.

Source: paulimer/src/clifford/clifford_impl.rs::left_mul_permutation assigns old preimages at support[permutation[i]] to support[i].

Validation: paulimer/tests/clifford_test.rs::left_mul_permutation_generic_test uses [2, 0, 1] to invert the corresponding forward three-cycle.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Claim: apply_clifford with supported_by=None targets every current simulation qubit, not a range inferred from the Clifford.

Source: paulimer/bindings/python/src/simulation.rs builds support as 0..self.qubit_count() when supported_by is absent.

Validation: Applying a one-qubit Clifford without support to a three-qubit simulation reaches the core support-length assertion.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Claim: with_capacity creates num_qubits active qubits; OutcomeFreeSimulation and OutcomeSpecificSimulation ignore num_random_outcomes and share outcome/random-outcome capacity.

Source: pauliverse/src/outcome_complete_simulation.rs::with_capacity stores qubit_count; outcome_free_simulation.rs::with_capacity and outcome_specific_simulation.rs::with_capacity ignore their random-outcome argument.

Validation: with_capacity(3, 0, 5) reports qubit_count 3 for all backends, but random_outcome_capacity 0 for the free and specific backends.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Claim: OutcomeSpecificSimulation.is_stabilizer uses sign_parity to compare the stabilizer sign with the XOR of selected concrete outcomes.

Source: pauliverse/src/outcome_specific_simulation.rs::is_stabilizer_with_conditional_sign computes total_parity over the selected outcome ids and compares it with the preimage phase.

Validation: With a sampled true random bit, Z stabilizes |0> without sign_parity but fails the conditional-sign check using that outcome.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Claim: with_zero_outcomes supplies zero whenever a random measurement result is needed; it does not pre-populate or suppress measurement records.

Source: pauliverse/src/outcome_specific_simulation.rs::new_with_zero_outcomes constructs the simulator with ZeroBitIterator.

Validation: Measuring Z after H records one outcome whose value is false.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Claim: FaultySimulation does not satisfy the Python StabilizerSimulation protocol exposed by this stub.

Source: paulimer/bindings/python/src/py_faulty_simulation.rs does not expose qubit_capacity, outcome_capacity, random count/capacity, reserve methods, or is_stabilizer.

Validation: Structural attribute inspection reports those protocol members absent from FaultySimulation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Claim: qubit_count reports the current logical extent, while qubit_capacity reports the allocation limit before resizing.

Source: the common Python getter delegates to Simulation::qubit_count; each backend updates qubit_count from the maximum support and reports storage separately through qubit_capacity.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Claim: random_outcome_count includes explicit allocate_random_bit calls, and random_bit_count is an exact alias on the Python surface.

Source: paulimer/bindings/python/src/simulation.rs::random_bit_count directly returns self.random_outcome_count(); backend allocate_random_bit implementations increment that same count.

Validation: After one explicit allocation, both properties report 1 on all three outcome simulation backends.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Claim: PauliGroup does not verify all_commute; it caches the supplied Boolean as the group abelianity result.

Source: paulimer/src/pauli_group.rs::with_promise initializes is_abelian_promise directly, and is_abelian returns that cached value.

Validation: Passing all_commute=False for commuting ZI and IZ generators makes is_abelian report false.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Claim: log2_size is binary_rank plus the base-2 rank contributed by the generated pure-phase subgroup.

Source: paulimer/src/pauli_group.rs::log2_size adds 0, 1, or 2 according to whether phases().len() is 1, 2, or 4.

Validation: A group generated only by iI has binary_rank 0 and log2_size 2.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Claim: weighted checks only that the total weight is positive; callers must enforce finite non-negative weights, and a failed total assertion surfaces as pyo3_runtime.PanicException.

Source: pauliverse/src/noise.rs::PauliDistribution::weighted asserts total > 0 and then builds the CDF without validating individual weights.

Validation: Weights [-1, 2] are accepted and exposed as probabilities [-1, 2], while total weight zero raises PanicException.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Claim: correlation_id gives each fault the same seeded random stream; exact trigger and sample coupling additionally requires matching probability, conditional execution, and random-value mapping.

Source: pauliverse/src/frame_propagator.rs::inject_noise reinitializes SmallRng from base_seed + correlation_id for each fault; noise.rs::sample maps draws through each distribution-specific sampler or CDF.

Validation: Same-length weighted CDFs [0.9, 1] and [0.1, 1] map draws between 0.1 and 0.9 to different indices.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Claim: FaultySimulation ignores outcome_count and instruction_count unless qubit_count is also provided.

Source: paulimer/bindings/python/src/py_faulty_simulation.rs matches only tuple variants whose first element is Some(q); every tuple beginning with None falls back to FaultySimulation::new().

Validation: FaultySimulation(outcome_count=8, instruction_count=9) remains the zero-capacity default representation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Claim: inv raises ValueError only for nonsquare input; a square singular matrix reaches a Rust assertion and surfaces through PyO3 as PanicException.

Source: binar/bindings/python/src/linalg.rs explicitly checks squareness, then calls BitMatrix::inverted; binar/src/matrix/aligned_bitmatrix.rs asserts full rank.

Validation: Inverting [[1, 1], [1, 1]] raises pyo3_runtime.PanicException in the native binding.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Claim: BitMatrix.rows materializes and returns a Python list rather than a lazy iterator.

Source: binar/bindings/python/src/py_bitmatrix.rs::rows returns Vec<PyBitVec>, which PyO3 converts to list.

Validation: type(BitMatrix.identity(1).rows) is list; the return annotation is updated with the docstring.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Claim: The echelon transform invariant is T @ original == RREF on the Python API; T * original performs elementwise AND.

Source: binar/bindings/python/src/py_bitmatrix.rs implements __matmul__ with matrix multiplication and __mul__ with bitwise matrix AND.

Validation: For [[0, 1], [1, 1]], transform @ original equals matrix while transform * original does not.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Claim: UnitaryOpcode values are accepted by simulation apply_unitary methods, but CliffordUnitary.from_name requires a string.

Source: paulimer/bindings/python/src/simulation.rs extracts PyUnitaryOp; py_clifford.rs::from_name accepts &str and parses it.

Validation: Passing UnitaryOpcode.Hadamard to from_name raises TypeError because it cannot be cast to str.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Claim: BitMatrix, BitVector, and DensePauli repr methods return their display strings rather than constructor-style representations.

Source: binar py_bitmatrix.rs and py_bitvec.rs, plus paulimer py_dense_pauli.rs, define the corresponding __repr__ methods.

Validation: Native repr values are "01\\n10\\n", "BitVector('[0110]')", "ZZZ", and "Z" for the documented examples.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@jmbr

Copy link
Copy Markdown
Member Author

Copilot Rerun build pipeline

Copilot AI commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Copilot Rerun build pipeline

Build pipeline rerun passed after installing the repo-required toolchain and Python deps; the relevant workspace and Python binding tests are green. No source changes were required.

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.

Wrong docstring in CliffordUnitary::from_images

3 participants