Три упражнения о вариационном решателе
VQE — вариационный квантовый решатель собственных значений: схема с параметрами готовит пробное состояние, измеряется средняя энергия, классический оптимизатор меняет параметры. В разделе автора обсуждаются Ry/RyRz со слоями вращений и CNOT (линейные связи соседей или полный набор пар), а также UCCSD, сохраняющая число частиц и использующая приближение Хартри–Фока. В авторском подсчёте COBYLA делает одно вычисление целевой функции на итерацию.
1. Дан гамильтониан H с обещанием, что его основное состояние близко к максимально запутанному состоянию n кубитов. Объясните, какая вариационная форма или формы, вероятно, смогут эффективно и точно найти энергию основного состояния H. Можно создать собственную форму и объяснить, почему она подходит.
2. Вычислите число выполнений схем за итерацию оптимизации при COBYLA, qasm_simulator с 1000 запусков и гамильтониане из 60 строк Паули.
3. Используйте VQE для оценки энергии основного состояния BeH₂ при межатомном расстоянии 1.3 Å. Автор предлагает повторно использовать get_qubit_op(dist), заменив
atom="Li .0 .0 .0; H .0 .0 " + str(dist)на
atom="Be .0 .0 .0; H .0 .0 -" + str(dist) + "; H .0 .0 " + str(dist)и вызвав get_qubit_op(1.3). Удаление незанятых орбиталей для этой молекулы не сохраняет химической точности, но позволяет уменьшить число кубитов до 6 для эффективного моделирования на большинстве ноутбуков; автор принимает эту потерю точности. За рамками упражнения заинтересованный читатель может уменьшить число кубитов до 7 без потери точности, используя симметрии.
Сохранённая ниже программа уже использует MoleculeInfo, а не строковый аргумент atom. Исходное указание о геометрии однозначно задаёт символы Be,H,H и координаты (0,0,0), (0,0,−dist), (0,0,dist); это та же геометрия, записанная полями используемого в программе объекта. Исходная строка условия сохранена без замены. Единица координат — ангстрем, $1\,\text{Å}=10^{-10}$ м. Исходная программа:
# pylint: disable=missing-function-docstring
import numpy as np
np.random.seed(999999)
p0 = np.random.random()
target_distr = {0: p0, 1: 1 - p0}
from qiskit import QuantumCircuit, ClassicalRegister, QuantumRegister
from qiskit.circuit import Parameter
params = [Parameter("theta"), Parameter("phi"), Parameter("lam")]
def get_var_form(params):
qr = QuantumRegister(1, name="q")
cr = ClassicalRegister(1, name="c")
qc = QuantumCircuit(qr, cr)
qc.u(params[0], params[1], params[2], qr[0])
qc.measure(qr, cr[0])
return qc
qc = get_var_form(params)
from qiskit_aer.primitives import Sampler, Estimator
sampler = Sampler()
def objective_function(params):
"""Compares the output distribution of our circuit with
parameters `params` to the target distribution."""
# Simulate the circuit instance with paramters
result = sampler.run(circuits=qc, parameter_values=params).result()
# Get the quasi distribution for each measured state
output_distr = result.quasi_dists[0]
# Calculate the cost as the distance between the output
# distribution and the target distribution
cost = sum(
abs(target_distr.get(i, 0) - output_distr.get(i, 0))
for i in range(2**qc.num_qubits)
)
return cost
from qiskit.algorithms.optimizers import SPSA, SLSQP, COBYLA
optimizer = COBYLA(maxiter=500, tol=0.0001)
# Create the initial parameters (noting that our
# single qubit variational form has 3 parameters)
initial_point = np.random.rand(3)
result = optimizer.minimize(fun=objective_function, x0=initial_point)
# Obtain the output distribution using the final parameters
output_distr = (
sampler.run(circuits=qc, parameter_values=result.x)
.result()
.quasi_dists[0]
)
print("Parameters Found:", result.x)
print("Target Distribution:", target_distr)
print("Obtained Distribution:", output_distr)
print("Cost:", objective_function(result.x))
from qiskit.circuit.library import EfficientSU2
entanglements = ["linear", "full"]
for entanglement in entanglements:
form = EfficientSU2(num_qubits=4, entanglement=entanglement)
print(f"{entanglement} entanglement:")
# We initialize all parameters to 0 for this demonstration
display(form.decompose().draw("mpl", fold=-1))
# pylint: disable=line-too-long
import qiskit_nature
from qiskit.algorithms.minimum_eigensolvers import NumPyMinimumEigensolver, VQE
from qiskit_nature.second_q.transformers import FreezeCoreTransformer
from qiskit_nature.second_q.formats.molecule_info import MoleculeInfo
from qiskit_nature.second_q.mappers import ParityMapper
from qiskit_nature.second_q.circuit.library import UCCSD, HartreeFock
qiskit_nature.settings.use_pauli_sum_op = False # pylint: disable=undefined-variable
# pylint: enable=line-too-long
from qiskit_nature.second_q.drivers import PySCFDriver
import matplotlib.pyplot as plt
from qiskit.circuit.library import EfficientSU2
def get_qubit_op(dist):
# Define Molecule
molecule = MoleculeInfo(
# Coordinates in Angstrom
symbols=["Li", "H"],
coords=([0.0, 0.0, 0.0], [dist, 0.0, 0.0]),
multiplicity=1, # = 2*spin + 1
charge=0,
)
driver = PySCFDriver.from_molecule(molecule)
# Get properties
properties = driver.run()
# Now you can get the reduced electronic structure problem
problem = FreezeCoreTransformer(
freeze_core=True, remove_orbitals=[-3, -2]
).transform(properties)
num_particles = problem.num_particles
num_spatial_orbitals = problem.num_spatial_orbitals
mapper = ParityMapper(num_particles=num_particles)
qubit_op = mapper.map(problem.second_q_ops()[0])
return qubit_op, num_particles, num_spatial_orbitals, problem, mapper
from qiskit_aer.primitives import Estimator
def exact_solver(qubit_op, problem):
sol = NumPyMinimumEigensolver().compute_minimum_eigenvalue(qubit_op)
result = problem.interpret(sol)
return result
distances = np.arange(0.5, 4.0, 0.2)
exact_energies = []
vqe_energies = []
optimizer = SLSQP(maxiter=10)
noiseless_estimator = Estimator(approximation=True)
# pylint: disable=undefined-loop-variable,line-too-long
for dist in distances:
(qubit_op, num_particles, num_spatial_orbitals, problem, mapper) = get_qubit_op(
dist
)
result = exact_solver(qubit_op, problem)
exact_energies.append(result.total_energies[0].real)
init_state = HartreeFock(num_spatial_orbitals, num_particles, mapper)
var_form = UCCSD(
num_spatial_orbitals, num_particles, mapper, initial_state=init_state
)
vqe = VQE(
noiseless_estimator,
var_form,
optimizer,
initial_point=[0] * var_form.num_parameters,
)
vqe_calc = vqe.compute_minimum_eigenvalue(qubit_op)
vqe_result = problem.interpret(vqe_calc).total_energies[0].real
vqe_energies.append(vqe_result)
print(
f"Interatomic Distance: {np.round(dist, 2)}",
f"VQE Result: {vqe_result:.5f}",
f"Exact Energy: {exact_energies[-1]:.5f}",
)
print("All energies have been calculated")Решения пока нет.
Предложить решение
Войти, чтобы отправить материал.