コード例 #1
0
    def test_custom_gate_with_params_bound_main_call(self):
        """Custom gate with unbound parameters that are bound in the main circuit"""
        parameter0 = Parameter("param_0")
        parameter1 = Parameter("param_1")

        custom = QuantumCircuit(2, name="custom")
        custom.rz(parameter0, 0)
        custom.rz(parameter1 / 2, 1)

        qr_q = QuantumRegister(3, "q")
        qr_r = QuantumRegister(3, "r")
        circuit = QuantumCircuit(qr_q, qr_r)
        circuit.append(custom.to_gate(), [qr_q[0], qr_r[0]])

        circuit.assign_parameters({
            parameter0: pi,
            parameter1: pi / 2
        },
                                  inplace=True)

        qubit_name = circuit.data[0][0].definition.qregs[0].name
        expected_qasm = "\n".join([
            "OPENQASM 3;",
            'include "stdgates.inc";',
            f"gate custom(param_0, param_1) {qubit_name}_0, {qubit_name}_1 {{",
            f"  rz(pi) {qubit_name}_0;",
            f"  rz(pi/4) {qubit_name}_1;",
            "}",
            "qubit[6] _q;",
            "let q = _q[0] || _q[1] || _q[2];",
            "let r = _q[3] || _q[4] || _q[5];",
            "custom(pi, pi/2) q[0], r[0];",
            "",
        ])
        self.assertEqual(Exporter().dumps(circuit), expected_qasm)
コード例 #2
0
    def test_decompose_propagates_deeply_bound_parameters(
            self, target_type, parameter_type):
        """Verify bind-before-decompose preserves deeply bound values."""
        theta = Parameter('th')
        qc1 = QuantumCircuit(1)
        qc1.rx(theta, 0)

        if target_type == 'gate':
            inst = qc1.to_gate()
        elif target_type == 'instruction':
            inst = qc1.to_instruction()

        qc2 = QuantumCircuit(1)
        qc2.append(inst, [0])

        if target_type == 'gate':
            inst = qc2.to_gate()
        elif target_type == 'instruction':
            inst = qc2.to_instruction()

        qc3 = QuantumCircuit(1)
        qc3.append(inst, [0])

        if parameter_type == 'numbers':
            bound_qc3 = qc3.assign_parameters({theta: 0.5})
            expected_parameters = set()
            expected_qc3 = QuantumCircuit(1)
            expected_qc3.rx(0.5, 0)
        else:
            phi = Parameter('ph')
            bound_qc3 = qc3.assign_parameters({theta: phi})
            expected_parameters = {phi}
            expected_qc3 = QuantumCircuit(1)
            expected_qc3.rx(phi, 0)

        deep_decomposed_qc3 = bound_qc3.decompose().decompose()

        with self.subTest(msg='testing parameters of initial circuit'):
            self.assertEqual(qc3.parameters, {theta})

        with self.subTest(msg='testing parameters of bound circuit'):
            self.assertEqual(bound_qc3.parameters, expected_parameters)

        with self.subTest(
                msg='testing parameters of deep decomposed bound circuit'):
            self.assertEqual(deep_decomposed_qc3.parameters,
                             expected_parameters)

        with self.subTest(msg='testing deep decomposed circuit'):
            self.assertEqual(deep_decomposed_qc3, expected_qc3)
コード例 #3
0
    def test_binding_across_broadcast_instruction(self):
        """Bind a parameter which was included via a broadcast instruction."""
        # ref: https://github.com/Qiskit/qiskit-terra/issues/3008

        from qiskit.extensions.standard import RZGate
        theta = Parameter('θ')
        n = 5

        qc = QuantumCircuit(n, 1)

        qc.h(0)
        for i in range(n-1):
            qc.cx(i, i+1)

        qc.barrier()
        qc.rz(theta, range(n))
        qc.barrier()

        for i in reversed(range(n-1)):
            qc.cx(i, i+1)
        qc.h(0)
        qc.measure(0, 0)

        theta_range = numpy.linspace(0, 2 * numpy.pi, 128)
        circuits = [qc.assign_parameters({theta: theta_val})
                    for theta_val in theta_range]

        self.assertEqual(len(circuits), len(theta_range))
        for theta_val, bound_circ in zip(theta_range, circuits):
            rz_gates = [inst for inst, qargs, cargs in bound_circ.data
                        if isinstance(inst, RZGate)]

            self.assertEqual(len(rz_gates), n)
            self.assertTrue(all(float(gate.params[0]) == theta_val
                                for gate in rz_gates))
コード例 #4
0
 def test_can_schedule_circuits_with_bounded_parameters(self, scheduling_method):
     idle_dur = Parameter("t")
     qc = QuantumCircuit(1, 1)
     qc.x(0)
     qc.delay(idle_dur, 0, "us")
     qc.measure(0, 0)
     qc = qc.assign_parameters({idle_dur: 0.1})
     circ = transpile(qc, self.backend_with_dt, scheduling_method=scheduling_method)
     self.assertIsNotNone(circ.duration)  # scheduled
コード例 #5
0
 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)
コード例 #6
0
    def test_decompose_propagates_bound_parameters(self, target_type,
                                                   parameter_type):
        """Verify bind-before-decompose preserves bound values."""
        # ref: https://github.com/Qiskit/qiskit-terra/issues/2482
        theta = Parameter('th')
        qc = QuantumCircuit(1)
        qc.rx(theta, 0)

        if target_type == 'gate':
            inst = qc.to_gate()
        elif target_type == 'instruction':
            inst = qc.to_instruction()

        qc2 = QuantumCircuit(1)
        qc2.append(inst, [0])

        if parameter_type == 'numbers':
            bound_qc2 = qc2.assign_parameters({theta: 0.5})
            expected_parameters = set()
            expected_qc2 = QuantumCircuit(1)
            expected_qc2.rx(0.5, 0)
        else:
            phi = Parameter('ph')
            bound_qc2 = qc2.assign_parameters({theta: phi})
            expected_parameters = {phi}
            expected_qc2 = QuantumCircuit(1)
            expected_qc2.rx(phi, 0)

        decomposed_qc2 = bound_qc2.decompose()

        with self.subTest(msg='testing parameters of initial circuit'):
            self.assertEqual(qc2.parameters, {theta})

        with self.subTest(msg='testing parameters of bound circuit'):
            self.assertEqual(bound_qc2.parameters, expected_parameters)

        with self.subTest(
                msg='testing parameters of deep decomposed bound circuit'):
            self.assertEqual(decomposed_qc2.parameters, expected_parameters)

        with self.subTest(msg='testing deep decomposed circuit'):
            self.assertEqual(decomposed_qc2, expected_qc2)
コード例 #7
0
 def test_can_transpile_circuits_after_assigning_parameters(self):
     """Check if not scheduled but duration is converted in dt"""
     idle_dur = Parameter("t")
     qc = QuantumCircuit(1, 1)
     qc.x(0)
     qc.delay(idle_dur, 0, "us")
     qc.measure(0, 0)
     qc = qc.assign_parameters({idle_dur: 0.1})
     circ = transpile(qc, self.backend_with_dt)
     self.assertEqual(circ.duration, None)  # not scheduled
     self.assertEqual(circ.data[1][0].duration, 450)  # converted in dt
コード例 #8
0
    def test_schedule_block_in_instmap(self):
        """Test schedule block in instmap can be scheduled."""
        duration = Parameter("duration")

        with build() as pulse_prog:
            play(Gaussian(duration, 0.1, 10), DriveChannel(0))

        instmap = InstructionScheduleMap()
        instmap.add("block_gate", (0, ), pulse_prog, ["duration"])

        qc = QuantumCircuit(1)
        qc.append(Gate("block_gate", 1, [duration]), [0])
        qc.assign_parameters({duration: 100}, inplace=True)

        sched = schedule(qc, self.backend, inst_map=instmap)

        ref_sched = Schedule()
        ref_sched += Play(Gaussian(100, 0.1, 10), DriveChannel(0))

        self.assertEqual(sched, ref_sched)
コード例 #9
0
    def test_to_instruction_with_expression(self, target_type, order):
        """Test preservation of expressions via parameterized instructions.

                  ┌───────┐┌──────────┐┌───────────┐
        qr1_0: |0>┤ Rx(θ) ├┤ Rz(pi/2) ├┤ Ry(phi*θ) ├
                  └───────┘└──────────┘└───────────┘

                     ┌───────────┐
        qr2_0: |0>───┤ Ry(delta) ├───
                  ┌──┴───────────┴──┐
        qr2_1: |0>┤ Circuit0(phi,θ) ├
                  └─────────────────┘
        qr2_2: |0>───────────────────
        """

        theta = Parameter('θ')
        phi = Parameter('phi')
        qr1 = QuantumRegister(1, name='qr1')
        qc1 = QuantumCircuit(qr1)

        qc1.rx(theta, qr1)
        qc1.rz(numpy.pi / 2, qr1)
        qc1.ry(theta * phi, qr1)

        if target_type == 'gate':
            gate = qc1.to_gate()
        elif target_type == 'instruction':
            gate = qc1.to_instruction()

        self.assertEqual(gate.params, [phi, theta])

        delta = Parameter('delta')
        qr2 = QuantumRegister(3, name='qr2')
        qc2 = QuantumCircuit(qr2)
        qc2.ry(delta, qr2[0])
        qc2.append(gate, qargs=[qr2[1]])

        self.assertEqual(qc2.parameters, {delta, theta, phi})

        binds = {delta: 1, theta: 2, phi: 3}
        expected_qc = QuantumCircuit(qr2)
        expected_qc.rx(2, 1)
        expected_qc.rz(numpy.pi / 2, 1)
        expected_qc.ry(3 * 2, 1)
        expected_qc.r(1, numpy.pi / 2, 0)

        if order == 'bind-decompose':
            decomp_bound_qc = qc2.assign_parameters(binds).decompose()
        elif order == 'decompose-bind':
            decomp_bound_qc = qc2.decompose().assign_parameters(binds)

        self.assertEqual(decomp_bound_qc.parameters, set())
        self.assertEqual(decomp_bound_qc, expected_qc)
コード例 #10
0
    def test_bound_parameter(self):
        """Test a circuit with a bound parameter is correctly serialized."""
        theta = Parameter("theta")
        qc = QuantumCircuit(5, 1)
        qc.h(0)
        for i in range(4):
            qc.cx(i, i + 1)

        qc.barrier()
        qc.rz(theta, range(5))
        qc.barrier()
        for i in reversed(range(4)):
            qc.cx(i, i + 1)
        qc.h(0)
        qc.measure(0, 0)
        qc.assign_parameters({theta: 3.14})

        qpy_file = io.BytesIO()
        dump(qc, qpy_file)
        qpy_file.seek(0)
        new_circ = load(qpy_file)[0]
        self.assertEqual(qc, new_circ)
コード例 #11
0
    def test_inst_map_transpilation(self):
        """Test that we can use the inst_map to inject the cals into the circuit."""

        cals = BackendCalibrations(
            FakeArmonk(),
            library=FixedFrequencyTransmon(basis_gates=["x"]),
        )

        param = Parameter("amp")
        cals.inst_map_add("Rabi", (0,), "x", assign_params={"amp": param})

        circ = QuantumCircuit(1)
        circ.x(0)
        circ.append(Gate("Rabi", num_qubits=1, params=[param]), (0,))

        circs, amps = [], [0.12, 0.25]

        for amp in amps:
            new_circ = circ.assign_parameters({param: amp}, inplace=False)
            circs.append(new_circ)

        # Check that calibrations are absent
        for circ in circs:
            self.assertEqual(len(circ.calibrations), 0)

        # Transpile to inject the cals.
        # TODO Enable this test once terra 0.19.0 is live.
        circs = transpile(circs)  # TODO add: inst_map=cals.instruction_schedule_map

        # Check that we have the expected schedules.
        with pulse.build() as x_expected:
            pulse.play(pulse.Drag(160, 0.5, 40, 0), pulse.DriveChannel(0))

        for idx, circ in enumerate(circs):
            amp = amps[idx]

            with pulse.build() as rabi_expected:
                pulse.play(pulse.Drag(160, amp, 40, 0), pulse.DriveChannel(0))

            self.assertEqual(circ.calibrations["x"][((0,), ())], x_expected)

            circ_rabi = next(iter(circ.calibrations["Rabi"].values()))
            self.assertEqual(circ_rabi, rabi_expected)

        # Test the removal of the Rabi instruction
        self.assertTrue(cals.default_inst_map.has("Rabi", (0,)))

        cals.default_inst_map.remove("Rabi", (0,))

        self.assertFalse(cals.default_inst_map.has("Rabi", (0,)))
コード例 #12
0
    def test_mixed_binding(self, inplace):
        """Test we can bind a mixed dict with Parameter objects and floats."""
        theta = Parameter('θ')
        x, new_x = Parameter('x'), Parameter('new_x')
        qr = QuantumRegister(1)
        qc = QuantumCircuit(qr)
        qc.rx(theta, qr)
        qc.u3(0, theta, x, qr)

        pqc = qc.assign_parameters({theta: 2, x: new_x}, inplace=inplace)
        if inplace:
            self.assertEqual(qc.parameters, {new_x})
        else:
            self.assertEqual(pqc.parameters, {new_x})
コード例 #13
0
    def test_to_instruction_expression_parameter_map(self, target_type, order):
        """Test preservation of expressions via instruction parameter_map."""

        theta = Parameter('θ')
        phi = Parameter('phi')
        qr1 = QuantumRegister(1, name='qr1')
        qc1 = QuantumCircuit(qr1)

        qc1.rx(theta, qr1)
        qc1.rz(numpy.pi / 2, qr1)
        qc1.ry(theta * phi, qr1)

        theta_p = Parameter('theta')
        phi_p = Parameter('phi')

        if target_type == 'gate':
            gate = qc1.to_gate(parameter_map={theta: theta_p, phi: phi_p})
        elif target_type == 'instruction':
            gate = qc1.to_instruction(parameter_map={
                theta: theta_p,
                phi: phi_p
            })

        self.assertEqual(gate.params, [phi_p, theta_p])

        delta = Parameter('delta')
        qr2 = QuantumRegister(3, name='qr2')
        qc2 = QuantumCircuit(qr2)
        qc2.ry(delta, qr2[0])
        qc2.append(gate, qargs=[qr2[1]])

        self.assertEqual(qc2.parameters, {delta, theta_p, phi_p})

        binds = {delta: 1, theta_p: 2, phi_p: 3}
        expected_qc = QuantumCircuit(qr2)
        expected_qc.rx(2, 1)
        expected_qc.rz(numpy.pi / 2, 1)
        expected_qc.ry(3 * 2, 1)
        expected_qc.r(1, numpy.pi / 2, 0)

        if order == 'bind-decompose':
            decomp_bound_qc = qc2.assign_parameters(binds).decompose()
        elif order == 'decompose-bind':
            decomp_bound_qc = qc2.decompose().assign_parameters(binds)

        self.assertEqual(decomp_bound_qc.parameters, set())
        self.assertEqual(decomp_bound_qc, expected_qc)
コード例 #14
0
    def test_bound_gate_to_matrix(self, gate_class):
        """Test to_matrix works if previously free parameters are bound.

        The conversion might fail, if trigonometric functions such as cos are called on the
        parameters and the parameters are still of type ParameterExpression.
        """
        num_parameters = 2 if gate_class == circlib.RGate else 1
        params = list(range(1, 1 + num_parameters))
        free_params = ParameterVector('th', num_parameters)
        gate = gate_class(*params)
        num_qubits = gate.num_qubits

        circuit = QuantumCircuit(num_qubits)
        circuit.append(gate_class(*free_params), list(range(num_qubits)))
        bound_circuit = circuit.assign_parameters({free_params: params})

        numpy.testing.assert_array_almost_equal(
            Operator(bound_circuit).data, gate.to_matrix())
コード例 #15
0
    def test_parameterized_calibrations_transpile(self):
        """Check that gates can be matched to their calibrations before and after parameter
        assignment."""
        tau = Parameter('tau')
        circ = QuantumCircuit(3, 3)
        circ.append(Gate('rxt', 1, [2*3.14*tau]), [0])

        def q0_rxt(tau):
            with pulse.build() as q0_rxt:
                pulse.play(pulse.library.Gaussian(20, 0.4*tau, 3.0), pulse.DriveChannel(0))
            return q0_rxt
        circ.add_calibration('rxt', [0], q0_rxt(tau), [2*3.14*tau])

        transpiled_circ = transpile(circ, FakeAlmaden())
        self.assertEqual(set(transpiled_circ.count_ops().keys()), {'rxt'})
        circ = circ.assign_parameters({tau: 1})
        transpiled_circ = transpile(circ, FakeAlmaden())
        self.assertEqual(set(transpiled_circ.count_ops().keys()), {'rxt'})
コード例 #16
0
    def runCircuit(cls,
                   circuit: QuantumCircuit,
                   parameterizations: list,
                   backend,
                   token,
                   shots,
                   add_measurements=False):
        """
            Runs the circuit with each parameterization in the provided list and
            on the provided quantum instance and

            parameters
                - circuit: a QuantumCircuit to run
                - parameterizations: a list of dictionaries [parameter name] -> [value]
                - add_measurements: (optional) adds measurement operations if instance is not a statevector instance

            returns
                - results: a list of the results from these runs
                - is_statevector: True if QInstance is statevector
        """

        Qbackend = QuantumBackendFactory.create_backend(backend, token)
        QInstance = QuantumInstance(Qbackend,
                                    seed_simulator=9283712,
                                    seed_transpiler=9283712,
                                    shots=shots)

        # add measurements
        if not QInstance.is_statevector and add_measurements:
            circuit.barrier()
            circuit.measure(circuit.qubits, circuit.clbits)

        circuits = []
        for parameterization in parameterizations:
            parameterization = parameterization_from_parameter_names(
                circuit, parameterization)
            curr_circuit = circuit.assign_parameters(parameterization)
            circuits.append(curr_circuit)

        results = QInstance.execute(circuits)

        return results, QInstance.is_statevector
コード例 #17
0
    def circuits(self,
                 backend: Optional[Backend] = None) -> List[QuantumCircuit]:
        """Create the circuits for the Drag calibration.

        Args:
            backend: A backend object.

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

        Raises:
            CalibrationError:
                - If the beta parameters in the xp and xm pulses are not the same.
                - If either the xp or xm pulse do not have at least one Drag pulse.
                - If the number of different repetition series is not three.
        """
        schedule = self.experiment_options.schedule

        if schedule is None:
            beta = Parameter("β")
            with pulse.build(backend=backend, name="drag") as schedule:
                pulse.play(
                    pulse.Drag(
                        duration=self.experiment_options.duration,
                        amp=self.experiment_options.amp,
                        sigma=self.experiment_options.sigma,
                        beta=beta,
                    ),
                    pulse.DriveChannel(self._physical_qubits[0]),
                )

        if len(schedule.parameters) != 1:
            raise CalibrationError(
                "The schedule for Drag calibration must have one free parameter."
                f"Found {len(schedule.parameters)}.")

        beta = next(iter(schedule.parameters))

        drag_gate = Gate(name=schedule.name, num_qubits=1, params=[beta])

        reps = self.experiment_options.reps
        if len(reps) != 3:
            raise CalibrationError(
                f"{self.__class__.__name__} must use exactly three repetition numbers. "
                f"Received {reps} with length {len(reps)} != 3.")

        circuits = []

        for idx, rep in enumerate(reps):
            circuit = QuantumCircuit(1)
            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(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
コード例 #18
0
 def append_adder(adder: QuantumCircuit, constant: int, idx: int):
     partial_constant = (pow(2, idx, N) * constant) % N
     angles = self._get_angles(partial_constant, n + 1)
     bound = adder.assign_parameters({angle_params: angles})
     circuit.append(bound,
                    [*ctrl_qreg, x_qreg[idx], *b_qreg, *flag_qreg])