Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor code for some ansatzes #86

Merged
merged 18 commits into from
Apr 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions doc/source/api-reference/ansatz.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
Ansatz
======

This section covers the API reference for various chemistry ansatzes.
This section covers the API reference for various chemistry circuit ansatzes.

Hardware-efficient
------------------

.. autofunction:: qibochem.ansatz.hardware_efficient.hea
.. autofunction:: qibochem.ansatz.hardware_efficient.he_circuit


Hartree-Fock
Expand Down
3 changes: 1 addition & 2 deletions doc/source/getting-started/quickstart.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ Here is an example of building the UCCD ansatz with the H2 molecule to test your
from qibo.models import VQE

from qibochem.driver.molecule import Molecule
from qibochem.ansatz.hf_reference import hf_circuit
from qibochem.ansatz.ucc import ucc_circuit
from qibochem.ansatz import hf_circuit, ucc_circuit

# Define the H2 molecule and obtain its 1-/2- electron integrals with PySCF
h2 = Molecule([('H', (0.0, 0.0, 0.0)), ('H', (0.0, 0.0, 0.7))])
Expand Down
24 changes: 7 additions & 17 deletions doc/source/tutorials/ansatz.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,12 @@ For the H\ :sub:`2` case discussed in previous sections, a possible hardware eff

.. code-block:: python

from qibo import Circuit
from qibochem.ansatz import he_circuit

from qibochem.ansatz import hardware_efficient

nlayers = 1
nqubits = 4
nfermions = 2
nlayers = 1

circuit = Circuit(4)
hardware_efficient_ansatz = hardware_efficient.hea(nlayers, nqubits)
circuit.add(hardware_efficient_ansatz)
circuit = he_circuit(nqubits, nlayers)
print(circuit.draw())

.. code-block:: output
Expand All @@ -43,11 +38,10 @@ The following example demonstrates how the energy of the H2 molecule is affected
.. code-block:: python

import numpy as np
from qibo import Circuit

from qibochem.driver.molecule import Molecule
from qibochem.driver import Molecule
from qibochem.measurement.expectation import expectation
from qibochem.ansatz import hardware_efficient
from qibochem.ansatz import he_circuit

mol = Molecule([("H", (0.0, 0.0, 0.0)), ("H", (0.0, 0.0, 0.74804))])
mol.run_pyscf()
Expand All @@ -57,10 +51,7 @@ The following example demonstrates how the energy of the H2 molecule is affected
nlayers = 1
nqubits = mol.nso
ntheta = 2 * nqubits * nlayers
hea_ansatz = hardware_efficient.hea(nlayers, nqubits)

circuit = Circuit(nqubits)
circuit.add(hea_ansatz)
circuit = he_circuit(nqubits, nlayers)

print("Energy expectation values for thetas: ")
print("-----------------------------")
Expand Down Expand Up @@ -116,8 +107,7 @@ An example of how to build a UCC doubles circuit ansatz for the :math:`H_2` mole
.. code-block:: python

from qibochem.driver.molecule import Molecule
from qibochem.ansatz.hf_reference import hf_circuit
from qibochem.ansatz.ucc import ucc_circuit
from qibochem.ansatz import hf_circuit, ucc_circuit

mol = Molecule([("H", (0.0, 0.0, 0.0)), ("H", (0.0, 0.0, 0.74804))])
mol.run_pyscf()
Expand Down
20 changes: 6 additions & 14 deletions examples/br_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,15 @@
"""

import numpy as np
from qibo import Circuit, gates, models
from qibo.optimizers import optimize
from scipy.optimize import minimize
from qibo.models import VQE

from qibochem.ansatz import basis_rotation
from qibochem.ansatz.hf_reference import hf_circuit
from qibochem.driver.molecule import Molecule
from qibochem.ansatz import basis_rotation, hf_circuit
from qibochem.driver import Molecule
from qibochem.measurement.expectation import expectation

# Define molecule and populate
mol = Molecule(xyz_file="h3p.xyz")
try:
mol.run_pyscf()
except ModuleNotFoundError:
mol.run_psi4()
mol.run_pyscf()

# Diagonalize H_core to use as the guess wave function

Expand Down Expand Up @@ -59,16 +53,14 @@ def basis_rotation_circuit(mol, parameters=0.0):
gate_layout = basis_rotation.basis_rotation_layout(nqubits)
gate_list, ordered_angles = basis_rotation.basis_rotation_gates(gate_layout, gate_angles, theta)

circuit = Circuit(nqubits)
for _i in range(mol.nelec):
circuit.add(gates.X(_i))
circuit = hf_circuit(nqubits, mol.nelec)
circuit.add(gate_list)

return circuit, gate_angles


br_circuit, qubit_parameters = basis_rotation_circuit(mol, parameters=0.1)
vqe = models.VQE(br_circuit, hamiltonian)
vqe = VQE(br_circuit, hamiltonian)
vqe_result = vqe.minimize(qubit_parameters)

print(f" HF energy: {mol.e_hf:.8f}")
Expand Down
48 changes: 25 additions & 23 deletions examples/ucc_example1.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,18 @@
from qibo.optimizers import optimize
from scipy.optimize import minimize

from qibochem.ansatz.hf_reference import hf_circuit
from qibochem.ansatz.ucc import ucc_circuit
from qibochem.ansatz import hf_circuit, ucc_circuit
from qibochem.driver.molecule import Molecule
from qibochem.measurement.expectation import expectation

# Define molecule and populate
mol = Molecule(xyz_file="lih.xyz")
try:
mol.run_pyscf()
except ModuleNotFoundError:
mol.run_psi4()
mol.run_pyscf()


# Apply embedding and boson encoding
mol.hf_embedding(active=[1, 2, 5])
hamiltonian = mol.hamiltonian(oei=mol.embed_oei, tei=mol.embed_tei, constant=mol.inactive_energy)
hamiltonian = mol.hamiltonian()

# Set parameters for the rest of the experiment
n_qubits = mol.n_active_orbs
Expand Down Expand Up @@ -56,11 +52,8 @@
n_unique_excitations = 5

# UCCSD: Circuit
all_coeffs = []
for _ex in excitations:
coeffs = []
circuit += ucc_circuit(n_qubits, _ex, coeffs=coeffs)
all_coeffs.append(coeffs)
circuit += ucc_circuit(n_qubits, _ex)

# Draw the circuit if interested
print(circuit.draw())
Expand All @@ -71,19 +64,28 @@ def electronic_energy(parameters):
r"""
Loss function for the UCCSD ansatz
"""
all_parameters = []
coeff_dict = {1: (-1.0, 1.0), 2: (-0.25, 0.25, 0.25, 0.25, -0.25, -0.25, -0.25, 0.25)}

# UCC parameters
# Expand the parameters to match the total UCC ansatz manually
_ucc = parameters[:n_unique_excitations]
# Unique UCC parameters
# Manually group the related excitations together
ucc_parameters = [_ucc[0], _ucc[1], _ucc[2], _ucc[2], _ucc[3], _ucc[3], _ucc[4], _ucc[4]]
# Need to iterate through each excitation this time
for _coeffs, _parameter in zip(all_coeffs, ucc_parameters):
ucc_parameters = [
parameters[0],
parameters[1],
parameters[2],
parameters[2],
parameters[3],
parameters[3],
parameters[4],
parameters[4],
]
all_parameters = []
# Iterate through each excitation, with the list of coefficients dependent on whether S/D excitation
for _ex, _parameter in zip(excitations, ucc_parameters):
coeffs = coeff_dict[len(_ex) // 2]
# Convert a single value to a array with dimension=n_param_gates
ucc_parameter = np.repeat(_parameter, len(_coeffs))
ucc_parameter = np.repeat(_parameter, len(coeffs))
# Multiply by coeffs
ucc_parameter *= _coeffs
ucc_parameter *= coeffs
all_parameters.append(ucc_parameter)

# Flatten all_parameters into a single list to set the circuit parameters
Expand All @@ -101,7 +103,7 @@ def electronic_energy(parameters):

best, params, extra = optimize(electronic_energy, params)

print("\nResults using Qibo optimize:")
print("\nResults using Qibo optimize: (With HF embedding)")
print(f"FCI energy: {fci_energy:.8f}")
print(f" HF energy: {mol.e_hf:.8f} (Classical)")
print(f"VQE energy: {best:.8f} (UCCSD ansatz)")
Expand All @@ -115,15 +117,15 @@ def electronic_energy(parameters):
result = minimize(electronic_energy, params)
best, params = result.fun, result.x

print("\nResults using scipy.optimize:")
print("\nResults using scipy.optimize: (With HF embedding)")
print(f"FCI energy: {fci_energy:.8f}")
print(f" HF energy: {mol.e_hf:.8f} (Classical)")
print(f"VQE energy: {best:.8f} (UCCSD ansatz)")
# print()
# print("Optimized parameters:", params)


full_ham = mol.hamiltonian("f")
full_ham = mol.hamiltonian("f", oei=mol.oei, tei=mol.tei, constant=0.0)
mol_fci_energy = mol.eigenvalues(full_ham)[0]

print(f"\nFCI energy: {mol_fci_energy:.8f} (Full Hamiltonian)")
91 changes: 0 additions & 91 deletions examples/ucc_example2.py

This file was deleted.

15 changes: 6 additions & 9 deletions src/qibochem/ansatz/__init__.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
from qibochem.ansatz.basis_rotation import (
basis_rotation_gates,
basis_rotation_layout,
givens_qr_decompose,
unitary,
)
from qibochem.ansatz.hardware_efficient import hea
from qibochem.ansatz.hf_reference import bk_matrix, bk_matrix_power2, hf_circuit
from qibochem.ansatz.basis_rotation import basis_rotation_gates
from qibochem.ansatz.hardware_efficient import he_circuit
from qibochem.ansatz.hf_reference import hf_circuit
from qibochem.ansatz.ucc import (
expi_pauli,
generate_excitations,
mp2_amplitude,
sort_excitations,
ucc_ansatz,
ucc_circuit,
)

# TODO: Probably can move some of the functions, e.g. generate_excitations/sort_excitations to a new 'util.py'
Loading
Loading