Beispiel #1
0
 def duplicate_instruction(inst):
     """Create a fresh instruction from an input instruction."""
     if issubclass(inst.__class__,
                   Instruction) and inst.__class__ not in [
                       Instruction, Gate]:
         if inst.name == 'barrier':
             new_inst = inst.__class__(inst.num_qubits)
         elif inst.name == 'initialize':
             params = getattr(inst, 'params', [])
             new_inst = inst.__class__(params)
         elif inst.name == 'snapshot':
             label = inst.params[0]
             snap_type = inst.params[1]
             new_inst = inst.__class__(inst.num_qubits,
                                       inst.num_clbits,
                                       label, snap_type)
         else:
             params = getattr(inst, 'params', [])
             new_inst = inst.__class__(*params)
     else:
         if isinstance(inst, Gate):
             new_inst = Gate(inst.name, inst.num_qubits,
                             inst.params)
         else:
             new_inst = Instruction(name=inst.name,
                                    num_qubits=inst.num_qubits,
                                    num_clbits=inst.num_clbits,
                                    params=inst.params)
         new_inst.definition = inst.definition
     return new_inst
Beispiel #2
0
    def test_transpiled_custom_gates_calibration(self):
        """Test if transpiled calibrations is equal to custom gates circuit calibrations."""
        custom_180 = Gate("mycustom", 1, [3.14])
        custom_90 = Gate("mycustom", 1, [1.57])

        circ = QuantumCircuit(2)
        circ.append(custom_180, [0])
        circ.append(custom_90, [1])

        with pulse.build() as q0_x180:
            pulse.play(pulse.library.Gaussian(20, 1.0, 3.0),
                       pulse.DriveChannel(0))
        with pulse.build() as q1_y90:
            pulse.play(pulse.library.Gaussian(20, -1.0, 3.0),
                       pulse.DriveChannel(1))

        # Add calibration
        circ.add_calibration(custom_180, [0], q0_x180)
        circ.add_calibration(custom_90, [1], q1_y90)

        backend = FakeAlmaden()
        transpiled_circuit = transpile(
            circ,
            backend=backend,
        )
        self.assertEqual(transpiled_circuit.calibrations, circ.calibrations)
        self.assertEqual(list(transpiled_circuit.count_ops().keys()),
                         ['mycustom'])
        self.assertEqual(list(transpiled_circuit.count_ops().values()), [2])
    def test_transpiled_custom_gates_calibration(self):
        """Test if transpiled calibrations is equal to custom gates circuit calibrations."""
        custom_180 = Gate("mycustom", 1, [3.14])
        custom_90 = Gate("mycustom", 1, [1.57])

        circ = QuantumCircuit(2)
        circ.append(custom_180, [0])
        circ.append(custom_90, [1])

        with pulse.build() as q0_x180:
            pulse.play(pulse.library.Gaussian(20, 1.0, 3.0),
                       pulse.DriveChannel(0))
        with pulse.build() as q1_y90:
            pulse.play(pulse.library.Gaussian(20, -1.0, 3.0),
                       pulse.DriveChannel(1))

        # Add calibration
        circ.add_calibration(custom_180, [0], q0_x180)
        circ.add_calibration(custom_90, [1], q1_y90)

        backend = FakeAlmaden()
        # TODO: Remove L783-L784 in the next PR
        transpiled_circuit = transpile(
            circ,
            backend=backend,
            basis_gates=backend.configuration().basis_gates +
            list(circ.calibrations.keys()),
        )
        self.assertEqual(transpiled_circuit.calibrations, circ.calibrations)
Beispiel #4
0
 def _create_op(self, name, params):
     if name in self.standard_extension:
         op = self.standard_extension[name](*params)
     elif name in self.gates:
         op = Gate(name=name, num_qubits=self.gates[name]['n_bits'], params=params)
         if not self.gates[name]['opaque']:
             # call a custom gate (otherwise, opaque)
             op.definition = self._gate_rules_to_qiskit_circuit(self.gates[name],
                                                                params=params)
     else:
         raise QiskitError("unknown operation for ast node name %s" % name)
     return op
Beispiel #5
0
def controlled_rotation_generic():
    A = Gate('A', 1, [])
    B = Gate('B', 1, [])
    C = Gate('C', 1, [])
    alpha = 1  # arbitrarily define alpha to allow drawing of circuit

    qc = QuantumCircuit(2)
    qc.append(C, [1])
    qc.cz(0, 1)
    qc.append(B, [1])
    qc.cz(0, 1)
    qc.append(A, [1])
    qc.p(alpha, 0)
    print(qc.draw())
Beispiel #6
0
    def inverse(self):
        """Return the inverse.

        Note that the resulting Gate object has an empty ``params`` property.
        """
        inverse_gate = Gate(
            name=self.name + "_dg", num_qubits=self.num_qubits,
            params=[])  # removing the params because arrays are deprecated

        definition = QuantumCircuit(*self.definition.qregs)
        for inst in reversed(self._definition):
            definition._append(
                inst.replace(operation=inst.operation.inverse()))
        inverse_gate.definition = definition
        return inverse_gate
    def inverse(self):
        """Return the inverse.

        Note that the resulting Gate object has an empty ``params`` property.
        """
        inverse_gate = Gate(
            name=self.name + "_dg", num_qubits=self.num_qubits, params=[]
        )  # removing the params because arrays are deprecated

        inverse_gate.definition = QuantumCircuit(*self.definition.qregs)
        inverse_gate.definition._data = [
            (inst.inverse(), qargs, []) for inst, qargs, _ in reversed(self._definition)
        ]

        return inverse_gate
    def test_can_append_to_quantum_circuit(self):
        """Test that we can add various objects with Operation interface to a Quantum Circuit."""
        qc = QuantumCircuit(6, 1)
        qc.append(XGate(), [2])
        qc.append(Barrier(3), [1, 2, 4])
        qc.append(CXGate(), [0, 1])
        qc.append(Measure(), [1], [0])
        qc.append(Reset(), [0])
        qc.cx(3, 4)
        qc.append(Gate("some_gate", 3, []), [1, 2, 3])
        qc.append(Initialize([0.5, 0.5, 0.5, 0.5]), [4, 5])
        qc.append(Isometry(np.eye(4, 4), 0, 0), [3, 4])
        qc.append(Pauli("II"), [0, 1])

        # Appending Clifford
        circ1 = QuantumCircuit(2)
        circ1.h(1)
        circ1.cx(0, 1)
        qc.append(Clifford(circ1), [0, 1])

        # Appending CNOTDihedral
        circ2 = QuantumCircuit(2)
        circ2.t(0)
        circ2.x(0)
        circ2.t(1)
        qc.append(CNOTDihedral(circ2), [2, 3])

        # If we got to here, we have successfully appended everything to qc
        self.assertIsInstance(qc, QuantumCircuit)
    def __init__(
        self,
        qubit: int,
        calibrations: Calibrations,
        schedule_name: str,
        backend: Optional[Backend] = None,
        cal_parameter_name: Optional[str] = "β",
        auto_update: bool = True,
    ):
        r"""see class :class:`FineDrag` for details.

        Note that this class implicitly assumes that the target angle of the gate
        is :math:`\pi` as seen from the default experiment options.

        Args:
            qubit: The qubit for which to run the fine drag calibration.
            calibrations: The calibrations instance with the schedules.
            schedule_name: The name of the schedule to calibrate.
            backend: Optional, the backend to run the experiment on.
            cal_parameter_name: The name of the parameter in the schedule to update.
            auto_update: Whether or not to automatically update the calibrations. By
                default this variable is set to True.
        """
        super().__init__(
            calibrations,
            qubit,
            Gate(name=schedule_name, num_qubits=1, params=[]),
            schedule_name=schedule_name,
            backend=backend,
            cal_parameter_name=cal_parameter_name,
            auto_update=auto_update,
        )

        self.set_transpile_options(basis_gates=["sx", schedule_name, "rz"])
Beispiel #10
0
    def test_opaque_gate(self):
        """
        Test parse an opaque gate

        See https://github.com/Qiskit/qiskit-terra/issues/1566.
        """

        qasm_string = (
            "\n".join(
                [
                    "OPENQASM 2.0;",
                    'include "qelib1.inc";',
                    "opaque my_gate(theta,phi,lambda) a,b;",
                    "qreg q[3];",
                    "my_gate(1,2,3) q[1],q[2];",
                ]
            )
            + "\n"
        )
        circuit = QuantumCircuit.from_qasm_str(qasm_string)

        qr = QuantumRegister(3, "q")
        expected = QuantumCircuit(qr)
        expected.append(Gate(name="my_gate", num_qubits=2, params=[1, 2, 3]), [qr[1], qr[2]])

        self.assertEqual(circuit, expected)
 def setUpClass(cls):
     super().setUpClass()
     class_list = Gate.__subclasses__() + ControlledGate.__subclasses__()
     exclude = {
         "ControlledGate",
         "DiagonalGate",
         "UCGate",
         "MCGupDiag",
         "MCU1Gate",
         "UnitaryGate",
         "HamiltonianGate",
         "MCPhaseGate",
         "UCPauliRotGate",
         "SingleQubitUnitary",
         "MCXGate",
         "VariadicZeroParamGate",
         "ClassicalFunction",
         "ClassicalElement",
         "StatePreparation",
         "LinearFunction",
     }
     cls._gate_classes = []
     for aclass in class_list:
         if aclass.__name__ not in exclude:
             cls._gate_classes.append(aclass)
Beispiel #12
0
    def _create_dag_op(self, name, params, qargs):
        """
        Create a DAG node out of a parsed AST op node.

        Args:
            name (str): operation name to apply to the dag.
            params (list): op parameters
            qargs (list(Qubit)): qubits to attach to

        Raises:
            QiskitError: if encountering a non-basis opaque gate
        """

        if name in self.standard_extension:
            op = self.standard_extension[name](*params)
        elif name in self.gates:
            if self.gates[name]['opaque']:
                # call an opaque gate
                op = Gate(name=name,
                          num_qubits=self.gates[name]['n_bits'],
                          params=params)
            else:
                # call a custom gate
                raise QiskitError(
                    'Custom non-opaque gates are not supported by as_to_dag module'
                )
        else:
            raise QiskitError("unknown operation for ast node name %s" % name)

        self.dag.apply_operation_back(op, qargs, [], condition=self.condition)
Beispiel #13
0
    def __init__(
        self,
        qubit: int,
        calibrations: Calibrations,
        schedule_name: str,
        backend: Optional[Backend] = None,
        cal_parameter_name: Optional[str] = "amp",
        auto_update: bool = True,
    ):
        """see class :class:`FineAmplitude` for details.

        Args:
            qubit: The qubit for which to run the fine amplitude calibration.
            calibrations: The calibrations instance with the schedules.
            schedule_name: The name of the schedule to calibrate.
            backend: Optional, the backend to run the experiment on.
            cal_parameter_name: The name of the parameter in the schedule to update.
            auto_update: Whether or not to automatically update the calibrations. By
                default this variable is set to True.
        """
        super().__init__(
            calibrations,
            qubit,
            Gate(name=schedule_name, num_qubits=1, params=[]),
            schedule_name=schedule_name,
            backend=backend,
            cal_parameter_name=cal_parameter_name,
            auto_update=auto_update,
        )

        self.set_transpile_options(inst_map=calibrations.default_inst_map)
Beispiel #14
0
    def test_single_circuit_delay_calibrations(self):
        """Test that disassembler parses delay instruction back to delay gate."""
        qc = QuantumCircuit(2)
        qc.append(Gate("test", 1, []), [0])
        test_sched = pulse.Delay(64, pulse.DriveChannel(0)) + pulse.Delay(
            160, pulse.DriveChannel(0)
        )

        qc.add_calibration("test", [0], test_sched)

        qobj = assemble(qc, FakeOpenPulse2Q())
        output_circuits, _, _ = disassemble(qobj)

        self.assertEqual(len(qc.calibrations), len(output_circuits[0].calibrations))
        self.assertEqual(qc.calibrations.keys(), output_circuits[0].calibrations.keys())
        self.assertTrue(
            all(
                qc_cal.keys() == out_qc_cal.keys()
                for qc_cal, out_qc_cal in zip(
                    qc.calibrations.values(), output_circuits[0].calibrations.values()
                )
            )
        )
        self.assertEqual(
            qc.calibrations["test"][((0,), ())], output_circuits[0].calibrations["test"][((0,), ())]
        )
Beispiel #15
0
    def cz_gate(self,
                q1,
                q2,
                theta: float,
                phase_delta: float = 0.,
                amp_increase: float = 0.):
        """
        Creates a CZ and inserts the schedule into the instruction
        schedule map of the backend to which the builder is tied.

        Args:
            q1: first qubit.
            q2: second qubit.
            theta: Rotation angle of the CZ gate.
            phase_delta: Multiplies the CR90_u pulses samples by np.exp(1.0j*phase_delta).
            amp_increase: Multiplies the CR90_u samples by (1. + amp_increase).
        """
        cz_name = self.name(theta,
                            phase_delta=phase_delta,
                            amp_increase=amp_increase)

        if not self._inst_map.has(cz_name, (q1, q2)):
            cz_schedule = self.build_cz_schedule(q1,
                                                 q2,
                                                 theta,
                                                 phase_delta=phase_delta,
                                                 amp_increase=amp_increase)
            self._inst_map.add(cz_name, (q1, q2), cz_schedule)
            self._inst_map.add(cz_name, (q2, q1), cz_schedule)

            if cz_name not in self._config.basis_gates:
                self._config.basis_gates.append(cz_name)

        return Gate(cz_name, 2, [])
Beispiel #16
0
 def test_append_opaque_wrong_dimension(self):
     """test appending opaque gate to wrong dimension wires.
     """
     qr = QuantumRegister(2)
     circ = QuantumCircuit(qr)
     opaque_gate = Gate(name='crz_2', num_qubits=2, params=[0.5])
     self.assertRaises(QiskitError, circ.append, opaque_gate, [qr[0]])
 def test_experiment_config(self):
     """Test converting to and from config works"""
     exp = FineDrag(0, Gate("Drag", num_qubits=1, params=[]))
     config = exp.config()
     loaded_exp = FineDrag.from_config(config)
     self.assertNotEqual(exp, loaded_exp)
     self.assertEqual(config, loaded_exp.config())
Beispiel #18
0
    def circuits(self) -> List[QuantumCircuit]:
        """Create the circuits for the Drag calibration.

        Returns:
            circuits: The circuits that will run the Drag calibration.

        Raises:
            QiskitError: if the number of different repetition series is not three.
        """
        schedule = self.experiment_options.schedule

        beta = next(iter(schedule.parameters))

        # Note: if the pulse has a reserved name, e.g. x, which does not have parameters
        # then we cannot directly call the gate x and attach a schedule to it. Doing so
        # would results in QObj errors.
        drag_gate = Gate(name="Drag(" + schedule.name + ")",
                         num_qubits=1,
                         params=[beta])

        reps = self.experiment_options.reps
        if len(reps) != 3:
            raise QiskitError(
                f"{self.__class__.__name__} uses exactly three repetitions. "
                f"Received {reps} with length {len(reps)} != 3.")

        circuits = []

        for idx, rep in enumerate(reps):
            circuit = self._pre_circuit()
            for _ in range(rep):
                circuit.append(drag_gate, (0, ))
                circuit.rz(np.pi, 0)
                circuit.append(drag_gate, (0, ))
                circuit.rz(np.pi, 0)

            circuit.measure_active()

            circuit.add_calibration("Drag(" + schedule.name + ")",
                                    self.physical_qubits,
                                    schedule,
                                    params=[beta])

            for beta_val in self.experiment_options.betas:
                beta_val = np.round(beta_val, decimals=6)

                assigned_circuit = circuit.assign_parameters({beta: beta_val},
                                                             inplace=False)

                assigned_circuit.metadata = {
                    "experiment_type": self._type,
                    "qubits": self.physical_qubits,
                    "xval": beta_val,
                    "series": idx,
                }

                circuits.append(assigned_circuit)

        return circuits
Beispiel #19
0
    def _template_circuit(self, amp_param) -> QuantumCircuit:
        """Return the template quantum circuit."""
        circuit = QuantumCircuit(1)
        circuit.x(0)
        circuit.append(Gate(name=self.__rabi_gate_name__, num_qubits=1, params=[amp_param]), (0,))
        circuit.measure_active()

        return circuit
Beispiel #20
0
def multiplexer_multi_controlled_x(num_control):
    # Multi-controlled X gate multiplexer
    identity = np.array(np.array([[1, 0], [0, 1]], dtype=complex))
    x_gate = np.array(np.array([[0, 1], [1, 0]], dtype=complex))
    num_qubits = num_control + 1
    multiplexer = Gate('multiplexer', num_qubits,
                       (2**num_control - 1) * [identity] + [x_gate])
    return multiplexer
Beispiel #21
0
 def _create_op(self, name, params):
     if name in self.standard_extension:
         op = self.standard_extension[name](*params)
     elif name in self.gates:
         if self.gates[name]['opaque']:
             # call an opaque gate
             op = Gate(name=name, num_qubits=self.gates[name]['n_bits'], params=params)
         else:
             # call a custom gate
             op = Instruction(name=name,
                              num_qubits=self.gates[name]['n_bits'],
                              num_clbits=0,
                              params=params)
             op.definition = self._gate_definition_to_qiskit_definition(self.gates[name],
                                                                        params=params)
     else:
         raise QiskitError("unknown operation for ast node name %s" % name)
     return op
Beispiel #22
0
 def test_opaque_gate(self):
     """test opaque gate functionality"""
     q = QuantumRegister(4)
     c = ClassicalRegister(4)
     circ = QuantumCircuit(q, c, name='circ')
     opaque_gate = Gate(name='crz_2', num_qubits=2, params=[0.5])
     circ.append(opaque_gate, [q[2], q[0]])
     self.assertEqual(circ.data[0][0].name, 'crz_2')
     self.assertEqual(circ.decompose(), circ)
    def test_end_to_end(self):
        """A simple test to check if the experiment will run and fit data."""

        drag = FineDrag(0, Gate("Drag", num_qubits=1, params=[]))
        drag.set_experiment_options(schedule=self.schedule)
        drag.set_transpile_options(basis_gates=["rz", "Drag", "sx"])
        exp_data = drag.run(FineDragTestBackend())

        self.assertEqual(exp_data.analysis_results(0).quality, "good")
    def test_circuits(self):
        """Test the circuits of the experiment."""

        drag = FineDrag(0, Gate("Drag", num_qubits=1, params=[]))
        drag.set_experiment_options(schedule=self.schedule)
        drag.backend = FakeArmonk()
        for circuit in drag.circuits()[1:]:
            for idx, name in enumerate(["Drag", "rz", "Drag", "rz"]):
                self.assertEqual(circuit.data[idx][0].name, name)
 def test_parametric_input(self):
     """Test that scheduling works with parametric pulses as input."""
     qr = QuantumRegister(1)
     qc = QuantumCircuit(qr)
     qc.append(Gate("gauss", 1, []), qargs=[qr[0]])
     custom_gauss = Schedule(Play(Gaussian(duration=25, sigma=4, amp=0.5j), DriveChannel(0)))
     self.inst_map.add("gauss", [0], custom_gauss)
     sched = schedule(qc, self.backend, inst_map=self.inst_map)
     self.assertEqual(sched.instructions[0], custom_gauss.instructions[0])
 def setUpClass(cls):
     class_list = Gate.__subclasses__() + ControlledGate.__subclasses__()
     exclude = {'ControlledGate', 'DiagonalGate', 'UCGate', 'MCGupDiag',
                'MCU1Gate', 'UnitaryGate', 'HamiltonianGate', 'MCPhaseGate',
                'UCPauliRotGate', 'SingleQubitUnitary', 'MCXGate',
                'VariadicZeroParamGate'}
     cls._gate_classes = []
     for aclass in class_list:
         if aclass.__name__ not in exclude:
             cls._gate_classes.append(aclass)
 def test_scheduler_with_params_bound(self):
     """Test scheduler with parameters defined and bound"""
     x = Parameter("x")
     qc = QuantumCircuit(2)
     qc.append(Gate("pulse_gate", 1, [x]), [0])
     expected_schedule = Schedule()
     qc.add_calibration(gate="pulse_gate", qubits=[0], schedule=expected_schedule, params=[x])
     qc = qc.assign_parameters({x: 1})
     sched = schedule(qc, self.backend)
     self.assertEqual(sched, expected_schedule)
 def test_scheduler_with_params_not_bound(self):
     """Test scheduler with parameters defined but not bound"""
     x = Parameter("amp")
     qc = QuantumCircuit(2)
     qc.append(Gate("pulse_gate", 1, [x]), [0])
     with build() as expected_schedule:
         play(Gaussian(duration=160, amp=x, sigma=40), DriveChannel(0))
     qc.add_calibration(gate="pulse_gate", qubits=[0], schedule=expected_schedule, params=[x])
     sched = schedule(qc, self.backend)
     self.assertEqual(sched, transforms.target_qobj_transform(expected_schedule))
 def setup(self, unique_pulses, channels):
     self.parametric_sched = build_parametric_pulse_schedule(
         unique_pulses, channels)
     qr = QuantumRegister(1)
     self.qc = QuantumCircuit(qr)
     self.qc.append(Gate('my_pulse', 1, []), qargs=[qr[0]])
     self.backend = FakeOpenPulse2Q()
     self.inst_map = self.backend.defaults().instruction_schedule_map
     self.add_inst_map = self.inst_map
     self.add_inst_map.add('my_pulse', [0], self.parametric_sched)
Beispiel #30
0
    def test_4_args_custom_gate_trivial_expansion(self):
        """test 'expansion' of 4 args in custom gate.
        See https://github.com/Qiskit/qiskit-terra/issues/2508"""
        qr = QuantumRegister(4)
        circ = QuantumCircuit(qr)
        circ.append(Gate("mcx", 4, []), [qr[0], qr[1], qr[2], qr[3]])

        self.assertEqual(len(circ.data), 1)
        self.assertEqual(circ.data[0].operation.name, "mcx")
        self.assertEqual(len(circ.data[0].qubits), 4)