Example #1
0
    def __init__(
        self,
        outfile=None,
        one_qubit_gate_map=None,
        two_qubit_gate_map=None,
        native_gates=None,
    ):
        BasicEngine.__init__(self)
        if native_gates is None:
            from qscout.v1.std import NATIVE_GATES

            native_gates = NATIVE_GATES
        self._circuit = CircuitBuilder(native_gates=native_gates)
        self._q = self._circuit.register("q", 0)
        self._block = UnscheduledBlockBuilder()
        self._circuit.expression.append(self._block.expression)
        self._block.gate("prepare_all")
        self.measure_accumulator = set()
        self.reset_accumulator = set()
        self.outfile = outfile
        if one_qubit_gate_map is None:
            self.one_qubit_gates = one_qubit_gates
        else:
            self.one_qubit_gates = one_qubit_gate_map
        if two_qubit_gate_map is None:
            self.two_qubit_gates = two_qubit_gates
        else:
            self.two_qubit_gates = two_qubit_gate_map
Example #2
0
 def test_2_ion_compilation(self):
     p = Program()
     ro = p.declare("ro", "BIT", 6)
     p += X(0)
     p += MEASURE(0, ro[0])
     p += MEASURE(1, ro[1])
     p += RESET(0)
     p += RESET(1)
     p += X(1)
     p += MEASURE(1, ro[3])
     p += MEASURE(0, ro[2])
     p += RESET()
     p += X(0)
     p += MEASURE(0, ro[4])
     p += MEASURE(1, ro[5])
     qc = get_ion_qc(2)
     circ = qc.compile(p)
     jcirc = CircuitBuilder()
     reg = jcirc.register("qreg", 2)
     block = jcirc.block()
     block.gate("prepare_all")
     block.gate("Px", reg[0])
     block.gate("measure_all")
     block.gate("prepare_all")
     block.gate("Px", reg[1])
     block.gate("measure_all")
     block.gate("prepare_all")
     block.gate("Px", reg[0])
     block.gate("measure_all")
     self.assertEqual(generate_jaqal_program(jcirc.build()),
                      generate_jaqal_program(circ))
 def test_transpile_2q_circuit(self):
     qr = QuantumRegister(2)
     cr = ClassicalRegister(4)
     circ = QuantumCircuit(qr, cr)
     circ.x(qr[0])
     circ.measure(qr[0], cr[0])
     circ.measure(qr[1], cr[1])
     circ.barrier()
     circ.reset(qr[0])
     circ.reset(qr[1])
     circ.barrier()
     circ.y(qr[0])
     dag = circuit_to_dag(circ)
     jcirc = CircuitBuilder()
     reg1 = jcirc.register("baseregister", 2)
     reg2 = jcirc.map(qr.name, reg1, slice(0, 2, 1))
     block = jcirc.block()
     block.gate("prepare_all")
     block.gate("Px", reg2[0])
     block.gate("measure_all")
     block = jcirc.block()
     block.gate("prepare_all")
     block = jcirc.block()
     block.gate("Py", reg2[0])
     block.gate("measure_all")
     self.assertEqual(
         generate_jaqal_program(jcirc.build()),
         generate_jaqal_program(jaqal_circuit_from_dag_circuit(dag)),
     )
Example #4
0
 def test_native_gates(self):
     gates = quil_gates()
     p = Program()
     ro = p.declare("ro", "BIT", 1)
     p += gates["SX"](0)
     p += MEASURE(0, ro[0])
     qc = get_ion_qc(1)
     circ = qc.compile(p)
     jcirc = CircuitBuilder()
     reg = jcirc.register("qreg", 1)
     block = jcirc.block()
     block.gate("prepare_all")
     block.gate("Sx", reg[0])
     block.gate("measure_all")
     self.assertEqual(generate_jaqal_program(jcirc.build()),
                      generate_jaqal_program(circ))
 def test_transpile_1q_circuit(self):
     c = Circuit(1, 1)
     c.Rz(1, 0)
     c.add_barrier([0])
     c.Measure(0, 0)
     qsc = jaqal_circuit_from_tket_circuit(c)
     jcirc = CircuitBuilder()
     reg = jcirc.register("baseregister", 1)
     reg2 = jcirc.map("q", reg, slice(0, 1, 1))
     block = jcirc.block()
     block.gate("prepare_all")
     block.gate("Rz", reg2[0], pi)
     block = jcirc.block()
     block.gate("measure_all")
     self.assertEqual(generate_jaqal_program(jcirc.build()),
                      generate_jaqal_program(qsc))
 def test_transpile_grid_circuit(self):
     c = Circuit()
     qb = pytket._tket.circuit.Qubit("grid", 0, 0)
     c.add_qubit(qb)
     c.Rz(1, qb)
     qsc = jaqal_circuit_from_tket_circuit(c)
     jcirc = CircuitBuilder()
     reg = jcirc.register("baseregister", 1)
     reg2 = jcirc.map("grid0_0", reg, slice(0, 1, 1))
     block = jcirc.block()
     block.gate("prepare_all")
     block.gate("Rz", reg2[0], pi)
     block.gate("measure_all")
     self.assertEqual(generate_jaqal_program(jcirc.build()),
                      generate_jaqal_program(qsc))
 def test_transpile_circuit(self):
     backend = JaqalBackend()
     engine_list = get_engine_list()
     eng = MainEngine(backend, engine_list, verbose=True)
     q1 = eng.allocate_qubit()
     q2 = eng.allocate_qubit()
     SqrtX | q1
     SqrtX | q2
     Barrier | (q1, q2)
     Rxx(1.0) | (q1, q2)
     All(Measure) | [q1, q2]
     eng.flush()
     circ = backend.circuit
     jcirc = CircuitBuilder()
     reg = jcirc.register("q", 2)
     block = jcirc.block()
     block.gate("prepare_all")
     block.gate("Sx", reg[0])
     block.gate("Sx", reg[1])
     block = jcirc.block()
     block.gate("MS", reg[0], reg[1], 0, 1.0)
     block.gate("measure_all")
     self.assertEqual(generate_jaqal_program(jcirc.build()),
                      generate_jaqal_program(circ))
Example #8
0
class JaqalBackend(BasicEngine):
    """
    A ProjectQ backend that converts the input circuit to Jaqal, building a
    :class:`jaqalpup.core.Circuit` object which can be retrieved with the
    :attr:`circuit` property. If an output file is supplied, it also writes the Jaqal
    code to it when the engine is flushed.

    :param str outfile: Optionally specify a path to output Jaqal code to. If omitted,
        the Jaqal program is only available via the :attr:`circuit` property.
    :param one_qubit_gate_map: A dictionary mapping ProjectQ gate classes to
        functions taking as arguments an instance of that class and a
        :class:`jaqalpup.core.NamedQubit` and returning a tuple of arguments for
        :meth:`jaqalpup.core.Circuit.build_gate`. Defaults to a mapping from
        :class:`projectq.ops.Rx`, :class:`projectq.ops.Ry`, :class:`projectq.ops.Rz`,
        :class:`projectq.ops.X`, :class:`projectq.ops.Y`, and :class:`projectq.ops.SqrtX`
        to their QSCOUT counterparts.
    :type one_qubit_gate_map: dict or None
    :param two_qubit_gate_map: A dictionary mapping ProjectQ gate classes to
        functions taking as arguments an instance of that class and two
        :class:`jaqalpup.core.NamedQubit` ojects and returning a tuple of arguments for
        :meth:`jaqalpup.core.Circuit.build_gate`. Defaults to a mapping from
        :class:`projectq.ops.Rxx` and :class:`projectq.ops.Ryy` to QSCOUT's
        Mølmer-Sørenson gate.
    :type two_qubit_gate_map: dict or None
    :param native_gates: The native gate set to target. If None, target the QSCOUT native gates.
    :type native_gates: dict or None
    """
    def __init__(
        self,
        outfile=None,
        one_qubit_gate_map=None,
        two_qubit_gate_map=None,
        native_gates=None,
    ):
        BasicEngine.__init__(self)
        if native_gates is None:
            from qscout.v1.std import NATIVE_GATES

            native_gates = NATIVE_GATES
        self._circuit = CircuitBuilder(native_gates=native_gates)
        self._q = self._circuit.register("q", 0)
        self._block = UnscheduledBlockBuilder()
        self._circuit.expression.append(self._block.expression)
        self._block.gate("prepare_all")
        self.measure_accumulator = set()
        self.reset_accumulator = set()
        self.outfile = outfile
        if one_qubit_gate_map is None:
            self.one_qubit_gates = one_qubit_gates
        else:
            self.one_qubit_gates = one_qubit_gate_map
        if two_qubit_gate_map is None:
            self.two_qubit_gates = two_qubit_gates
        else:
            self.two_qubit_gates = two_qubit_gate_map

    @property
    def circuit(self):
        """
        Allows access to the Jaqal circuit generated by the transpilation process.
        """
        return self._circuit.build()

    def is_available(self, cmd):
        """
        Returns whether Jaqal supports the specified command for transpilation. Any gate
        in the QSCOUT native gate set, as well as measure, allocate, deallocate, and
        barrier statements, are supported. Controlled gates are not supported.
        The :func:`jaqalpaq.transpilers.projectq.get_engine_list` function provides the
        ProjectQ engines that will compile a circuit to this gate basis.

        :param projectq.ops.Command cmd: The command for which to check availability.
        """
        if get_control_count(cmd) > 0:
            return False
        if cmd.gate in self.one_qubit_gates.keys() + self.two_qubit_gates.keys(
        ):
            return True
        if cmd in (Measure, Allocate, Deallocate, Barrier):
            return True
        return False

    def receive(self, command_list):
        """
        Converts each instruction in the input into its Jaqal equivalent and saves it.
        This should rarely be called directly by users; usually it will be called by
        ``projectq.cengines.MainEngine``.

        :param command_list: The ProjectQ program to convert.
        :type command_list: list(projectq.ops.Command)
        """
        for cmd in command_list:
            if cmd.gate == FlushGate():
                if self.outfile is not None:
                    from jaqalpaq.generator import generate_jaqal_program

                    with open(self.outfile, "w+") as f:
                        f.write(generate_jaqal_program(self.circuit))
            else:
                self._store(cmd)

    def _mapped_qubit_id(self, qubit):
        """
        Converts a qubit from a logical to a mapped qubit if there is a mapper.
        """
        mapper = self.main_engine.mapper
        if mapper is not None:
            if qubit.id not in mapper.current_mapping:
                raise RuntimeError("Unknown qubit id. "
                                   "Please make sure you have called "
                                   "eng.flush().")
            return mapper.current_mapping[qubit.id]
        else:
            return qubit.id

    def _store(self, cmd):
        gate = cmd.gate

        if len(self.measure_accumulator) == len(self._q) and len(self._q) > 0:
            self.measure_accumulator = set()
            self._block.gate("prepare_all")

        if gate == Allocate:
            qid = self._mapped_qubit_id(cmd.qubits[0][0])
            self._circuit.stretch_register(qid + 1)

        elif gate == Deallocate:
            pass  # The user might stop caring about the qubit, but we need to keep it around.

        elif gate == Measure:
            qid = self._mapped_qubit_id(cmd.qubits[0][0])
            if qid in self.measure_accumulator:
                raise JaqalError("Can't measure qubit %d twice!" % qid)
            else:
                self.measure_accumulator.add(qid)
                if len(self.measure_accumulator) == len(self._q):
                    self._block.gate("measure_all")

        elif gate == Barrier:
            self._block = UnscheduledBlockBuilder()
            self._circuit.expression.append(self._block.expression)

        elif type(gate) in one_qubit_gates:
            qid = self._mapped_qubit_id(cmd.qubits[0][0])
            if qid in self.measure_accumulator:
                raise JaqalError(
                    "Can't do gates in the middle of measurement!")
            else:
                self._block.gate(
                    *self.one_qubit_gates[type(gate)](gate, self._q[qid]))

        elif type(gate) in two_qubit_gates:
            qids = [self._mapped_qubit_id(qb[0]) for qb in cmd.qubits]
            for qid in qids:
                if qid in self.measure_accumulator:
                    raise JaqalError(
                        "Can't do gates in the middle of measurement!")
            self._block.gate(*self.two_qubit_gates[type(gate)](
                gate, *[self._q[qid] for qid in qids]))

        else:
            raise JaqalError("Unknown instruction! %s" % gate)
Example #9
0
def jaqal_circuit_from_cirq_circuit(ccirc, names=None, native_gates=None):
    """Converts a Cirq Circuit object to a :class:`jaqalpaq.core.Circuit`.
    The circuit will be structured as a sequence of parallel blocks, one for each Cirq
    Moment in the input.

    Measurement are supported, but only if applied to every qubit in the circuit in the
    same moment. If so, they will be mapped to a measure_all gate. If the measure_all gate
    is not the last gate in the circuit, a prepare_all gate will be inserted after it.
    Additionally, a prepare_all gate will be inserted before the first moment. If the
    circuit does not end with a measurement, then a measure_all gate will be appended.

    Circuits built on a line register will map each qubit to the qubit of the same index
    on the hardware. This may leave some qubits unused. Otherwise, the qubits will be
    mapped onto the hardware in the order given by ccirc.all_qubits().

    :param cirq.Circuit ccirc: The Circuit to convert.
    :param names: A mapping from Cirq gate classes to the corresponding native Jaqal gate
        names. If omitted, maps ``cirq.XXPowGate``, ``cirq.XPowGate``, ``cirq.YPowGate``,
        ``cirq.ZPowGate``, and ``cirq.PhasedXPowGate`` to their QSCOUT counterparts. The
        ``cirq.ConvertToIonGates`` function will transpile a circuit into this basis.
    :type names: dict or None
    :param native_gates: The native gate set to target. If None, target the QSCOUT native gates.
    :type native_gates: dict or None
    :returns: The same quantum circuit, converted to JaqalPaq.
    :rtype: Circuit
    :raises JaqalError: If the circuit includes a gate not included in `names`.
    """
    if native_gates is None:
        from qscout.v1.std import NATIVE_GATES

        native_gates = NATIVE_GATES
    builder = CircuitBuilder(native_gates=native_gates)
    if names is None:
        names = CIRQ_NAMES
    try:
        n = 1 + max([qb.x for qb in ccirc.all_qubits()])
        line = True
    except:
        cqubits = ccirc.all_qubits()
        n = len(cqubits)
        qubitmap = {cqubits[i]: i for i in range(n)}
        line = False
    allqubits = builder.register("allqubits", n)
    need_prep = True
    for moment in ccirc:
        if len(moment) == 0:
            continue
        if need_prep:
            builder.gate("prepare_all")
            need_prep = False
        if (
            len(moment) == n
            and all([op.gate for op in moment])
            and all([isinstance(op.gate, MeasurementGate) for op in moment])
        ):
            builder.gate("measure_all")
            need_prep = True
            continue
        if len(moment) > 1:
            block = builder.block(parallel=True)
            # Note: If you tell Cirq you want MS gates in parallel, we'll generate a Jaqal
            # file with exactly that, never mind that QSCOUT can't execute it.
        else:
            block = builder
        for op in moment:
            if op.gate:
                if type(op.gate) in names:
                    if line:
                        targets = [allqubits[qb.x] for qb in op.qubits]
                    else:
                        targets = [allqubits[qubitmap[qb]] for qb in op.qubits]
                    block.gate(*names[type(op.gate)](op.gate, *targets))
                else:
                    raise JaqalError("Convert circuit to ion gates before compiling.")
            else:
                raise JaqalError("Cannot compile operation %s." % op)
    if not need_prep:
        # If we just measured, or the circuit is empty, don't add a final measurement.
        builder.gate("measure_all")
    return builder.build()
Example #10
0
    def native_quil_to_executable(self, nq_program: Program) -> Optional[Circuit]:
        """
        Compiles a Quil program to a :class:`qscout.core.Circuit`. Because Quil
        does not support any form of schedule control, the entire circuit will be put in a
        single unscheduled block. If the :mod:`qscout.scheduler` is run on the circuit, as
        many as possible of those gates will be parallelized, while maintaining the order
        of gates that act on the same qubits. Otherwise, the circuit will be treated as a
        fully sequential circuit.

        Measurement and reset commands are supported, but only if applied to every qubit in
        the circuit in immediate succession. If so, they will be mapped to a prepare_all or
        measure_all gate. If the circuit does not end with a measurement, then a measure_all
        gate will be appended to it.

        :param pyquil.quil.Program nq_program: The program to compile.
        :returns: The same quantum program, converted to JaqalPaq.
        :rtype: qscout.core.Circuit
        :raises JaqalError: If the program includes a non-gate instruction other than resets or measurements.
        :raises JaqalError: If the user tries to measure or reset only some of the qubits, rather than all of them.
        :raises JaqalError: If the program includes a gate not included in `names`.
        """
        n = max(nq_program.get_qubits()) + 1
        if n > len(self._device.qubits()):
            raise JaqalError(
                "Program uses more qubits (%d) than device supports (%d)."
                % (n, len(self._device.qubits()))
            )
        qsc = CircuitBuilder(native_gates=self.native_gates)
        block = UnscheduledBlockBuilder()
        qsc.expression.append(block.expression)
        # Quil doesn't support barriers, so either the user
        # won't run the the scheduler and everything will happen
        # sequentially, or the user will and everything can be
        # rescheduled as needed.
        qreg = qsc.register("qreg", n)
        block.gate("prepare_all")
        reset_accumulator = set()
        measure_accumulator = set()
        in_preamble = True
        for instr in nq_program:
            if reset_accumulator:
                if isinstance(instr, ResetQubit):
                    reset_accumulator.add(instr.qubit.index)
                    if nq_program.get_qubits() <= reset_accumulator:
                        block.gate("prepare_all")
                        reset_accumulator = set()
                        in_preamble = False
                    continue
                else:
                    raise JaqalError(
                        "Cannot reset only qubits %s and not whole register."
                        % reset_accumulator
                    )
                    # reset_accumulator = set()
            if measure_accumulator:
                if isinstance(instr, Measurement):
                    measure_accumulator.add(instr.qubit.index)
                    if nq_program.get_qubits() <= measure_accumulator:
                        block.gate("measure_all")
                        measure_accumulator = set()
                        in_preamble = False
                    continue
                else:
                    raise JaqalError(
                        "Cannot measure only qubits %s and not whole register."
                        % measure_accumulator
                    )
                    # measure_accumulator = set()
            if isinstance(instr, Gate):
                if instr.name in self.names:
                    block.gate(
                        self.names[instr.name],
                        *[qreg[qubit.index] for qubit in instr.qubits],
                        *[float(p) for p in instr.params]
                    )
                    in_preamble = False
                else:
                    raise JaqalError("Gate %s not in native gate set." % instr.name)
            elif isinstance(instr, Reset):
                if not in_preamble:
                    block.gate("prepare_all")
                    in_preamble = False
            elif isinstance(instr, ResetQubit):
                if not in_preamble:
                    reset_accumulator = {instr.qubit.index}
                    if nq_program.get_qubits() <= reset_accumulator:
                        block.gate("prepare_all")
                        reset_accumulator = set()
            elif isinstance(instr, Measurement):
                measure_accumulator = {instr.qubit.index}
                # We ignore the classical register.
                if nq_program.get_qubits() <= measure_accumulator:
                    block.gate("measure_all")
                    measure_accumulator = set()
                    in_preamble = False
            elif isinstance(instr, Declare):
                pass  # Ignore allocations of classical memory.
            else:
                raise JaqalError("Instruction %s not supported." % instr.out())
        block.gate("measure_all", no_duplicate=True)
        return qsc.build()
 def test_transpile_line_circuit(self):
     c = cirq.Circuit()
     qubits = [cirq.LineQubit(0), cirq.LineQubit(1)]
     c.append(cirq.H.on(qubits[0]))
     c.append(cirq.CNOT(*qubits))
     ic = cirq.ConvertToIonGates().convert_circuit(c)
     ic.append(
         cirq.measure_each(*qubits),
         strategy=cirq.circuits.InsertStrategy.NEW_THEN_INLINE,
     )
     jc = jaqal_circuit_from_cirq_circuit(ic)
     jcirc = CircuitBuilder()
     reg = jcirc.register("allqubits", 2)
     jcirc.gate("prepare_all")
     jcirc.gate("R", reg[0], pi, pi)
     jcirc.gate("MS", reg[0], reg[1], 0, pi / 2)
     block = jcirc.block(True)
     block.gate("R", reg[0], -1.5707963267948972, pi / 2)
     # Last few digits are off if we just use -pi/2
     block.gate("R", reg[1], pi, pi / 2)
     jcirc.gate("Rz", reg[0], -pi / 2)
     jcirc.gate("measure_all")
     self.assertEqual(
         generate_jaqal_program(jcirc.build()), generate_jaqal_program(jc)
     )
Example #12
0
def jaqal_circuit_from_qiskit_circuit(circuit, names=None, native_gates=None):
    """
    Converts a Qiskit circuit to a :class:`jaqalpaq.core.Circuit`. The circuit
    will be structured into a sequence of unscheduled blocks. All instructions between one
    barrier statement and the next will be put into an unscheduled block together. If the
    :mod:`qscout.scheduler` is run on the circuit, as many as possible of those gates will
    be parallelized within each block, while maintaining the order of the blocks.
    Otherwise, the circuit will be treated as a fully sequential circuit.

    Measurement and reset commands are supported, but only if applied to every qubit in
    the circuit in immediate succession. If so, they will be mapped to a prepare_all or
    measure_all gate. If the circuit does not end with a measurement, then a measure_all
    gate will be appended to it.

    Circuits containing multiple quantum registers will be converted to circuits with a
    single quantum register, containing all the qubits from each register. The parts of
    that larger register that correspond to each of the original registers will be mapped
    with the appropriate names.

    :param qiskit.circuit.QuantumCircuit circuit: The circuit to convert.
    :param names: A mapping from names of Qiskit gates to the corresponding native Jaqal
        gate names. If omitted, maps i, r (:class:`jaqalpaq.transpilers.qiskit.RGate`),
        sx (:class:`jaqalpaq.qiskit.SXGate`), sy (:class:`jaqalpaq.qiskit.SYGate`), x, y,
        rz, and ms2 (:class:`jaqalpaq.qiskit.MSGate`) to their QSCOUT counterparts.
    :type names: dict or None
    :param native_gates: The native gate set to target. If None, target the QSCOUT native
        gates.
    :type native_gates: dict or None
    :returns: The same quantum circuit, converted to JaqalPaq.
    :rtype: jaqalpaq.core.Circuit
    :raises JaqalError: If any instruction acts on a qubit from a register other than the
        circuit's qregs.
    :raises JaqalError: If the circuit includes a snapshot instruction.
    :raises JaqalError: If the user tries to measure or reset only some of the qubits,
        rather than all of them.
    :raises JaqalError: If the circuit includes a gate not included in `names`.
    """
    if native_gates is None:
        from qscout.v1.std import NATIVE_GATES

        native_gates = NATIVE_GATES
    n = sum([qreg.size for qreg in circuit.qregs])
    qsc = CircuitBuilder(native_gates=native_gates)
    if names is None:
        names = QISKIT_NAMES
    baseregister = qsc.register("baseregister", n)
    offset = 0
    registers = {}
    for qreg in circuit.qregs:
        registers[qreg.name] = qsc.map(qreg.name, baseregister,
                                       slice(offset, offset + qreg.size))
        offset += qreg.size
    # We're going to divide the circuit up into blocks. Each block will contain every gate
    # between one barrier statement and the next. If the circuit is output with no further
    # processing, then the gates in each block will be run in sequence. However, if the
    # circuit is passed to the scheduler, it'll try to parallelize as many of the gates
    # within each block as possible, while keeping the blocks themselves sequential.
    block = UnscheduledBlockBuilder()
    qsc.expression.append(block.expression)
    block.gate("prepare_all")
    measure_accumulator = set()
    reset_accumulator = set()
    in_preamble = True
    for instr in circuit.data:
        if reset_accumulator:
            if instr[0].name == "reset":
                target = instr[1][0]
                if target.register.name in registers:
                    reset_accumulator.add(
                        registers[target.register.name].resolve_qubit(
                            target.index)[1])
                else:
                    raise JaqalError("Register %s invalid!" %
                                     target.register.name)
                if len(reset_accumulator) == n:
                    block.gate("prepare_all")
                    reset_accumulator = {}
                continue
            else:
                raise JaqalError(
                    "Cannot reset only qubits %s and not whole register." %
                    reset_accumulator)
                # reset_accumulator = set()
        if measure_accumulator:
            if instr[0].name == "measure":
                target = instr[1][0]
                if target.register.name in registers:
                    measure_accumulator.add(
                        registers[target.register.name].resolve_qubit(
                            target.index)[1])
                else:
                    raise JaqalError("Register %s invalid!" %
                                     target.register.name)
                if len(measure_accumulator) == n:
                    block.gate("measure_all")
                    measure_accumulator = {}
                continue
            else:
                raise JaqalError(
                    "Cannot measure only qubits %s and not whole register." %
                    reset_accumulator)
                # measure_accumulator = set()
        if instr[0].name == "measure":
            in_preamble = False
            target = instr[1][0]
            if target.register.name in registers:
                measure_accumulator = {
                    registers[target.register.name].resolve_qubit(
                        target.index)[1]
                }
                if len(measure_accumulator) == n:
                    block.gate("measure_all")
                    measure_accumulator = {}
                continue
            else:
                raise JaqalError("Register %s invalid!" % target.register.name)
        elif instr[0].name == "reset":
            if not in_preamble:
                target = instr[1][0]
                if target.register.name in registers:
                    reset_accumulator = {
                        registers[target.register.name].resolve_qubit(
                            target.index)[1]
                    }
                    if len(reset_accumulator) == n:
                        block.gate("prepare_all")
                        reset_accumulator = {}
                else:
                    raise JaqalError("Register %s invalid!" %
                                     target.register.name)
        elif instr[0].name == "barrier":
            block = UnscheduledBlockBuilder()
            qsc.expression.append(block.expression)
            # Use barriers to inform the scheduler, as explained above.
        elif instr[0].name == "snapshot":
            raise JaqalError(
                "Physical hardware does not support snapshot instructions.")
        elif instr[0].name in names:
            in_preamble = False
            targets = instr[1]
            for target in targets:
                if target.register.name not in registers:
                    raise JaqalError("Gate register %s invalid!" %
                                     target.register.name)
            block.gate(
                names[instr[0].name], *[
                    registers[target.register.name][target.index]
                    for target in targets
                ], *[float(param) for param in instr[0].params])
        else:
            raise JaqalError(
                "Instruction %s not available on trapped ion hardware; try unrolling first."
                % instr[0].name)
    block.gate("measure_all", no_duplicate=True)
    return qsc.build()