Skip to content
This repository has been archived by the owner on Dec 7, 2021. It is now read-only.

Fix opflow bugs #1390

Merged
merged 24 commits into from
Oct 31, 2020
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
902513e
fix #1311
ikkoham Oct 23, 2020
2b2c9dd
fix #1317
ikkoham Oct 23, 2020
0060fd2
add a test of reps for trotterization
ikkoham Oct 26, 2020
8a592fd
fix tests for #1311
ikkoham Oct 26, 2020
f87a39a
fix typing
ikkoham Oct 26, 2020
5acedfb
fix #1321
ikkoham Oct 26, 2020
ce2ce74
add release note
ikkoham Oct 26, 2020
42c661b
fix #1381
ikkoham Oct 26, 2020
f848fce
add a test for to_opflow
ikkoham Oct 26, 2020
ff84ed4
Update qiskit/aqua/operators/converters/circuit_sampler.py
ikkoham Oct 27, 2020
c884ebb
remove None from constructor
ikkoham Oct 27, 2020
f2f6fa8
Merge branch 'master' into fix-opflow-bugs
Oct 27, 2020
91f782a
simplify logic
ikkoham Oct 27, 2020
feee254
Merge branch 'fix-opflow-bugs' of https://github.com/ikkoham/qiskit-a…
ikkoham Oct 27, 2020
effbf30
Merge branch 'master' into fix-opflow-bugs
manoelmarques Oct 28, 2020
c4d3113
Merge branch 'master' into fix-opflow-bugs
manoelmarques Oct 28, 2020
dac3b1a
Revert "remove None from constructor"
ikkoham Oct 28, 2020
b8f01bc
add releasenote
ikkoham Oct 28, 2020
cca3498
simplify logic (not iscomplex to isreal)
ikkoham Oct 28, 2020
19b04e4
remove Optional
ikkoham Oct 28, 2020
249e64b
Update qiskit/aqua/operators/legacy/weighted_pauli_operator.py
woodsp-ibm Oct 30, 2020
6bd7969
Update qiskit/aqua/operators/legacy/weighted_pauli_operator.py
woodsp-ibm Oct 30, 2020
020f527
Update qiskit/aqua/operators/legacy/weighted_pauli_operator.py
woodsp-ibm Oct 30, 2020
c84e868
Merge branch 'master' into fix-opflow-bugs
woodsp-ibm Oct 30, 2020
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
16 changes: 14 additions & 2 deletions qiskit/aqua/operators/converters/circuit_sampler.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from qiskit.providers import Backend
from qiskit.circuit import QuantumCircuit, Parameter, ParameterExpression
from qiskit import QiskitError
from qiskit.aqua import QuantumInstance
from qiskit.aqua import QuantumInstance, AquaError
from qiskit.aqua.utils.backend_utils import is_aer_provider, is_statevector_backend
from qiskit.aqua.operators.operator_base import OperatorBase
from qiskit.aqua.operators.list_ops.list_op import ListOp
Expand Down Expand Up @@ -165,6 +165,8 @@ def convert(self,

Returns:
The converted Operator with CircuitStateFns replaced by DictStateFns or VectorStateFns.
Raises:
AquaError: if extracted circuits are empty.
"""
if self._last_op is None or id(operator) != id(self._last_op):
# Clear caches
Expand All @@ -181,6 +183,11 @@ def convert(self,
if not self._circuit_ops_cache:
self._circuit_ops_cache = {}
self._extract_circuitstatefns(self._reduced_op_cache)
if not self._circuit_ops_cache:
raise AquaError(
'Circuits are empty. '
'Check that the operator is an instance of CircuitStateFn or its ListOp.'
)

if params:
p_0 = list(params.values())[0] # type: ignore
Expand Down Expand Up @@ -243,8 +250,13 @@ def sample_circuits(self,

Returns:
The dictionary mapping ids of the CircuitStateFns to their replacement StateFns.
Raises:
AquaError: if extracted circuits are empty.
"""
if circuit_sfns or not self._transpiled_circ_cache:
if not circuit_sfns and not self._transpiled_circ_cache:
raise AquaError('CircuitStateFn is empty and there is no cache.')

if circuit_sfns:
if self._statevector:
circuits = [op_c.to_circuit(meas=False) for op_c in circuit_sfns]
else:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ def __init__(self,
Args:
reps: The number of times to repeat the Trotterization circuit.
"""
super().__init__(order=1, reps=1)
super().__init__(order=1, reps=reps)
15 changes: 12 additions & 3 deletions qiskit/aqua/operators/legacy/weighted_pauli_operator.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,18 @@ def to_opflow(self, reverse_endianness=False):
pauli_ops = []
for [w, p] in self.paulis:
pauli = Pauli.from_label(str(p)[::-1]) if reverse_endianness else p
# Adding the imaginary is necessary to handle the imaginary coefficients in UCCSD.
# TODO fix these or add support for them in Terra.
pauli_ops += [PrimitiveOp(pauli, coeff=np.real(w) + np.imag(w))]
# This weighted pauli operator has the coeff stored as a complex type irrespective of
# whether the value has any imaginary part or not. For many operators the coeff will
# be real. Hence here the coeff is made real, since it can be stored then as a float, if its
# value is real, i.e. has no imaginary part. This avoids any potential issues around
# complex - but if there are complex coeffs then maybe that using the opflow later
# will fail if it happens to be used where complex is not supported.
# Now there imaginary coefficients in UCCSD that would need to be handled when
# this is converted to opflow (evolution of hopping operators where currently Terra
# does not handle complex.
# TODO fix these or add support for them in Terra
woodsp-ibm marked this conversation as resolved.
Show resolved Hide resolved
coeff = np.real(w) if np.isreal(w) else w
pauli_ops += [PrimitiveOp(pauli, coeff=coeff)]
return sum(pauli_ops)

@property
Expand Down
2 changes: 1 addition & 1 deletion qiskit/aqua/operators/state_fns/dict_state_fn.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ def sample(self,
shots: int = 1024,
massive: bool = False,
reverse_endianness: bool = False) -> dict:
probs = np.array(list(self.primitive.values()))**2
probs = np.square(np.abs(np.array(list(self.primitive.values()))))
unique, counts = np.unique(aqua_globals.random.choice(list(self.primitive.keys()),
size=shots,
p=(probs / sum(probs))),
Expand Down
2 changes: 1 addition & 1 deletion qiskit/aqua/operators/state_fns/operator_state_fn.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class OperatorStateFn(StateFn):

# TODO allow normalization somehow?
def __init__(self,
primitive: Union[OperatorBase] = None,
primitive: OperatorBase = None,
coeff: Union[int, float, complex, ParameterExpression] = 1.0,
is_measurement: bool = False) -> None:
"""
Expand Down
17 changes: 17 additions & 0 deletions releasenotes/notes/fix-operator-flow-33a0bd315151562c.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
fixes:
- |
:meth`~qiskit.aqua.operators.state_fns.DictStateFn.sample()` could only handle
real amplitudes, but it is fixed to handle complex amplitudes.
`#1311 <https://github.com/Qiskit/qiskit-aqua/issues/1311>` for more details.
- |
Trotter class did not use the reps argument in constructor.
`#1317 <https://github.com/Qiskit/qiskit-aqua/issues/1317>` for more details.
- |
Raise an `AquaError` if :class`qiskit.aqua.operators.converters.CircuitSampler`
samples an empty operator.
`#1321 <https://github.com/Qiskit/qiskit-aqua/issues/1321>` for more details.
- |
:meth:`~qiskit.aqua.operators.legacy.WeightedPauliOperator.to_opflow()`
returns a correct operator when coefficients are complex numbers.
`#1381 <https://github.com/Qiskit/qiskit-aqua/issues/1381>` for more details.
17 changes: 17 additions & 0 deletions test/aqua/operators/legacy/test_weighted_pauli_operator.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from qiskit.aqua.operators import WeightedPauliOperator
from qiskit.aqua.operators.legacy import op_converter
from qiskit.aqua.components.initial_states import Custom
from qiskit.aqua.operators import I, X, Y, Z


@ddt
Expand Down Expand Up @@ -610,6 +611,22 @@ def eval_op(op):
expectation_value, _ = eval_op(wpo2)
self.assertAlmostEqual(expectation_value, -3.0, places=2)

def test_to_opflow(self):
"""Test for to_opflow() in WeightedPauliOperator"""
pauli_a = 'IXYZ'
pauli_b = 'ZYIX'
coeff_a = 0.5 + 1j
coeff_b = -0.5 - 1j
pauli_term_a = [coeff_a, Pauli.from_label(pauli_a)]
pauli_term_b = [coeff_b, Pauli.from_label(pauli_b)]
op_a = WeightedPauliOperator(paulis=[pauli_term_a])
op_b = WeightedPauliOperator(paulis=[pauli_term_b])
legacy_op = op_a + op_b

op = coeff_a * (I ^ X ^ Y ^ Z) + coeff_b * (Z ^ Y ^ I ^ X)

self.assertEqual(op, legacy_op.to_opflow())


if __name__ == '__main__':
unittest.main()
18 changes: 16 additions & 2 deletions test/aqua/operators/test_evolution.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@
from qiskit.circuit import ParameterVector, Parameter

from qiskit.aqua.operators import (X, Y, Z, I, CX, H, ListOp, CircuitOp, Zero, EvolutionFactory,
EvolvedOp, PauliTrotterEvolution, QDrift)

EvolvedOp, PauliTrotterEvolution, QDrift, Trotter, Suzuki)

# pylint: disable=invalid-name


class TestEvolution(QiskitAquaTestCase):
"""Evolution tests."""

Expand Down Expand Up @@ -255,6 +255,20 @@ def test_mixed_evolution(self):
for p in thetas[1:]:
self.assertNotIn(p, circuit_params)

def test_reps(self):
"""Test reps and order params in Trotterization"""
reps = 7
trotter = Trotter(reps=reps)
self.assertEqual(trotter.reps, reps)

order = 5
suzuki = Suzuki(reps=reps, order=order)
self.assertEqual(suzuki.reps, reps)
self.assertEqual(suzuki.order, order)

qdrift = QDrift(reps=reps)
self.assertEqual(qdrift.reps, reps)


if __name__ == '__main__':
unittest.main()
8 changes: 4 additions & 4 deletions test/aqua/operators/test_state_construction.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,10 @@ def test_circuit_state_fn_from_complex_vector_initialize(self):

def test_sampling(self):
""" state fn circuit from dict initialize test """
statedict = {'101': .5,
'100': .1,
'000': .2,
'111': .5}
statedict = {'101': .5 + 1.j,
'100': .1 + 2.j,
'000': .2 + 0.j,
'111': .5 + 1.j}
sfc = CircuitStateFn.from_dict(statedict)
circ_samples = sfc.sample()
dict_samples = StateFn(statedict).sample()
Expand Down