Using QubitPlaceholders

In PyQuil, we typically use integers to identify qubits


In [1]:
from pyquil.quil import Program
from pyquil.gates import CNOT, H
print(Program(H(0), CNOT(0, 1)))


H 0
CNOT 0 1

However, when running on real, near-term QPUs we care about what particular physical qubits our program will run on. In fact, we may want to run the same program on an assortment of different qubits. This is where using QubitPlaceholders comes in.


In [2]:
from pyquil.quilatom import QubitPlaceholder
q0 = QubitPlaceholder()
q1 = QubitPlaceholder()
prog = Program(H(q0), CNOT(q0, q1))
print(prog)


H {q4402789176}
CNOT {q4402789176} {q4402789120}

If you try to use this program directly, it will not work


In [3]:
print(prog.out())


---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-3-da474d3af403> in <module>()
----> 1 print(prog.out())

~/sources/pyquil/pyquil/quil.py in out(self)
    380             (dg.out() for dg in self._defined_gates),
    381             (instr.out() for instr in self.instructions),
--> 382             [''],
    383         ))
    384 

~/sources/pyquil/pyquil/quil.py in <genexpr>(.0)
    379         return '\n'.join(itertools.chain(
    380             (dg.out() for dg in self._defined_gates),
--> 381             (instr.out() for instr in self.instructions),
    382             [''],
    383         ))

~/sources/pyquil/pyquil/quilbase.py in out(self)
    109                                     _format_qubits_out(self.qubits))
    110         else:
--> 111             return "{} {}".format(self.name, _format_qubits_out(self.qubits))
    112 
    113     def __repr__(self):

~/sources/pyquil/pyquil/quilbase.py in _format_qubits_out(qubits)
     69 
     70 def _format_qubits_out(qubits):
---> 71     return " ".join([qubit.out() for qubit in qubits])
     72 
     73 

~/sources/pyquil/pyquil/quilbase.py in <listcomp>(.0)
     69 
     70 def _format_qubits_out(qubits):
---> 71     return " ".join([qubit.out() for qubit in qubits])
     72 
     73 

~/sources/pyquil/pyquil/quilatom.py in out(self)
     53 class QubitPlaceholder(QuilAtom):
     54     def out(self):
---> 55         raise RuntimeError("Qubit {} has not been assigned an index".format(self))
     56 
     57     def __str__(self):

RuntimeError: Qubit q4402789176 has not been assigned an index

Instead, you must explicitly map the placeholders to physical qubits. By default, the function address_qubits will address qubits from 0 to N.


In [4]:
from pyquil.quil import address_qubits
print(address_qubits(prog))


H 0
CNOT 0 1

The real power comes into play when you provide an explicit mapping


In [5]:
print(address_qubits(prog, qubit_mapping={
    q0: 14,
    q1: 19,
}))


H 14
CNOT 14 19

Register

Usually, your algorithm will use an assortment of qubits. You can use the convenience function QubitPlaceholder.register() to request a list of qubits to build your program.


In [6]:
qbyte = QubitPlaceholder.register(8)
prog2 = Program(H(q) for q in qbyte)
print(address_qubits(prog2, {q: i*2 for i, q in enumerate(qbyte)}))


H 0
H 2
H 4
H 6
H 8
H 10
H 12
H 14