qml.AdaptiveOptimizer¶
-
class
AdaptiveOptimizer
(param_steps=10, stepsize=0.5)[source]¶ Bases:
object
Optimizer for building fully trained quantum circuits by adding gates adaptively.
Quantum circuits can be built by adding gates adaptively. The adaptive optimizer implements an algorithm that grows and optimizes an input quantum circuit by selecting and adding gates from a user-defined collection of operators. The algorithm starts by adding all the gates to the circuit and computing the circuit gradients with respect to the gate parameters. The algorithm then retains the gate which has the largest gradient and optimizes its parameter. The process of growing the circuit can be repeated until the computed gradients converge to zero within a given threshold. The optimizer returns the fully trained and adaptively-built circuit. The adaptive optimizer can be used to implement algorithms such as ADAPT-VQE.
- Parameters
param_steps (int) – number of steps for optimizing the parameter of a selected gate
stepsize (float) – step size for optimizing the parameter of a selected gate
Example
This examples shows an implementation of the ADAPT-VQE algorithm for building an adaptive circuit for the \(\text{H}_3^+\) cation.
>>> import pennylane as qml >>> from pennylane import numpy as pnp
The molecule is defined and the Hamiltonian is computed with:
>>> symbols = ["H", "H", "H"] >>> geometry = pnp.array([[0.01076341, 0.04449877, 0.0], ... [0.98729513, 1.63059094, 0.0], ... [1.87262415, -0.00815842, 0.0]], requires_grad=False) >>> H, qubits = qml.qchem.molecular_hamiltonian(symbols, geometry, charge = 1)
The collection of gates to grow the circuit adaptively contains all single and double excitations:
>>> n_electrons = 2 >>> singles, doubles = qml.qchem.excitations(n_electrons, qubits) >>> singles_excitations = [qml.SingleExcitation(0.0, x) for x in singles] >>> doubles_excitations = [qml.DoubleExcitation(0.0, x) for x in doubles] >>> operator_pool = doubles_excitations + singles_excitations
An initial circuit preparing the Hartree-Fock state and returning the expectation value of the Hamiltonian is defined:
>>> hf_state = qml.qchem.hf_state(n_electrons, qubits) >>> dev = qml.device("default.qubit", wires=qubits) >>> @qml.qnode(dev) ... def circuit(): ... qml.BasisState(hf_state, wires=range(qubits)) ... return qml.expval(H)
The optimizer is instantiated and then the circuit is created and optimized adaptively:
>>> opt = AdaptiveOptimizer() >>> for i in range(len(operator_pool)): ... circuit, energy, gradient = opt.step_and_cost(circuit, operator_pool, drain_pool=True) ... print('Energy:', energy) ... print(qml.draw(circuit, show_matrices=False)()) ... print('Largest Gradient:', gradient) ... print() ... if gradient < 1e-3: ... break
Energy: -1.2465499384199699 0: ─╭|Ψ⟩─╭G²(0.20)─┤ ╭<𝓗> 1: ─├|Ψ⟩─├G²(0.20)─┤ ├<𝓗> 2: ─├|Ψ⟩─│─────────┤ ├<𝓗> 3: ─├|Ψ⟩─│─────────┤ ├<𝓗> 4: ─├|Ψ⟩─├G²(0.20)─┤ ├<𝓗> 5: ─╰|Ψ⟩─╰G²(0.20)─┤ ╰<𝓗> Largest Gradient: 0.1439987277673651 Energy: -1.2613740231522532 0: ─╭|Ψ⟩─╭G²(0.20)─╭G²(0.19)─┤ ╭<𝓗> 1: ─├|Ψ⟩─├G²(0.20)─├G²(0.19)─┤ ├<𝓗> 2: ─├|Ψ⟩─│─────────├G²(0.19)─┤ ├<𝓗> 3: ─├|Ψ⟩─│─────────╰G²(0.19)─┤ ├<𝓗> 4: ─├|Ψ⟩─├G²(0.20)───────────┤ ├<𝓗> 5: ─╰|Ψ⟩─╰G²(0.20)───────────┤ ╰<𝓗> Largest Gradient: 0.13493495624211427 Energy: -1.2743971719772815 0: ─╭|Ψ⟩─╭G²(0.20)─╭G²(0.19)──────────┤ ╭<𝓗> 1: ─├|Ψ⟩─├G²(0.20)─├G²(0.19)─╭G(0.00)─┤ ├<𝓗> 2: ─├|Ψ⟩─│─────────├G²(0.19)─│────────┤ ├<𝓗> 3: ─├|Ψ⟩─│─────────╰G²(0.19)─╰G(0.00)─┤ ├<𝓗> 4: ─├|Ψ⟩─├G²(0.20)────────────────────┤ ├<𝓗> 5: ─╰|Ψ⟩─╰G²(0.20)────────────────────┤ ╰<𝓗> Largest Gradient: 0.0004084175253678331
Methods
step
(circuit, operator_pool[, params_zero])Update the circuit with one step of the optimizer.
step_and_cost
(circuit, operator_pool[, …])Update the circuit with one step of the optimizer, return the corresponding objective function value prior to the step, and return the maximum gradient
-
step
(circuit, operator_pool, params_zero=True)[source]¶ Update the circuit with one step of the optimizer.
-
step_and_cost
(circuit, operator_pool, drain_pool=False, params_zero=True)[source]¶ Update the circuit with one step of the optimizer, return the corresponding objective function value prior to the step, and return the maximum gradient
- Parameters
- Returns
the optimized circuit, the objective function output prior to the step, and the largest gradient
- Return type
tuple[QNode, float, float]