Skip to content

Commit

Permalink
Fix existing initial points with reps (#808) (#812)
Browse files Browse the repository at this point in the history
* Repeat initial point parameters based on ansatz reps.

* Add release note.

* Add tests.

* Account for reps in initial_points tests.

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
(cherry picked from commit 88bf668)

Co-authored-by: Declan Millar <declan.millar@ibm.com>
  • Loading branch information
mergify[bot] and declanmillar authored Aug 30, 2022
1 parent e80d749 commit 02642b2
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 5 deletions.
3 changes: 2 additions & 1 deletion qiskit_nature/algorithms/initial_points/hf_initial_point.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,8 @@ def compute(
self._compute()

def _compute(self) -> None:
self._parameters = np.zeros(len(self._excitation_list))
reps = self._ansatz.reps if self._ansatz is not None else 1
self._parameters = np.zeros(reps * len(self._excitation_list))

def get_energy(self) -> float:
"""The reference energy.
Expand Down
4 changes: 3 additions & 1 deletion qiskit_nature/algorithms/initial_points/mp2_initial_point.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,9 @@ def to_numpy_array(self) -> np.ndarray:
"""The initial point as an array."""
if self._corrections is None:
self.compute()
return np.asarray([correction.coefficient for correction in self._corrections])
coefficients = np.asarray([correction.coefficient for correction in self._corrections])
reps = self._ansatz.reps if self._ansatz is not None else 1
return np.tile(coefficients, reps)

def get_energy_corrections(self) -> np.ndarray:
"""The energy corrections for each excitation."""
Expand Down
4 changes: 2 additions & 2 deletions qiskit_nature/algorithms/initial_points/vscf_initial_point.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,5 +129,5 @@ def compute(
"Set the ansatz or call compute with it as an argument. "
"The ansatz is not required if the excitation list has been set directly."
)

self._parameters = np.zeros(len(self._excitation_list))
reps = self._ansatz.reps if self._ansatz is not None else 1
self._parameters = np.zeros(reps * len(self._excitation_list))
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
fixes:
- |
Fix the initial point classes to account for the number of times the evolved operators are
repeated in the ansatz.
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ def setUp(self):
algorithm_globals.random_seed = self.seed

self.reference_energy = -1.1373060356951838
self.mp2_initial_point = [0.0, 0.0, -0.07197145]

self.qubit_converter = QubitConverter(JordanWignerMapper())
self.electronic_structure_problem = ElectronicStructureProblem(self.driver)
Expand Down Expand Up @@ -583,7 +584,55 @@ def test_vqe_ucc_factory_with_mp2(self):
res = calc.solve(self.electronic_structure_problem)

np.testing.assert_array_almost_equal(
solver.initial_point.to_numpy_array(), [0.0, 0.0, -0.07197145]
solver.initial_point.to_numpy_array(), self.mp2_initial_point
)
self.assertAlmostEqual(res.total_energies[0], self.reference_energy, places=6)

def test_vqe_ucc_factory_with_reps(self):
"""Test when using the default initial point with repeated evolved operators."""
ansatz = UCCSD(
qubit_converter=self.qubit_converter,
num_particles=self.num_particles,
num_spin_orbitals=self.num_spin_orbitals,
reps=2,
)

solver = VQEUCCFactory(
ansatz=ansatz,
quantum_instance=QuantumInstance(BasicAer.get_backend("statevector_simulator")),
)
calc = GroundStateEigensolver(self.qubit_converter, solver)
res = calc.solve(self.electronic_structure_problem)

np.testing.assert_array_almost_equal(
solver.initial_point.to_numpy_array(), np.zeros(6, dtype=float)
)
self.assertAlmostEqual(res.total_energies[0], self.reference_energy, places=6)

def test_vqe_ucc_factory_with_mp2_with_reps(self):
"""Test when using MP2InitialPoint to generate the initial point with repeated evolved
operators.
"""

initial_point = MP2InitialPoint()

ansatz = UCCSD(
qubit_converter=self.qubit_converter,
num_particles=self.num_particles,
num_spin_orbitals=self.num_spin_orbitals,
reps=2,
)

solver = VQEUCCFactory(
ansatz=ansatz,
quantum_instance=QuantumInstance(BasicAer.get_backend("statevector_simulator")),
initial_point=initial_point,
)
calc = GroundStateEigensolver(self.qubit_converter, solver)
res = calc.solve(self.electronic_structure_problem)

np.testing.assert_array_almost_equal(
solver.initial_point.to_numpy_array(), np.tile(self.mp2_initial_point, 2)
)
self.assertAlmostEqual(res.total_energies[0], self.reference_energy, places=6)

Expand Down
2 changes: 2 additions & 0 deletions test/algorithms/initial_points/test_hf_initial_point.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ def test_missing_ansatz(self):
def test_set_get_ansatz(self):
"""Test set get ansatz."""
ansatz = Mock(spec=UCC)
ansatz.reps = 1
ansatz.excitation_list = self.excitation_list
self.hf_initial_point.ansatz = ansatz
self.assertEqual(ansatz, self.hf_initial_point.ansatz)
Expand Down Expand Up @@ -89,6 +90,7 @@ def test_compute(self):
"""Test length of HF initial point array."""
grouped_property = Mock(spec=GroupedSecondQuantizedProperty)
ansatz = Mock(spec=UCC)
ansatz.reps = 1
ansatz.excitation_list = self.excitation_list
self.hf_initial_point.compute(ansatz=ansatz, grouped_property=grouped_property)
initial_point = self.hf_initial_point.to_numpy_array()
Expand Down
3 changes: 3 additions & 0 deletions test/algorithms/initial_points/test_mp2_initial_point.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ def setUp(self):

self.excitation_list = [[[0], [1]]]
self.mock_ansatz = Mock(spec=UCC)
self.mock_ansatz.reps = 1
self.mock_ansatz.excitation_list = self.excitation_list

electronic_energy = Mock(spec=ElectronicEnergy)
Expand Down Expand Up @@ -133,6 +134,7 @@ def test_no_orbital_energies(self):
self.mock_grouped_property.get_property = Mock(return_value=electronic_energy)

ansatz = Mock(spec=UCC)
ansatz.reps = 1
ansatz.excitation_list = self.excitation_list

mp2_initial_point = MP2InitialPoint()
Expand Down Expand Up @@ -239,6 +241,7 @@ def test_mp2_initial_point_with_real_molecules(
driver_result = problem.grouped_property_transformed

ansatz = Mock(spec=UCC)
ansatz.reps = 1
ansatz.excitation_list = excitations

mp2_initial_point = MP2InitialPoint()
Expand Down
2 changes: 2 additions & 0 deletions test/algorithms/initial_points/test_vscf_initial_point.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ def test_missing_ansatz(self):
def test_set_get_ansatz(self):
"""Test set get ansatz."""
ansatz = Mock(spec=UVCC)
ansatz.reps = 1
ansatz.excitation_list = self.excitation_list
self.vscf_initial_point.ansatz = ansatz
self.assertEqual(ansatz, self.vscf_initial_point.ansatz)
Expand All @@ -64,6 +65,7 @@ def test_vscf_with_excitation_list_set_directly(self):
def test_vscf_compute(self):
"""Test VSCF initial point is all zero when called via compute."""
ansatz = Mock(spec=UVCC)
ansatz.reps = 1
ansatz.excitation_list = self.excitation_list
self.vscf_initial_point.compute(ansatz)
initial_point = self.vscf_initial_point.to_numpy_array()
Expand Down

0 comments on commit 02642b2

Please sign in to comment.