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
5.04k stars 2.32k forks source link

It seems that CircuitStateFn will automatically optimize the circuit #7058

Closed AlaricCheng closed 1 year ago

AlaricCheng commented 2 years ago

Context

I'm trying to use qiskit for noisy simulation. Since I want to specify the location of the noise, I choose to add an identity gate to the place I want to add noise, and then set the identity gates to be noisy. Below is an example,

from qiskit import QuantumCircuit, Aer
import qiskit.providers.aer.noise as noise

# define noise model
error_gate1 = noise.pauli_error([("Z", 0.4), ("I", 0.6)]) # single-qubit error
noise_phase = noise.NoiseModel()
noise_phase.add_all_qubit_quantum_error(error_gate1, ["id"])

# define the circuit
circ = QuantumCircuit(1)
circ.h(0)
circ.id(0)

Readon why I want to do this

I want to do this because I want all single-qubit gates (more specifically, single-qubit Clifford gate) to have the same error rate. If I specify the noisy gate set to be something like ["h", "s", "x", "y", "z"], then the gate that is decomposed into longer sequence will be more noisy.

Problem

If I use the following script to get the expectation value:

backend = Aer.get_backend("aer_simulator")
q_instance = QuantumInstance(backend = backend, noise_model = noise_phase, optimization_level = 0)

psi = CircuitStateFn(circ) # convert to state function

# define the state to sample
measurable_expression = StateFn(X, is_measurement = True).compose(psi)

# convert to expectation value
expectation = PauliExpectation().convert(measurable_expression) # this will alter the circuit

# get state sampler (you can also pass the backend directly)
sampler = CircuitSampler(q_instance).convert(expectation)

print(sampler.eval().real) 

the result will be 1, the ideal value. And the reason is that psi = CircuitStateFn(circ) will delete the identity gate even if I set the optimization_level to 0 when defining q_instance. This can be verified with print(psi). Since the identity gate disappears, there is no noisy instruction and the expectation becomes 1.

What is the expected enhancement?

To be more flexible, I think there should be an optimization_level option in the CircuitStateFn to let users to set up. Or just do not optimize the circuit since this option is specified by the QuantumInstance.

Why I don't use save_expectation_value

I do realize that a more direct way is to use circ.save_expectation_value(X, circ.qubits). But when X is replaced with some more complicated operator (like PauliSumOp) and when the number of qubits scale up, this step takes much time. After checking the source code, I found the reason might be that in operator.py, it will first convert the operator to a matrix with the to_matrix() method, even if I want to use the stabilizer simulator. So it seems that the CircuitSampler approach is more reasonable. Or maybe there are other ways to get the expectation values in qiskit?

woodsp-ibm commented 2 years ago

Indeed the CircuitStateFn has logic to remove Identity gates. https://github.com/Qiskit/qiskit-terra/blob/7c8815390b1a79e76e040fbdd2b130d8b6e7d41f/qiskit/opflow/state_fns/circuit_state_fn.py#L367-L380 I know this reduce method is called when doing a string conversion. I imagine that in your flow above that this reduce method ends up getting called via another path.

Or maybe there are other ways to get the expectation values in qiskit?

This is something that is being looked at presently. #6451 was created a while back and there is work in progress now on this. FYI @t-imamichi @ikkoham

ikkoham commented 2 years ago

The problem is that we cannot simulate noise because the noise is defined in the identity gate and the identity gate disappears in the computation process of expval. it is difficult to solve this problem because of the design philosophy of Opflow. Opflow is a high-level framework.

In the near future, you can add QuantumError instructions directly to the QuantumCircuit. https://github.com/Qiskit/qiskit-aer/pull/1350

work-around: you can define a different instruction to insert noise.

AlaricCheng commented 2 years ago

Adding QuantumError directly to the QuantumCircuit would be cool!

woodsp-ibm commented 1 year ago

Opflow is now deprecated soon to be removed. New features/enhancements are no longer a consideration.