Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error for when passing folded circuit to calculate expectation value in qiskit #1150

Closed
anhdpham opened this issue Mar 1, 2022 · 8 comments
Labels
bug Something isn't working priority/mid Should be fixed by the next 1-2 milestones.

Comments

@anhdpham
Copy link

anhdpham commented Mar 1, 2022

I think there is a problem with passing a folded circuit generated by mitiq to the expectation value routine used to calculate in mitiq

def ansatz(parameter):
circuit = QuantumCircuit(2)
circuit.rx(parameter[0],0)
circuit.cnot(0,1)
circuit.rx(parameter[0],1)
circuit.cnot(0,1)
circuit.rx(parameter[0],0)
return circuit

angles = []
for angle in np.linspace(0, 2 * np.pi, 50):
angles.append(angle)

circuits = []
for angle in angles:
circuits.append(ansatz([angle]))

def qiskit_executor(circuit: qiskit.QuantumCircuit, shots: int = 8192) -> float:
quantum_instance = QuantumInstance(backend=Aer.get_backend('qasm_simulator'),noise_model = noise_model,
basis_gates = noise_model.basis_gates, shots=10000)
psi = CircuitStateFn(circuit)
measurable_expression = StateFn(Hamiltonian, is_measurement=True).compose(psi)
expectation = PauliExpectation().convert(measurable_expression)
sampler = CircuitSampler(quantum_instance).convert(expectation)
value = sampler.eval().real
return value

scale_factors = [1., 1.5, 2., 2.5, 3.]
folded_circuits = [
zne.scaling.fold_gates_at_random(circuits[0], scale)
for scale in scale_factors
]

qiskit_executor(folded_circuits[0])

Error:

ValueError Traceback (most recent call last)
/tmp/ipykernel_300/1422248828.py in
----> 1 qiskit_executor(folded_circuits[0])

/tmp/ipykernel_300/1414635650.py in qiskit_executor(circuit, shots)
4 # ansatz_value = ansatz.bind_parameters({theta: val for val in theta_val})
5 psi = CircuitStateFn(circuit)
----> 6 measurable_expression = StateFn(Hamiltonian, is_measurement=True).compose(psi)
7 expectation = PauliExpectation().convert(measurable_expression)
8 sampler = CircuitSampler(quantum_instance).convert(expectation)

~/anaconda3/envs/IBM_qiskit/lib/python3.9/site-packages/qiskit/opflow/state_fns/state_fn.py in compose(self, other, permutation, front)
308 )
309
--> 310 new_self, other = self._expand_shorter_operator_and_permute(other, permutation)
311
312 if front:

~/anaconda3/envs/IBM_qiskit/lib/python3.9/site-packages/qiskit/opflow/state_fns/state_fn.py in _expand_shorter_operator_and_permute(self, other, permutation)
263 return self, StateFn("0" * self.num_qubits)
264
--> 265 return super()._expand_shorter_operator_and_permute(other, permutation)
266
267 def to_matrix(self, massive: bool = False) -> np.ndarray:

~/anaconda3/envs/IBM_qiskit/lib/python3.9/site-packages/qiskit/opflow/operator_base.py in _expand_shorter_operator_and_permute(self, other, permutation)
436 other = Zero.class("0" * self.num_qubits)
437 elif other.num_qubits < self.num_qubits:
--> 438 other = other._expand_dim(self.num_qubits - other.num_qubits)
439 elif other.num_qubits > self.num_qubits:
440 new_self = self._expand_dim(other.num_qubits - self.num_qubits)

~/anaconda3/envs/IBM_qiskit/lib/python3.9/site-packages/qiskit/opflow/state_fns/circuit_state_fn.py in _expand_dim(self, num_qubits)
383 # this is equivalent to self.tensor(identity_operator), but optimized for better performance
384 # just like in tensor method, qiskit endianness is reversed here
--> 385 return self.permute(list(range(num_qubits, num_qubits + self.num_qubits)))
386
387 def permute(self, permutation: List[int]) -> "CircuitStateFn":

~/anaconda3/envs/IBM_qiskit/lib/python3.9/site-packages/qiskit/opflow/state_fns/circuit_state_fn.py in permute(self, permutation)
396 A new CircuitStateFn containing the permuted circuit.
397 """
--> 398 new_qc = QuantumCircuit(max(permutation) + 1).compose(self.primitive, qubits=permutation)
399 return CircuitStateFn(new_qc, coeff=self.coeff, is_measurement=self.is_measurement)

ValueError: max() arg is an empty sequence

It works fine if i pass a circuit created by QuantumCircuit in qiskit.

@github-actions
Copy link

github-actions bot commented Mar 1, 2022

Hello @anhdpham, thank you for your interest in Mitiq!
If this is a bug report, please provide screenshots and/or minimum viable code to reproduce your issue, so we can do our best to help get it fixed. If you have any questions in the meantime, you can also ask us on the Unitary Fund Discord.

@andreamari andreamari added bug Something isn't working Qiskit priority/mid Should be fixed by the next 1-2 milestones. labels Mar 2, 2022
@andreamari
Copy link
Member

Thanks @anhdpham for reporting this!
It seems a Mitiq bug but we need to investigate more to understand the problem.

@nathanshammah
Copy link
Member

@anhdpham thanks for opening this and the other issue. If it could help clarify them, you're welcome to join the Mitiq community call on Unitary Fund's Discord, which is on Fridays at 18:00 CET (https://discord.com/invite/JqVGmpkP96).

@Aaron-Robertson
Copy link
Contributor

Aaron-Robertson commented Mar 28, 2022

Hi @anhdpham, could you provide more details on your Hamiltonian, noise_model, and installed packages? Can use the mitiq.about() function to retrieve the installed dependencies.

I attempted to reproduce this error but was unable to with my interpretation of the provided code (plus a few fast/unchecked assumptions from tutorials), to yield ~-1.063038113954:

from qiskit.utils import QuantumInstance
from qiskit.opflow import I, X, Y, Z, CircuitStateFn, StateFn, CircuitSampler, PauliExpectation
from qiskit.providers.aer.noise.errors.standard_errors import coherent_unitary_error
from qiskit.providers.aer.noise import NoiseModel
import qiskit.quantum_info as qi
import numpy as np
from mitiq import zne

def ansatz(parameter):
    circuit = QuantumCircuit(2)
    circuit.rx(parameter[0],0)
    circuit.cnot(0,1)
    circuit.rx(parameter[0],1)
    circuit.cnot(0,1)
    circuit.rx(parameter[0],0)
    return circuit

epsilon = 0.1

err_h = QuantumCircuit(1, 1)
err_h.h(0)
err_h.p(epsilon, 0)
err_h.h(0)
err_h.p(-epsilon, 0)

u_err_h = qi.Operator(err_h)

noise_model = NoiseModel()
noise_model.add_all_qubit_quantum_error(coherent_unitary_error(u_err_h), 'h')

angles = []
for angle in np.linspace(0, 2 * np.pi, 50):
    angles.append(angle)

circuits = []
for angle in angles:
    circuits.append(ansatz([angle]))

Hamiltonian = (-1.0523732 * I^I) + \
              (0.39793742 * I^Z) + \
              (-0.3979374 * Z^I) + \
              (-0.0112801 * Z^Z) + \
              (0.18093119 * X^X)

def qiskit_executor(circuit: QuantumCircuit, shots: int = 8192) -> float:
    quantum_instance = QuantumInstance(
        backend=Aer.get_backend('qasm_simulator'),
        noise_model = noise_model,
        basis_gates = noise_model.basis_gates, shots=10000
    )
    psi = CircuitStateFn(circuit)
    measurable_expression = StateFn(Hamiltonian, is_measurement=True).compose(psi)
    expectation = PauliExpectation().convert(measurable_expression)
    sampler = CircuitSampler(quantum_instance).convert(expectation)
    value = sampler.eval().real
    return value

scale_factors = [1., 1.5, 2., 2.5, 3.]
folded_circuits = [
    zne.scaling.fold_gates_at_random(circuits[0], scale)
    for scale in scale_factors
]

qiskit_executor(folded_circuits[0])

@anhdpham
Copy link
Author

Hi @Aaron-Robertson. My dependancies from !pip list:

Package Version


anyio 2.2.0
appnope 0.1.2
argon2-cffi 20.1.0
async-generator 1.10
attrs 21.4.0
Babel 2.9.1
backcall 0.2.0
bleach 4.1.0
brotlipy 0.7.0
cachetools 4.2.4
certifi 2021.10.8
cffi 1.15.0
charset-normalizer 2.0.10
cirq 0.10.0
cryptography 36.0.1
cycler 0.11.0
debugpy 1.5.1
decorator 4.4.2
defusedxml 0.7.1
dill 0.3.4
docplex 2.22.213
entrypoints 0.3
fonttools 4.28.5
google-api-core 1.31.5
google-auth 1.35.0
googleapis-common-protos 1.54.0
graphviz 0.19.1
grpcio 1.43.0
gurobipy 9.5.0
h5py 3.6.0
ibm-quantum-widgets 1.0.3
idna 3.3
importlib-metadata 4.8.2
ipykernel 6.4.1
ipython 7.29.0
ipython-genutils 0.2.0
ipywidgets 7.6.5
jedi 0.18.0
Jinja2 2.11.3
joblib 1.1.0
json5 0.9.6
jsonschema 3.2.0
jupyter-client 7.1.0
jupyter-core 4.9.1
jupyter-server 1.4.1
jupyterlab 3.2.1
jupyterlab-pygments 0.1.2
jupyterlab-server 2.10.2
jupyterlab-widgets 1.0.2
kiwisolver 1.3.2
lark-parser 0.12.0
MarkupSafe 2.0.1
matplotlib 3.5.1
matplotlib-inline 0.1.2
mistune 0.8.4
mitiq 0.12.0
mpmath 1.2.1
nbclassic 0.2.6
nbclient 0.5.3
nbconvert 6.3.0
nbformat 5.1.3
nest-asyncio 1.5.1
networkx 2.5.1
notebook 6.4.6
ntlm-auth 1.5.0
numpy 1.22.2
packaging 21.3
pandas 1.3.5
pandocfilters 1.4.3
parso 0.8.3
pbr 5.8.0
pexpect 4.8.0
pickleshare 0.7.5
Pillow 9.0.0
pip 21.2.4
ply 3.11
prometheus-client 0.12.0
prompt-toolkit 3.0.20
protobuf 3.13.0
psutil 5.9.0
ptyprocess 0.7.0
pyasn1 0.4.8
pyasn1-modules 0.2.8
pycparser 2.21
Pygments 2.10.0
pylatexenc 2.10
pyOpenSSL 21.0.0
pyparsing 3.0.4
pyrsistent 0.18.0
pyscf 2.0.1
PySocks 1.7.1
python-constraint 1.4.0
python-dateutil 2.8.2
pytket 0.19.0
pytket-qiskit 0.22.0
pytz 2021.3
pyzmq 22.3.0
qiskit 0.34.1
qiskit-aer 0.10.2
qiskit-ibmq-provider 0.18.3
qiskit-ignis 0.7.0
qiskit-ionq 0.1.4
qiskit-nature 0.3.0
qiskit-optimization 0.3.0
qiskit-terra 0.19.1
requests 2.27.1
requests-ntlm 1.1.0
retworkx 0.11.0
rsa 4.8
scikit-learn 1.0.2
scipy 1.7.3
seaborn 0.11.2
Send2Trash 1.8.0
setuptools 58.0.4
six 1.16.0
sniffio 1.2.0
sortedcontainers 2.4.0
stevedore 3.5.0
symengine 0.8.1
sympy 1.9
terminado 0.9.4
testpath 0.5.0
threadpoolctl 3.0.0
tornado 6.1
tqdm 4.62.3
traitlets 5.1.1
tweedledum 1.1.1
types-Jinja2 2.11.9
types-MarkupSafe 1.1.10
types-pkg-resources 0.1.3
typing-extensions 3.10.0.2
urllib3 1.26.8
wcwidth 0.2.5
webencodings 0.5.1
websocket-client 1.2.3
wheel 0.37.1
widgetsnbextension 3.5.2
zipp 3.7.0

Here is my code that created the error in the last line when trying to evaluate the expectation value of the folded circuit using qiskit.

import pylab
import qiskit
import numpy as np
from qiskit import Aer, BasicAer
from qiskit.compiler import transpile
from qiskit.opflow import X, Z, I, Y, StateFn, CircuitStateFn, SummedOp, PauliExpectation, CircuitSampler
from qiskit.quantum_info.operators import Operator, Pauli
from qiskit.utils import QuantumInstance, algorithm_globals
from qiskit.algorithms import VQE, NumPyMinimumEigensolver
from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit
from qiskit.algorithms.optimizers import COBYLA, L_BFGS_B, SLSQP
from qiskit.circuit.library import TwoLocal
from mitiq.interface.mitiq_qiskit.qiskit_utils import initialized_depolarizing_noise
from qiskit.circuit import Parameter
from mitiq.zne import mitigate_executor
from mitiq.zne.inference import RichardsonFactory
from mitiq import zne
from mitiq.zne.scaling.folding import fold_gates_from_left, fold_gates_from_right
from scipy.optimize import minimize, minimize_scalar

H2_op = (-1.052373245772859 * I ^ I) + (0.39793742484318045 * I ^ Z) + (-0.39793742484318045 * Z ^ I) +
(-0.01128010425623538 * Z ^ Z) + (0.18093119978423156 * X ^ X)

def trial_circuit(parameter):
circuit=QuantumCircuit(2)
circuit.ry(parameter[0],0)
circuit.ry(parameter[1],1)
circuit.cz(0,1)
circuit.ry(parameter[2],0)
circuit.ry(parameter[3],1)
return circuit

scale_factors = [1., 1.5, 2., 2.5, 3.]
folded_circuits = [
zne.scaling.fold_gates_at_random(trial_circuit([0,0,0,0]), scale)
for scale in scale_factors
]

def qiskit_executor_no_noise(circuit: qiskit.QuantumCircuit, shots: int = 8192) -> float:
quantum_instance = QuantumInstance(backend=Aer.get_backend('qasm_simulator'), shots=20000)
psi = CircuitStateFn(circuit)
value_list = []
for i in range(0,len(H2_op),1):
measurable_expression = StateFn(H2_op[i], is_measurement=True).compose(psi)
expectation = PauliExpectation().convert(measurable_expression)
sampler = CircuitSampler(quantum_instance).convert(expectation)
value = sampler.eval().real
value_list.append(value)
return value_list

qiskit_executor_no_noise(trial_circuit([0,0,0,0]))

qiskit_executor_no_noise(folded_circuits[0])

@Aaron-Robertson
Copy link
Contributor

Aaron-Robertson commented Mar 28, 2022

@anhdpham I see! I reproduced the error with qiskit>=0.34. Official mitiq support (currently) is qiskit~=0.32.1, and your code block passes when using that version (and latest mitiq==0.13). We strive to support the latest frontend versions, and I'll make sure that version support is better documented, but in the meantime you may want to try an older release.

@anhdpham
Copy link
Author

@Aaron-Robertson Thanks. Will retest the program using a qiskit=0.32.1

@Aaron-Robertson
Copy link
Contributor

Closing with documentation issue noted in #1201

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working priority/mid Should be fixed by the next 1-2 milestones.
Projects
None yet
Development

No branches or pull requests

4 participants