Пример #1
0
    def inverse(self):
        """Return the inverse.

        Note that the resulting gate 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
Пример #2
0
    def inverse(self):
        """Return the inverse.

        Note that the resulting gate 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
Пример #3
0
    def inverse(self):
        """Return the inverse.

        This does not re-compute the decomposition for the multiplexer with the inverse of the
        gates but simply inverts the existing decomposition.
        """
        inverse_gate = Gate(name=self.name + '_dg',
                            num_qubits=self.num_qubits,
                            params=[])  # remove parameters since array is deprecated as parameter

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

        return inverse_gate
Пример #4
0
    def test_custom_gate(self):
        """Test that custom  gate is correctly serialized"""
        custom_gate = Gate("black_box", 1, [])
        custom_definition = QuantumCircuit(1)
        custom_definition.h(0)
        custom_definition.rz(1.5, 0)
        custom_definition.sdg(0)
        custom_gate.definition = custom_definition

        qc = QuantumCircuit(1)
        qc.append(custom_gate, [0])
        qpy_file = io.BytesIO()
        dump(qc, qpy_file)
        qpy_file.seek(0)
        new_circ = load(qpy_file)[0]
        self.assertEqual(qc, new_circ)
        self.assertEqual(qc.decompose(), new_circ.decompose())
    def test_custom_gate_with_label(self):
        """Test that custom  gate is correctly serialized with a label"""
        custom_gate = Gate("black_box", 1, [])
        custom_definition = QuantumCircuit(1)
        custom_definition.h(0)
        custom_definition.rz(1.5, 0)
        custom_definition.sdg(0)
        custom_gate.definition = custom_definition
        custom_gate.label = "My special black box with a definition"

        qc = QuantumCircuit(1)
        qc.append(custom_gate, [0])
        qpy_file = io.BytesIO()
        dump(qc, qpy_file)
        qpy_file.seek(0)
        new_circ = load(qpy_file)[0]
        self.assertEqual(qc, new_circ)
        self.assertEqual(qc.decompose(), new_circ.decompose())
        self.assertEqual([x[0].label for x in qc.data], [x[0].label for x in new_circ.data])
    def test_nested_controlled_gate(self):
        """Test a custom nested controlled gate."""
        custom_gate = Gate("black_box", 1, [])
        custom_definition = QuantumCircuit(1)
        custom_definition.h(0)
        custom_definition.rz(1.5, 0)
        custom_definition.sdg(0)
        custom_gate.definition = custom_definition

        qc = QuantumCircuit(3)
        qc.append(custom_gate, [0])
        controlled_gate = custom_gate.control(2)
        qc.append(controlled_gate, [0, 1, 2])
        qpy_file = io.BytesIO()
        dump(qc, qpy_file)
        qpy_file.seek(0)
        new_circ = load(qpy_file)[0]
        self.assertEqual(qc, new_circ)
        self.assertEqual(qc.decompose(), new_circ.decompose())
Пример #7
0
    def inverse(self):
        """Return the inverse.

        This does not re-compute the decomposition for the multiplexer with the inverse of the
        gates but simply inverts the existing decomposition.
        """
        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()))

        definition.global_phase = -self.definition.global_phase

        inverse_gate.definition = definition
        return inverse_gate
Пример #8
0
def generate_open_controlled_gates():
    """Test QPY serialization with custom ControlledGates with open controls."""
    circuits = []
    qc = QuantumCircuit(3)
    controlled_gate = DCXGate().control(1, ctrl_state=0)
    qc.append(controlled_gate, [0, 1, 2])
    circuits.append(qc)

    custom_gate = Gate("black_box", 1, [])
    custom_definition = QuantumCircuit(1)
    custom_definition.h(0)
    custom_definition.rz(1.5, 0)
    custom_definition.sdg(0)
    custom_gate.definition = custom_definition
    nested_qc = QuantumCircuit(3)
    nested_qc.append(custom_gate, [0])
    controlled_gate = custom_gate.control(2, ctrl_state=1)
    nested_qc.append(controlled_gate, [0, 1, 2])
    nested_qc.measure_all()
    circuits.append(nested_qc)

    return circuits
Пример #9
0
def circuit_to_gate(circuit, parameter_map=None):
    """Build a ``Gate`` object from a ``QuantumCircuit``.

    The gate is anonymous (not tied to a named quantum register),
    and so can be inserted into another circuit. The gate will
    have the same string name as the circuit.

    Args:
        circuit (QuantumCircuit): the input circuit.
        parameter_map (dict): For parameterized circuits, a mapping from
           parameters in the circuit to parameters to be used in the gate.
           If None, existing circuit parameters will also parameterize the
           Gate.

    Raises:
        QiskitError: if circuit is non-unitary or if
            parameter_map is not compatible with circuit

    Return:
        Gate: a Gate equivalent to the action of the
        input circuit. Upon decomposition, this gate will
        yield the components comprising the original circuit.
    """
    if circuit.clbits:
        raise QiskitError('Circuit with classical bits cannot be converted '
                          'to gate.')

    for inst, _, _ in circuit.data:
        if not isinstance(inst, Gate):
            raise QiskitError(
                ('One or more instructions cannot be converted to'
                 ' a gate. "{}" is not a gate instruction').format(inst.name))

    if parameter_map is None:
        parameter_dict = {p: p for p in circuit.parameters}
    else:
        parameter_dict = circuit._unroll_param_dict(parameter_map)

    if parameter_dict.keys() != circuit.parameters:
        raise QiskitError(('parameter_map should map all circuit parameters. '
                           'Circuit parameters: {}, parameter_map: {}').format(
                               circuit.parameters, parameter_dict))

    gate = Gate(name=circuit.name,
                num_qubits=sum([qreg.size for qreg in circuit.qregs]),
                params=sorted(parameter_dict.values(), key=lambda p: p.name))
    gate.condition = None

    def find_bit_position(bit):
        """find the index of a given bit (Register, int) within
        a flat ordered list of bits of the circuit
        """
        if isinstance(bit, Qubit):
            ordered_regs = circuit.qregs
        else:
            ordered_regs = circuit.cregs
        reg_index = ordered_regs.index(bit.register)
        return sum([reg.size for reg in ordered_regs[:reg_index]]) + bit.index

    target = circuit.assign_parameters(parameter_dict, inplace=False)

    # pylint: disable=cyclic-import
    from qiskit.circuit.equivalence_library import SessionEquivalenceLibrary as sel
    # pylint: enable=cyclic-import
    sel.add_equivalence(gate, target)

    definition = target.data

    if gate.num_qubits > 0:
        q = QuantumRegister(gate.num_qubits, 'q')

    # The 3rd parameter in the output tuple) is hard coded to [] because
    # Gate objects do not have cregs set and we've verified that all
    # instructions are gates
    definition = list(
        map(
            lambda x:
            (x[0], list(map(lambda y: q[find_bit_position(y)], x[1])), []),
            definition))
    gate.definition = definition

    return gate
Пример #10
0
def circuit_to_gate(circuit, parameter_map=None, equivalence_library=None, label=None):
    """Build a ``Gate`` object from a ``QuantumCircuit``.

    The gate is anonymous (not tied to a named quantum register),
    and so can be inserted into another circuit. The gate will
    have the same string name as the circuit.

    Args:
        circuit (QuantumCircuit): the input circuit.
        parameter_map (dict): For parameterized circuits, a mapping from
           parameters in the circuit to parameters to be used in the gate.
           If None, existing circuit parameters will also parameterize the
           Gate.
        equivalence_library (EquivalenceLibrary): Optional equivalence library
           where the converted gate will be registered.
        label (str): Optional gate label.

    Raises:
        QiskitError: if circuit is non-unitary or if
            parameter_map is not compatible with circuit

    Return:
        Gate: a Gate equivalent to the action of the
        input circuit. Upon decomposition, this gate will
        yield the components comprising the original circuit.
    """
    # pylint: disable=cyclic-import
    from qiskit.circuit.quantumcircuit import QuantumCircuit

    if circuit.clbits:
        raise QiskitError("Circuit with classical bits cannot be converted " "to gate.")

    for inst, _, _ in circuit.data:
        if not isinstance(inst, Gate):
            raise QiskitError(
                (
                    "One or more instructions cannot be converted to"
                    ' a gate. "{}" is not a gate instruction'
                ).format(inst.name)
            )

    if parameter_map is None:
        parameter_dict = {p: p for p in circuit.parameters}
    else:
        parameter_dict = circuit._unroll_param_dict(parameter_map)

    if parameter_dict.keys() != circuit.parameters:
        raise QiskitError(
            (
                "parameter_map should map all circuit parameters. "
                "Circuit parameters: {}, parameter_map: {}"
            ).format(circuit.parameters, parameter_dict)
        )

    gate = Gate(
        name=circuit.name,
        num_qubits=sum([qreg.size for qreg in circuit.qregs]),
        params=[*parameter_dict.values()],
        label=label,
    )
    gate.condition = None

    target = circuit.assign_parameters(parameter_dict, inplace=False)

    if equivalence_library is not None:
        equivalence_library.add_equivalence(gate, target)

    rules = target.data

    if gate.num_qubits > 0:
        q = QuantumRegister(gate.num_qubits, "q")

    qubit_map = {bit: q[idx] for idx, bit in enumerate(circuit.qubits)}

    # The 3rd parameter in the output tuple) is hard coded to [] because
    # Gate objects do not have cregs set and we've verified that all
    # instructions are gates
    rules = [(inst, [qubit_map[y] for y in qargs], []) for inst, qargs, _ in rules]
    qc = QuantumCircuit(q, name=gate.name, global_phase=target.global_phase)
    for instr, qargs, cargs in rules:
        qc._append(instr, qargs, cargs)
    gate.definition = qc
    return gate
Пример #11
0
def circuit_to_gate(circuit, parameter_map=None):
    """Build a ``Gate`` object from a ``QuantumCircuit``.

    The gate is anonymous (not tied to a named quantum register),
    and so can be inserted into another circuit. The gate will
    have the same string name as the circuit.

    Args:
        circuit (QuantumCircuit): the input circuit.
        parameter_map (dict): For parameterized circuits, a mapping from
           parameters in the circuit to parameters to be used in the gate.
           If None, existing circuit parameters will also parameterize the
           Gate.

    Raises:
        QiskitError: if circuit is non-unitary or if
            parameter_map is not compatible with circuit

    Return:
        Gate: a Gate equivalent to the action of the
            input circuit. Upon decomposition, this gate will
            yield the components comprising the original circuit.
    """
    for inst, _, _ in circuit.data:
        if not isinstance(inst, Gate):
            raise QiskitError('One or more instructions in this instruction '
                              'cannot be converted to a gate')

    if parameter_map is None:
        parameter_dict = {p: p for p in circuit.parameters}
    else:
        parameter_dict = circuit._unroll_param_dict(parameter_map)

    if parameter_dict.keys() != circuit.parameters:
        raise QiskitError(('parameter_map should map all circuit parameters. '
                           'Circuit parameters: {}, parameter_map: {}').format(
                               circuit.parameters, parameter_dict))

    gate = Gate(name=circuit.name,
                num_qubits=sum([qreg.size for qreg in circuit.qregs]),
                params=sorted(parameter_dict.values(), key=lambda p: p.name))
    gate.condition = None

    def find_bit_position(bit):
        """find the index of a given bit (Register, int) within
        a flat ordered list of bits of the circuit
        """
        if isinstance(bit, Qubit):
            ordered_regs = circuit.qregs
        else:
            ordered_regs = circuit.cregs
        reg_index = ordered_regs.index(bit.register)
        return sum([reg.size for reg in ordered_regs[:reg_index]]) + bit.index

    target = circuit.copy()
    target._substitute_parameters(parameter_dict)

    definition = target.data

    if gate.num_qubits > 0:
        q = QuantumRegister(gate.num_qubits, 'q')

    definition = list(
        map(
            lambda x:
            (x[0], list(map(lambda y: q[find_bit_position(y)], x[1]))),
            definition))
    gate.definition = definition

    return gate