Skip to content

VQE

from cascaqit import VQE

VQE

VQE(
    operator: VQEInput,
    layers: int = 1,
    ansatz: HardwareEfficientAnsatz
    | CardinalityPreservingAnsatz
    | Circuit
    | None = None,
    algorithm_id: str | None = None,
)

Construct a variational eigensolver from a PauliHamiltonian, QUBOProblemIR or IsingModelIR. QUBO and Ising inputs are converted to a Pauli Hamiltonian. layers must be a positive integer. With ansatz=None, each layer applies RY then RZ rotations followed by linear CX entanglement in logical-qubit order. Import HardwareEfficientAnsatz or CardinalityPreservingAnsatz from cascaqit.algorithms to change the structure.

An explicit Circuit must match the Hamiltonian’s qubits and order, contain no terminal measurement, and have unbound parameters that are all referenced. Construction snapshots the circuit. layers does not repeat a custom circuit, and automatic layer-growth experiments do not accept one. The default algorithm_id derives from the Hamiltonian identifier.

Evaluation accepts a mapping with exactly the declared parameter names or a numeric sequence in parameter_names order. Values must be finite real numbers, excluding booleans. backend=None uses the local backend; these methods perform local CPU simulation. Noisy exact objectives require density-matrix execution. Sampled objectives allow supported density-matrix or trajectory execution, subject to preflight validation.

This one-qubit example checks energy and gradient against cos(theta) and its analytic derivative:

from math import cos, sin, isclose
from cascaqit import HamiltonianTerm, PauliHamiltonian, PauliZ, VQE

vqe = VQE(PauliHamiltonian("z", (HamiltonianTerm("z", 1.0, PauliZ("q0")),),
                          logical_order=("q0",)))
point = (0.4, 0.2)
evaluation = vqe.evaluate(point)
assert isclose(evaluation.energy, cos(point[0]), abs_tol=1e-12)
gradient = vqe.gradient(point)
assert isclose(gradient.gradient[vqe.parameter_names[0]], -sin(point[0]), abs_tol=1e-12)
assert abs(gradient.gradient[vqe.parameter_names[1]]) < 1e-12
assert vqe.build_circuit() is not vqe.build_circuit()

For sampled optimization, set objective measurements, candidate confirmation and final sampling separately:

from cascaqit import OptimizerConfig, PauliMeasurementConfig, SampledSelectionConfig

result = vqe.run(
    optimizer=OptimizerConfig(method="SPSA", max_iterations=1, seed=7),
    initial_parameters=point,
    measurement=PauliMeasurementConfig(shots_per_group=32),
    sampled_selection=SampledSelectionConfig(candidate_count=2, repeats_per_candidate=2),
    final_shots=16,
)
assert result.sampled_selection is not None
assert sum(result.final_result.counts.values()) == 16
assert result.optimality_claim == "not_claimed"

See the finite-shot VQE project and VariationalResult.

hamiltonian

hamiltonian: PauliHamiltonian

Return the PauliHamiltonian used for evaluation, including the converted constant and logical-qubit order. Reading it does not run simulation.

parameter_names

parameter_names: tuple[str, ...]

Return parameter names in circuit declaration order. Use this order for positional values, including custom circuits.

build_circuit

build_circuit() -> Circuit

Return an independent parameterized Circuit snapshot. Editing it does not change later builds. This neither binds values nor evaluates an objective.

ansatz_spec

ansatz_spec() -> AnsatzSpecIR

Return AnsatzSpecIR describing structure, layers, logical order, parameters, required gates and provenance. It contains the ansatz declaration, not an optimization result.

parameter_schema

parameter_schema() -> ParameterSchemaIR

Return ParameterSchemaIR retaining parameter order, types, units and bounds for binding and checking results.

evaluate

evaluate(
    parameters: ParameterValues,
    *,
    backend: LocalBackend | None = None,
    evaluation_index: int = 0,
    algorithm_run_id: str | None = None,
    seed: int | None = None,
    noise: NoiseModel | None = None,
    options: SimulationOptions | None = None,
) -> ObjectiveEvaluationIR

Synchronously return ObjectiveEvaluationIR for one exact objective evaluation, including the Hamiltonian constant in energy. Internally this executes one backend Job without estimating energy from finite shots. evaluation_index identifies the record, algorithm_run_id links the experiment, and seed is passed to execution. noise/options select supported noisy execution; its exact objective is a density-matrix expectation.

evaluate_sampled

evaluate_sampled(
    parameters: ParameterValues,
    *,
    measurement: PauliMeasurementConfig | None = None,
    backend: LocalBackend | None = None,
    evaluation_index: int = 0,
    algorithm_run_id: str | None = None,
    seed: int | None = None,
    noise: NoiseModel | None = None,
    options: SimulationOptions | None = None,
) -> SampledObjectiveEvaluationIR

Execute finite-shot Pauli measurement groups and return SampledObjectiveEvaluationIR with energy estimate, standard error, group counts and costs. measurement=None uses PauliMeasurementConfig(). One call can execute multiple backend Jobs; read recorded costs instead of inferring shots from method-call count.

gradient

gradient(
    parameters: ParameterValues,
    *,
    backend: LocalBackend | None = None,
    gradient_index: int = 0,
    objective_evaluation_offset: int = 0,
    max_backend_executions: int | None = None,
    algorithm_run_id: str | None = None,
    seed: int | None = None,
    config: GradientConfig | None = None,
    measurement: PauliMeasurementConfig | None = None,
    noise: NoiseModel | None = None,
    options: SimulationOptions | None = None,
) -> ObjectiveGradientIR

Return ObjectiveGradientIR using parameter shifts. config=None uses default GradientConfig; measurement selects exact or sampled gradients. Shared parameters can occur in multiple gates, so costs follow the shift plan rather than always being two evaluations per parameter. gradient_index and objective_evaluation_offset number records; max_backend_executions caps this call’s budget. Unsupported gates or parameter expressions are rejected during plan validation.

run

run(
    *,
    backend: LocalBackend | None = None,
    optimizer: OptimizerConfig | None = None,
    initial_parameters: ParameterValues | None = None,
    algorithm_run_id: str | None = None,
    final_shots: int = 2048,
    noise: NoiseModel | None = None,
    options: SimulationOptions | None = None,
    measurement: None = None,
    sampled_selection: None = None,
) -> VariationalResult[ObjectiveEvaluationIR]
run(
    *,
    backend: LocalBackend | None = None,
    optimizer: OptimizerConfig | None = None,
    initial_parameters: ParameterValues | None = None,
    algorithm_run_id: str | None = None,
    final_shots: int = 2048,
    noise: NoiseModel | None = None,
    options: SimulationOptions | None = None,
    measurement: PauliMeasurementConfig,
    sampled_selection: SampledSelectionConfig | None = None,
) -> VariationalResult[SampledObjectiveEvaluationIR]
run(
    *,
    backend: LocalBackend | None = None,
    optimizer: OptimizerConfig | None = None,
    initial_parameters: ParameterValues | None = None,
    algorithm_run_id: str | None = None,
    final_shots: int = 2048,
    noise: NoiseModel | None = None,
    options: SimulationOptions | None = None,
    measurement: PauliMeasurementConfig | None = None,
    sampled_selection: SampledSelectionConfig | None = None,
) -> VariationalResult[
    Union[
        ObjectiveEvaluationIR, SampledObjectiveEvaluationIR
    ]
]

Synchronously optimize and sample the final computational-basis distribution, returning VariationalResult. optimizer=None uses OptimizerConfig(); initial_parameters supplies an explicit start, otherwise initialization follows the optimizer configuration. measurement=None uses exact objectives; sampled optimization supports only SPSA or ADAM. Optional sampled_selection independently confirms candidates and requires measurement. final_shots controls only final computational-basis sampling. Read selected_evaluation for the final point and inspect termination and costs separately; success does not establish convergence or global optimality.

benchmark_sampling

benchmark_sampling(
    config: VQESamplingBenchmarkConfig,
    *,
    backend: LocalBackend | None = None,
) -> VQESamplingBenchmarkResult

Compare exact, sampled_single, sampled_fixed and sampled_adaptive using VQESamplingBenchmarkConfig, returning VQESamplingBenchmarkResult. Strategies within each repeat share initialization and seed. The budget bounds objective evaluations; confirmation and final sampling cost extra. The reference is the same-repeat exact strategy’s selected point, not the true ground state. See the configuration page for restrictions. This method has no noise/options arguments.

optimize_layers_repeated

optimize_layers_repeated(
    *,
    max_layers: int,
    repeats: int,
    optimizer: OptimizerConfig | None = None,
    confidence_level: float = 0.95,
    min_improvement: float = 0.0,
    patience: int = 1,
    final_shots: int = 2048,
    seed: int = 0,
    backend: LocalBackend | None = None,
    noise: NoiseModel | None = None,
    options: SimulationOptions | None = None,
    measurement: PauliMeasurementConfig | None = None,
    sampled_selection: SampledSelectionConfig | None = None,
) -> VQERepeatedLayerExperimentResult

Return VQERepeatedLayerExperimentResult. Experiments start at one layer and continue up to max_layers regardless of this object’s layers. Each depth has repeats runs, with repeats at least two. Only built-in ansatz definitions are supported. The optimizer must use random initialization, seed=None and no bounds. Each deeper run inherits selected_evaluation parameters from the preceding depth with the same repeat index. A one-sided Student-t lower bound compares paired energy improvement against the currently selected depth. Selection changes only when this bound exceeds 1e-12 and meets min_improvement. Otherwise the no-improvement count increases, stopping at patience. confidence_level lies in (0.5,1), min_improvement is nonnegative, and patience is a positive integer. Sampled mode requires both measurement and sampled_selection with SPSA/ADAM. The separate seed derives run seeds. Depth selection does not prove global optimality.