Skip to main content

Simulate

Struct Simulate 

Source
pub struct Simulate<'c, SeedState> { /* private fields */ }
Expand description

Builder for query-aware simulation requests.

Implementations§

Source§

impl<'c> Simulate<'c, Seeded>

Source

pub fn braket_results(self, specs: &[ResultSpec]) -> Result<Vec<ResultValue>>

Evaluate the result requests a Braket program declared.

Every expectation and variance request is served by a single traversal: their observables are lowered to Pauli sums, the distinct strings across all of them are evaluated together through Simulate::expectation_values, and each requested value is then a weighted sum over that one evaluation. state_vector and amplitude share one export, and a probability or density_matrix request beside them is read off that same export. Without one it runs on its own, keeping the routing its own width earns: a subset marginal of a wide Clifford circuit stays on the tableau rather than forcing a dense export.

sample is declined here: it reports per-shot eigenvalues, which Simulate::braket_results_sampled answers. So is a circuit carrying a measurement, reset or conditional, which has no one exact output state to read: Braket rejects the same programs at zero shots.

§Errors

Returns BackendUnsupported for a sample request, IncompatibleBackend for a circuit that is not unitary, and whatever the underlying terminal returns for a route that cannot serve a request.

Source

pub fn braket_results_sampled( self, specs: &[ResultSpec], shots: usize, ) -> Result<Vec<ResultValue>>

Evaluate the result requests a Braket program declared, from a shot record rather than from the exact state.

Each observable is diagonalized and the rotations carrying them onto the computational basis are appended to the circuit once, so a single sampling pass answers every sample, expectation and variance request together. Two observables reading one qubit in different bases cannot share a record and are rejected rather than answered from whichever basis was applied first. A probability request reads the computational basis and so takes its own unrotated pass whenever any rotation was applied.

§Errors

Returns BackendUnsupported for state_vector, density_matrix and amplitude, which report the state itself and which Braket admits only at zero shots, and InvalidParameter for zero shots or for observables that cannot share one measurement.

Source§

impl<'c, SeedState> Simulate<'c, SeedState>

Source

pub fn backend(self, kind: BackendKind) -> Self

Select an explicit backend kind instead of BackendKind::Auto routing.

Source

pub fn require_exact(self) -> Self

Reject a route that could return an approximate answer, rather than taking it and saying so in the result.

BackendKind::Auto sends a circuit past the statevector cap to an MPS at a bounded bond dimension, which is the only route those circuits have; the result reports Exactness::Approximate either way. Call this when an approximate answer is worse than no answer, and the run returns IncompatibleBackend naming the engine it would have used.

Routes that can be decided from the circuit are rejected before any state is allocated; sparse Pauli dynamics only learns that it truncated while propagating, so that one is caught on the finished result instead.

Source

pub fn noise(self, model: &'c NoiseModel) -> Self

Attach a noise model.

Simulate::shots and Simulate::sample_counts accept one on any backend with a per-shot pure state, averaging trajectories. Simulate::run, Simulate::marginals, Simulate::expectation_values and Simulate::reduced_density_matrix answer from the exact mixture instead, which only BackendKind::DensityMatrix and its device sibling hold, so they require one of those, as does Simulate::expectation_gradient_shift and, only to decline on it, Simulate::entanglement_entropy: a mixture has no Schmidt decomposition. Simulate::expectation_gradient rejects a noise model on every backend.

Source

pub fn initial_state(self, amplitudes: &'c [Complex64]) -> Self

Start from amplitudes instead of |0…0⟩.

Indexed with qubit 0 in the least significant bit, length 2^n for the circuit’s n qubits, and normalized. A vector failing any of those is rejected with InvalidParameter before the run.

A start state also constrains the route, because shape-based dispatch reads the circuit alone and its shortcuts hold only from |0…0⟩: BackendKind::Auto resolves to the statevector, and every backend other than the statevector (dense, device, or distributed) and BackendKind::DensityMatrix reports IncompatibleBackend. Simulate::expectation_gradient declines a start state, as do Simulate::shots and Simulate::sample_counts with a noise model attached, since trajectory replay has no start-state path.

Source

pub fn gpu(self, context: Arc<GpuContext>) -> Self

Available on crate feature gpu only.
Source

pub fn gpu_auto(self, context: Arc<GpuContext>) -> Self

Available on crate feature gpu only.

Automatic backend selection with GPU acceleration opted in via context.

Routes like BackendKind::Auto, but a selected statevector or stabilizer block that clears the qubit crossover with VRAM to spare runs on the device. Unsupported cases fall back to the identical CPU path.

Source

pub fn distributed(self, context: Arc<DistributedContext>) -> Self

Available on crate feature distributed only.

Distribute the exact state vector across the ranks of context.

With a single rank this behaves like Simulate::backend with BackendKind::Statevector.

Source§

impl<'c> Simulate<'c, Unseeded>

Source

pub fn seed(self, seed: u64) -> Simulate<'c, Seeded>

Query methods exist only on the seeded builder.

Source§

impl<'c> Simulate<'c, Seeded>

Source

pub fn run(self) -> Result<RunOutcome>

Execute the circuit once.

With a noise model attached the probabilities are the exact noisy distribution rather than one trajectory, so the run needs the density-matrix backend; the classical bits are one draw, matching shots(1). Readout error reaches the draw and not the state, so a model carrying it is rejected rather than answered with two fields from different distributions; shots and sample_counts apply it.

Source

pub fn shots(self, num_shots: usize) -> Result<ShotsResult>

Execute num_shots times, collecting per-shot classical bits. Accepts an attached noise model.

Source

pub fn sample_counts(self, num_shots: usize) -> Result<CountsResult>

Sample a frequency histogram over num_shots executions. Accepts an attached noise model.

Counts may be sampled directly from the output distribution, so seeded counts can differ from Simulate::shots plus ShotsResult::counts while drawing from the identical distribution.

Source

pub fn marginals(self) -> Result<MarginalsResult>

Per-qubit marginal probabilities as (P(0), P(1)) pairs. Rejects backends without probability output, and with a noise model attached answers exactly from the mixture, which needs the density-matrix backend, and rejects a model carrying readout error, since sample_counts is the terminal that applies it.

Source

pub fn expectation_values( self, observables: &[Vec<PauliTerm>], ) -> Result<Vec<f64>>

Compute ⟨ψ|P|ψ⟩ for each joint Pauli observable on the circuit’s output state, honoring the selected backend.

Each observable is a product of single-qubit Paulis (identity factors omitted). The circuit must be unitary. Clifford circuits propagate each observable exactly. Non-Clifford circuits use the state vector while they fit it; above that cap the selected backend evaluates the observable on its own representation, and a backend without one reports BackendUnsupported naming itself.

With a noise model attached the value is the exact Tr(rho P) on the evolved mixture, which needs the density-matrix backend. A model carrying readout error is rejected: readout acts on the measurement record, which no observable sees, and shots on the same model would disagree by the readout rate.

Source

pub fn expectation_values_reported( self, observables: &[Vec<PauliTerm>], ) -> Result<ExpectationResult>

Simulate::expectation_values with the provenance of the run and, for a route that estimates rather than evaluates, a standard error per value.

Source

pub fn observable_expectation( self, observable: &PauliObservable, ) -> Result<ObservableExpectation>

Compute ⟨H⟩ and its grouped-measurement variance for a weighted Pauli observable on the circuit’s output state.

The statevector family evaluates one traversal per qubit-wise-commuting group and reports the variance; see ObservableExpectation::variance for what the number means. Every other route, including runs with a noise model or start state attached, evaluates term by term through Simulate::expectation_values semantics and reports the weighted mean with no variance. A noise model carrying readout error is rejected for the same reason as there.

Source

pub fn observable_variance( self, observable: &PauliObservable, ) -> Result<ObservableVariance>

Var(H) = <H^2> - <H>^2 for a weighted Pauli observable on the circuit’s output state.

This is the spread of the operator itself, the number a shot-based estimate of <H> converges on dividing by the shot count. It is not ObservableExpectation::variance, which sums per-group variances and so drops the covariance between measurement groups.

Evaluates H and the square of its traceless part through Simulate::observable_expectation, so backend routing, noise, and start states behave as they do there. The constant term is held out of the square rather than cancelled inside it; see PauliObservable::split_identity. The square carries up to T^2 terms over H’s T; see PauliObservable::square.

Source

pub fn probabilities_of(self, qubits: &[usize]) -> Result<Vec<f64>>

Joint probability distribution over qubits, 2^k entries with qubits[0] in the lowest bit.

The subset generalizes Simulate::marginals, which reports each qubit on its own and so cannot show correlation: a Bell pair reads (0.5, 0.5) twice there and [0.5, 0, 0, 0.5] here. Routing follows Simulate::run, including the exact mixture a noise model asks for and its rejection of readout error, which acts on the measurement record rather than on the state.

A backend that exposes no distribution for the circuit reports BackendUnsupported naming itself.

Source

pub fn state_vector(self) -> Result<Vec<Complex64>>

Full amplitude vector of the circuit’s output state, honoring the selected backend.

Indexed with qubit 0 in the least significant bit, so x q[0] puts the amplitude at index 1. The circuit must be unitary, for the reason Simulate::reduced_density_matrix gives.

A noise model declines: a mixture has no single amplitude vector, and Simulate::reduced_density_matrix over the whole register is the terminal that answers there. The density-matrix backend declines for the same reason whether or not noise is attached.

The vector holds 2^n amplitudes, so a register past the dense export cap reports IncompatibleBackend before allocating rather than after.

Source

pub fn reduced_density_matrix( self, qubits: &[usize], ) -> Result<ReducedDensityMatrix>

Reduced density matrix of qubits on the circuit’s output state, honoring the selected backend.

Row major with side 2^k; ReducedDensityMatrix::data states the index order. The subsystem is named once and may be the whole register. The circuit must be unitary: the answer is read off one state, and a measurement, reset or conditional leaves one seeded branch of several.

An explicitly selected backend that holds no partial trace reports BackendUnsupported naming itself. Under BackendKind::Auto a route that cannot answer falls back to the statevector while the circuit fits its cap, so the diagnostic is served rather than declined by a choice the caller did not make. With a noise model attached the answer is the marginal of the exact mixture, which needs the density-matrix backend.

Source

pub fn entanglement_entropy(self, subsystem: &[usize]) -> Result<EntropyResult>

Entanglement entropy of subsystem across its cut with the rest of the register, in nats, honoring the selected backend.

subsystem must leave both sides of the cut non-empty, and the circuit must be unitary, for the reason Simulate::reduced_density_matrix gives. The Schmidt values come back with the entropy, descending and normalized.

A backend that holds the entropy without the spectrum behind it, a stabilizer cut past the export cap, answers with EntropyResult::schmidt_values set to None. An explicitly selected backend that holds neither reports BackendUnsupported naming itself; under BackendKind::Auto such a route falls back to the statevector while the circuit fits its cap. A noise model declines outright: it sends the run to the density matrix, whose mixed state has no Schmidt decomposition.

Source

pub fn overlap(self, other: Simulate<'_, Seeded>) -> Result<OverlapResult>

|<a|b>|^2 between this circuit’s output state and other’s, honoring the backend each side selected.

The two circuits must declare the same width, and both must be unitary for the reason Simulate::reduced_density_matrix gives. Each side carries its own backend, seed and start state, and each resolves to a single backend rather than the decomposed route, since two circuits need not split into the same independent blocks.

A pair of unlike representations is served by a dense export of both states, so it reaches as far as the export cap does. A pair that shares one answers natively at any width: two chains in the same site order, two tableaux, two product states, or two sparse maps. A noise model on either side is rejected, since the fidelity of two mixtures is not an inner product.

Source

pub fn expectation_gradient( self, hamiltonian: &[(f64, Vec<PauliTerm>)], params: &Parameters, ) -> Result<ExpectationGradient>

Compute ⟨H⟩ and its exact gradient with respect to the bound parameters using the adjoint method.

hamiltonian is a weighted Pauli sum Σ c_k P_k with real coefficients. params declares which gate instructions carry parameters. Runs on the statevector backend; the selected backend must be Auto or Statevector. The circuit must be unitary. See gradient::run_expectation_gradient.

Source

pub fn expectation_gradient_shift( self, hamiltonian: &[(f64, Vec<PauliTerm>)], params: &Parameters, ) -> Result<ExpectationGradient>

Compute ⟨H⟩ and its gradient by the parameter-shift rule on the selected backend.

Serves the cases Simulate::expectation_gradient declines: any backend with a native observable path, circuits containing QftBlock, widths past the statevector cap, and a noise model. It differentiates the same gate set (Rx, Ry, Rz, Rzz, P, PauliRot) at 1 + 2 * links circuit evaluations against the adjoint’s one, so the adjoint stays the better choice where it applies. A backend with no native observable path reports BackendUnsupported naming itself. Under a noise model every evaluation reads the exact mixture, so the backend must be BackendKind::DensityMatrix or its device sibling; the shift stays exact because the channels do not depend on the shifted angle. See gradient::run_expectation_gradient_shift.

Auto Trait Implementations§

§

impl<'c, SeedState> !RefUnwindSafe for Simulate<'c, SeedState>

§

impl<'c, SeedState> !UnwindSafe for Simulate<'c, SeedState>

§

impl<'c, SeedState> Freeze for Simulate<'c, SeedState>
where SeedState: Freeze,

§

impl<'c, SeedState> Send for Simulate<'c, SeedState>
where SeedState: Send,

§

impl<'c, SeedState> Sync for Simulate<'c, SeedState>
where SeedState: Sync,

§

impl<'c, SeedState> Unpin for Simulate<'c, SeedState>
where SeedState: Unpin,

§

impl<'c, SeedState> UnsafeUnpin for Simulate<'c, SeedState>
where SeedState: UnsafeUnpin,

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> 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> 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, 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