Skip to main content

Statevector

Struct Statevector 

Source
pub struct Statevector {
    pub num_qubits: usize,
    /* private fields */
}
Expand description

Quantum statevector representing a pure quantum state.

A statevector describes the quantum state of an N-qubit system as a vector of 2^N complex amplitudes. The state |ψ⟩ = Σᵢ αᵢ|i⟩ is stored with αᵢ as the amplitude for basis state |i⟩ (i in binary representation).

§Memory Layout

The data vector uses contiguous memory layout (compatible with C/NumPy), where the amplitude at index i corresponds to basis state |i⟩ with qubit indices mapping to bits from least significant (qubit 0) to most.

§Memory Layout

The data buffer uses a 64-byte aligned allocation so that SIMD kernels (AVX2, SSE2) can safely use aligned load/store instructions.

§Example

use cqlib_core::qis::Statevector;

// Create a 2-qubit state in |00⟩
let sv = Statevector::new(2);
assert_eq!(sv.num_qubits, 2);
assert_eq!(sv.data().len(), 4); // 2^2 amplitudes

// |00⟩ state: amplitude 1.0 at index 0, 0.0 elsewhere
assert_eq!(sv.data()[0], num_complex::Complex64::new(1.0, 0.0));

Fields§

§num_qubits: usize

Number of qubits in the system.

Implementations§

Source§

impl Statevector

Source

pub fn data(&self) -> &[Complex64] ⓘ

Returns the complex amplitudes as a shared slice.

Length is 2^num_qubits. The amplitude at index i is the coefficient of basis state |i⟩ in the computational basis.

§Example
use cqlib_core::qis::Statevector;

let sv = Statevector::new(2); // |00⟩
assert_eq!(sv.data().len(), 4);
assert_eq!(sv.data()[0], num_complex::Complex64::new(1.0, 0.0));
Source

pub fn data_mut(&mut self) -> &mut [Complex64] ⓘ

Returns the complex amplitudes as a mutable slice.

Mutating the slice can break normalization; callers are responsible for preserving a valid statevector.

Source

pub fn new(num_qubits: usize) -> Self

Creates a new statevector initialized to the |0…0⟩ state.

The statevector represents the quantum state as a vector of 2^N complex amplitudes, where N is the number of qubits. All amplitudes are initialized to zero except the first element (|0…0⟩) which is set to 1.0.

§Arguments
  • num_qubits - Number of qubits in the system
§Returns

A new Statevector instance in the ground state

§Example
use cqlib_core::qis::Statevector;

let sv = Statevector::new(2); // |00⟩ state
assert_eq!(sv.num_qubits, 2);
assert_eq!(sv.data().len(), 4); // 2^2 amplitudes
§Panics

Panics if the dimension is unrepresentable or allocation fails. Use Self::try_new to receive an error instead.

Source

pub fn try_new(num_qubits: usize) -> Result<Self, QisError>

Creates the ground state, returning an error for an unrepresentable dimension or a failed allocation.

§Errors

Returns QisError::InvalidParameterValue for an unrepresentable dimension, or QisError::UnsupportedOperation if allocation fails.

Source

pub fn from_state( num_qubits: usize, initial_state: Vec<Complex64>, ) -> Result<Self, QisError>

Creates a statevector from initial amplitudes with normalization check.

§Arguments
  • num_qubits - Number of qubits in the system
  • initial_state - Vector of 2^N complex amplitudes
§Errors

Returns an error if:

  • initial_state length doesn’t match 2^num_qubits
  • State is not normalized (sum of probabilities ≠ 1.0 within a dimension-scaled tolerance)
§Example
use cqlib_core::qis::Statevector;
use num_complex::Complex64;

// Create |+0⟩ = (|00⟩ + |10⟩)/√2
let amps = vec![
    Complex64::new(std::f64::consts::FRAC_1_SQRT_2, 0.0), // |00⟩
    Complex64::new(0.0, 0.0),                             // |01⟩
    Complex64::new(std::f64::consts::FRAC_1_SQRT_2, 0.0), // |10⟩
    Complex64::new(0.0, 0.0),                             // |11⟩
];
let sv = Statevector::from_state(2, amps);
Source

pub fn from_circuit(circuit: &Circuit) -> Result<Self, QisError>

Constructs a statevector by simulating a quantum circuit.

Executes the circuit gates sequentially to evolve the initial |0…0⟩ state. Complex gates are decomposed before execution.

§Arguments
  • circuit - The quantum circuit to simulate
§Returns
  • Ok(Statevector) - The resulting state after circuit execution
  • Err(QisError) - If the circuit contains unsupported operations (control flow gates, symbolic parameters) or decomposition fails
§Supported Instructions
  • Standard single and multi-qubit gates
  • Controlled gates (CX, CY, CZ, CRX, CRY, CRZ)
  • Multi-controlled gates (CCX/Toffoli)
  • Unitary gates with matrix representation
  • Barriers and delays (ignored)
§Example
use cqlib_core::circuit::{Circuit, Qubit};
use cqlib_core::qis::Statevector;

// Create Bell state: |Φ+⟩ = (|00⟩ + |11⟩)/√2
let mut circuit = Circuit::new(2);
circuit.h(Qubit::new(0)).unwrap();
circuit.cx(Qubit::new(0), Qubit::new(1)).unwrap();

let sv = Statevector::from_circuit(&circuit).unwrap();
Source

pub fn apply_circuit(&mut self, circuit: &Circuit) -> Result<(), QisError>

Applies a quantum circuit to this statevector in-place.

The circuit’s resolved global phase is applied, retaining nonzero residuals. Once bound to circuit qubit IDs, subsequent circuits must have the same IDs in the same order. The mapping is committed only on success; gates completed before an error are not rolled back.

As in from_circuit, terminal measurements are ignored. A measured qubit used by a later gate or Reset is rejected before the state is changed. Independent gates, repeated measurements, Barrier, Delay, and Store are allowed.

The circuit is first decomposed into basic gates via Circuit::decompose, then each operation is applied sequentially to the current state.

§Arguments
  • circuit - The circuit to apply. Must have the same number of qubits as this statevector.
§Returns
  • Ok(()) - If all operations were applied successfully
  • Err(QisError) - If the circuit cannot be simulated
§Errors
§Supported Instructions
  • Standard single and multi-qubit gates
  • Controlled gates (CX, CY, CZ, CRX, CRY, CRZ)
  • Multi-controlled gates (CCX / Toffoli)
  • Unitary gates with an explicit matrix representation
  • Reset
  • Barriers and delays (ignored)
  • Measurement output declarations from Circuit::measure* (ignored)
Source

pub fn apply_standard_gate( &mut self, gate: StandardGate, qubits: &[usize], params: &[f64], ) -> Result<(), QisError>

Applies a standard gate to the statevector.

Internal dispatcher that routes to specialized implementations based on gate type.

§Arguments
  • gate - The standard gate to apply
  • qubits - Target qubit indices
  • params - Gate parameters (for parameterized gates)
Source

pub fn probabilities(&self) -> Vec<f64>

Computes the measurement probability distribution over all basis states.

Returns P(|i⟩) = |αᵢ|² for each basis state |i⟩. Uses parallel iteration for large statevectors.

§Returns

Vector of probabilities summing to 1.0 (within floating-point precision).

§Example
use cqlib_core::qis::Statevector;

let mut sv = Statevector::new(1);
sv.apply_h(0);
let probs = sv.probabilities();
// |+⟩ state: P(|0⟩) = P(|1⟩) = 0.5
assert!((probs[0] - 0.5).abs() < 1e-10);
assert!((probs[1] - 0.5).abs() < 1e-10);
Source

pub fn apply_single_qubit_gate( &mut self, qubit: usize, matrix: [[Complex64; 2]; 2], ) -> Result<(), QisError>

Applies an arbitrary single-qubit gate.

General-purpose method for applying any 2x2 unitary matrix. For standard gates, prefer specialized methods (apply_h, apply_x, etc.) which have optimized implementations.

§Arguments
  • qubit - Target qubit index
  • matrix - 2x2 unitary matrix [[u00, u01], [u10, u11]]
§Errors

Returns QisError::IndexOutOfBounds if qubit is out of bounds.

§Example
ⓘ
use cqlib_core::qis::Statevector;
use num_complex::Complex64;

let mut sv = Statevector::new(1);
// Apply a custom rotation
let matrix = [
    [Complex64::new(0.0, 0.0), Complex64::new(1.0, 0.0)],
    [Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0)],
];
sv.apply_single_qubit_gate(0, matrix); // Equivalent to X gate
Source

pub fn apply_two_qubit_gate( &mut self, q0: usize, q1: usize, matrix: [[Complex64; 4]; 4], ) -> Result<(), QisError>

Apply a general two-qubit gate.

§Arguments
  • q0 - First qubit index (logical)
  • q1 - Second qubit index (logical)
  • matrix - 4x4 unitary matrix in the standard computational basis ordered as |00⟩, |01⟩, |10⟩, |11⟩ where the bits are (q0, q1). That is, matrix[i][j] is the amplitude of |i⟩ when input is |j⟩, with i = q0*2 + q1 (binary: q0 is MSB, q1 is LSB).
§Example - CNOT with q0 as control and q1 as target:

The CNOT gate flips the target when control is |1⟩: |00⟩ -> |00⟩, |01⟩ -> |01⟩, |10⟩ -> |11⟩, |11⟩ -> |10⟩

This corresponds to the matrix (rows/cols ordered as |00⟩, |01⟩, |10⟩, |11⟩):

[[1, 0, 0, 0],
 [0, 1, 0, 0],
 [0, 0, 0, 1],
 [0, 0, 1, 0]]
Source

pub fn apply_unitary_gate( &mut self, qubits: &[usize], matrix: &Array2<Complex64>, ) -> Result<(), QisError>

Applies an arbitrary n-qubit unitary gate.

General-purpose method for applying any 2^n × 2^n unitary matrix. Uses block-iteration with bit-manipulation for efficient index calculation. Supports parallel execution for large statevectors.

For standard gates, prefer specialized methods which are more optimized.

§Arguments
  • qubits - Slice of qubit indices the gate acts on (logical order)
  • matrix - The unitary matrix as a 2^n × 2^n ndarray
§Errors

Returns an error if:

  • Qubit indices are out of bounds
  • Qubit indices contain duplicates
  • Matrix dimensions don’t match 2^n × 2^n
§Example
ⓘ
use cqlib_core::qis::Statevector;
use ndarray::Array2;
use num_complex::Complex64;

let mut sv = Statevector::new(2);
// Create SWAP gate matrix
let swap = Array2::from_shape_vec(
    (4, 4),
    vec![
        Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0),
        Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0),
        Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0),
        Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0),
        Complex64::new(0.0, 0.0), Complex64::new(1.0, 0.0),
        Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0),
        Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0),
        Complex64::new(0.0, 0.0), Complex64::new(1.0, 0.0),
    ]
).unwrap();
sv.apply_unitary_gate(&[0, 1], &swap);
Source

pub fn apply_pauli_rotation( &mut self, pauli: &PauliString, theta: f64, ) -> Result<(), QisError>

Applies a native Pauli-string rotation in place.

The operation is

exp(-i * theta / 2 * P)

where P is a Hermitian PauliString. This fused kernel avoids decomposing a Pauli exponential into basis changes, a CNOT ladder, and an RZ gate. It is intended for high-frequency variational workloads.

§Errors

Returns an error if the Pauli string has a different number of qubits or carries an imaginary global phase (and is therefore not Hermitian).

Source

pub fn apply_x(&mut self, qubit: usize) -> Result<(), QisError>

Apply Pauli-X gate: bit flip Matrix: [[0, 1], [1, 0]] Cost: 0 muls, 0 adds, just memory swap.

Source

pub fn apply_y(&mut self, qubit: usize) -> Result<(), QisError>

Apply Pauli-Y gate Matrix: [[0, -i], [i, 0]] Cost: Manual component swapping (faster than complex mul).

Source

pub fn apply_z(&mut self, qubit: usize) -> Result<(), QisError>

Apply Pauli-Z gate: phase flip Matrix: [[1, 0], [0, -1]] Cost: Only processes half the array. 1 negation.

Source

pub fn apply_h(&mut self, qubit: usize) -> Result<(), QisError>

Apply Hadamard gate Matrix: 1/sqrt(2) * [[1, 1], [1, -1]] Creates superposition: H|0⟩ = (|0⟩ + |1⟩)/√2, H|1⟩ = (|0⟩ - |1⟩)/√2

Source

pub fn apply_u( &mut self, qubit: usize, theta: f64, phi: f64, lambda: f64, ) -> Result<(), QisError>

Apply U gate (generic single-qubit rotation) Matrix: [[cos(θ/2), -e^(iλ)sin(θ/2)], [e^(iφ)sin(θ/2), e^(i(φ+λ))cos(θ/2)]]

This is the most general single-qubit unitary (up to global phase). Parameters: theta: rotation angle phi: phase of the rotation axis lambda: second phase parameter

Source

pub fn apply_s(&mut self, qubit: usize) -> Result<(), QisError>

Apply S gate (Phase gate, Z^1/2) Matrix: [[1, 0], [0, i]]

Source

pub fn apply_sdg(&mut self, qubit: usize) -> Result<(), QisError>

Apply S† (S-dagger) gate Matrix: [[1, 0], [0, -i]]

Source

pub fn apply_t(&mut self, qubit: usize) -> Result<(), QisError>

Apply T gate (Z^1/4) Matrix: [[1, 0], [0, e^(i*pi/4)]]

Source

pub fn apply_tdg(&mut self, qubit: usize) -> Result<(), QisError>

Apply T† (T-dagger) gate Matrix: [[1, 0], [0, e^(-i*pi/4)]]

Source

pub fn apply_phase(&mut self, qubit: usize, theta: f64) -> Result<(), QisError>

Apply P (Phase) gate Matrix: [[1, 0], [0, e^(i*theta)]]

Source

pub fn apply_rx(&mut self, qubit: usize, theta: f64) -> Result<(), QisError>

Apply Rx(theta) gate Matrix: [[cos(t/2), -isin(t/2)], [-isin(t/2), cos(t/2)]]

Source

pub fn apply_ry(&mut self, qubit: usize, theta: f64) -> Result<(), QisError>

Apply Ry(theta) gate Matrix: [[cos(t/2), -sin(t/2)], [sin(t/2), cos(t/2)]]

Source

pub fn apply_rz(&mut self, qubit: usize, theta: f64) -> Result<(), QisError>

Apply Rz(theta) gate Matrix: [[e^(-itheta/2), 0], [0, e^(itheta/2)]]

Source

pub fn apply_x2p(&mut self, qubit: usize) -> Result<(), QisError>

Applies X2P gate: Rx(π/2), also known as √X.

Matrix: 1/√2 * [[1, -i], [-i, 1]]

§Optimization

Uses constant factors only, no trigonometric functions.

Source

pub fn apply_x2m(&mut self, qubit: usize) -> Result<(), QisError>

Applies X2M gate: Rx(-π/2), inverse of √X.

Matrix: 1/√2 * [[1, i], [i, 1]]

Source

pub fn apply_y2p(&mut self, qubit: usize) -> Result<(), QisError>

Applies Y2P gate: Ry(π/2).

Matrix: 1/√2 * [[1, -1], [1, 1]]

Source

pub fn apply_y2m(&mut self, qubit: usize) -> Result<(), QisError>

Applies Y2M gate: Ry(-π/2).

Matrix: 1/√2 * [[1, 1], [-1, 1]]

Source

pub fn apply_xy2p(&mut self, qubit: usize, theta: f64) -> Result<(), QisError>

Applies XY2P gate: Rz(θ - π/2) Ry(π/2) Rz(π/2 - θ).

Matrix: 1/√2 * [[1, -i·e^(-iθ)], [-i·e^(iθ), 1]]

§Arguments
  • qubit - Target qubit index
  • theta - Rotation angle
Source

pub fn apply_xy2m(&mut self, qubit: usize, theta: f64) -> Result<(), QisError>

Applies XY2M gate: Rz(-θ + π/2) Ry(-π/2) Rz(-π/2 + θ).

Matrix: 1/√2 * [[1, i·e^(-iθ)], [i·e^(iθ), 1]]

§Arguments
  • qubit - Target qubit index
  • theta - Rotation angle
Source

pub fn apply_xy(&mut self, qubit: usize, theta: f64) -> Result<(), QisError>

Applies XY gate.

Matrix: [[0, -i·e^(-iθ)], [-i·e^(iθ), 0]]

This is a single-qubit gate distinct from XY2P/XY2M.

§Arguments
  • qubit - Target qubit index
  • theta - Rotation angle
Source

pub fn apply_rxy( &mut self, qubit: usize, theta: f64, phi: f64, ) -> Result<(), QisError>

Apply general rotation R(theta, phi).

Rotates around axis cos(phi)X + sin(phi)Y by angle theta. Matrix: [[cos(t/2), -ie^(-iphi)sin(t/2)], [-ie^(i*phi)*sin(t/2), cos(t/2)]]

§Arguments
  • qubit - Target qubit index
  • theta - Rotation angle
  • phi - Rotation axis angle in XY plane
Source

pub fn apply_swap(&mut self, q0: usize, q1: usize) -> Result<(), QisError>

Applies SWAP gate to exchange two qubits.

Matrix: [[1,0,0,0], [0,0,1,0], [0,1,0,0], [0,0,0,1]]

§Arguments
  • q0 - First qubit index
  • q1 - Second qubit index
§Errors

Returns QisError::IndexOutOfBounds if either qubit is out of bounds, or QisError::QubitMismatch if q0 == q1.

§Optimization

Uses memory swap without floating-point operations.

Source

pub fn apply_cx( &mut self, control: usize, target: usize, ) -> Result<(), QisError>

Applies CNOT (CX) gate: controlled-X operation.

Flips the target qubit when the control qubit is |1⟩. Matrix: [[1,0,0,0], [0,1,0,0], [0,0,0,1], [0,0,1,0]]

§Arguments
  • control - Control qubit index
  • target - Target qubit index
§Errors

Returns QisError::IndexOutOfBounds if either qubit is out of bounds, or QisError::QubitMismatch if control == target.

Source

pub fn apply_cy( &mut self, control: usize, target: usize, ) -> Result<(), QisError>

Applies controlled-Y (CY) gate.

Applies Y gate to target when control qubit is |1⟩. Y matrix: [[0, -i], [i, 0]]

§Arguments
  • control - Control qubit index
  • target - Target qubit index
§Errors

Returns QisError::IndexOutOfBounds if either qubit is out of bounds, or QisError::QubitMismatch if control == target.

Source

pub fn apply_cz(&mut self, q0: usize, q1: usize) -> Result<(), QisError>

Applies controlled-Z (CZ) gate.

Applies phase flip (-1) to |11⟩ component. Leaves |00⟩, |01⟩, |10⟩ unchanged.

§Arguments
  • q0 - First qubit index (acts as control)
  • q1 - Second qubit index (acts as control)
§Errors

Returns QisError::IndexOutOfBounds if either qubit is out of bounds, or QisError::QubitMismatch if q0 == q1.

Source

pub fn apply_ccx( &mut self, c0: usize, c1: usize, target: usize, ) -> Result<(), QisError>

Apply Toffoli gate (CCX - Controlled-Controlled-X) Two control qubits and one target qubit. Flips the target if and only if both controls are |1⟩.

§Arguments
  • c0 - First control qubit index
  • c1 - Second control qubit index
  • target - Target qubit index
Source

pub fn apply_rxx( &mut self, q0: usize, q1: usize, theta: f64, ) -> Result<(), QisError>

Applies RXX gate (Ising XX interaction).

Matrix: exp(-i·θ/2 · X⊗X) = cos(θ/2)I - i·sin(θ/2)·X⊗X

§Arguments
  • q0 - First qubit index
  • q1 - Second qubit index
  • theta - Interaction angle
Source

pub fn apply_ryy( &mut self, q0: usize, q1: usize, theta: f64, ) -> Result<(), QisError>

Applies RYY gate (Ising YY interaction).

Matrix: exp(-i·θ/2 · Y⊗Y) = cos(θ/2)I - i·sin(θ/2)·Y⊗Y

§Arguments
  • q0 - First qubit index
  • q1 - Second qubit index
  • theta - Interaction angle
Source

pub fn apply_rzz( &mut self, q0: usize, q1: usize, theta: f64, ) -> Result<(), QisError>

Applies RZZ gate (Ising ZZ interaction).

Matrix: exp(-i·θ/2 · Z⊗Z) - applies phase based on qubit parity

§Arguments
  • q0 - First qubit index
  • q1 - Second qubit index
  • theta - Interaction angle
Source

pub fn apply_rzx( &mut self, q0: usize, q1: usize, theta: f64, ) -> Result<(), QisError>

Applies RZX gate (Ising ZX interaction).

Matrix: exp(-i·θ/2 · Z⊗X)

§Arguments
  • q0 - First qubit index (Z rotation)
  • q1 - Second qubit index (X rotation)
  • theta - Interaction angle
Source

pub fn apply_crx( &mut self, control: usize, target: usize, theta: f64, ) -> Result<(), QisError>

Applies controlled-RX gate.

Applies RX(θ) to target when control is |1⟩.

§Arguments
  • control - Control qubit index
  • target - Target qubit index
  • theta - Rotation angle
Source

pub fn apply_cry( &mut self, control: usize, target: usize, theta: f64, ) -> Result<(), QisError>

Applies controlled-RY gate.

Applies RY(θ) to target when control is |1⟩.

§Arguments
  • control - Control qubit index
  • target - Target qubit index
  • theta - Rotation angle
Source

pub fn apply_crz( &mut self, control: usize, target: usize, theta: f64, ) -> Result<(), QisError>

Applies controlled-RZ gate.

Applies RZ(θ) to target when control is |1⟩.

§Arguments
  • control - Control qubit index
  • target - Target qubit index
  • theta - Rotation angle
Source

pub fn apply_fsim( &mut self, q0: usize, q1: usize, theta: f64, phi: f64, ) -> Result<(), QisError>

Applies Fermionic Simulation (fSim) gate.

Native gate for superconducting qubits. Combines iSWAP and controlled-phase.

Matrix: [[1, 0, 0, 0], [0, c, -i·s, 0], [0, -i·s, c, 0], [0, 0, 0, e^(-iφ)]] where c = cos(θ), s = sin(θ)

§Arguments
  • q0 - First qubit index
  • q1 - Second qubit index
  • theta - iSWAP angle
  • phi - Controlled-phase angle
Source

pub fn apply_gphase(&mut self, phi: f64) -> Result<(), QisError>

Applies global phase.

Multiplies the entire statevector by e^(iφ). Physically undetectable but mathematically relevant for circuit composition.

§Arguments
  • phi - Phase angle
Source

pub fn expectation(&self, h: &dyn Observable) -> Result<f64, QisError>

Computes the expectation value of a Hamiltonian observable.

Calculates ⟨ψ|H|ψ⟩ for the current statevector |ψ⟩ and a given Hamiltonian H. The Hamiltonian is represented as a sum of Pauli strings with coefficients.

§Arguments
  • h - The Hamiltonian observable.
§Returns

The expectation value as a real number (f64), or a QisError if the qubit counts do not match.

§Errors

Returns QisError::CircuitError if the observable acts on a different number of qubits than the statevector.

§Example
use cqlib_core::qis::{Statevector, Hamiltonian};
use cqlib_core::qis::pauli::{Pauli, PauliString};
use num_complex::Complex64;

let mut sv = Statevector::new(1);
sv.apply_x(0);

// Create Hamiltonian H = Z (Pauli-Z observable)
let mut ps = PauliString::new(1);
ps.set_pauli(0, Pauli::Z);
let h = Hamiltonian::from_pauli(ps);

let exp = sv.expectation(&h).unwrap();
// For |1⟩ state, ⟨Z⟩ = -1
Source

pub fn measure(&mut self, qubit: usize) -> Result<bool, QisError>

Measures qubit qubit in the Z basis, collapsing the statevector.

Returns false for outcome |0⟩ and true for outcome |1⟩. After measurement the statevector is normalised in the post-measurement subspace.

This is a destructive operation — clone the statevector first if you need to preserve the pre-measurement state.

Source

pub fn measure_with_rng( &mut self, qubit: usize, rng: &mut impl Rng, ) -> Result<bool, QisError>

Measures qubit qubit using a caller-provided random number generator.

This is useful for reproducible simulations. For one-off non-deterministic measurements, use measure.

Source

pub fn reset(&mut self, qubit: usize) -> Result<(), QisError>

Resets qubit to the |0⟩ state.

Reset is modeled as a Z-basis measurement followed by an X correction when the measured outcome is |1⟩. This is destructive, matching circuit reset semantics.

Source

pub fn measure_all(&mut self) -> Outcome

Measures all qubits sequentially, returning a bit-packed Outcome.

Equivalent to calling measure(q) for each qubit q in order 0..num_qubits. The statevector is fully collapsed after this call. Use Outcome::is_one(q) to read qubit q’s result.

Source

pub fn measure_all_with_rng(&mut self, rng: &mut impl Rng) -> Outcome

Measures all qubits in storage order using the supplied random stream.

Source

pub fn sample_shots(&self, shots: usize) -> Vec<Outcome>

Samples shots independent measurement outcomes in parallel.

Each Rayon worker thread reuses a single pre-allocated clone of the statevector (via reset_from), avoiding per-shot heap allocation. Returns a Vec<Outcome> of bit-packed results.

§Example
use cqlib_core::qis::Statevector;

let mut sv = Statevector::new(2);
sv.apply_h(0).unwrap();
sv.apply_cx(0, 1).unwrap(); // |Φ⁺⟩ Bell state

let shots = sv.sample_shots(200);
// All outcomes must be |00⟩ or |11⟩
assert!(shots.iter().all(|v| v.is_one(0) == v.is_one(1)));
Source

pub fn sample_shots_with_seed( &self, shots: usize, seed: Option<u64>, ) -> Vec<Outcome>

Samples without changing this state. An explicit seed assigns a random stream to each shot before parallel execution, independent of scheduling.

Source

pub fn sample( &self, measurement: &Measurement, shots: usize, ) -> Result<ExecutionResult, QisError>

Samples the state using a circuit Measurement as the output contract.

measurement.qubits()[i] becomes bit i in each Outcome. The returned ExecutionResult reuses the device result shape, with counts projected to only the qubits named by the measurement.

Source

pub fn sample_with_seed( &self, measurement: &Measurement, shots: usize, seed: Option<u64>, ) -> Result<ExecutionResult, QisError>

Projects seeded full-state samples onto the requested measurement.

Source

pub fn probs( &self, measurement: &Measurement, ) -> Result<HashMap<Outcome, f64>, QisError>

Returns the marginal probability distribution selected by a circuit Measurement.

This method does not execute circuit IR. It treats the Measurement as a self-contained output contract and aggregates the full statevector computational-basis probabilities over unmeasured qubits.

Trait Implementations§

Source§

impl Clone for Statevector

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Statevector

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl StateVisualizationSource for Statevector

Source§

fn num_qubits(&self) -> usize

Number of qubits represented by the state.
Source§

fn density_matrix_data(&self) -> Result<Vec<Complex64>, VisualizationError>

Return row-major density-matrix data for visualization.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> ByRef<T> for T

Source§

fn by_ref(&self) -> &T

Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> Conv for T

Source§

fn conv<T>(self) -> T
where Self: Into<T>,

Converts self into T using Into<T>. Read more
Source§

impl<T> DistributionExt for T
where T: ?Sized,

Source§

fn rand<T>(&self, rng: &mut (impl Rng + ?Sized)) -> T
where Self: Distribution<T>,

Source§

impl<T> FmtForward for T

Source§

fn fmt_binary(self) -> FmtBinary<Self>
where Self: Binary,

Causes self to use its Binary implementation when Debug-formatted.
Source§

fn fmt_display(self) -> FmtDisplay<Self>
where Self: Display,

Causes self to use its Display implementation when Debug-formatted.
Source§

fn fmt_lower_exp(self) -> FmtLowerExp<Self>
where Self: LowerExp,

Causes self to use its LowerExp implementation when Debug-formatted.
Source§

fn fmt_lower_hex(self) -> FmtLowerHex<Self>
where Self: LowerHex,

Causes self to use its LowerHex implementation when Debug-formatted.
Source§

fn fmt_octal(self) -> FmtOctal<Self>
where Self: Octal,

Causes self to use its Octal implementation when Debug-formatted.
Source§

fn fmt_pointer(self) -> FmtPointer<Self>
where Self: Pointer,

Causes self to use its Pointer implementation when Debug-formatted.
Source§

fn fmt_upper_exp(self) -> FmtUpperExp<Self>
where Self: UpperExp,

Causes self to use its UpperExp implementation when Debug-formatted.
Source§

fn fmt_upper_hex(self) -> FmtUpperHex<Self>
where Self: UpperHex,

Causes self to use its UpperHex implementation when Debug-formatted.
Source§

fn fmt_list(self) -> FmtList<Self>
where &'a Self: for<'a> IntoIterator,

Formats each item in a sequence. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Imply<T> for U
where T: ?Sized, U: ?Sized,

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pipe for T
where T: ?Sized,

Source§

fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
where Self: Sized,

Pipes by value. This is generally the method you want to use. Read more
Source§

fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> R
where R: 'a,

Borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> R
where R: 'a,

Mutably borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
where Self: Borrow<B>, B: 'a + ?Sized, R: 'a,

Borrows self, then passes self.borrow() into the pipe function. Read more
Source§

fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
where Self: BorrowMut<B>, B: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.borrow_mut() into the pipe function. Read more
Source§

fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
where Self: AsRef<U>, U: 'a + ?Sized, R: 'a,

Borrows self, then passes self.as_ref() into the pipe function.
Source§

fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
where Self: AsMut<U>, U: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.as_mut() into the pipe function.
Source§

fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
where Self: Deref<Target = T>, T: 'a + ?Sized, R: 'a,

Borrows self, then passes self.deref() into the pipe function.
Source§

fn pipe_deref_mut<'a, T, R>( &'a mut self, func: impl FnOnce(&'a mut T) -> R, ) -> R
where Self: DerefMut<Target = T> + Deref, T: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.deref_mut() into the pipe function.
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Tap for T

Source§

fn tap(self, func: impl FnOnce(&Self)) -> Self

Immutable access to a value. Read more
Source§

fn tap_mut(self, func: impl FnOnce(&mut Self)) -> Self

Mutable access to a value. Read more
Source§

fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Immutable access to the Borrow<B> of a value. Read more
Source§

fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Mutable access to the BorrowMut<B> of a value. Read more
Source§

fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Immutable access to the AsRef<R> view of a value. Read more
Source§

fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Mutable access to the AsMut<R> view of a value. Read more
Source§

fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Immutable access to the Deref::Target of a value. Read more
Source§

fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Mutable access to the Deref::Target of a value. Read more
Source§

fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self

Calls .tap() only in debug builds, and is erased in release builds.
Source§

fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self

Calls .tap_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Calls .tap_borrow() only in debug builds, and is erased in release builds.
Source§

fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Calls .tap_borrow_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Calls .tap_ref() only in debug builds, and is erased in release builds.
Source§

fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Calls .tap_ref_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Calls .tap_deref() only in debug builds, and is erased in release builds.
Source§

fn tap_deref_mut_dbg<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Calls .tap_deref_mut() only in debug builds, and is erased in release builds.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> TryConv for T

Source§

fn try_conv<T>(self) -> Result<T, Self::Error>
where Self: TryInto<T>,

Attempts to convert self into T using TryInto<T>. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V