Skip to content

Commit eb83547

Browse files
authored
Merge pull request #86 from qiboteam/refactor-ansatzes
Refactor code for some ansatzes
2 parents 2e60ecc + c4a5564 commit eb83547

File tree

11 files changed

+248
-345
lines changed

11 files changed

+248
-345
lines changed

doc/source/api-reference/ansatz.rst

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22
Ansatz
33
======
44

5-
This section covers the API reference for various chemistry ansatzes.
5+
This section covers the API reference for various chemistry circuit ansatzes.
66

77
Hardware-efficient
88
------------------
99

10-
.. autofunction:: qibochem.ansatz.hardware_efficient.hea
10+
.. autofunction:: qibochem.ansatz.hardware_efficient.he_circuit
1111

1212

1313
Hartree-Fock

doc/source/getting-started/quickstart.rst

+1-2
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ Here is an example of building the UCCD ansatz with the H2 molecule to test your
1515
from qibo.models import VQE
1616

1717
from qibochem.driver.molecule import Molecule
18-
from qibochem.ansatz.hf_reference import hf_circuit
19-
from qibochem.ansatz.ucc import ucc_circuit
18+
from qibochem.ansatz import hf_circuit, ucc_circuit
2019

2120
# Define the H2 molecule and obtain its 1-/2- electron integrals with PySCF
2221
h2 = Molecule([('H', (0.0, 0.0, 0.0)), ('H', (0.0, 0.0, 0.7))])

doc/source/tutorials/ansatz.rst

+7-17
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,12 @@ For the H\ :sub:`2` case discussed in previous sections, a possible hardware eff
1616

1717
.. code-block:: python
1818
19-
from qibo import Circuit
19+
from qibochem.ansatz import he_circuit
2020
21-
from qibochem.ansatz import hardware_efficient
22-
23-
nlayers = 1
2421
nqubits = 4
25-
nfermions = 2
22+
nlayers = 1
2623
27-
circuit = Circuit(4)
28-
hardware_efficient_ansatz = hardware_efficient.hea(nlayers, nqubits)
29-
circuit.add(hardware_efficient_ansatz)
24+
circuit = he_circuit(nqubits, nlayers)
3025
print(circuit.draw())
3126
3227
.. code-block:: output
@@ -43,11 +38,10 @@ The following example demonstrates how the energy of the H2 molecule is affected
4338
.. code-block:: python
4439
4540
import numpy as np
46-
from qibo import Circuit
4741
48-
from qibochem.driver.molecule import Molecule
42+
from qibochem.driver import Molecule
4943
from qibochem.measurement.expectation import expectation
50-
from qibochem.ansatz import hardware_efficient
44+
from qibochem.ansatz import he_circuit
5145
5246
mol = Molecule([("H", (0.0, 0.0, 0.0)), ("H", (0.0, 0.0, 0.74804))])
5347
mol.run_pyscf()
@@ -57,10 +51,7 @@ The following example demonstrates how the energy of the H2 molecule is affected
5751
nlayers = 1
5852
nqubits = mol.nso
5953
ntheta = 2 * nqubits * nlayers
60-
hea_ansatz = hardware_efficient.hea(nlayers, nqubits)
61-
62-
circuit = Circuit(nqubits)
63-
circuit.add(hea_ansatz)
54+
circuit = he_circuit(nqubits, nlayers)
6455
6556
print("Energy expectation values for thetas: ")
6657
print("-----------------------------")
@@ -116,8 +107,7 @@ An example of how to build a UCC doubles circuit ansatz for the :math:`H_2` mole
116107
.. code-block:: python
117108
118109
from qibochem.driver.molecule import Molecule
119-
from qibochem.ansatz.hf_reference import hf_circuit
120-
from qibochem.ansatz.ucc import ucc_circuit
110+
from qibochem.ansatz import hf_circuit, ucc_circuit
121111
122112
mol = Molecule([("H", (0.0, 0.0, 0.0)), ("H", (0.0, 0.0, 0.74804))])
123113
mol.run_pyscf()

examples/br_example.py

+6-14
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,15 @@
44
"""
55

66
import numpy as np
7-
from qibo import Circuit, gates, models
8-
from qibo.optimizers import optimize
9-
from scipy.optimize import minimize
7+
from qibo.models import VQE
108

11-
from qibochem.ansatz import basis_rotation
12-
from qibochem.ansatz.hf_reference import hf_circuit
13-
from qibochem.driver.molecule import Molecule
9+
from qibochem.ansatz import basis_rotation, hf_circuit
10+
from qibochem.driver import Molecule
1411
from qibochem.measurement.expectation import expectation
1512

1613
# Define molecule and populate
1714
mol = Molecule(xyz_file="h3p.xyz")
18-
try:
19-
mol.run_pyscf()
20-
except ModuleNotFoundError:
21-
mol.run_psi4()
15+
mol.run_pyscf()
2216

2317
# Diagonalize H_core to use as the guess wave function
2418

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

62-
circuit = Circuit(nqubits)
63-
for _i in range(mol.nelec):
64-
circuit.add(gates.X(_i))
56+
circuit = hf_circuit(nqubits, mol.nelec)
6557
circuit.add(gate_list)
6658

6759
return circuit, gate_angles
6860

6961

7062
br_circuit, qubit_parameters = basis_rotation_circuit(mol, parameters=0.1)
71-
vqe = models.VQE(br_circuit, hamiltonian)
63+
vqe = VQE(br_circuit, hamiltonian)
7264
vqe_result = vqe.minimize(qubit_parameters)
7365

7466
print(f" HF energy: {mol.e_hf:.8f}")

examples/ucc_example1.py

+25-23
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,18 @@
66
from qibo.optimizers import optimize
77
from scipy.optimize import minimize
88

9-
from qibochem.ansatz.hf_reference import hf_circuit
10-
from qibochem.ansatz.ucc import ucc_circuit
9+
from qibochem.ansatz import hf_circuit, ucc_circuit
1110
from qibochem.driver.molecule import Molecule
1211
from qibochem.measurement.expectation import expectation
1312

1413
# Define molecule and populate
1514
mol = Molecule(xyz_file="lih.xyz")
16-
try:
17-
mol.run_pyscf()
18-
except ModuleNotFoundError:
19-
mol.run_psi4()
15+
mol.run_pyscf()
2016

2117

2218
# Apply embedding and boson encoding
2319
mol.hf_embedding(active=[1, 2, 5])
24-
hamiltonian = mol.hamiltonian(oei=mol.embed_oei, tei=mol.embed_tei, constant=mol.inactive_energy)
20+
hamiltonian = mol.hamiltonian()
2521

2622
# Set parameters for the rest of the experiment
2723
n_qubits = mol.n_active_orbs
@@ -56,11 +52,8 @@
5652
n_unique_excitations = 5
5753

5854
# UCCSD: Circuit
59-
all_coeffs = []
6055
for _ex in excitations:
61-
coeffs = []
62-
circuit += ucc_circuit(n_qubits, _ex, coeffs=coeffs)
63-
all_coeffs.append(coeffs)
56+
circuit += ucc_circuit(n_qubits, _ex)
6457

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

76-
# UCC parameters
77-
# Expand the parameters to match the total UCC ansatz manually
78-
_ucc = parameters[:n_unique_excitations]
69+
# Unique UCC parameters
7970
# Manually group the related excitations together
80-
ucc_parameters = [_ucc[0], _ucc[1], _ucc[2], _ucc[2], _ucc[3], _ucc[3], _ucc[4], _ucc[4]]
81-
# Need to iterate through each excitation this time
82-
for _coeffs, _parameter in zip(all_coeffs, ucc_parameters):
71+
ucc_parameters = [
72+
parameters[0],
73+
parameters[1],
74+
parameters[2],
75+
parameters[2],
76+
parameters[3],
77+
parameters[3],
78+
parameters[4],
79+
parameters[4],
80+
]
81+
all_parameters = []
82+
# Iterate through each excitation, with the list of coefficients dependent on whether S/D excitation
83+
for _ex, _parameter in zip(excitations, ucc_parameters):
84+
coeffs = coeff_dict[len(_ex) // 2]
8385
# Convert a single value to a array with dimension=n_param_gates
84-
ucc_parameter = np.repeat(_parameter, len(_coeffs))
86+
ucc_parameter = np.repeat(_parameter, len(coeffs))
8587
# Multiply by coeffs
86-
ucc_parameter *= _coeffs
88+
ucc_parameter *= coeffs
8789
all_parameters.append(ucc_parameter)
8890

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

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

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

118-
print("\nResults using scipy.optimize:")
120+
print("\nResults using scipy.optimize: (With HF embedding)")
119121
print(f"FCI energy: {fci_energy:.8f}")
120122
print(f" HF energy: {mol.e_hf:.8f} (Classical)")
121123
print(f"VQE energy: {best:.8f} (UCCSD ansatz)")
122124
# print()
123125
# print("Optimized parameters:", params)
124126

125127

126-
full_ham = mol.hamiltonian("f")
128+
full_ham = mol.hamiltonian("f", oei=mol.oei, tei=mol.tei, constant=0.0)
127129
mol_fci_energy = mol.eigenvalues(full_ham)[0]
128130

129131
print(f"\nFCI energy: {mol_fci_energy:.8f} (Full Hamiltonian)")

examples/ucc_example2.py

-91
This file was deleted.

src/qibochem/ansatz/__init__.py

+6-9
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
1-
from qibochem.ansatz.basis_rotation import (
2-
basis_rotation_gates,
3-
basis_rotation_layout,
4-
givens_qr_decompose,
5-
unitary,
6-
)
7-
from qibochem.ansatz.hardware_efficient import hea
8-
from qibochem.ansatz.hf_reference import bk_matrix, bk_matrix_power2, hf_circuit
1+
from qibochem.ansatz.basis_rotation import basis_rotation_gates
2+
from qibochem.ansatz.hardware_efficient import he_circuit
3+
from qibochem.ansatz.hf_reference import hf_circuit
94
from qibochem.ansatz.ucc import (
10-
expi_pauli,
115
generate_excitations,
126
mp2_amplitude,
137
sort_excitations,
8+
ucc_ansatz,
149
ucc_circuit,
1510
)
11+
12+
# TODO: Probably can move some of the functions, e.g. generate_excitations/sort_excitations to a new 'util.py'

0 commit comments

Comments
 (0)