Usar un ansatz similar a UCC con un VQE#

Cuando se utiliza un ansatz de estilo UCC con un VQE, se debe prestar especial atención al atributo initial_point que indica a partir de qué conjunto de parámetros iniciales debe comenzar la rutina de optimización. Por defecto, VQE comenzará desde un punto inicial aleatorio. En este tutorial, mostramos cómo se puede establecer un punto inicial personalizado (por ejemplo, para garantizar que uno comience desde el estado Hartree-Fock).

  1. Obtenemos un ElectronicStructureProblem que queremos resolver:

from qiskit_nature.second_q.drivers import PySCFDriver
driver = PySCFDriver(atom="H 0 0 0; H 0 0 0.735", basis="sto-3g")
problem = driver.run()
  1. Configuramos nuestro QubitMapper:

from qiskit_nature.second_q.mappers import JordanWignerMapper
mapper = JordanWignerMapper()
  1. Configuramos nuestro ansatz:

from qiskit_nature.second_q.circuit.library import UCCSD, HartreeFock
ansatz = UCCSD(
    problem.num_spatial_orbitals,
    problem.num_particles,
    mapper,
    initial_state=HartreeFock(
        problem.num_spatial_orbitals,
        problem.num_particles,
        mapper,
    ),
)
  1. Configuramos un VQE:

import numpy as np
from qiskit_algorithms import VQE
from qiskit_algorithms.optimizers import SLSQP
from qiskit.primitives import Estimator
vqe = VQE(Estimator(), ansatz, SLSQP())
  1. Ahora viene el paso clave: elegir el punto inicial. Ya que elegimos el estado inicial de HartreeFock antes, para asegurarnos de que comenzamos desde eso, necesitamos inicializar nuestro initial_point con todos los parámetros todo en cero. Una forma de hacerlo es así:

vqe.initial_point = np.zeros(ansatz.num_parameters)

Alternativamente, también se puede usar HFInitialPoint así:

from qiskit_nature.second_q.algorithms.initial_points import HFInitialPoint
initial_point = HFInitialPoint()
initial_point.ansatz = ansatz
initial_point.problem = problem
vqe.initial_point = initial_point.to_numpy_array()

Puede parecer que esto no agrega muchos beneficios, pero el aspecto clave aquí es que puedes construir tu código sobre la interfaz InitialPoint en la que también tengamos el MP2InitialPoint que te permite comenzar desde un punto de inicio de MP2 así:

from qiskit_nature.second_q.algorithms.initial_points import MP2InitialPoint
initial_point = MP2InitialPoint()
initial_point.ansatz = ansatz
initial_point.problem = problem
vqe.initial_point = initial_point.to_numpy_array()
  1. Finalmente, ahora podemos resolver nuestro problema:

from qiskit_nature.second_q.algorithms import GroundStateEigensolver
solver = GroundStateEigensolver(mapper, vqe)
result = solver.solve(problem)

print(f"Total ground state energy = {result.total_energies[0]:.4f}")
Total ground state energy = -1.1373