ProjectQ-Framework / ProjectQ

ProjectQ: An open source software framework for quantum computing
https://projectq.ch
Apache License 2.0
888 stars 274 forks source link

StatePreparation causes "Circuit cannot be mapped without using Swaps" on IBM #279

Closed cgogolin closed 5 years ago

cgogolin commented 6 years ago

Consider the following rather simple program:

import projectq as pq
from projectq.ops import All, X, StatePreparation, Measure
from projectq import MainEngine
import projectq.setups.ibm as ibm_setup

backend = pq.backends.IBMBackend(user='XXX', password='XXX')
eng = MainEngine(backend, engine_list=ibm_setup.get_engine_list())

qureg = eng.allocate_qureg(4)
StatePreparation([0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) | qureg
All(Measure) | qureg
eng.flush()

which should be realizable by an application of X operations to some of the qubits.

On the IBM backend, it results in the following error:

RuntimeError: Circuit cannot be mapped without using Swaps. Mapping failed.
 raised in:
'  File "/home/cgogolin/.local/lib/python3.5/site-packages/projectq/cengines/_ibm5qubitmapper.py", line 137, in _run'
'    raise RuntimeError("Circuit cannot be mapped without using "'

The same happens for any other StatePreparation of basis state, including the trivial one, which shouldn't do anything. On up to three qubits all basis state preparations work flawlessly.

After changing to the simulator by putting

backend = pq.backends.Simulator()
eng = MainEngine(backend)

instead of the corresponding lines in the code above, everything also works on four qubits.

damiansteiger commented 6 years ago

ProjectQ's compiler for the 5 qubit IBM chip does not perform any Swap gates. So if it cannot find a way to run a circuit without Swap gates, this error message appears (as e.g. also in see #276).

Possible solution:

As you have noticed, StatePreparation does the correct operations if you run it with a simulator but it requires in your case too many operations. There is currently only one decomposition rule for it, which is fairly efficient to prepare general states. So far it has been used for chemistry simulations. For basis states, either directly use X gates or write a second decomposition rules for StatePreparation which only works for, e.g., basis states using just X gates. In that case the compiler can automatically choose the rule with lower gate count depending on the input state.

cgogolin commented 5 years ago

Thanks. In the end I implemented my own BasisState() operation that applies appropriate XGate()s in its __or__() method. The relevant part looks essentially like this:

class BasisState(SelfInverseGate):
    def __init__(self, basis_state_to_prep):
        self.basis_state_to_prep = basis_state_to_prep

    def __or__(self, qubits):
        for i,qureg in enumerate(qubits):
            if self.basis_state_to_prep[i] == 1:
                pq.ops.XGate() | qureg

    def __eq__(self, other):
        if isinstance(other, self.__class__):
            return self.basis_state_to_prep == other.basis_state_to_prep
        else:
            return False

If you want, feel free to include such a convenience gate in ProjectQ.

cgogolin commented 5 years ago

I am closing this as #289 will provide an easy way to do what I was trying to achieve here.