Skip to content

Commit

Permalink
Merge branch 'main' into latticemodel
Browse files Browse the repository at this point in the history
  • Loading branch information
ikkoham authored Nov 24, 2021
2 parents 166d976 + e13fd46 commit a640d93
Show file tree
Hide file tree
Showing 9 changed files with 165 additions and 13 deletions.
4 changes: 2 additions & 2 deletions .github/actions/install-psi4/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ runs:
source "$CONDA/etc/profile.d/conda.sh"
conda activate psi4env
if [ "${{ inputs.os }}" == "windows-latest" ]; then
conda install -y psi4=1.4rc4.dev7 python=${{ inputs.python-version }} -c psi4/label/dev -c conda-forge
conda install -y psi4 python=${{ inputs.python-version }} -c conda-forge -c psi4/label/dev
psi4 --test
else
conda install -y psi4=1.4rc3 python=${{ inputs.python-version }} -c psi4/label/dev
conda install -y psi4 python=${{ inputs.python-version }} -c psi4
pip install -U numpy
fi
shell: bash
5 changes: 4 additions & 1 deletion qiskit_nature/algorithms/excited_states_solvers/qeom.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,10 @@ def solve(
groundstate_result = self._gsc.solve(problem)

# 2. Prepare the excitation operators
self._untapered_qubit_op_main = self._gsc._qubit_converter.map(problem.second_q_ops()[0])
self._untapered_qubit_op_main = self._gsc.qubit_converter.convert_only(
problem.second_q_ops()[0], problem.num_particles
)

matrix_operators_dict, size = self._prepare_matrix_operators(problem)

# 3. Evaluate eom operators
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,16 +114,18 @@ def _build_single_hopping_operator(
label[unocc] = "-"
fer_op = FermionicOp(("".join(label), 4.0 ** len(excitation[0])), display_format="sparse")

qubit_op: PauliSumOp = qubit_converter.convert_match(fer_op)
qubit_op: PauliSumOp = qubit_converter.convert_only(fer_op, qubit_converter.num_particles)
z2_symmetries = qubit_converter.z2symmetries

commutativities = []
if not z2_symmetries.is_empty():
for symmetry in z2_symmetries.symmetries:
symmetry_op = PauliSumOp.from_list([(symmetry.to_label(), 1.0)])
commuting = qubit_op.primitive.table.commutes_with_all(symmetry_op.primitive.table)
anticommuting = qubit_op.primitive.table.anticommutes_with_all(
symmetry_op.primitive.table
paulis = qubit_op.primitive.paulis
len_paulis = len(paulis)
commuting = len(paulis.commutes_with_all(symmetry_op.primitive.paulis)) == len_paulis
anticommuting = (
len(paulis.anticommutes_with_all(symmetry_op.primitive.paulis)) == len_paulis
)

if commuting != anticommuting: # only one of them is True
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ def _pick_sector(z2_symmetries: Z2Symmetries, hf_str: List[bool]) -> List[int]:
# Finding all the symmetries using the find_Z2_symmetries:
taper_coeff: List[int] = []
for sym in z2_symmetries.symmetries:
coeff = -1 if np.logical_xor.reduce(np.logical_and(sym.z[::-1], hf_str)) else 1
coeff = -1 if np.logical_xor.reduce(np.logical_and(sym.z, hf_str)) else 1
taper_coeff.append(coeff)

return taper_coeff
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,12 @@ def _validate_num_orbitals(self, nelec_inactive: int, particle_number: ParticleN
)
if max(self._active_orbitals) >= particle_number._num_spin_orbitals // 2:
raise QiskitNatureError("More orbitals requested than available.")
if sum(self._mo_occ_total[self._active_orbitals]) != self._num_electrons:
expected_num_electrons = (
self._num_electrons
if isinstance(self._num_electrons, int)
else sum(self._num_electrons)
)
if sum(self._mo_occ_total[self._active_orbitals]) != expected_num_electrons:
raise QiskitNatureError(
"The number of electrons in the selected active orbitals "
"does not match the specified number of active electrons."
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
fixes:
- |
Fixed the manual active orbital selection when specifying the active number
of electrons as a tuple rather than an integer.
10 changes: 10 additions & 0 deletions releasenotes/notes/qeom_fix-4341f74549f22891.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
fixes:
- |
Fixes QEOM such that when using parity mapping with two_qubit_reduction,
or Z2 symmetries with any mapping, that the excited states are computed
as expected.
Fix the electronic structure problem sector locator such that the 'auto'
Z2 symmetry conversion, of the qubit converter, results in the ground state
for such problems and not some other value due to incorrect sector selection.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@

from qiskit_nature.drivers import UnitsType
from qiskit_nature.drivers.second_quantization import PySCFDriver
from qiskit_nature.mappers.second_quantization import JordanWignerMapper
from qiskit_nature.mappers.second_quantization import (
BravyiKitaevMapper,
JordanWignerMapper,
ParityMapper,
)
from qiskit_nature.converters.second_quantization import QubitConverter
from qiskit_nature.problems.second_quantization import ElectronicStructureProblem
from qiskit_nature.algorithms import (
Expand Down Expand Up @@ -75,10 +79,51 @@ def test_numpy_mes(self):
for idx, energy in enumerate(self.reference_energies):
self.assertAlmostEqual(results.computed_energies[idx], energy, places=4)

def test_vqe_mes(self):
"""Test VQEUCCSDFactory with QEOM"""
def test_vqe_mes_jw(self):
"""Test VQEUCCSDFactory with QEOM + Jordan Wigner mapping"""
converter = QubitConverter(JordanWignerMapper())
self._solve_with_vqe_mes(converter)

def test_vqe_mes_jw_auto(self):
"""Test VQEUCCSDFactory with QEOM + Jordan Wigner mapping + auto symmetry"""
converter = QubitConverter(JordanWignerMapper(), z2symmetry_reduction="auto")
self._solve_with_vqe_mes(converter)

def test_vqe_mes_parity(self):
"""Test VQEUCCSDFactory with QEOM + Parity mapping"""
converter = QubitConverter(ParityMapper())
self._solve_with_vqe_mes(converter)

def test_vqe_mes_parity_2q(self):
"""Test VQEUCCSDFactory with QEOM + Parity mapping + reduction"""
converter = QubitConverter(ParityMapper(), two_qubit_reduction=True)
self._solve_with_vqe_mes(converter)

def test_vqe_mes_parity_auto(self):
"""Test VQEUCCSDFactory with QEOM + Parity mapping + auto symmetry"""
converter = QubitConverter(ParityMapper(), z2symmetry_reduction="auto")
self._solve_with_vqe_mes(converter)

def test_vqe_mes_parity_2q_auto(self):
"""Test VQEUCCSDFactory with QEOM + Parity mapping + reduction + auto symmetry"""
converter = QubitConverter(
ParityMapper(), two_qubit_reduction=True, z2symmetry_reduction="auto"
)
self._solve_with_vqe_mes(converter)

def test_vqe_mes_bk(self):
"""Test VQEUCCSDFactory with QEOM + Bravyi-Kitaev mapping"""
converter = QubitConverter(BravyiKitaevMapper())
self._solve_with_vqe_mes(converter)

def test_vqe_mes_bk_auto(self):
"""Test VQEUCCSDFactory with QEOM + Bravyi-Kitaev mapping + auto symmetry"""
converter = QubitConverter(BravyiKitaevMapper(), z2symmetry_reduction="auto")
self._solve_with_vqe_mes(converter)

def _solve_with_vqe_mes(self, converter: QubitConverter):
solver = VQEUCCFactory(self.quantum_instance)
gsc = GroundStateEigensolver(self.qubit_converter, solver)
gsc = GroundStateEigensolver(converter, solver)
esc = QEOM(gsc, "sd")
results = esc.solve(self.electronic_structure_problem)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,88 @@ def test_active_space_for_q_molecule_v2(self):

self.assertDriverResult(driver_result_reduced, driver_result)

def test_tuple_num_electrons_with_manual_orbitals(self):
"""Regression test against https://github.com/Qiskit/qiskit-nature/issues/434."""
driver = HDF5Driver(
hdf5_input=self.get_resource_path(
"H2_631g.hdf5", "transformers/second_quantization/electronic"
)
)
driver_result = driver.run()

trafo = ActiveSpaceTransformer(
num_electrons=(1, 1),
num_molecular_orbitals=2,
active_orbitals=[0, 1],
)
driver_result_reduced = trafo.transform(driver_result)

expected = ElectronicStructureDriverResult()
expected.add_property(
ElectronicEnergy(
[
OneBodyElectronicIntegrals(
ElectronicBasis.MO,
(np.asarray([[-1.24943841, 0.0], [0.0, -0.547816138]]), None),
),
TwoBodyElectronicIntegrals(
ElectronicBasis.MO,
(
np.asarray(
[
[
[[0.652098466, 0.0], [0.0, 0.433536565]],
[[0.0, 0.0794483182], [0.0794483182, 0.0]],
],
[
[[0.0, 0.0794483182], [0.0794483182, 0.0]],
[[0.433536565, 0.0], [0.0, 0.385524695]],
],
]
),
None,
None,
None,
),
),
],
energy_shift={"ActiveSpaceTransformer": 0.0},
)
)
expected.add_property(
ElectronicDipoleMoment(
[
DipoleMoment(
"x",
[OneBodyElectronicIntegrals(ElectronicBasis.MO, (np.zeros((2, 2)), None))],
shift={"ActiveSpaceTransformer": 0.0},
),
DipoleMoment(
"y",
[OneBodyElectronicIntegrals(ElectronicBasis.MO, (np.zeros((2, 2)), None))],
shift={"ActiveSpaceTransformer": 0.0},
),
DipoleMoment(
"z",
[
OneBodyElectronicIntegrals(
ElectronicBasis.MO,
(
np.asarray(
[[0.69447435, -1.01418298], [-1.01418298, 0.69447435]]
),
None,
),
)
],
shift={"ActiveSpaceTransformer": 0.0},
),
]
)
)

self.assertDriverResult(driver_result_reduced, expected)


if __name__ == "__main__":
unittest.main()

0 comments on commit a640d93

Please sign in to comment.