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.23k stars 2.36k forks source link

Qubit mapping error using measurement error mitigation #7581

Open cpossel opened 3 years ago

cpossel commented 3 years ago

Information

What is the current behavior?

Raises an error when using measurement error mitigation for ground state energy calculation of LiH:

Traceback (most recent call last):
  File ".\minimal_example_for_error_reproduction_LiH.py", line 82, in <module>
    result = algorithm.compute_minimum_eigenvalue(qubit_op)
  File "C:\Users\poc\Anaconda3\envs\qiskit-0-29-1\lib\site-packages\qiskit\algorithms\minimum_eigen_solvers\vqe.py", line 490, in compute_minimum_eigenvalue
    opt_params, opt_value, nfev = self.optimizer.optimize(
  File "C:\Users\poc\Anaconda3\envs\qiskit-0-29-1\lib\site-packages\qiskit\algorithms\optimizers\scipy_optimizer.py", line 140, in optimize
    res = minimize(
  File "C:\Users\poc\Anaconda3\envs\qiskit-0-29-1\lib\site-packages\scipy\optimize\_minimize.py", line 623, in minimize
    return _minimize_lbfgsb(fun, x0, args, jac, bounds,
  File "C:\Users\poc\Anaconda3\envs\qiskit-0-29-1\lib\site-packages\scipy\optimize\lbfgsb.py", line 306, in _minimize_lbfgsb
    sf = _prepare_scalar_function(fun, x0, jac=jac, args=args, epsilon=eps,
  File "C:\Users\poc\Anaconda3\envs\qiskit-0-29-1\lib\site-packages\scipy\optimize\optimize.py", line 261, in _prepare_scalar_function
    sf = ScalarFunction(fun, x0, args, grad, hess,
  File "C:\Users\poc\Anaconda3\envs\qiskit-0-29-1\lib\site-packages\scipy\optimize\_differentiable_functions.py", line 140, in __init__
    self._update_fun()
  File "C:\Users\poc\Anaconda3\envs\qiskit-0-29-1\lib\site-packages\scipy\optimize\_differentiable_functions.py", line 233, in _update_fun
    self._update_fun_impl()
  File "C:\Users\poc\Anaconda3\envs\qiskit-0-29-1\lib\site-packages\scipy\optimize\_differentiable_functions.py", line 137, in update_fun
    self.f = fun_wrapped(self.x)
  File "C:\Users\poc\Anaconda3\envs\qiskit-0-29-1\lib\site-packages\scipy\optimize\_differentiable_functions.py", line 134, in fun_wrapped
    return fun(np.copy(x), *args)
  File "C:\Users\poc\Anaconda3\envs\qiskit-0-29-1\lib\site-packages\qiskit\algorithms\minimum_eigen_solvers\vqe.py", line 562, in energy_evaluation
    sampled_expect_op = self._circuit_sampler.convert(expect_op, params=param_bindings)
  File "C:\Users\poc\Anaconda3\envs\qiskit-0-29-1\lib\site-packages\qiskit\opflow\converters\circuit_sampler.py", line 218, in convert
    sampled_statefn_dicts = self.sample_circuits(circuit_sfns=circs, param_bindings=p_b)
  File "C:\Users\poc\Anaconda3\envs\qiskit-0-29-1\lib\site-packages\qiskit\opflow\converters\circuit_sampler.py", line 329, in sample_circuits
    results = self.quantum_instance.execute(
  File "C:\Users\poc\Anaconda3\envs\qiskit-0-29-1\lib\site-packages\qiskit\utils\quantum_instance.py", line 429, in execute
    get_measured_qubits(circuits)
  File "C:\Users\poc\Anaconda3\envs\qiskit-0-29-1\lib\site-packages\qiskit\utils\measurement_error_mitigation.py", line 62, in get_measured_qubits
    raise QiskitError(
qiskit.exceptions.QiskitError: 'The used qubit index are different. ([8, 14, 13, 12, 10, 7, 4, 3, 2, 1]) vs ([8, 11, 14, 13, 12, 10, 0, 1, 7, 4]).\nCurrently, we only support all circuits using the same set of qubits regardless qubit order.'

Steps to reproduce the problem

Run below minimal example (adjusted from the example code in the qiskit-nature README.md). When changing the molecule definition from LiH back to H2, everything runs fine.

from qiskit.utils.quantum_instance import QuantumInstance
from qiskit_nature.drivers import Molecule
from qiskit_nature.drivers.second_quantization import (
    ElectronicStructureDriverType,
    ElectronicStructureMoleculeDriver,
    MethodType,
)
from qiskit_nature.problems.second_quantization.electronic import ElectronicStructureProblem
from qiskit.ignis.mitigation.measurement import CompleteMeasFitter
from qiskit.test.mock import FakeToronto
from qiskit.providers.aer import AerSimulator
from qiskit.algorithms import VQE

molecule = Molecule(
    geometry=[
        ["Li", [0.0, 0.0, 0.0]],
        ["H", [0.0, 0.0, 1.625]],
    ],
    charge=0,
    multiplicity=1,
)
driver = ElectronicStructureMoleculeDriver(
    molecule=molecule,
    basis="sto3g",
    method=MethodType.RHF,
    driver_type=ElectronicStructureDriverType.AUTO,  # tried both with pyquante and psi4
)
problem = ElectronicStructureProblem(driver)

# generate the second-quantized operators
second_q_ops = problem.second_q_ops()
main_op = second_q_ops[0]

particle_number = problem.grouped_property_transformed.get_property("ParticleNumber")

num_particles = (particle_number.num_alpha, particle_number.num_beta)
num_spin_orbitals = particle_number.num_spin_orbitals

# setup the classical optimizer for VQE
from qiskit.algorithms.optimizers import L_BFGS_B

optimizer = L_BFGS_B(maxiter=10)

from qiskit_nature.converters.second_quantization import QubitConverter

# setup the mapper and qubit converter
from qiskit_nature.mappers.second_quantization import ParityMapper

mapper = ParityMapper()
converter = QubitConverter(mapper=mapper, two_qubit_reduction=True)

# map to qubit operators
qubit_op = converter.convert(main_op, num_particles=num_particles)

# setup the initial state for the ansatz
from qiskit_nature.circuit.library import HartreeFock

init_state = HartreeFock(num_spin_orbitals, num_particles, converter)

# setup the ansatz for VQE
from qiskit.circuit.library import TwoLocal

ansatz = TwoLocal(num_spin_orbitals, ["ry", "rz"], "cz")

# add the initial state
ansatz.compose(init_state, front=True, inplace=True)

# set the backend for the quantum computation
backend = AerSimulator.from_backend(FakeToronto())

# setup and run VQE
measurement_error_mitigation_cls = CompleteMeasFitter
quantum_instance = QuantumInstance(
    shots=10, backend=backend, measurement_error_mitigation_cls=measurement_error_mitigation_cls
)

algorithm = VQE(ansatz, optimizer=optimizer, quantum_instance=quantum_instance)

result = algorithm.compute_minimum_eigenvalue(qubit_op)
print(result.eigenvalue.real)

electronic_structure_result = problem.interpret(result)
print(electronic_structure_result)

What is the expected behavior?

Automatically choosing the same qubits for measurement error mitigation run and production run in order to get the ground state energy output.

Suggested solutions

Share the list of used qubits between VQE solver and measurement_error_mitigation fitter. Or give the user some kind of (documented) interface to pass the list of used qubits. Note: Usually I use the BOPESSampler for calculations, i.e. the basic circuits and their mapping aren't easily available to pass to the mitigation code by hand. So, some automated way would be preferable.

cpossel commented 3 years ago

It seems the measurement error mitigation code is part of qiskit ignis, but I don't know where in the code with all the qiskit-nature stuff the adjustments must be made. So, I'd be thankful if you moved it to qiskit ignis if you think it belongs there.

cpossel commented 3 years ago

I just found a similar(/the same?) issue at qiskit-terra/issues/5730. So, should this issue be closed here in favor of the one in qiskit-terra?

mrossinek commented 2 years ago

I just verified that this issue still occurs with the CompleteMeasFitter class being migrated to Terra: qiskit.utils.mitigation.CompleteMeasFitter.

I will attempt to transfer this issue to Terra because this is not Nature-related.

EDIT: I do not have the permissions for such a transfer. @woodsp-ibm @manoelmarques @dlasecki can anyone of you do that?

1ucian0 commented 2 years ago

moved from qiskit-nature as per @mrossinek request.