Create an Estimator
Goal
Construct an estimator for use in Adaptive/Iterative VQE (e.g., FAST-VQE), choosing between a high-performance excitation-gate estimator or a backend-powered estimator, and optionally enabling estimator-level error mitigation.
Quick Start (default estimator)
For a simple working estimator, stick with the defaults:
import qrunch as qc
estimator = (
qc.estimator_creator()
.create()
)
The estimator builder follows the pattern explained in Understanding and Using Kvantify Qrunch’s Fluent Builder Pattern. In practice, one usually narrows down to a specific estimator type. The options are:
.backend(): third-party simulators, noisy simulators, and real hardware (see Choose a Backend).excitation_gate(): Kvantify’s proprietary chemistry tailored excitation-gate simulator.memory_restricted(): Kvantify’s proprietary chemistry tailored memory-restricted simulator.tensor_network(): tensor network based simulator (NumPy or GPU-accelerated cuTensorNet).qiskit_statevector(): Qiskit state-vector simulator.cuquantum_statevector(): NVIDIA CuQuantum GPU-accelerated state-vector simulator
Excitation Gate Estimator
The excitation gate estimator is a fast, chemistry-tailored simulator and a great default for running VQEs for molecular systems.
import qrunch as qc
estimator = (
qc.estimator_creator()
.excitation_gate()
.create()
)
The excitation gate estimator can be configured with the following options:
import qrunch as qc
estimator = (
qc.estimator_creator()
.excitation_gate()
.with_float_type("f64") # Precision of internal floats: "f64" (default) or "f32"
.with_parallel_setting("parallel") # Parallelization behavior: "serial" or "parallel"
.with_spin_particle_conservation() # Use spin particle conservation policy (see note below):
.with_seed(1234) # Reproducibility: set a seed (or None to disable)
.with_eps(1e-12) # Sampling epsilon lower bound (absolute amplitude threshold), or None
.create()
)
Note that the excitation gate estimator is a state vector simulator and while it currently does support shot-based sampling, we are deprecating this functionality. At the current time, you can still use the excitation gate estimator together with the with_estimator_shots() option, but we recommend using the memory restricted estimator, which is both quicker, scales to larger calculations, and supports advanced groupers and shot distributors.
Note on particle conservation policies
with_spin_particle_conservation()specifies that the number of spin up and spin down particles are conserved separately (fermionic encoding). Excitation gates are expected to conserve the number of particles in the two parts of the circuits corresponding to the spin up and spin down orbitals. This is the situation with the fermionic encoding in FAST-VQE.with_total_particle_conservation()Specify that the total number of particles are conserved (bosonic encoding). Excitation gates are expected to conserve the total number of particles. This is the case of the hard-core bosonic encoding (BEAST-VQE) where the qubits represent spatial orbitals occupied by electron pairs. Thus, the total number of (electron-pair) particles is conserved.
Note that the particle conservation policy is only relevant when using the excitation gate simulator and the reason for this is related to memory usage.
Memory Restricted Estimator
The memory restricted estimator is the recommended simulator for large scale calculations. It is designed to handle large Hilbert spaces by capping memory usage. Thus it is not an exact simulator, but rather a high-performance approximate simulator.
import qrunch as qc
estimator = (
qc.estimator_creator()
.memory_restricted()
.create()
)
Note that the memory restricted estimator only resorts to approximating the state when certain criteria are met, when enough gates have been added to the circuit. A warning will be issued when the simulator starts truncating the number of amplitudes of the state vector.
It has an easy way to define precise (but still approximate) defaults:
import qrunch as qc
estimator_precise = (
qc.estimator_creator()
.memory_restricted()
.with_precise_defaults()
.create()
)
Or fast (and less precise) defaults:
import qrunch as qc
estimator_fast = (
qc.estimator_creator()
.memory_restricted()
.with_quick_defaults()
.create()
)
The memory restricted estimator can also be manually configured with the options shown in the following example:
import qrunch as qc
options = qc.options.MemoryRestrictedSimulatorOptions(
suppress_warnings=False,
max_number_of_amplitudes=1_000_000,
max_memory_usage_in_kb=None,
)
estimator_custom = (
qc.estimator_creator()
.memory_restricted()
.with_options(options)
.create()
)
Alternatively, one can set the maximum memory usage instead of the maximum number of amplitudes:
import qrunch as qc
estimator_custom = (
qc.estimator_creator()
.memory_restricted()
.with_max_memory(max_memory_usage_in_kb=512_000)
.create()
)
In this example, the estimator will use at most 512 MB of RAM (512.000 kilobytes). See section on Backend Estimator for information in groupers and shots distributors, which are also available for the excitation gate estimator.
Backend Estimator
This estimator is designed for use with third-party simulators, noisy simulators, or real quantum computers.
import qrunch as qc
estimator = (
qc.estimator_creator()
.backend()
.create()
)
See Choose a Backend for how to choose and configure a non-default backend.
Choose Grouper
It is possible to choose different groupers for grouping Pauli strings.
import qrunch as qc
estimator = (
qc.estimator_creator()
.excitation_gate()
.choose_grouper()
# .<pick-one-grouper>(...)
.create()
)
The options are:
identity()creates an identity (trivial) measurement grouper.qubit_wise()creates a qubit-wise commuting measurement grouper.shadow()creates a shadow measurement grouper.beast()creates a BEAST measurement grouper (default).
Choose Shot Distributor
It is possible to choose different shot distributors for distributing shots across measurement groups.
import qrunch as qc
estimator = (
qc.estimator_creator()
.excitation_gate()
.choose_shot_distributor()
# .<pick-one-distributor>(...)
.create()
)
The options are:
homogeneous()distributes shots evenly across groups.group_size()distributes shots proportionally to number of pauli strings in each group.l2_norm()distributes shots proportionally to the L2 norm of the coefficients of the Pauli strings in each group.minimal_posterior_variance()distributes shots to minimize the expected error of the expectation value (default).
Qiskit State Vector
The Qiskit State Vector estimator.
import qrunch as qc
estimator = (
qc.estimator_creator()
.qiskit_statevector()
.create()
)
CuQuantum State Vector Estimator
The CuQuantum state vector estimator is a GPU-accelerated exact simulator powered by NVIDIA cuQuantum’s cuStateVec library.
Prerequisites
This estimator requires an NVIDIA GPU with CUDA support. If CUDA is not available on your
system, attempting to create the estimator will raise a RuntimeError.
Basic Usage
import qrunch as qc
estimator = (
qc.estimator_creator()
.cuquantum_statevector()
.create()
)
Shots
Like all state vector estimators, this estimator computes exact expectation values and
does not support shot-based sampling. The shots argument must always be None; any
other value will raise an EstimatorError.
Cleanup
The estimator holds a cuStateVec library handle and associated GPU memory. Once you are
done with it, call cleanup() to release GPU resources explicitly:
estimator = (
qc.estimator_creator()
.cuquantum_statevector()
.create()
)
# ... use the estimator ...
estimator.cleanup()
Failing to call cleanup() after use may result in GPU memory not being freed until
the Python process exits.
Tensor Network Estimator
The tensor network estimator simulates quantum circuits by representing them as tensor
networks and contracting them to compute expectation values. It is configured through
.tensor_network(), which selects an estimator algorithm and an optional
contraction path finder.
It supports the following estimator algorithms:
CPU (default): exact contraction powered by
opt_einsum.GPU: exact contraction powered by NVIDIA cuTensorNet (requires CUDA).
Here the “exact” indicates that the estimator computes exact expectation values, as opposed to approximate methods that may be used in other estimators (e.g., memory restricted estimator).
Only recommended for BEAST or Paired Electron Approximation Circuits
For BEAST circuits (iterative VQE calculator with beast or paired_electron_approximation)
It is possible to scale the tensor network estimator to larger circuits than the ExcitationGateEstimator, without sacrificing accuracy.
However, it is not recommended for FAST circuits (iterative VQE calculator with standard).
Basic Usage
import qrunch as qc
estimator = (
qc.estimator_creator()
.tensor_network()
.create()
)
This uses the default CPU estimator algorithm with precision="float64".
Choosing the Estimator Algorithm
Use choose_estimator_algorithm() to override the default configuration:
.exact_cpu(): CPU-based exact algorithm, powered byopt_einsum(default)..exact_gpu(): GPU-accelerated exact algorithm, powered by NVIDIA cuTensorNet (requires CUDA).
import qrunch as qc
# CPU opt_einsum algorithm (default)
estimator_default = (
qc.estimator_creator()
.tensor_network()
.create()
)
# CPU opt_einsum algorithm with custom precision
estimator_cpu = (
qc.estimator_creator()
.tensor_network()
.choose_estimator_algorithm()
.exact_cpu(precision="float32")
.create()
)
# cuTensorNet GPU algorithm (requires CUDA)
estimator_gpu = (
qc.estimator_creator()
.tensor_network()
.choose_estimator_algorithm()
.exact_gpu(precision="float32")
.create()
)
Choosing Precision
Both algorithms accept a precision argument controlling the numeric precision of the
internal tensors. The allowed values and defaults differ between CPU and GPU:
Algorithm method |
Allowed |
Default |
|---|---|---|
|
|
|
|
|
|
Real precisions ("float64", "float32", "float16") use an optimized internal
path; complex precisions ("complex128", "complex64") keep explicit complex
tensors. When a real precision is selected, the circuit gate tensors must be entirely
real-valued; use a complex precision for circuits containing gates with imaginary
components.
The special value "mixed" selects the MixedPrecisionEstimatorAlgorithm, which
combines several precision tiers to balance accuracy and performance. On GPU, the mixed
tiers use bfloat16 / tfloat32 / float32 compute paths.
The CPU algorithm defaults to "float64" for high accuracy, while the GPU algorithm
defaults to "float32" since FP32 is typically the sweet spot for GPU throughput.
Choosing the Contraction Path Finder
See Choose a Contraction Path Finder for a detailed description of all available contraction path finders and their options.
Shots
The tensor network estimator computes exact expectation values and does not support
shot-based estimation. The shots argument must always be None.
Verify the Result
You now have a configured
estimatorinstance ready to be plugged into a VQE
Next Step
You can use the estimator in a FAST gate selector: Create a FAST Gate Selector
You can use the estimator to build a VQE calculator: Build a VQE Calculator
If targeting third-party simulators or hardware, continue here: Choose a Backend