Variational algorithms
Recently, variational quantum algorithms are actively studied, where optimal values of parameters in parametric quantum circuits are searched. In this section, we see how to construct one of the variational algorithms, variational quantum eigensolver (VQE), using the gradient.
Variational quantum eigensolver (VQE) is a method to optimize an expectation value of an operator (e.g. energy of a molecule) over parametrized quantum states. There are two major components in VQE:
- Ansatz: A parametric quantum circuit which generates the parametrized quantum states subject to optimization
- Optimizer: A method to numerically optimize the expectation value of the operator
Ansatz
In context of VQE, ansatz refers to a parametric quantum circuit used for generating parametrized quantum states for which expectation values of the target operator is evaluated. You can define a (LinearMapped)UnboundParametricQuantumCircuit
on your own, or use a well-known ansatz defined in quri_parts.algo.ansatz
package. In this example we use a hardware-efficient ansatz1:
from quri_parts.algo.ansatz import HardwareEfficient
hw_ansatz = HardwareEfficient(qubit_count=4, reps=3)
In order to evaluate the expectation value, the parametrized quantum state is necessary, which is obtained by applying the ansatz to a specific initial state. Here we use a computational basis state .
from quri_parts.core.state import quantum_state, apply_circuit
cb_state = quantum_state(4, bits=0b0011)
parametric_state = apply_circuit(hw_ansatz, cb_state)
List of available ansatz
Here we list out all the available ansatz provided by quri_parts.algo.ansatz
. There are more chemistry-related ansatz provided in quri_parts.chem.ansatz
and quri_parts.openfermion.ansatz
, which are introduced in the quantum chemistry tutorial.
Optimizer
An optimizer searches optimal parameters that minimize a given cost function. In context of VQE, the cost function is the expectation value of the target operator. Some optimizers use only the cost function itself, while others use gradient of the cost function for efficient optimization. You can use optimizers provided by libraries such as scipy.optimize
, or ones provided in quri_parts.algo.optimizer
package. In this example we use Adam2, which uses the gradient.
from quri_parts.algo.optimizer import Adam
# You can pass optional parameters. See the reference for details
adam_optimizer = Adam()
List of available optimizers
Here, we list out all the optimizers available in QURI Parts.
Running VQE
We first define a target operator, whose expectation value is subject to the optimization:
from quri_parts.core.operator import Operator, pauli_label, PAULI_IDENTITY
# This is Jordan-Wigner transformed Hamiltonian of a hydrogen molecule
hamiltonian = Operator({
PAULI_IDENTITY: 0.03775110394645542,
pauli_label("Z0"): 0.18601648886230593,
pauli_label("Z1"): 0.18601648886230593,
pauli_label("Z2"): -0.2694169314163197,
pauli_label("Z3"): -0.2694169314163197,
pauli_label("Z0 Z1"): 0.172976101307451,
pauli_label("Z0 Z2"): 0.12584136558006326,
pauli_label("Z0 Z3"): 0.16992097848261506,
pauli_label("Z1 Z2"): 0.16992097848261506,
pauli_label("Z1 Z3"): 0.12584136558006326,
pauli_label("Z2 Z3"): 0.17866777775953396,
pauli_label("X0 X1 Y2 Y3"): -0.044079612902551774,
pauli_label("X0 Y1 Y2 X3"): 0.044079612902551774,
pauli_label("Y0 X1 X2 Y3"): 0.044079612902551774,
pauli_label("Y0 Y1 X2 X3"): -0.044079612902551774,
})
Using this operator and the parametric state prepared above, we can define the cost function as a function of the circuit parameters:
from typing import Sequence
from quri_parts.qulacs.estimator import create_qulacs_vector_parametric_estimator
estimator = create_qulacs_vector_parametric_estimator()
def cost_fn(param_values: Sequence[float]) -> float:
estimate = estimator(hamiltonian, parametric_state, param_values)
return estimate.value.real