qarp.algorithms¶
Algorithms. Public depth: flat — every primitive and composite algorithm is
qarp.algorithms.<Name>, together with the eigenspectrum helpers.
Submodules are private implementation and may be reorganised without notice.
- class qarp.algorithms.AdaptVQD(reference_block: Block, hamiltonian: QubitOperator, excitation_pool: List[QubitOperator], orthogonal_states: List[Block], betas: List[float], gradient: bool | str = False, optimizer: Optimizer | None = None, diminishing: bool = False, exc_per_iter: int = 1, verbose: bool = True, term_gradient: str = 'ADAPT-VQD', convergence_thresh=1e-07, gradient_thresh=1e-07, primitive: PrimitiveAlgorithm | None = None, engine: Engine | None = None)[source]¶
Bases:
AdaptAnsatzMixin,CompositeAlgorithm- build()[source]¶
Build the composite algorithm by constructing all sub-algorithms.
This method should: 1. Create and configure all necessary sub-algorithms 2. Build each sub-algorithm
- Returns:
Self for method chaining
- get_final_state_block()[source]¶
Use the current object reference, ansatz excitations and symbols to construct a wavefunction object.
- Returns:
A wavefunction object constructed with the current AdaptVQE attributes.
- class qarp.algorithms.AdaptVQE(reference_block: Block, system_hamiltonian: QubitOperator, excitation_pool: List[QubitOperator], optimizer: Optimizer | None = None, gradient: bool | str = False, verbose: bool = True, diminishing: bool = False, exc_per_iter: int = 1, qubit_adapt: bool = False, gradient_thresh: float = 1e-05, convergence_thresh: float = 1e-06, primitive: PrimitiveAlgorithm | None = None, engine: Engine | None = None)[source]¶
Bases:
AdaptAnsatzMixin,CompositeAlgorithm- build()[source]¶
Build the composite algorithm by constructing all sub-algorithms.
This method should: 1. Create and configure all necessary sub-algorithms 2. Build each sub-algorithm
- Returns:
Self for method chaining
- get_final_state_block()[source]¶
Use the current object reference, ansatz excitations and symbols to construct a wavefunction object.
- Returns:
A wavefunction object constructed with the current AdaptVQE attributes.
- class qarp.algorithms.AmplitudeAmplification(state_preparation: Block, oracle: Block, n_iterations: int, *, good_states: Sequence[int] | None = None, primitive: PrimitiveAlgorithm | None = None, engine: Engine | None = None)[source]¶
Bases:
CompositeAlgorithmPrepare a state and apply a fixed number of amplification iterates.
The built circuit is
Afollowed byn_iterationsapplications ofAmplitudeAmplificationBlock. The suppliedoraclemust implement exactlyI - 2 Pi_good; see the block documentation for the phase convention.good_statesis optional classical reporting metadata. It contains full-register integer labels and is used only to sum the returned sampling probabilities. It neither defines nor modifies the quantum oracle.The iterate and the probability law
sin((2 * n_iterations + 1) * theta)**2follow Brassard, Hoyer, Mosca, and Tapp, Quantum Amplitude Amplification and Estimation, arXiv:quant-ph/0005055, Eqs. (1), (5), and (8).- Parameters:
state_preparation – Unitary
Apreparing the initial state.oracle – Good-state phase oracle on the same positive-width register.
n_iterations – Explicit non-negative number of amplification iterates.
good_states – Optional unique full-register integer labels whose returned probabilities are summed into
success_probability.primitive – Sampling primitive. Defaults to a private
Sampler. A sampler carryinginitial_stateis rejected: the amplification law assumes the circuit starts in|0...0>, soAmust act on that state and not on a seeded one.engine – Execution engine. Defaults to
QarpEnginethrough the composite-algorithm base class.
- class qarp.algorithms.AmplitudeEstimation(state_preparation: Block, oracle: Block, n_ancilla: int, *, primitive: PrimitiveAlgorithm | None = None, engine: Engine | None = None)[source]¶
Bases:
CompositeAlgorithmEstimate the initial good-state probability with canonical QAE.
The supplied oracle must implement exactly
I - 2 Pi_good. WithM = 2**n_ancilla, a sampled QPE labelymaps tosin(pi*y/M)**2. The conjugate phase branches are folded together atz = min(y, M-y)before selecting the most probable estimate.This is the canonical estimator of Brassard, Hoyer, Mosca, and Tapp, arXiv:quant-ph/0005055.
- Parameters:
state_preparation – Unitary preparing the state whose amplitude is estimated.
oracle – Phase-exact good-state oracle on the same register.
n_ancilla – Positive number of estimation qubits.
primitive – Sampling primitive. Defaults to a private
Sampler.engine – Execution engine.
- class qarp.algorithms.BasisRotationAveraging(ket: Block | None = None, integrals: tuple | None = None, constant: float = 0.0, tolerance: float = 1e-08, n_shots: int | Shots | None = None)[source]¶
Bases:
PrimitiveAlgorithm- build() Self[source]¶
Construct circuits: populate self.sub_blocks with qx.Block instances.
Returns
selfso callers can chainprimitive.build().
- class qarp.algorithms.CompositeAlgorithm(primitive: PrimitiveAlgorithm, engine: Engine | None = None)[source]¶
Bases:
ABC
- class qarp.algorithms.CuttingPrimitive(ket: Block | None = None, operator: QubitOperator | None = None, max_subcircuit_qubits: int | None = None, n_shots: int = 5000, force_max_number_cuts: bool = False, experiment_fraction: float | None = None, rng_seed: int | None = None)[source]¶
Bases:
PrimitiveAlgorithmPrimitiveAlgorithm that evaluates expectation values via QPD circuit cutting.
Works with any OpenQARP engine without modification.
- build() Self[source]¶
Partition the circuit and build all measurement sub-blocks.
Uses streaming experiment generation and QWC grouping so that sub_blocks contains n_experiments × n_subcircuits × n_qwc_groups blocks (instead of × n_obs_terms).
- class qarp.algorithms.DOSQPE(unitary: Block, n_ancilla: int, hamming_weight: int | None = None, primitive: PrimitiveAlgorithm | None = None, engine: Engine | None = None)[source]¶
Bases:
CompositeAlgorithm- build()[source]¶
Build the DOS Phase Estimation circuit.
First offers the problem to the engine’s structured fast path (
Engine.prepare_structured_qpe— matrix exponentiation, the controlled-U ladder is never compiled). Engines without the path, or refusing it (EXACT readout, noise, routing, parametric U — seeQarpEngine.prepare_structured_qpe), return None and the full DOSQPEBlock circuit is built instead.- Returns:
The instance of the class.
- Return type:
self
- property freqs¶
Get the frequency grid for the ancilla register.
- plot(figsize=None, return_fig=False, max_xticks=11)[source]¶
Plot the results of the DOS Phase Estimation algorithm.
- plot_against_spectrum(unique_eigs, normalized_degeneracy, unique_occ_numbers, figsize=None, return_fig=False, max_xticks=11)[source]¶
Plot the results of the DOS Phase Estimation algorithm against the spectrum.
- Parameters:
unique_eigs (list) – Unique eigenvalues.
normalized_degeneracy (list) – Normalized degeneracy.
unique_occ_numbers (list) – Unique occupation numbers.
figsize (tuple) – Size of the figure. If None, scales with n_ancilla.
return_fig (bool) – If True, return (fig, ax) for external saving/customization.
max_xticks (int) – Upper bound on the number of x-axis ticks.
- Returns:
(fig, ax) if return_fig is True, otherwise None.
- class qarp.algorithms.GroupedTransitionHadamardTest(bra: Block | None = None, operator: QubitOperator | None = None, ket: Block | None = None, real: bool = True, imaginary: bool = True, n_shots: int | Shots | None = None, grouping: GroupingStrategy | None = None)[source]¶
Bases:
PrimitiveAlgorithmEstimate a full-operator transition amplitude by QWC grouping.
The circuit for a group samples the correlation between the ancilla quadrature and every Pauli parity in that group. The primitive returns
<bra|H|ket>directly; it does not expose or run one sub-primitive per Pauli term.- Parameters:
bra – State-preparation block for
<bra|.operator – Real-coefficient
QubitOperatorto measure.ket – State-preparation block for
|ket>.real – Include real-quadrature circuits.
imaginary – Include imaginary-quadrature circuits.
n_shots – Shots per group/quadrature;
Nonedefers to the engine.grouping – Term grouping strategy. The initial circuit primitive supports strategies with
qubit_wise=True; default isQubitWiseCommuting.
General (non-QWC) commuting groups require an entangling diagonalisation and are intentionally rejected until a transition-aware Clifford path is added. This keeps the first implementation exact and easy to validate.
- build() Self[source]¶
Construct circuits: populate self.sub_blocks with qx.Block instances.
Returns
selfso callers can chainprimitive.build().
- run(results: list) float | complex[source]¶
Post-process the engine’s sampling output into a result.
Contract: a pure function of
results— no simulator or engine access. Keeps every estimator unit-testable with synthetic results (anything exposingcounts/n_shots/n_qubits).- Parameters:
results – One
qx.SamplingResultper entry inself.sub_blocks, as produced by the engine’s sampler.- Returns:
A scalar (float / complex) for expectation/overlap-style primitives, or a
SamplingDictionary({bitstring-tuple: probability}) forSampler.
- class qarp.algorithms.Grover(oracle: Block, n_marked: int = 1, *, good_states: Sequence[int] | None = None, primitive: PrimitiveAlgorithm | None = None, engine: Engine | None = None)[source]¶
Bases:
CompositeAlgorithmSearch a uniform basis-state space with a known marked-state count.
good_statesis optional reporting metadata. It is never used to build or modify the oracle; when supplied, its returned probability mass is exposed assuccess_probability. It is not cross-checked against the oracle (an opaque unitary cannot be inspected without an exponential dense matrix), so declaring labels the oracle does not actually mark yields a misleadingsuccess_probability— the labels are the caller’s promise.most_likely_statesis only meaningful once amplification has concentrated the distribution. When the optimal iteration count is zero (n_marked >= N/2, so the uniform state is already at or past the amplification optimum) the distribution stays (near-)uniform andmost_likely_statesis the entire register; readpredicted_success_probabilityto see that no concentration occurred.The algorithm follows Grover, arXiv:quant-ph/9605043, with the known-count analysis of Boyer, Brassard, Hoyer, and Tapp, arXiv:quant-ph/9605034.
- Parameters:
oracle – Phase oracle implementing exactly
I - 2 Pi_good.n_marked – Number of basis states marked by the oracle.
good_states – Optional explicit marked integer labels for reporting only.
primitive – Sampling primitive. Defaults to a private
Sampler.engine – Execution engine.
- class qarp.algorithms.HadamardTest(bra: Block | None = None, operator: Block | None = None, ket: Block | None = None, real: bool = True, imaginary: bool = True, n_shots: int | Shots | None = None)[source]¶
Bases:
PrimitiveAlgorithm- build() Self[source]¶
Construct circuits: populate self.sub_blocks with qx.Block instances.
Returns
selfso callers can chainprimitive.build().
- run(results: list) complex[source]¶
Post-process the engine’s sampling output into a result.
Contract: a pure function of
results— no simulator or engine access. Keeps every estimator unit-testable with synthetic results (anything exposingcounts/n_shots/n_qubits).- Parameters:
results – One
qx.SamplingResultper entry inself.sub_blocks, as produced by the engine’s sampler.- Returns:
A scalar (float / complex) for expectation/overlap-style primitives, or a
SamplingDictionary({bitstring-tuple: probability}) forSampler.
- class qarp.algorithms.InterferometricTest(bra: ComputationalBasisStateBlock | None = None, operator: Block | None = None, ket: ComputationalBasisStateBlock | None = None, real: bool = True, imaginary: bool = True, sampling_algorithm: PrimitiveAlgorithm | None = None, n_shots: int | Shots | None = None)[source]¶
Bases:
PrimitiveAlgorithm- build() Self[source]¶
Construct circuits: populate self.sub_blocks with qx.Block instances.
Returns
selfso callers can chainprimitive.build().
- run(results: list) complex[source]¶
Post-process the engine’s sampling output into a result.
Contract: a pure function of
results— no simulator or engine access. Keeps every estimator unit-testable with synthetic results (anything exposingcounts/n_shots/n_qubits).- Parameters:
results – One
qx.SamplingResultper entry inself.sub_blocks, as produced by the engine’s sampler.- Returns:
A scalar (float / complex) for expectation/overlap-style primitives, or a
SamplingDictionary({bitstring-tuple: probability}) forSampler.
- class qarp.algorithms.MMQCELS(operator: QubitOperator | ndarray | TrotterBlock, state: ndarray | Block, *, execution_mode: Literal['classical', 'statevector', 'hadamard'], T0: float, parameter_mode: Literal['standard', 'error_rate'] = 'standard', N0: int | None = None, Nj: int | Sequence[int] | None = None, n_dominant_eigenvalues: int = 1, error_rate: float = 0.001, n_levels: int | None = None, q: float | None = None, gamma: float = 1.0, initial_eigenvalues: Sequence[float] | None = None, n_initial_guesses: int = 10, n_shots: int | Shots | None = None, lam_min: float = -3.141592653589793, lam_max: float = 3.141592653589793, optimizer: Optimizer | None = None, seed: int | None = None, verbose: bool = True, engine: Engine | None = None)[source]¶
Bases:
CompositeAlgorithmEstimate several dominant eigenvalues with MM-QCELS.
The implementation follows Algorithm 2 and Eq. (13) of Ding and Lin, Quantum 7, 1136 (2023): times are independent truncated-Gaussian draws, observations are complex, and the time scale doubles between levels.
parameter_mode="standard"is the recommended default. It requiresT0,N0,Nj, and exactly one ofqorn_levels.parameter_mode="error_rate"retains OpenQARP’s historical epsilon-derived level and sample-count helpers as an explicitly opt-in convenience. It is not a theorem-backed MM-QCELS parameter calibration.- Parameters:
operator – Hamiltonian in classical mode, or a symbolic-time
TrotterBlockin circuit modes.state – Statevector/block in classical mode, or a built block in circuit modes.
execution_mode – Required data-generation strategy:
"classical","statevector", or"hadamard".T0 – Positive initial Gaussian time scale.
parameter_mode –
"standard"or the opt-in"error_rate"compatibility preset.N0 – Number of samples at level zero. Required in standard mode.
Nj – Positive sample count reused after level zero, or one count per subsequent level. Required in standard mode, even though a scalar value is unused when
n_levels=1.n_dominant_eigenvalues – Number of dominant modes
K.error_rate – Accuracy
epsilonused byparameter_mode="error_rate"and by standard mode’sqschedule. It does not affect a standard schedule with an explicitn_levels.n_levels – Explicit number of evaluated levels. Mutually exclusive with
qin standard mode.q – Theorem-1 schedule parameter. Standard mode derives
l=max(ceil(log2(q/(epsilon*T0))), 1)and evaluatesl+1levels.gamma – Truncation radius in standard deviations. Sampled times lie in
[-gamma*T_j, gamma*T_j].initial_eigenvalues – Optional length-
Kfirst-level phase guess.n_initial_guesses – Total number of first-level optimization starts, including
initial_eigenvalueswhen supplied.n_shots – Hadamard shots per quadrature.
Nonemeans one shot, as in the paper;qarp.EXACTevaluates the exact protocol.lam_min – Initial lower eigenvalue bound.
lam_max – Initial upper eigenvalue bound.
optimizer – SciPy-compatible bounded optimizer.
seed – Seed for time sampling and generated optimizer starts. When no engine is supplied, it also seeds the default QarpEngine.
verbose – Print per-level progress.
engine – Optional configured execution engine.
- Variables:
result – Eigenvalues returned by the latest successful
run().eigenvalues – Alias of
result, following the QPE output style.amplitudes – Complex amplitudes fitted alongside the eigenvalues.
level_losses – Final complex least-squares loss at every level.
sample_counts – Number of observations used at every level.
sampled_max_times – Largest absolute sampled time at every level.
sampled_total_times – Sum of absolute sampled times at every level.
optimizer_failed_starts – Number of discarded optimizer starts at every level. A level for which every start fails raises instead.
Every evaluated level must contain more observations than dominant modes; otherwise the variable-projection residual cannot identify the frequencies.
- generate_dataset(T: float, n: int | None = None) list[tuple[float, complex]][source]¶
Generate one independent MM-QCELS dataset at scale
T.
- generate_times(T: float, n: int) NDArray[float64][source]¶
Draw
nindependent samples from Eq. (3)’s distribution.
- objective(eigenvalues: ArrayLike, dataset: Sequence[tuple[float, complex]]) float[source]¶
Evaluate the full complex Eq. (13) loss after eliminating amplitudes.
- optimal_dataset_length() int[source]¶
Return OpenQARP’s historical epsilon-only sample-count heuristic.
- optimal_number_of_iterations() int[source]¶
Return the predecessor-QCELS epsilon-only level heuristic.
- class qarp.algorithms.MirrorTest(bra: Block | None = None, operator: Block | None = None, ket: Block | None = None, n_shots: int | Shots | None = None)[source]¶
Bases:
PrimitiveAlgorithm- build() Self[source]¶
Construct circuits: populate self.sub_blocks with qx.Block instances.
Returns
selfso callers can chainprimitive.build().
- class qarp.algorithms.MonteCarlo(hamiltonian: QubitOperator | ndarray, approx_ground_state_energy: float | List[float], total_time: float, time_step: float, reference_walker_label: int | List[int], unitary_block: Block, num_target_states: int = 1, initial_walker_count: int | List[int] = 200, walker_basis: List[WalkerState] | None = None, shift_damping: float | List[float] = 0.1, population_threshold: int = 350, mode: str = 'Semiclassical', primitive: PrimitiveAlgorithm | None = None, n_shots: int = 1000, num_trajectories: int = 10, ham_cache: Dict[Tuple[int, int], Tuple[complex, float]] | None = None, save_walker_history: bool = False, history_save_interval: int = 1, qdrift: bool = False, qdrift_samples: int = 100, qdrift_ratio: float | None = None, verbose: bool = False, engine: Engine | None = None, seed: int | None = None)[source]¶
Bases:
CompositeAlgorithm- build()[source]¶
Build the simulator by setting up walker states and caches.
- Returns:
Self for method chaining
- estimate_ground_state_energy(walkers_by_label: Dict[str, List[WalkerState]], initial_energy: float, visited_states: Set[int]) float[source]¶
Calculate energy using pre-grouped walkers (semiclassical mode).
- estimate_ground_state_energy_quantum(walkers: List[WalkerState], initial_energy: float, visited_states: Set[int]) float[source]¶
Calculate ground state energy from walker list (quantum mode).
- prepare_vector_and_projector(walkers) Tuple[ndarray, ndarray][source]¶
From list of walkers, return vector in walker basis and projector of that vector
- project_for_orthogonalization(current_excitation, projectors) Tuple[List[WalkerState], float][source]¶
Apply projectors onto current ES walker vector to ensure orthogonalisation with lower energy states
- remove_opposite_sign_pairs(walkers: List[WalkerState]) List[WalkerState][source]¶
Remove walkers with opposite signs in the same state (annihilation).
- Parameters:
walkers – List of walker states
- Returns:
Walkers after annihilation
- class qarp.algorithms.PCE(graph: Graph, order: int, ket: Block, merging: bool = False, classical_function: Callable = <function classical_function_max_cut>, quantum_function: Callable = <function quantum_function_max_cut>, initial_parameters: Iterable[float] | None = None, optimizer: Optimizer | None = None, verbose: bool = True, gradient: bool | str = False, primitive: PrimitiveAlgorithm | None = None, engine: Engine | None = None)[source]¶
Bases:
CompositeAlgorithm- build()[source]¶
Build the PCE object with UCC ansatz
If not all attributes are set, some defaults are loaded. These are: - COBYLA as optimizer - No gradients used - StateVector for all measurement strategies - QarpEngine() for all backends
- Returns:
self
- get_gradient_function()[source]¶
Builds a gradient function as an option for certain optimizers to minimize
- Returns:
The gradient function assisting the optimizer
- class qarp.algorithms.PauliAveraging(bra: Block | None = None, operator: QubitOperator | None = None, ket: Block | None = None, n_shots: int | Shots | None = None, grouping: GroupingStrategy | None = None)[source]¶
Bases:
PrimitiveAlgorithm- build() Self[source]¶
Construct circuits: populate self.sub_blocks with qx.Block instances.
Returns
selfso callers can chainprimitive.build().
- run(results: list) float[source]¶
Per-group expectation, weighted sum, plus the constant term.
After the group’s diagonalising Clifford, term
iequalss_i · Z^{mask_i}(s_i = ±1), so from the measurement counts:E[term_i] = s_i · (1/n_shots) Σ_outcome counts[outcome] · (-1)^popcount(outcome & mask_i)
⟨H⟩ = constant + Σ_groups Σ_terms c_i · E[term_i].
- class qarp.algorithms.PauliKernel(n_qubits: int)[source]¶
Bases:
ShadowKernelRandom-Pauli (local-Clifford) inverse channel.
A setting is one axis per qubit (
0/1/2=X/Y/Z). The inverse channel factorizes per qubit: for a Pauli termPa snapshot contributesprod_{q in supp(P)} 3 * (-1)^{b_q}iff the measured axis on every qubit ofsupp(P)matchesP’s axis there, and0otherwise.
- class qarp.algorithms.PauliShadow(operator: str | QubitOperator, ket: Block | None = None, *, dataset: ShadowDataset | None = None, n_settings: int = 1000, n_shots: int = 1, seed: int | None = None)[source]¶
Bases:
ShadowProtocolRandom-Pauli classical shadows (Huang–Kueng–Preskill, 2020).
- class qarp.algorithms.PrimitiveAlgorithm(ket: Any = None, bra: Any = None, operator: Any = None, n_shots: int | Shots | None = None, target: Target = Target.SAMPLING)[source]¶
Bases:
ABCPure Python base class for qarpx-backed primitive algorithms.
Uses the C++ kernel (qarpx) for compilation and simulation. All algorithm logic — circuit construction and result post-processing — lives in Python, keeping the boundary simple.
Subclasses must implement:
build()— populate self.sub_blocks with qx.Block instancesrun(results)— post-process the engine’s per-sub-block results (qx.SamplingResult, or ExactResult under n_shots=qarp.EXACT) → scalar
- Variables:
sub_blocks – Populated by build(); list of qx.Block to compile.
compiled_circuits – Set by QarpEngine.build(); list of command lists.
_n_qubits_list – Set by QarpEngine.build(); n_qubits per circuit.
Class capability metadata (override on the subclass; class-level so it survives the
deepcopy-then-mutate pattern QSE/MonteCarlo/QMEGS use):supported_targets: TheTargetvalues this primitive can estimate.consumes:Consumes.COUNTS— estimator reads sampled measurement statistics (the default);Consumes.AMPLITUDES— estimator contracts simulator statevectors directly, and engines dispatch torun_from_amplitudes(compiled_circuits)instead of sampling.supports_exact:Trueiff the protocol has a meaningful ∞-shot limit. Consulted only for COUNTS consumers (an AMPLITUDES primitive is always exact);Falsefor inherently stochastic protocols (CuttingPrimitive).supports_backprop_gradient:Trueiff the primitive is eligible for the engine’s adjoint backprop gradient path (Engine.run_gradient). DefaultFalse— sampling primitives use the parameter-shift fallback instead.gradient_kind: what a shift rule may assume aboutrun()as a function of each compiled circuit’s state, separately:"expectation"(bilinear — every sampled estimator),"amplitude"(linear or antilinear in one circuit’s amplitudes),"squared_overlap"(run()returns ⟨bra|ket⟩, the gradient is of |·|²), or"none"(non-linear, e.g. a median-of-means or a ratio: parameter shift refuses, finite differences still apply). Default"none"— a new primitive loses speed, never correctness, until it declares its class.requires_noiseless:Trueiff the estimator’s post-processing is only valid under ideal (noiseless) measurement. Enforced inEngine._validate_primitive: a primitive with this flag is rejected on an engine whose noise model is active. DefaultFalse(noise is fine).PauliShadowsets it — the shadow inverse channel assumes ideal readout, so a noisy campaign fed through it is silently biased.returns_probability:Trueiff anOVERLAPestimator’srun()already returns|⟨bra|ket⟩|²rather than the amplitude⟨bra|ket⟩. Consumers that need the squared overlap (VQD/ADAPT-VQD deflation) must not square such a value again. DefaultFalse(amplitude-returning).
- abstractmethod build() PrimitiveAlgorithm[source]¶
Construct circuits: populate self.sub_blocks with qx.Block instances.
Returns
selfso callers can chainprimitive.build().
- infer_target() Target[source]¶
Detect which quantity to compute from the
{ket, bra, operator}inputs.Single source of truth for input-driven target detection, shared by the primitives that vary their operation with their inputs (
HadamardTest,StateVector). Sets and returnsself.target, and defaultsbratoketfor the expectation-value case. Fixed-purpose primitives (Sampler,SWAPTest,MirrorTest, …) pass an explicittargetto__init__and never call this.- Rules:
ketonly →SAMPLINGket+operator→EXPECTATION_VALUE(bra≔ket)bra≠ket+operator→TRANSITION_AMPLITUDEbra≠ket, no operator →OVERLAP
The
bra ≔ ketdefault is live: whilebrahas never been explicitly assigned, every call re-derives it from the current{ket, operator}, so rebinding onlyket(e.g. on a deepcopy) keeps an EXPECTATION_VALUE primitive an expectation value. Any explicit assignment takes ownership;bra = Nonehands it back.- Raises:
RuntimeError – if
ketis missing, orbrawas explicitly set to the same object asketwith no operator (a degenerate ⟨ψ|ψ⟩ request).
- abstractmethod run(results: list) float | complex | dict[tuple[int, ...], float][source]¶
Post-process the engine’s sampling output into a result.
Contract: a pure function of
results— no simulator or engine access. Keeps every estimator unit-testable with synthetic results (anything exposingcounts/n_shots/n_qubits).- Parameters:
results – One
qx.SamplingResultper entry inself.sub_blocks, as produced by the engine’s sampler.- Returns:
A scalar (float / complex) for expectation/overlap-style primitives, or a
SamplingDictionary({bitstring-tuple: probability}) forSampler.
- run_from_amplitudes(compiled_circuits: list, simulator=None) float | complex[source]¶
Evaluate the target directly from simulator amplitudes.
Only called by engines when
self.consumesisConsumes.AMPLITUDES. Default raises — sampling primitives don’t override this.- Parameters:
compiled_circuits – One command stream per
sub_blocksentry, already parameter-substituted.simulator – Optional statevector backend (anything implementing
statevector(commands, n_qubits)). Engines pass their own simulator so amplitude primitives run on the same backend — e.g.CudaqEnginepasses its GPUqx.CudaqSimulator. Defaults to a CPUqx.QarpSimulatorwhen None.
- class qarp.algorithms.ProjectedVQE(operator: QubitOperator, ket: Block, projector: Block | Sequence[Block] | None = None, projector_matrix: ndarray | None = None, initial_parameters: NDArray[float64] | None = None, optimizer: Optimizer | None = None, verbose: bool = False, engine: Engine | None = None, postselection_tol: float = 1e-14, save_energy_history: bool = False)[source]¶
Bases:
VQEVariation-after-projection VQE using a fast StateVector objective.
- Parameters:
operator – Hamiltonian as a qarp
QubitOperatoron the system register, with no ancilla shift.ket – Parameterized ansatz block on the system register.
projector – One symmetry-projector block, or a sequence of them (applied as a product). Known projector blocks are converted to dense system-register projector matrices and are not simulated as circuits during optimization.
projector_matrix – Dense projector matrix in qarpx LSB ordering, for custom projectors. Mutually exclusive with
projector.postselection_tol – Squared-norm threshold below which the projected state counts as annihilated; the objective returns
+infthere.
- class qarp.algorithms.QAOA(problem: Graph | QubitOperator, n_layers: int = 1, use_rzz: bool = True, initial_parameters: NDArray[float64] | None = None, gradient: bool | str = False, optimizer: Optimizer | None = None, verbose: bool = False, primitive: PrimitiveAlgorithm | None = None, engine: Engine | None = None, save_energy_history: bool = False)[source]¶
Bases:
VQA
- class qarp.algorithms.QITE(hamiltonian: QubitOperator, initial_block: Block, dtau: float, n_steps: int, *, pool: List[QubitOperator] | None = None, regularization: float = 1e-06, trotter_steps: int = 1, trotter_order: int = 2, engine: Engine | None = None, verbose: bool = False)[source]¶
Bases:
CompositeAlgorithm- build() QITE[source]¶
Build the composite algorithm by constructing all sub-algorithms.
This method should: 1. Create and configure all necessary sub-algorithms 2. Build each sub-algorithm
- Returns:
Self for method chaining
- class qarp.algorithms.QMEGS(unitary: Block, state: Block, n_shots: int | Shots | None, target_indices: List[int], sigma: float = 1.0, eta: float = 0.01, T: int = 100, filtering_function: Callable | None = None, mode_dataset: Literal['analytical', 'sampling'] = 'analytical', mode_time: Literal['rvs', 'rejection_sampling'] = 'rvs', overlaps: Literal['classical'] | Tuple[float, float] = 'classical', verbose: bool = False, primitive: PrimitiveAlgorithm | None = None, engine: Engine | None = None)[source]¶
Bases:
CompositeAlgorithmQuantum Multiple Eigenvalue Gaussian filtered Search (QMEGS) algorithm.
Implementation based on arxiv2402.01013. This algorithm finds multiple eigenphases of a unitary operator using Hadamard tests with Gaussian filtered time sampling.
- Parameters:
unitary – Block representing the time-evolution unitary.
state – Block representing the trial state.
n_shots – Number of measurement shots — same meaning in both modes: an int adds shot noise (synthetic in “analytical” mode, sampled in “sampling” mode with a sampling primitive);
qarp.EXACTmeans no shot noise;Nonemeans the default shot count (10_000 / engine default). The default exact primitive ignores it in “sampling” mode.target_indices – List of indices of target eigenvalues to find (Dset in the paper).
sigma – Truncation level for time sampling.
eta – Error tolerance for the algorithm.
T – Time window for time sampling.
filtering_function – Custom filtering function for time sampling. Defaults to truncated_gaussian_density.
mode_dataset – Dataset generation mode. - “analytical”: Generate data using classical simulation (faster, for testing). - “sampling”: Generate data using actual sampling execution.
mode_time – Time sampling mode. - “rvs”: Use scipy’s truncnorm.rvs for fast sampling. - “rejection_sampling”: Use rejection sampling (enables arbitrary filtering functions).
overlaps –
Where the algorithm’s a-priori inputs
p_min/p_tail(Theorem 1 of arXiv:2402.01013) come from. -"classical"(default):build()dense-diagonalises theHamiltonian (O(4^n)) and reads the trial statevector through the engine’s simulator — a validation harness, refused on a noisy or routed engine. Required by
mode_dataset="analytical".(pmin, ptail): the two overlaps supplied by the user; no diagonalisation, no statevector. Onlylen(target_indices)is consulted (the number of eigenvalues to extract) — the index values themselves are not used.
verbose – Whether to print progress information.
primitive – Primitive used to evaluate ⟨ψ|U(t)|ψ⟩ in “sampling” mode. Defaults to
StateVector()— exact, noise-free amplitudes. PassHadamardTest()for finite-shot protocol realism.engine – Quantum engine for circuit execution.
- build()[source]¶
Build the algorithm by computing necessary parameters.
Calculates overlaps, probabilities, and algorithm parameters based on the input unitary and trial state.
- Returns:
Self for method chaining.
- Raises:
ValueError – If the algorithm’s assumptions are not satisfied (pmin must be greater than ptail).
- filtered_density_function(dataset: List[tuple], theta_js: ndarray, n_samples: int) ndarray[source]¶
Compute the filtered density function G_j for given theta values.
- Parameters:
dataset – List of (time, measurement) tuples from quantum measurements.
theta_js – Array of theta values to evaluate.
n_samples – Number of samples for normalization.
- Returns:
filtered density values for each theta.
- Return type:
G_js
- generate_data() List[tuple][source]¶
Generate the measurement dataset according to selected mode.
- Returns:
List of (time, measurement) tuples.
- run() List[float][source]¶
Run the QMEGS algorithm to find eigenphases.
Follows Algorithm 2 in arxiv2402.01013.
- Returns:
List of found eigenphases.
- validate_inputs()[source]¶
Validate input parameters for correctness.
- Raises:
ValueError – If any input parameter is invalid.
- class qarp.algorithms.QPE(state: Block, unitary: Block, n_ancilla: int, primitive: PrimitiveAlgorithm | None = None, engine: Engine | None = None)[source]¶
Bases:
CompositeAlgorithm- build()[source]¶
Build the Canonical Phase Estimation circuit.
First offers the problem to the engine’s structured fast path (
Engine.prepare_structured_qpe— matrix exponentiation, the controlled-U ladder is never compiled). Engines without the path, or refusing it (EXACT readout, noise, routing, parametric U — seeQarpEngine.prepare_structured_qpe), return None and the full QPE circuit is built instead.- Returns:
The instance of the class.
- Return type:
self
- estimate_phase(fit_range=None, verbose=False)[source]¶
Estimation of the phase done by fitting the Dirichlet kernel squared to the distribution obtained from the run.
- class qarp.algorithms.QSE(hamiltonian: QubitOperator | Block, ground_state: Block, primitive: PrimitiveAlgorithm, overlap_primitive: PrimitiveAlgorithm, excitation_operators: List[QubitOperator], engine: Engine | None = None, real_symmetric: bool = False, verbose: bool = False)[source]¶
Bases:
CompositeAlgorithm- build()[source]¶
Build the composite algorithm by constructing all sub-algorithms.
This method should: 1. Create and configure all necessary sub-algorithms 2. Build each sub-algorithm
- Returns:
Self for method chaining
- compute_hamiltonian()[source]¶
Constructs the Hamiltonian matrix H in HC = SCe from the primitives.
Note
It is assumed that the QSE Hamiltonian is symmetric or Hermitian.
- Returns:
A numpy array representing the Hamiltonian matrix H.
- compute_overlap()[source]¶
Constructs the overlap matrix S from the primitives.
Note
Assumes that the QSE overlap matrix is real valued and symmetric or Hermitian.
- Returns:
A numpy array representing the overlap matrix S.
- property hamiltonian_primitives: List[PrimitiveAlgorithm]¶
- property overlap_primitives: List[PrimitiveAlgorithm]¶
- class qarp.algorithms.SSVQE(operator: QubitOperator | Block, basis_state_blocks: List[Block], ansatz_block: Block, weights: List[float], initial_parameters: Mapping | NDArray[float64] | None = None, optimizer: Optimizer | None = None, verbose: bool = True, gradient: bool | str = False, primitive: PrimitiveAlgorithm | None = None, engine: Engine | None = None)[source]¶
Bases:
CompositeAlgorithm- build()[source]¶
Build the composite algorithm by constructing all sub-algorithms.
This method should: 1. Create and configure all necessary sub-algorithms 2. Build each sub-algorithm
- Returns:
Self for method chaining
- get_final_state_block(index: int) Block[source]¶
Built block for optimized state
index: basis state + ansatz bound at the optimal parameters. No symbol handling required — evaluate ⟨N⟩, ⟨S²⟩, etc. directly on the returned block.
- class qarp.algorithms.SWAPTest(bra: Block | None = None, operator: Block | None = None, ket: Block | None = None, n_shots: int | Shots | None = None)[source]¶
Bases:
PrimitiveAlgorithm- build() Self[source]¶
Construct circuits: populate self.sub_blocks with qx.Block instances.
Returns
selfso callers can chainprimitive.build().
- class qarp.algorithms.Sampler(ket: Block | None = None, n_shots: int | Shots | None = None, measured_qubits: list[int] | None = None, initial_state=None)[source]¶
Bases:
PrimitiveAlgorithmqarpx-backed sampling primitive.
- Parameters:
ket – Block to execute.
n_shots – Number of measurement shots (default: use engine default).
qarp.EXACTreturns the exact Born distribution|ψ|²— note: probabilities, not amplitudes (phases are discarded; raw amplitudes are simulator internals,sim.statevector).measured_qubits – Qubit indices whose outcomes appear in the output tuple. Defaults to
range(ket.n_qubits). Non-measured qubits are marginalised out by summing probabilities over their bit values.initial_state – Optional LSB-indexed amplitudes seeding the register instead of
|0…0⟩(length2**n_qubits, unit norm within1e-10—ValueErrorat run otherwise). QarpEngine only; other engines raiseCapabilityErrorat build. Mutable between runs for step → snapshot → re-seed loops.
- build() Self[source]¶
Construct circuits: populate self.sub_blocks with qx.Block instances.
Returns
selfso callers can chainprimitive.build().
- class qarp.algorithms.ShadowDataset(kernel: ShadowKernel, n_qubits: int, records: list[tuple[ndarray, dict[int, float]]], shot_exact: bool = False)[source]¶
Bases:
objectA collected campaign: settings + outcomes + the ensemble kernel.
- estimator()[source]¶
Return a
ShadowEstimatorover this dataset.
- classmethod from_dict(d: dict) ShadowDataset[source]¶
- merge(other: ShadowDataset) ShadowDataset[source]¶
Concatenate two compatible campaigns (same ensemble,
n_qubits,shot_exact). Batching is round-robin by setting index, so the merged batches stay evenly mixed between the two campaigns.
- class qarp.algorithms.ShadowEstimate(value: float, error: float, delta: float, n_batches: int, ensemble_only: bool)[source]¶
Bases:
NamedTupleOne estimate with the HKP Theorem-1 accuracy half-width.
erroris theeps = sqrt(34 * V_hat / N)of arXiv:2002.08953 Theorem 1 (V_hatthe empirical single-setting variance,Nthe per-batch size) — the half-width for whichPr[|value - true| >= error] <= deltaat thedeltathat fixedn_batches. That promise holds for the true variancesigma^2;V_hatis a plug-in for it, so the reported bar inherits whatever error that estimate carries (and HKP’s own Remark that the constant 34 is a loose worst case).
- class qarp.algorithms.ShadowEstimator(dataset)[source]¶
Bases:
objectEstimate observables from a collected
ShadowDataset.- expval(observable: str | QubitOperator, *, delta: float = 0.05, n_batches: int | None = None) ShadowEstimate[source]¶
Median-of-means estimate of
<observable>(sum-inside for a multi-term operator).
- expval_many(observables: Sequence[str | QubitOperator], *, delta: float = 0.05, n_batches: int | None = None, marginal: bool = False) list[ShadowEstimate][source]¶
Estimate a family of observables from the one dataset.
By default this is exactly Theorem 1 of HKP applied to the family: the batch count uses the union bound
K = ~2 ln(2M/delta)over theMsupplied, so eacherroris the half-width for which allMestimates lie within their band jointly with probability at least1 - delta.marginal=Trueopts out to a per-observabledelta(K = ~2 ln(2/delta), no union correction).Looping
expval()yourself does not give the joint guarantee — use this method for a family. And choosing observables after seeing results from the same dataset voids it: collect fresh or split.An explicit
n_batchesoverrides the derived count for every estimate (power-user knob; it then defeats the union bound this method exists to apply, so the joint guarantee no longer holds atdelta).
- class qarp.algorithms.ShadowKernel(n_qubits: int)[source]¶
Bases:
ABCStateless inversion kernel for one measurement ensemble.
- Variables:
ensemble (str) – registry tag used by
ShadowDataset.from_dict().n_qubits – register width the kernel was built for.
capabilities (frozenset[str]) – estimator features this ensemble supports (e.g.
{"expval"}; matchgate would add"rdm"). The estimator raisesCapabilityErrorfor anything outside this set.
- classmethod from_params(n_qubits: int, params: dict) ShadowKernel[source]¶
- class qarp.algorithms.ShadowProtocol(operator: str | QubitOperator, ket: Block | None = None, *, dataset: ShadowDataset | None = None, n_settings: int = 1000, n_shots: int = 1, seed: int | None = None)[source]¶
Bases:
PrimitiveAlgorithmBase collector for a randomized-measurement shadow ensemble.
- build()[source]¶
Construct circuits: populate self.sub_blocks with qx.Block instances.
Returns
selfso callers can chainprimitive.build().
- property dataset: ShadowDataset¶
The collected (or passed)
ShadowDataset. Raises if neither a dataset was passed nor a campaign collected yet.
- release() None[source]¶
Free the compiled circuits in place (the detached dataset stays valid).
run()never does this automatically — the engine reuses the compiled circuits underrebuild=Falseand acrossbatch_runparameter sets. Afterrelease(), a re-run needs a rebuild.
- run(results: list) float[source]¶
Post-process the engine’s sampling output into a result.
Contract: a pure function of
results— no simulator or engine access. Keeps every estimator unit-testable with synthetic results (anything exposingcounts/n_shots/n_qubits).- Parameters:
results – One
qx.SamplingResultper entry inself.sub_blocks, as produced by the engine’s sampler.- Returns:
A scalar (float / complex) for expectation/overlap-style primitives, or a
SamplingDictionary({bitstring-tuple: probability}) forSampler.
- class qarp.algorithms.Shor(number: int, *, base: int | None = None, n_counting_qubits: int | None = None, max_attempts: int = 8, base_seed: int | None = None, force_quantum: bool = False, primitive: Sampler | None = None, engine: Engine | None = None)[source]¶
Bases:
CompositeAlgorithmExact small-integer/reference implementation of Shor factoring.
This implementation uses an exponentially synthesized basis permutation for modular arithmetic and supports at most
ModularMultiplicationBlock.MAX_REFERENCE_WORK_QUBITSwork qubits (number <= 64for the shipped value of six). It establishes a correct reference workflow for small examples; it does not claim cryptographic-scale performance or an asymptotic quantum speedup.build()prepares the order-finding samplers andrun()produces the factor pair, classical shortcuts included.run()executes the batch once; a repeated call returns the stored outcome,Noneincluded, so a finite-shot retry is a new instance. Bases are processed in attempt order, as in Shor’s sequential algorithm: every coprime base gets an order-finding circuit, and the first non-coprime base ends the attempt list withgcd(base, number)as a classical fallback thatrun()returns only if every quantum attempt was inconclusive. Even and perfect-power inputs are factored classically without any circuit.- Parameters:
number – Composite integer greater than one to factor.
base – Optional first modular-order-finding base. Must satisfy
1 < base < number. A non-coprime base is a valid classical gcd shortcut unlessforce_quantumis set.n_counting_qubits – Counting-register width. Defaults to twice the work width and must be at least that large.
max_attempts – Maximum number of distinct bases to try.
base_seed – Seed for the algorithm-local base-selection RNG.
force_quantum – Guarantee the quantum path. Disables the gcd shortcut (random bases are drawn coprime; a supplied non-coprime base is rejected) and rejects even or perfect-power inputs, which lie outside the preconditions of Shor’s order-finding theorem: for
N = 2pand oddN = p**kevery even order givesa**(r/2) == -1 (mod N), so no base can succeed.primitive – Sampling primitive. A private deep copy is used, and Shor owns its
ketandmeasured_qubits(the counting register); the caller’s sampler contributes shot settings only.engine – Execution engine. Defaults to
QarpEngine.
- class qarp.algorithms.StateVector(bra: Block | None = None, operator: QubitOperator | Block | None = None, ket: Block | None = None, initial_state: ndarray | None = None)[source]¶
Bases:
PrimitiveAlgorithm- build() Self[source]¶
Populate
sub_blockswith [ket] (or [bra, ket] for overlap-type).Re-disambiguates
self.targetfrom the currentbra/operator/ketattributes so callers (VQA-family composites) that mutate the primitive after construction get the right target without having to re-instantiate.
- run(results: list) complex | float[source]¶
Convenience entry point: evaluate the build-time compiled circuits.
Engines dispatch directly to
run_from_amplitudes()(becauseconsumesisConsumes.AMPLITUDES), so this method exists mainly for callers driving the primitive without an engine. Symbolic parameters must be substituted intoself.compiled_circuitsbefore calling.
- run_from_amplitudes(compiled_circuits: list, simulator=None) complex | float[source]¶
Simulate the substituted commands and contract the statevectors.
- Parameters:
compiled_circuits – One command stream per entry in
self.sub_blocks, already parameter-substituted by the engine (or by the caller).simulator – Optional statevector backend implementing
statevector(commands, n_qubits). Defaults to a CPUqx.QarpSimulator;CudaqEngineinjects its GPU simulator so the statevectors are computed on-device. A simulator that also providestransition(bra, ket, n_qubits, observable)(QarpSimulatordoes) contracts the operator in C++; otherwise the numpy sweeppauli_expectation()is used.
- class qarp.algorithms.Target(*values)[source]¶
Bases:
EnumEnumeration of measurement targets for primitive algorithms.
Target specifies the type of quantum measurement being performed by a primitive algorithm. Different targets determine how measurement circuits are constructed and how results are post-processed to compute the desired quantum mechanical quantity.
- Variables:
SAMPLING – Return raw measurement distribution as a dictionary of bitstrings to probabilities.
EXPECTATION_VALUE – Compute the expectation value <ket|operator|ket⟩.
OVERLAP – Compute the overlap (inner product) ⟨bra|ket⟩.
TRANSITION_AMPLITUDE – Compute the transition amplitude ⟨bra|operator|ket⟩.
- EXPECTATION_VALUE = 1¶
- OVERLAP = 2¶
- SAMPLING = 0¶
- TRANSITION_AMPLITUDE = 3¶
- class qarp.algorithms.TermwiseHadamardTest(bra: Block | None = None, operator: Block | List[Block] | QubitOperator | None = None, ket: Block | None = None, coefficients: List[float] | None = None, real: bool = True, imaginary: bool = True, n_shots: int | Shots | None = None)[source]¶
Bases:
PrimitiveAlgorithm- build() TermwiseHadamardTest[source]¶
Construct circuits: populate self.sub_blocks with qx.Block instances.
Returns
selfso callers can chainprimitive.build().
- get_hadamard_test(index: int) HadamardTest[source]¶
- run(results: list) complex[source]¶
Post-process the engine’s sampling output into a result.
Contract: a pure function of
results— no simulator or engine access. Keeps every estimator unit-testable with synthetic results (anything exposingcounts/n_shots/n_qubits).- Parameters:
results – One
qx.SamplingResultper entry inself.sub_blocks, as produced by the engine’s sampler.- Returns:
A scalar (float / complex) for expectation/overlap-style primitives, or a
SamplingDictionary({bitstring-tuple: probability}) forSampler.
- class qarp.algorithms.TermwiseSWAPTest(bra: Block | List[Block], ket: Block | None = None, coefficients: List[float] | None = None, n_shots: int | Shots | None = None)[source]¶
Bases:
PrimitiveAlgorithm- build() TermwiseSWAPTest[source]¶
Construct circuits: populate self.sub_blocks with qx.Block instances.
Returns
selfso callers can chainprimitive.build().
- run(results: list) float[source]¶
Post-process the engine’s sampling output into a result.
Contract: a pure function of
results— no simulator or engine access. Keeps every estimator unit-testable with synthetic results (anything exposingcounts/n_shots/n_qubits).- Parameters:
results – One
qx.SamplingResultper entry inself.sub_blocks, as produced by the engine’s sampler.- Returns:
A scalar (float / complex) for expectation/overlap-style primitives, or a
SamplingDictionary({bitstring-tuple: probability}) forSampler.
- class qarp.algorithms.VFF(operator: QubitOperator | Block, ansatz_block: Block, use_trotter: bool = False, t_time: float = 1.0, t_steps: int = 1, t_order: int = 1, initial_parameters: NDArray[float64] | None = None, optimizer: Optimizer | None = None, verbose: bool = True, primitive: PrimitiveAlgorithm | None = None, engine=None)[source]¶
Bases:
CompositeAlgorithm- build()[source]¶
Build the composite algorithm by constructing all sub-algorithms.
This method should: 1. Create and configure all necessary sub-algorithms 2. Build each sub-algorithm
- Returns:
Self for method chaining
- property optimal_parameters¶
Optimized parameters keyed by symbol — the order-proof surface.
- class qarp.algorithms.VQA(operator: QubitOperator | Block, ket: Block, name: str, initial_parameters: Mapping | NDArray[float64] | None = None, gradient: bool | str = False, optimizer: Optimizer | None = None, verbose: bool = False, primitive: PrimitiveAlgorithm | None = None, engine: Engine | None = None, save_energy_history: bool = False)[source]¶
Bases:
CompositeAlgorithm- build()[source]¶
Build the composite algorithm by constructing all sub-algorithms.
This method should: 1. Create and configure all necessary sub-algorithms 2. Build each sub-algorithm
- Returns:
Self for method chaining
- class qarp.algorithms.VQD(operator: QubitOperator | Block, kets: List[Block], weights: List[float], initial_parameters: Iterable[Iterable[float]] | None = None, verbose: bool = False, gradient: bool | str = False, optimizer: Optimizer | None = None, primitive: PrimitiveAlgorithm | None = None, engine: Engine | None = None)[source]¶
Bases:
CompositeAlgorithm- build() Self[source]¶
Build the composite algorithm by constructing all sub-algorithms.
This method should: 1. Create and configure all necessary sub-algorithms 2. Build each sub-algorithm
- Returns:
Self for method chaining
- class qarp.algorithms.VQE(operator: QubitOperator | Block, ket: Block, initial_parameters: NDArray[float64] | None = None, gradient: bool | str = False, optimizer: Optimizer | None = None, verbose: bool = False, primitive: PrimitiveAlgorithm | None = None, engine: Engine | None = None, save_energy_history: bool = False)[source]¶
Bases:
VQA
- class qarp.algorithms.WalkerState(state_data: ndarray | Block, sign: float, label: str)[source]¶
Bases:
NamedTupleRepresents a quantum walker state.
- Variables:
- state_data: ndarray | Block¶
Alias for field number 0
- class qarp.algorithms.cPCE(graph: Graph, order: int, ket: Block, merging: bool = False, classical_function: Callable = <function classical_function>, quantum_function: Callable = <function quantum_function>, coefficients: Iterable[float] | None = None, initial_parameters: Iterable[float] | None = None, optimizer: Optimizer | None = None, verbose: bool = True, gradient: bool | str = False, primitive: PrimitiveAlgorithm | None = None, engine: Engine | None = None)[source]¶
Bases:
PCEContinuous Pauli Correlation Encoding (cPCE).
cPCE reuses the same measurement and optimization machinery as PCE, but drops the tanh + sign thresholding step used to turn Pauli expectation values into a discrete bitstring. Instead, the expectation values are used directly (optionally rescaled by coefficients) as the solution to a real-valued optimization problem.
This implementation follows the approach described in https://arxiv.org/abs/2604.05637.
- qarp.algorithms.calculate_qubits(n_nodes: int, order: int, merging: bool = False) int[source]¶
Compute the needed number of qubits for a given number of graph nodes and order
- Parameters:
n_nodes – Number of nodes to map into the qubits.
order – Order to consider in the Pauli correlators.
merging – If True, considers merging of same Pauli terms of different correlators.
- Returns:
Number of qubits required.
- qarp.algorithms.classical_function_max_cut(graph: Graph, binary_string: list[int]) float[source]¶
Calculate the cut size of the given partitions of the graph.
- Parameters:
graph – Original graph over which to compute the cut size.
binary_string – Binary representation of solution, where each position represents a node, and it value (0 or 1) represents the subset location.
- Returns:
Sum of weighted edges cut due to the partitions.
- qarp.algorithms.dirichlet_kernel_squared(x, phi, N)[source]¶
Dirichlet kernel squared function. Used to reconstruct the phase information in the QPE algorithm.
- qarp.algorithms.find_eigenspectrum_degeneracy(eigs, tolerance=1e-15, verbose=False)[source]¶
Finds the degeneracy of the eigenvalues in the eigenspectrum.
- qarp.algorithms.find_occupation_numbers(hamiltonian, n_qubits, tolerance=1e-15, verbose=False)[source]¶
Finds the occupation numbers of the eigenstates of a Hamiltonian.
- Parameters:
hamiltonian (FermionOperator) – The Hamiltonian operator.
n_qubits (int) – The number of qubits.
tolerance (float) – The tolerance for determining occupation numbers.
verbose (bool) – If True, prints the eigenvalues and occupation numbers.
- Returns:
An array of occupation numbers for the eigenstates.
- Return type:
np.ndarray
- qarp.algorithms.find_unique_eigs_and_occupation_numbers(eigs, occ_numbers, select_occ=None, tolerance=1e-15, verbose=False)[source]¶
Finds unique eigenvalues and their corresponding occupation numbers.
- Parameters:
eigs (np.ndarray) – The eigenvalues of the Hamiltonian.
occ_numbers (np.ndarray) – The occupation numbers corresponding to the eigenvalues.
select_occ (int, optional) – If provided, filters the unique eigenvalues by this occupation number.
tolerance (float) – The tolerance for determining degeneracy.
verbose (bool) – If True, prints the unique eigenvalues and their occupation numbers.
- Returns:
- A tuple containing:
dict: A dictionary with unique eigenvalues as keys and their degeneracy as values.
list: A list of unique occupation numbers corresponding to the unique eigenvalues.
- Return type:
- qarp.algorithms.generate_states_new_basis(U: Block, hamming_weight: int | List[int] | None = None, get_statevector: bool = True) Tuple[List[ndarray], List[Block], List[int]][source]¶
Apply a unitary block
Uto every computational basis state and (optionally) compute the resulting statevectors.The new basis is \(\{ U |i\rangle : i \in \mathrm{indices} \}\).
WARNING: exponential scaling — the indices set is
2^n_qubitsunlesshamming_weightfilters it down.- Parameters:
U – A built
qarp.blocks.AnyBlockwhose unitary is the change of basis.hamming_weight – If int, restrict to computational basis states with exactly that Hamming weight. If list[int], restrict to the union of those weights. If None, use every basis state.
get_statevector – If True, compute each new basis state’s statevector via the qarpx simulator (still exponential). If False, return an empty statevector list.
- Returns:
new_basis_states— list of length-2^n_qubitsndarrays (only populated whenget_statevector=True).new_basis_blocks—Blockper basis state:ComputationalBasisStateBlock(bitstring) + U.basis_states_indices— the integer indices the basis was built from.
- Return type:
(new_basis_states, new_basis_blocks, basis_states_indices)where
- qarp.algorithms.get_overlaps(trial_state: Block, hamiltonian: QubitOperator, return_eigenvalues: bool = False) ndarray | Tuple[ndarray, ndarray][source]¶
Compute overlaps of trial state with eigenstates of the Hamiltonian.
- Parameters:
trial_state – Block representing the trial state.
hamiltonian – QubitOperator representing the Hamiltonian.
return_eigenvalues – If True, also return the eigenvalues.
- Returns:
Array of overlap probabilities with each eigenstate, sorted by ascending eigenvalue. If
return_eigenvaluesis True, returns a(overlaps, eigenvalues)tuple instead.
Note
Uses np.linalg.eigh which returns eigenvectors as COLUMNS of the matrix. The overlaps are computed correctly by iterating over columns.
- class qarp.algorithms.iterativePCE(graph: Graph, order: int, ket: Block, pce_cls: type = <class 'qarp.algorithms._composite.pce.PCE'>, alpha0: float = 1.0, threshold: float = 0.9, max_outer_iterations: int = 50, stabilized_update: bool = False, verbose: bool = True, **pce_kwargs)[source]¶
Bases:
CompositeAlgorithmIterative-alpha Pauli Correlation Encoding.
Wraps a PCE-like algorithm (by default PCE, but compatible with any class sharing its constructor/build/run/get_objective_function surface) and repeatedly re-runs it, progressively increasing the sharpness parameter alpha used to binarize Pauli-correlator expectation values via tanh(alpha * <Pi>). At each round, only the least-binarized correlator is pushed just past the binarization threshold M, and the ansatz parameters are warm-started from the previous round’s optimum.
This avoids the tradeoff of a single fixed alpha: too small and the loss/constraint is evaluated on an under-binarized (and thus misleading) solution; too large and tanh’s vanishing derivative stalls the optimizer everywhere at once.
Implements Algorithm 1 (“Iterative-alpha PCE heuristic”) from https://arxiv.org/abs/2602.17479.
After run(), alpha_history, raw_expectations_history and solution_history hold, per round, the alpha used, the raw <Pi_i> expectation values obtained at convergence, and the rounded solution. There is exactly ONE inner algorithm — built once and re-run — so sub_algorithms has a single entry, not one per round.
- build()[source]¶
No-op: each round’s inner algorithm is built when it is constructed in run.
- Returns:
self
- run()[source]¶
Run the Iterative-alpha PCE heuristic.
At every round, runs pce_cls to convergence with the current alpha, then rescales alpha to push the least-binarized correlator just past threshold, warm-starting the next round from the converged ansatz parameters. Stops once every correlator is binarized or max_outer_iterations is reached.
- Returns:
The final energy, final parameters and solution, as returned by the last round’s pce_cls.run().