Fix Python stubs' docstrings. - #168
Open
Juan M. Bello-Rivas (jmbr) wants to merge 22 commits into
Open
Juan M. Bello-Rivas (jmbr) wants to merge 22 commits into
Juan M. Bello-Rivas (jmbr) wants to merge 22 commits into
Conversation
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>
Juan M. Bello-Rivas (jmbr)
requested review from
Adam Paetznick (apaetz) and
Mathias Soeken (msoeken)
August 19, 2026 15:38
Mathias Soeken (msoeken)
approved these changes
Aug 19, 2026
Member
Author
|
Copilot Rerun build pipeline |
Contributor
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. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.