Qiskit / qiskit

Qiskit is an open-source SDK for working with quantum computers at the level of extended quantum circuits, operators, and primitives.
https://www.ibm.com/quantum/qiskit
Apache License 2.0
4.85k stars 2.29k forks source link

PauliEvolutionGate: ValueError: Operator contains complex coefficients, which are not supported. #10370

Open afrah opened 1 year ago

afrah commented 1 year ago

Environment

What is happening?

The PauliTrotterEvolution class fails to exponentiate my Hamiltonain simulation. Attempting to do so gives the error message

ValueError                                Traceback (most recent call last)
Input In [21], in <cell line: 1>()
----> 1 trotterized_op = PauliTrotterEvolution(trotter_mode='trotter', reps=num_time_slices).convert(evolution_op)

File ~/anaconda3/envs/qsilver/lib/python3.10/site-packages/qiskit/opflow/evolutions/pauli_trotter_evolution.py:106, in PauliTrotterEvolution.convert(self, operator)
     92 r"""
     93 Traverse the operator, replacing ``EvolvedOps`` with ``CircuitOps`` containing
     94 Trotterized evolutions equalling the exponentiation of -i * operator.
   (...)
    100     The converted operator.
    101 """
    102 # TODO uncomment when we implement Abelian grouped evolution.
    103 # if self._grouper:
    104 #     # Sort into commuting groups
    105 #     operator = self._grouper.convert(operator).reduce()
--> 106 return self._recursive_convert(operator)

File ~/anaconda3/envs/qsilver/lib/python3.10/site-packages/qiskit/opflow/evolutions/pauli_trotter_evolution.py:119, in PauliTrotterEvolution._recursive_convert(self, operator)
    117 pauli = operator.primitive.primitive
    118 time = operator.coeff * operator.primitive.coeff
--> 119 evo = PauliEvolutionGate(
    120     pauli, time=time, synthesis=self._get_evolution_synthesis()
    121 )
    122 return CircuitOp(evo)
    123 # operator = EvolvedOp(operator.primitive.to_pauli_op(), coeff=operator.coeff)

File ~/anaconda3/envs/qsilver/lib/python3.10/site-packages/qiskit/circuit/library/pauli_evolution.py:102, in PauliEvolutionGate.__init__(self, operator, time, label, synthesis)
    100     operator = [_to_sparse_pauli_op(op) for op in operator]
    101 else:
--> 102     operator = _to_sparse_pauli_op(operator)
    104 if synthesis is None:
    105     synthesis = LieTrotter()

File ~/anaconda3/envs/qsilver/lib/python3.10/site-packages/qiskit/circuit/library/pauli_evolution.py:172, in _to_sparse_pauli_op(operator)
    169     raise ValueError(f"Unsupported operator type for evolution: {type(operator)}.")
    171 if any(np.iscomplex(sparse_pauli.coeffs)):
--> 172     raise ValueError("Operator contains complex coefficients, which are not supported.")
    174 return sparse_pauli

ValueError: Operator contains complex coefficients, which are not supported.

How can we reproduce the issue?

I want to solve a PDE discretized matrix using HHL. The following code is a minimal working example.

A = np.array([[ 1.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  , 0.  , 0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ],
       [ 0.  ,  1.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  , 0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ],
       [ 0.  ,  0.  ,  1.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  , 0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ],
       [ 0.  ,  0.  ,  0.  ,  1.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  , 0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ],
       [ 0.  ,  0.  ,  0.  ,  0.  ,  1.  ,  0.  ,  0.  ,  0.  ,  0.  , 0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ],
       [ 0.  ,  0.25,  0.  ,  0.  ,  0.25, -1.  ,  0.25,  0.  ,  0.  , 0.25,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ],
       [ 0.  ,  0.  ,  0.25,  0.  ,  0.  ,  0.25, -1.  ,  0.25,  0.  , 0.  ,  0.25,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ],
       [ 0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  1.  ,  0.  , 0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ],
       [ 0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  1.  , 0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ],
       [ 0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.25,  0.  ,  0.  ,  0.25,-1.  ,  0.25,  0.  ,  0.  ,  0.25,  0.  ,  0.  ],
       [ 0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.25,  0.  ,  0.  , 0.25, -1.  ,  0.25,  0.  ,  0.  ,  0.25,  0.  ],
       [ 0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  , 0.  ,  0.  ,  1.  ,  0.  ,  0.  ,  0.  ,  0.  ],
       [ 0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  , 0.  ,  0.  ,  0.  ,  1.  ,  0.  ,  0.  ,  0.  ],
       [ 0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  , 0.  ,  0.  ,  0.  ,  0.  ,  1.  ,  0.  ,  0.  ],
       [ 0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  , 0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  1.  ,  0.  ],
       [ 0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  , 0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  1.  ]])

b = np.array([-1. , -1. , -1. , -1. ,  0.5,  0. ,  0. ,  1. ,  0.5,  0. ,  0. , 1. , -2. , -2. , -2. , -2. ])

n = 4
num_time_slices = 1
H=I
for i in range(n-1):
    H=H^I

H=0*H

paulis=[I,X,Y,Z]

for i in range(4**n):
    term=paulis[i%4]
    i=i//4
    for j in range(n-1):
        term=term^paulis[i%4]
        i=i//4
    a=sum([((term.to_matrix())@(A))[k][k] for k in range(2**n)])/(2**n)
    H+=(a*term)

evolution_op = (-H).exp_i()
trotterized_op = PauliTrotterEvolution(trotter_mode='trotter', reps=num_time_slices).convert(evolution_op)

What should happen?

This error should not happen. The error message is not informative enough.

Any suggestions?

The suggestion mentioned here does not help.

from qiskit.circuit.library import PauliEvolutionGate
from qiskit.quantum_info import SparsePauliOp

evo_gate = PauliEvolutionGate(H) 

gives the same error,

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Input In [23], in <cell line: 4>()
      1 from qiskit.circuit.library import PauliEvolutionGate
      2 from qiskit.quantum_info import SparsePauliOp
----> 4 evo_gate = PauliEvolutionGate(H)

File ~/anaconda3/envs/qsilver/lib/python3.10/site-packages/qiskit/circuit/library/pauli_evolution.py:102, in PauliEvolutionGate.__init__(self, operator, time, label, synthesis)
    100     operator = [_to_sparse_pauli_op(op) for op in operator]
    101 else:
--> 102     operator = _to_sparse_pauli_op(operator)
    104 if synthesis is None:
    105     synthesis = LieTrotter()

File ~/anaconda3/envs/qsilver/lib/python3.10/site-packages/qiskit/circuit/library/pauli_evolution.py:172, in _to_sparse_pauli_op(operator)
    169     raise ValueError(f"Unsupported operator type for evolution: {type(operator)}.")
    171 if any(np.iscomplex(sparse_pauli.coeffs)):
--> 172     raise ValueError("Operator contains complex coefficients, which are not supported.")
    174 return sparse_pauli

ValueError: Operator contains complex coefficients, which are not supported.
Cryoris commented 1 year ago

It seems something might be going wrong in your operator construction. If the operator contains Pauli terms with complex coefficients, exponentiating it would not provide a unitary operation, which is why the code is raising an error. You can also double check this by computing the matrix representation of your operator, which should be hermitian but is not:

>>> h = H.to_matrix()
>>> np.allclose(np.conj(h.T), h)
False  # should be True, such that the exponential will be unitary
afrah commented 1 year ago

Yes I symmetrizd the matrix using B = [[0 A],[A' 0]] with bb = [0 b ]and it works. Thank you.