VarQRTE¶
Variational Quantum Real-Time Evolution¶
Variational Quantum Real-Time Evolution, or VarQRTE, approximates real-time
Schrodinger evolution inside a parameterized quantum circuit. In this package
it is exposed through qite.run_qrte(...) and the qite run-qrte command.
Use VarQRTE when you already have a relevant initial state and want projected real-time dynamics without leaving the variational ansatz manifold. It is a dynamics workflow, not a ground-state optimizer. For relaxation toward a low-energy state, use VarQITE or VQE first.
Quickstart¶
Python:
from qite import run_qrte
result = run_qrte(
molecule="H2",
ansatz_name="UCCSD",
steps=50,
dt=0.05,
plot=False,
)
print(result["energy"])
print(result["times"][-5:])
CLI:
python -m qite run-qrte --molecule H2 --ansatz UCCSD --steps 50 --dt 0.05 --no-show
What The Solver Does¶
Real-time evolution applies:
VarQRTE approximates that trajectory with an ansatz state |psi(theta)>.
Instead of exactly applying the full unitary evolution, the solver projects the
real-time derivative into the tangent space of the ansatz at each step.
The implementation uses a McLachlan projected update for real time. At each
iteration it builds a tangent-space linear system, solves for dot(theta), and
advances the parameters by a time step dt.
Inputs¶
run_qrte(...) uses the same shared problem-resolution layer as VQE, QPE, and
VarQITE. It supports built-in molecules, explicit geometries, active-space
chemistry runs, and expert-mode qubit Hamiltonians.
Registry Molecule¶
from qite import run_qrte
result = run_qrte(molecule="H2", steps=50, dt=0.05, plot=False)
Explicit Geometry¶
from qite import run_qrte
result = run_qrte(
symbols=["H", "H"],
coordinates=[[0.0, 0.0, 0.0], [0.0, 0.0, 0.7414]],
basis="sto-3g",
charge=0,
unit="angstrom",
steps=50,
dt=0.05,
plot=False,
)
CLI equivalent:
python -m qite run-qrte \
--symbols H,H \
--coordinates "0,0,0; 0,0,0.7414" \
--basis sto-3g \
--steps 50 \
--dt 0.05
Active Space¶
from qite import run_qrte
result = run_qrte(
molecule="LiH",
active_electrons=2,
active_orbitals=2,
steps=50,
dt=0.025,
plot=False,
)
Expert-Mode Hamiltonian¶
import pennylane as qml
from qite import run_qrte
hamiltonian = qml.Hamiltonian(
[1.0, -0.5, 0.25],
[qml.PauliZ(0), qml.PauliX(0), qml.PauliZ(0) @ qml.PauliZ(1)],
)
result = run_qrte(
hamiltonian=hamiltonian,
num_qubits=2,
reference_state=[1, 0],
ansatz_name="auto",
steps=40,
dt=0.05,
plot=False,
)
Expert-mode runs are cacheable. The cache key includes a canonical Hamiltonian fingerprint, the qubit count, the reference state, the time step, and the numerical controls.
Initial State And Prepared Parameters¶
By default, VarQRTE initializes the selected ansatz from the same seeded parameter initialization used by the QITE ansatz builder. For dynamics studies, you often want to start from a prepared state instead.
The Python API accepts initial_params:
import numpy as np
from qite import run_qite, run_qrte
prepared = run_qite(molecule="H2", steps=75, dtau=0.2, plot=False)
initial_params = np.array(prepared["final_params"]).reshape(
prepared["final_params_shape"]
)
trajectory = run_qrte(
molecule="H2",
initial_params=initial_params,
steps=50,
dt=0.05,
plot=False,
)
When initial_params is provided, its flattened size must match the parameter
count for the selected ansatz. The returned result records
"initialization": "provided".
Ansatz Selection¶
VarQRTE delegates ansatz construction to the same shared QITE/VQE ansatz
plumbing used by VarQITE. The default is UCCSD for small chemistry examples.
Common choices:
Ansatz |
Use when |
|---|---|
|
Small chemistry problems with a chemistry reference state |
|
Lightweight smoke tests and compact demos |
|
Generic variational baselines |
|
Expert-mode qubit Hamiltonians where the package should choose a conservative ansatz |
Additional ansatz options can be passed through ansatz_kwargs from Python:
result = run_qrte(
molecule="H2",
ansatz_name="StronglyEntanglingLayers",
ansatz_kwargs={"layers": 2},
steps=40,
dt=0.025,
plot=False,
)
Numerical Controls¶
The main VarQRTE controls are:
Parameter |
Default |
Meaning |
|---|---|---|
|
|
Number of real-time updates |
|
|
Real-time step size |
|
|
Central finite-difference step for tangent vectors |
|
|
Diagonal regularization added to the tangent-space matrix |
|
|
Linear-system backend: |
|
|
Cutoff used by the pseudoinverse solver |
Use smaller dt values when the trajectory is unstable or the energy drifts
more than expected for the chosen ansatz. Increase reg or use
solver="pinv" when the tangent-space solve is ill-conditioned.
CLI example:
python -m qite run-qrte \
--molecule H2 \
--steps 100 \
--dt 0.025 \
--solver pinv \
--reg 1e-5 \
--pinv-rcond 1e-9
Outputs¶
run_qrte(...) returns a dictionary with the final energy, time grid, energy
trace, final state, final parameters, parameter history, timing metadata, and
VarQRTE numerical settings.
Important fields:
Field |
Meaning |
|---|---|
|
Final energy in Hartree |
|
Energy after initialization and each real-time step |
|
Time grid matching |
|
Flattened final ansatz parameters |
|
Shape needed to reconstruct the parameter array |
|
Flattened parameter vector after each recorded time |
|
Final statevector components |
|
|
|
|
|
Time spent computing or original cached compute time |
|
Wall time for this call, including cache lookup |
|
Whether the returned result came from cache |
Reconstructing the final parameters:
import numpy as np
params = np.array(result["final_params"]).reshape(result["final_params_shape"])
Caching¶
VarQRTE stores JSON run records under the package’s standard results/qite/
location. Cache keys include the resolved problem, ansatz, seed, step count,
dt, initialization mode, active-space settings, and numerical controls such
as fd_eps, reg, solver, and pinv_rcond.
Use force=True or --force to ignore an existing cache record:
result = run_qrte(molecule="H2", force=True, plot=False)
python -m qite run-qrte --molecule H2 --force
Noise Policy¶
VarQRTE projected updates require pure statevectors. Noisy or mixed-state
real-time parameter updates are intentionally rejected by run_qrte(...).
For noisy post-evaluation workflows, use VarQITE’s qite eval-noise path for
converged VarQITE circuits. VarQRTE does not currently expose an equivalent
noisy trajectory-evaluation CLI.
Plotting¶
By default, run_qrte(...) plots and saves the energy trace against time step.
In scripts, CI, or docs examples, disable plotting:
result = run_qrte(molecule="H2", plot=False)
For CLI runs, --no-show is useful in headless environments:
python -m qite run-qrte --molecule H2 --no-show
Method Selection¶
Use VarQRTE when:
you want projected real-time dynamics on a prepared variational state
you need a time-resolved comparison against exact evolution on small systems
you want to study how an ansatz represents real-time trajectories
the problem is small enough for statevector derivative calculations
Prefer VarQITE when:
you want imaginary-time relaxation toward a low-energy state
you need converged parameters before dynamics
Prefer VQE when:
the main goal is a stationary ground-state energy
optimizer and ansatz benchmarking is the primary question
Prefer QPE when:
phase, spectral, or eigenvalue-estimation behavior is the target
Troubleshooting¶
Symptom |
Likely cause |
Try |
|---|---|---|
Energy drifts strongly |
|
Lower |
Direct solve fails |
Tangent-space matrix is singular or ill-conditioned |
Use |
Run is slow |
Finite-difference state derivatives scale with parameter count |
Use a smaller ansatz, fewer steps, or a smaller active space |
|
Prepared parameters do not match the selected ansatz |
Use the same ansatz/problem settings as the preparation run |
|
VarQRTE updates are pure-state only |
Run noiseless projected dynamics |
Repeated run returns immediately |
Cache hit |
Use |
Further Reading¶
The implementation details live in:
qite.core.run_qrteqite.engine.qrte_stepqite.engine.make_state_qnodeqite.engine.make_energy_qnode
Related notebooks:
notebooks/getting_started/11_getting_started_qrte_h2.ipynbnotebooks/qite/H2/Real_Time.ipynbnotebooks/benchmarks/qite/H2/Exact_QRTE_Benchmark.ipynb