Пример #1
0
    def run(self, dag: DAGCircuit) -> DAGCircuit:
        """Run the Decompose pass on `dag`.

        Args:
            dag: input dag.

        Returns:
            output dag where ``gate`` was expanded.
        """
        # Walk through the DAG and expand each non-basis node
        for node in dag.op_nodes():
            if self._should_decompose(node):
                if getattr(node.op, "definition", None) is None:
                    continue
                # TODO: allow choosing among multiple decomposition rules
                rule = node.op.definition.data
                if len(rule) == 1 and len(node.qargs) == len(
                        rule[0].qubits) == 1:
                    if node.op.definition.global_phase:
                        dag.global_phase += node.op.definition.global_phase
                    dag.substitute_node(node, rule[0].operation, inplace=True)
                else:
                    decomposition = circuit_to_dag(node.op.definition)
                    dag.substitute_node_with_dag(node, decomposition)

        return dag
Пример #2
0
    def run(self, dag: DAGCircuit) -> DAGCircuit:
        """Run the UnitarySynthesis pass on `dag`.

        Args:
            dag: input dag.

        Returns:
            Output dag with UnitaryGates synthesized to target basis.
        """
        for node in dag.nodes():
            if node.type != 'op':
                continue  # skip all nodes that do not represent operations

            if not node.op.num_qubits == 1:
                continue  # ignore all non-single qubit gates, possible raise error here?

            matrix = node.op.to_matrix()

            # call solovay kitaev
            approximation = self._sk.run(matrix, self._recursion_degree)

            # convert to a dag and replace the gate by the approximation
            substitute = circuit_to_dag(approximation)
            dag.substitute_node_with_dag(node, substitute)

        return dag
Пример #3
0
    def run(self, dag: DAGCircuit) -> DAGCircuit:
        """Run the Decompose pass on `dag`.

        Args:
            dag: input dag.

        Returns:
            output dag where ``gate`` was expanded.
        """
        # Walk through the DAG and expand each non-basis node
        for node in dag.op_nodes(self.gate):
            # opaque or built-in gates are not decomposable
            if not node.op.definition:
                continue
            if node.op.definition.global_phase:
                dag.global_phase += node.op.definition.global_phase
            # TODO: allow choosing among multiple decomposition rules
            rule = node.op.definition.data

            if len(rule) == 1 and len(node.qargs) == len(rule[0][1]) == 1:
                dag.substitute_node(node, rule[0][0], inplace=True)
            else:
                decomposition = circuit_to_dag(node.op.definition)
                dag.substitute_node_with_dag(node, decomposition)
        return dag
Пример #4
0
def circuit_stripping(circuit,gates_to_strip):
    dag = circuit_to_dag(circuit)
    stripped_dag = DAGCircuit()
    [stripped_dag.add_qreg(x) for x in circuit.qregs]
    for vertex in dag.topological_op_nodes():
        if vertex.op.name not in gates_to_strip:
            stripped_dag.apply_operation_back(op=vertex.op, qargs=vertex.qargs)
    return dag_to_circuit(stripped_dag)
Пример #5
0
def circuit_stripping(circuit):
    # Remove all single qubit gates and barriers in the circuit
    dag = circuit_to_dag(circuit)
    stripped_dag = DAGCircuit()
    [stripped_dag.add_qreg(x) for x in circuit.qregs]
    for vertex in dag.topological_op_nodes():
        if len(vertex.qargs) == 2 and vertex.op.name!='barrier':
            stripped_dag.apply_operation_back(op=vertex.op, qargs=vertex.qargs)
    return dag_to_circuit(stripped_dag)
Пример #6
0
def dagdependency_to_dag(dagdependency):
    """Build a ``DAGCircuit`` object from a ``DAGDependency``.

    Args:
        dag dependency (DAGDependency): the input dag.

    Return:
        DAGCircuit: the DAG representing the input circuit.
    """

    dagcircuit = DAGCircuit()
    dagcircuit.name = dagdependency.name

    qregs = list(dagdependency.qregs.values())
    cregs = list(dagdependency.cregs.values())

    for register in qregs:
        dagcircuit.add_qreg(register)

    for register in cregs:
        dagcircuit.add_creg(register)

    for node in dagdependency.get_nodes():
        # Get arguments for classical control (if any)
        inst = node.op.copy()
        inst.condition = node.condition

        dagcircuit.apply_operation_back(inst, node.qargs, node.cargs,
                                        inst.condition)

    return dagcircuit
Пример #7
0
def circuit_to_dag(circuit):
    """Build a ``DAGCircuit`` object from a ``QuantumCircuit``.

    Args:
        circuit (QuantumCircuit): the input circuit.

    Return:
        DAGCircuit: the DAG representing the input circuit.
    """
    dagcircuit = DAGCircuit()
    dagcircuit.name = circuit.name
    for register in circuit.qregs:
        dagcircuit.add_qreg(register)
    for register in circuit.cregs:
        dagcircuit.add_creg(register)

    for instruction, qargs, cargs in circuit.data:
        # Get arguments for classical control (if any)
        if instruction.control is None:
            control = None
        else:
            control = (instruction.control[0], instruction.control[1])

        instruction = copy.deepcopy(instruction)
        dagcircuit.apply_operation_back(instruction, qargs, cargs, control)

    return dagcircuit
    def run(self, dag: DAGCircuit) -> DAGCircuit:
        """Run the UnitarySynthesis pass on `dag`.

        Args:
            dag: input dag.

        Returns:
            Output dag with UnitaryGates synthesized to target basis.

        Raises:
            TranspilerError:
                1. pulse_optimize is True but pulse optimal decomposition is not known
                   for requested basis.
                2. pulse_optimize is True and natural_direction is True but a preferred
                   gate direction can't be determined from the coupling map or the
                   relative gate lengths.
        """

        euler_basis = _choose_euler_basis(self._basis_gates)
        kak_gate = _choose_kak_gate(self._basis_gates)
        decomposer1q, decomposer2q = None, None
        if euler_basis is not None:
            decomposer1q = one_qubit_decompose.OneQubitEulerDecomposer(
                euler_basis)
        if kak_gate is not None:
            decomposer2q = TwoQubitBasisDecomposer(
                kak_gate,
                euler_basis=euler_basis,
                pulse_optimize=self._pulse_optimize)

        for node in dag.named_nodes(*self._synth_gates):
            if self._basis_gates and node.name in self._basis_gates:
                continue
            synth_dag = None
            wires = None
            if len(node.qargs) == 1:
                if decomposer1q is None:
                    continue
                synth_dag = circuit_to_dag(
                    decomposer1q._decompose(node.op.to_matrix()))
            elif len(node.qargs) == 2:
                if decomposer2q is None:
                    continue
                synth_dag, wires = self._synth_natural_direction(
                    node, dag, decomposer2q)
            else:
                synth_dag = circuit_to_dag(
                    isometry.Isometry(node.op.to_matrix(), 0, 0).definition)

            dag.substitute_node_with_dag(node, synth_dag, wires=wires)

        return dag
Пример #9
0
def circuit_to_dag(circuit):
    """Build a ``DAGCircuit`` object from a ``QuantumCircuit``.

    Args:
        circuit (QuantumCircuit): the input circuit.

    Return:
        DAGCircuit: the DAG representing the input circuit.
    """
    dagcircuit = DAGCircuit()
    dagcircuit.name = circuit.name
    for register in circuit.qregs:
        dagcircuit.add_qreg(register)
    for register in circuit.cregs:
        dagcircuit.add_creg(register)

    for instruction, qargs, cargs in circuit.data:
        # Get arguments for classical control (if any)
        if instruction.control is None:
            control = None
        else:
            control = (instruction.control[0], instruction.control[1])

        def duplicate_instruction(inst):
            """Create a fresh instruction from an input instruction."""
            if issubclass(inst.__class__,
                          inst_mod.Instruction) and inst.__class__ not in [
                              inst_mod.Instruction, gate.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.Gate):
                    new_inst = gate.Gate(inst.name, inst.num_qubits,
                                         inst.params)
                else:
                    new_inst = inst_mod.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

        dagcircuit.apply_operation_back(duplicate_instruction(instruction),
                                        qargs, cargs, control)

    return dagcircuit
    def run(self, dag: DAGCircuit) -> DAGCircuit:
        """Run the LinearFunctionsSynthesis pass on `dag`.
        Args:
            dag: input dag.
        Returns:
            Output dag with LinearFunctions synthesized.
        """

        for node in dag.named_nodes("linear_function"):
            decomposition = circuit_to_dag(node.op.definition)
            dag.substitute_node_with_dag(node, decomposition)

        return dag
Пример #11
0
    def run(self, dag: DAGCircuit) -> DAGCircuit:
        """Run the HighLevelSynthesis pass on `dag`.
        Args:
            dag: input dag.
        Returns:
            Output dag with high level objects synthesized.
        """

        for node in dag.named_nodes("clifford"):
            decomposition = circuit_to_dag(decompose_clifford(node.op))
            dag.substitute_node_with_dag(node, decomposition)

        return dag
Пример #12
0
def dag_stripping(dag, max_gates):
    '''
    Remove all single qubit gates and barriers in the DAG
    Only leaves the first max_gates gates
    If max_gates is None, do all gates
    '''
    stripped_dag = DAGCircuit()
    [stripped_dag.add_qreg(dag.qregs[qreg_name]) for qreg_name in dag.qregs]
    vertex_added = 0
    for vertex in dag.topological_op_nodes():
        within_gate_count = max_gates is None or vertex_added<max_gates
        if vertex.op.name!='barrier' and len(vertex.qargs)==2 and within_gate_count:
            stripped_dag.apply_operation_back(op=vertex.op, qargs=vertex.qargs)
            vertex_added += 1
    return stripped_dag
    def run(self, dag: DAGCircuit) -> DAGCircuit:
        """Run the LinearFunctionsToPermutations pass on `dag`.
        Args:
            dag: input dag.
        Returns:
            Output dag with LinearFunctions synthesized.
        """

        for node in dag.named_nodes("linear_function"):
            try:
                pattern = node.op.permutation_pattern()
            except CircuitError:
                continue

            permutation = Permutation(len(pattern), pattern)
            dag.substitute_node(node, permutation.to_instruction())
        return dag
Пример #14
0
def circuit_to_dag(circuit):
    """Build a ``DAGCircuit`` object from a ``QuantumCircuit``.

    Args:
        circuit (QuantumCircuit): the input circuit.

    Return:
        DAGCircuit: the DAG representing the input circuit.
    """
    dagcircuit = DAGCircuit()
    dagcircuit.name = circuit.name
    for register in circuit.qregs:
        dagcircuit.add_qreg(register)
    for register in circuit.cregs:
        dagcircuit.add_creg(register)

    for main_instruction in circuit.data:
        # TODO: generate nodes for CompositeGates;
        # for now simply drop their instructions into the DAG
        instruction_list = []
        is_composite = isinstance(main_instruction, CompositeGate)
        if is_composite:
            instruction_list = main_instruction.instruction_list()
        else:
            instruction_list.append(main_instruction)

        for instruction in instruction_list:
            # Get arguments for classical control (if any)
            if instruction.control is None:
                control = None
            else:
                control = (instruction.control[0], instruction.control[1])

            def duplicate_instruction(inst):
                """Create a fresh instruction from an input instruction."""
                if inst.name == 'barrier':
                    params = [inst.qargs]
                elif inst.name == 'snapshot':
                    params = inst.params + [inst.qargs]
                else:
                    params = inst.params + inst.qargs + inst.cargs
                new_inst = inst.__class__(*params)
                return new_inst

            inst = duplicate_instruction(instruction)
            dagcircuit.apply_operation_back(inst, inst.qargs, inst.cargs,
                                            control)

    return dagcircuit
Пример #15
0
 def apply_back_to_dag_circuit(
     self,
     dag_circuit: DAGCircuit,
     initial_mapping: ty.Dict[Qubit, int],
     trans_mapping: ty.Dict[Qubit, int],
 ):
     reversed_trans_mapping = {
         val: key
         for key, val in trans_mapping.items()
     }
     for op in self._operations:
         logical_qubits = [initial_mapping[qubit] for qubit in op.qargs]
         new_physical_qubits = [
             reversed_trans_mapping[qubit_index]
             for qubit_index in logical_qubits
         ]
         #print(new_physical_qubits)
         dag_circuit.apply_operation_back(op.op, new_physical_qubits,
                                          op.cargs, op.condition)
Пример #16
0
def _to_dag(circuit):
    qiskit_dag = DAGCircuit()
    qreg = QuantumRegister(circuit.num_qubits())
    qiskit_dag.add_qreg(qreg)
    if circuit.num_cbits():
        creg = ClassicalRegister(circuit.num_cbits())
        qiskit_dag.add_creg(creg)
    for instruction in circuit:
        gate = _convert_tweedledum_op(instruction)
        qubits = [qreg[qubit.uid()] for qubit in instruction.qubits()]
        cbits = [creg[cbit.uid()] for cbit in instruction.cbits()]
        qiskit_dag.apply_operation_back(gate, qubits, cbits)
    return qiskit_dag
Пример #17
0
    def run(self, dag: DAGCircuit) -> DAGCircuit:
        """Run the UnitarySynthesis pass on `dag`.

        Args:
            dag: input dag.

        Returns:
            Output dag with UnitaryGates synthesized to target basis.
        """
        euler_basis = _choose_euler_basis(self._basis_gates)
        kak_gate = _choose_kak_gate(self._basis_gates)

        decomposer1q, decomposer2q = None, None
        if euler_basis is not None:
            decomposer1q = one_qubit_decompose.OneQubitEulerDecomposer(
                euler_basis)
        if kak_gate is not None:
            decomposer2q = TwoQubitBasisDecomposer(kak_gate,
                                                   euler_basis=euler_basis)

        for node in dag.named_nodes("unitary"):

            synth_dag = None
            if len(node.qargs) == 1:
                if decomposer1q is None:
                    continue
                synth_dag = circuit_to_dag(
                    decomposer1q._decompose(node.op.to_matrix()))
            elif len(node.qargs) == 2:
                if decomposer2q is None:
                    continue
                synth_dag = circuit_to_dag(
                    decomposer2q(node.op.to_matrix(),
                                 basis_fidelity=self._approximation_degree))
            else:
                synth_dag = circuit_to_dag(
                    isometry.Isometry(node.op.to_matrix(), 0, 0).definition)

            dag.substitute_node_with_dag(node, synth_dag)

        return dag
Пример #18
0
def _create_empty_dagcircuit_from_existing(dagcircuit: DAGCircuit) -> DAGCircuit:
    result = DAGCircuit()
    for creg in dagcircuit.cregs.values():
        result.add_creg(creg)
    for qreg in dagcircuit.qregs.values():
        result.add_qreg(qreg)
    return result
Пример #19
0
def circuit_to_dag(circuit):
    """Build a ``DAGCircuit`` object from a ``QuantumCircuit``.

    Args:
        circuit (QuantumCircuit): the input circuit.

    Return:
        DAGCircuit: the DAG representing the input circuit.

    Example:
        .. jupyter-execute::

            from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit
            from qiskit.dagcircuit import DAGCircuit
            from qiskit.converters import circuit_to_dag
            from qiskit.visualization import dag_drawer
            %matplotlib inline

            q = QuantumRegister(3, 'q')
            c = ClassicalRegister(3, 'c')
            circ = QuantumCircuit(q, c)
            circ.h(q[0])
            circ.cx(q[0], q[1])
            circ.measure(q[0], c[0])
            circ.rz(0.5, q[1]).c_if(c, 2)
            dag = circuit_to_dag(circ)
            dag_drawer(dag)
    """
    dagcircuit = DAGCircuit()
    dagcircuit.name = circuit.name
    dagcircuit.global_phase = circuit.global_phase

    for register in circuit.qregs:
        dagcircuit.add_qreg(register)
    for register in circuit.cregs:
        dagcircuit.add_creg(register)

    for instruction, qargs, cargs in circuit.data:
        dagcircuit.apply_operation_back(instruction.copy(), qargs, cargs)
    return dagcircuit
Пример #20
0
def tweedledum_to_qiskit_dag(circuit):
    qiskit_dag = DAGCircuit()
    qiskit_dag.add_qreg(circuit.num_qubits(), circuit.num_cbits())
    for instruction in circuit:
        gate = _convert_tweedledum_op(instruction)
        qubits = [qubit.uid() for qubit in instruction.qubits()]
        cbits = [cbit.uid() for cbit in instruction.cbits()]
        qiskit_dag.apply_operation_back(gate, qubits, cbits)
    return qiskit_dag
Пример #21
0
def circuit_to_dag(circuit):
    """Build a ``DAGCircuit`` object from a ``QuantumCircuit``.

    Args:
        circuit (QuantumCircuit): the input circuit.

    Return:
        DAGCircuit: the DAG representing the input circuit.
    """
    dagcircuit = DAGCircuit()
    dagcircuit.name = circuit.name
    for register in circuit.qregs:
        dagcircuit.add_qreg(register)
    for register in circuit.cregs:
        dagcircuit.add_creg(register)

    for instruction, qargs, cargs in circuit.data:
        dagcircuit.apply_operation_back(instruction.copy(), qargs, cargs,
                                        instruction.condition)
    return dagcircuit
    def __init__(self, max_matches, circuit_dag_dep, template_dag_dep):
        """
        Initialize TemplateSubstitution with necessary arguments.
        Args:
            max_matches (list): list of maximal matches obtained from the running
             the template matching algorithm.
            circuit_dag_dep (DAGDependency): circuit in the dag dependency form.
            template_dag_dep (DAGDependency): template in the dag dependency form.
        """

        self.match_stack = max_matches
        self.circuit_dag_dep = circuit_dag_dep
        self.template_dag_dep = template_dag_dep

        self.substitution_list = []
        self.unmatched_list = []
        self.dag_dep_optimized = DAGDependency()
        self.dag_optimized = DAGCircuit()
Пример #23
0
 def apply(self, dag_circuit: DAGCircuit, front_layer: QuantumLayer,
           initial_mapping: ty.Dict[Qubit, int],
           trans_mapping: ty.Dict[Qubit, int]):
     dag_circuit.apply_operation_back(CXGate(), [self.left, self.middle])
     dag_circuit.apply_operation_back(CXGate(), [self.middle, self.right])
     dag_circuit.apply_operation_back(CXGate(), [self.left, self.middle])
     dag_circuit.apply_operation_back(CXGate(), [self.middle, self.right])
     # dag_circuit.apply_operation_back(
     #     _BridgeGate(), [self.left, self.middle, self.right]
     # )
     # Do not forget to remove the CNOT gate from self.left to self.right from the
     # front layer.
     op_to_remove: ty.Optional[DAGNode] = None
     for op in front_layer.ops:
         q1, q2 = initial_mapping[op.qargs[0]], initial_mapping[op.qargs[1]]
         if (len(op.qargs) == 2 and q1 == trans_mapping[self.left]
                 and q2 == trans_mapping[self.right]):
             op_to_remove = op
     if op_to_remove is None:
         logger.warning(
             "Could not find a corresponding CNOT gate to remove with "
             "Bridge usage. Resulting circuit will likely be wrong.")
     else:
         front_layer.remove_operation(op_to_remove)
Пример #24
0
    def run(self, dag: DAGCircuit) -> DAGCircuit:
        """Run the Decompose pass on `dag`.

        Args:
            dag: input dag.

        Returns:
            output dag where ``gate`` was expanded.
        """
        # Walk through the DAG and expand each non-basis node
        for node in dag.op_nodes(self.gate):
            # opaque or built-in gates are not decomposable
            if not node.op.definition:
                continue
            # TODO: allow choosing among multiple decomposition rules
            rule = node.op.definition

            if len(rule) == 1 and len(node.qargs) == len(rule[0][1]):
                dag.substitute_node(node, rule[0][0], inplace=True)
            else:
                # hacky way to build a dag on the same register as the rule is defined
                # TODO: need anonymous rules to address wires by index
                decomposition = DAGCircuit()
                qregs = {qb.register for inst in rule for qb in inst[1]}
                cregs = {cb.register for inst in rule for cb in inst[2]}
                for qreg in qregs:
                    decomposition.add_qreg(qreg)
                for creg in cregs:
                    decomposition.add_creg(creg)
                for inst in rule:
                    decomposition.apply_operation_back(*inst)
                dag.substitute_node_with_dag(node, decomposition)
        return dag
    def __init__(self,
                 max_matches,
                 circuit_dag_dep,
                 template_dag_dep,
                 user_cost_dict=None):
        """
        Initialize TemplateSubstitution with necessary arguments.
        Args:
            max_matches (list): list of maximal matches obtained from the running
             the template matching algorithm.
            circuit_dag_dep (DAGDependency): circuit in the dag dependency form.
            template_dag_dep (DAGDependency): template in the dag dependency form.
            user_cost_dict (Optional[dict]): user provided cost dictionary that will override
                the default cost dictionary.
        """

        self.match_stack = max_matches
        self.circuit_dag_dep = circuit_dag_dep
        self.template_dag_dep = template_dag_dep

        self.substitution_list = []
        self.unmatched_list = []
        self.dag_dep_optimized = DAGDependency()
        self.dag_optimized = DAGCircuit()

        if user_cost_dict is not None:
            self.cost_dict = dict(user_cost_dict)
        else:
            self.cost_dict = {
                "id": 0,
                "x": 1,
                "y": 1,
                "z": 1,
                "h": 1,
                "t": 1,
                "tdg": 1,
                "s": 1,
                "sdg": 1,
                "u1": 1,
                "u2": 2,
                "u3": 2,
                "rx": 1,
                "ry": 1,
                "rz": 1,
                "r": 2,
                "cx": 2,
                "cy": 4,
                "cz": 4,
                "ch": 8,
                "swap": 6,
                "iswap": 8,
                "rxx": 9,
                "ryy": 9,
                "rzz": 5,
                "rzx": 7,
                "ms": 9,
                "cu3": 10,
                "crx": 10,
                "cry": 10,
                "crz": 10,
                "ccx": 21,
                "rccx": 12,
                "c3x": 96,
                "rc3x": 24,
                "c4x": 312,
                "p": 1,
            }
Пример #26
0
    def run(self, dag: DAGCircuit) -> DAGCircuit:
        """Run the UnitarySynthesis pass on `dag`.

        Args:
            dag: input dag.

        Returns:
            Output dag with UnitaryGates synthesized to target basis.

        Raises:
            TranspilerError: if a 'method' was specified for the class and is not
                found in the installed plugins list. The list of installed
                plugins can be queried with
                :func:`~qiskit.transpiler.passes.synthesis.plugin.unitary_synthesis_plugin_names`
        """
        if self.method not in self.plugins.ext_plugins:
            raise TranspilerError(
                "Specified method: %s not found in plugin list" % self.method)
        default_method = self.plugins.ext_plugins["default"].obj
        plugin_method = self.plugins.ext_plugins[self.method].obj
        if plugin_method.supports_coupling_map:
            dag_bit_indices = {bit: idx for idx, bit in enumerate(dag.qubits)}
        kwargs = {}
        if plugin_method.supports_basis_gates:
            kwargs["basis_gates"] = self._basis_gates
        if plugin_method.supports_natural_direction:
            kwargs["natural_direction"] = self._natural_direction
        if plugin_method.supports_pulse_optimize:
            kwargs["pulse_optimize"] = self._pulse_optimize
        if plugin_method.supports_gate_lengths:
            kwargs["gate_lengths"] = _build_gate_lengths(self._backend_props)
        if plugin_method.supports_gate_errors:
            kwargs["gate_errors"] = _build_gate_errors(self._backend_props)
        supported_bases = plugin_method.supported_bases
        if supported_bases is not None:
            kwargs["matched_basis"] = _choose_bases(self._basis_gates,
                                                    supported_bases)

        # Handle approximation degree as a special case for backwards compatibility, it's
        # not part of the plugin interface and only something needed for the default
        # pass.
        default_method._approximation_degree = self._approximation_degree
        if self.method == "default":
            plugin_method._approximation_degree = self._approximation_degree

        for node in dag.named_nodes(*self._synth_gates):
            if self._min_qubits is not None and len(
                    node.qargs) < self._min_qubits:
                continue
            if plugin_method.supports_coupling_map:
                kwargs["coupling_map"] = (
                    self._coupling_map,
                    [dag_bit_indices[x] for x in node.qargs],
                )
            synth_dag = None
            unitary = node.op.to_matrix()
            n_qubits = len(node.qargs)
            if (plugin_method.max_qubits is not None
                    and n_qubits > plugin_method.max_qubits) or (
                        plugin_method.min_qubits is not None
                        and n_qubits < plugin_method.min_qubits):
                synth_dag = default_method.run(unitary, **kwargs)
            else:
                synth_dag = plugin_method.run(unitary, **kwargs)
            if synth_dag is not None:
                if isinstance(synth_dag, tuple):
                    dag.substitute_node_with_dag(node,
                                                 synth_dag[0],
                                                 wires=synth_dag[1])
                else:
                    dag.substitute_node_with_dag(node, synth_dag)
        return dag
def dagdependency_to_dag(dagdependency):
    """Build a ``DAGCircuit`` object from a ``DAGDependency``.

    Args:
        dag dependency (DAGDependency): the input dag.

    Return:
        DAGCircuit: the DAG representing the input circuit.
    """

    dagcircuit = DAGCircuit()
    dagcircuit.name = dagdependency.name
    dagcircuit.metadata = dagdependency.metadata

    dagcircuit.add_qubits(dagdependency.qubits)
    dagcircuit.add_clbits(dagdependency.clbits)

    for register in dagdependency.qregs.values():
        dagcircuit.add_qreg(register)

    for register in dagdependency.cregs.values():
        dagcircuit.add_creg(register)

    for node in dagdependency.get_nodes():
        # Get arguments for classical control (if any)
        inst = node.op.copy()
        dagcircuit.apply_operation_back(inst, node.qargs, node.cargs)

    # copy metadata
    dagcircuit.global_phase = dagdependency.global_phase
    dagcircuit.calibrations = dagdependency.calibrations

    return dagcircuit
Пример #28
0
 def apply(self, dag_circuit: DAGCircuit, front_layer: QuantumLayer,
           initial_mapping: ty.Dict[Qubit, int],
           trans_mapping: ty.Dict[Qubit, int]):
     dag_circuit.apply_operation_back(SwapGate(), [self.left, self.right])
Пример #29
0
    def __init__(self,
                 max_matches,
                 circuit_dag_dep,
                 template_dag_dep,
                 user_cost_dict=None):
        """
        Initialize TemplateSubstitution with necessary arguments.
        Args:
            max_matches (list): list of maximal matches obtained from the running
             the template matching algorithm.
            circuit_dag_dep (DAGDependency): circuit in the dag dependency form.
            template_dag_dep (DAGDependency): template in the dag dependency form.
            user_cost_dict (Optional[dict]): user provided cost dictionary that will override
                the default cost dictionary.
        """

        self.match_stack = max_matches
        self.circuit_dag_dep = circuit_dag_dep
        self.template_dag_dep = template_dag_dep

        self.substitution_list = []
        self.unmatched_list = []
        self.dag_dep_optimized = DAGDependency()
        self.dag_optimized = DAGCircuit()

        if user_cost_dict is not None:
            self.cost_dict = dict(user_cost_dict)
        else:
            self.cost_dict = {
                'id': 0,
                'x': 1,
                'y': 1,
                'z': 1,
                'h': 1,
                't': 1,
                'tdg': 1,
                's': 1,
                'sdg': 1,
                'u1': 1,
                'u2': 2,
                'u3': 2,
                'rx': 1,
                'ry': 1,
                'rz': 1,
                'r': 2,
                'cx': 2,
                'cy': 4,
                'cz': 4,
                'ch': 8,
                'swap': 6,
                'iswap': 8,
                'rxx': 9,
                'ryy': 9,
                'rzz': 5,
                'rzx': 7,
                'ms': 9,
                'cu3': 10,
                'crx': 10,
                'cry': 10,
                'crz': 10,
                'ccx': 21,
                'rccx': 12,
                'c3x': 96,
                'rc3x': 24,
                'c4x': 312,
                'p': 1
            }
Пример #30
0
    def run(self, dag: DAGCircuit) -> DAGCircuit:
        """Run the UnitarySynthesis pass on `dag`.

        Args:
            dag: input dag.

        Returns:
            Output dag with UnitaryGates synthesized to target basis.

        Raises:
            TranspilerError: if a 'method' was specified for the class and is not
                found in the installed plugins list. The list of installed
                plugins can be queried with
                :func:`~qiskit.transpiler.passes.synthesis.plugin.unitary_synthesis_plugin_names`
        """
        if self.method not in self.plugins.ext_plugins:
            raise TranspilerError(
                "Specified method: %s not found in plugin list" % self.method)
        # Return fast if we have no synth gates (ie user specified an empty
        # list or the synth gates are all in the basis
        if not self._synth_gates:
            return dag

        plugin_method = self.plugins.ext_plugins[self.method].obj
        plugin_kwargs = {"config": self._plugin_config}
        _gate_lengths = _gate_errors = None
        dag_bit_indices = {}

        if self.method == "default":
            # If the method is the default, we only need to evaluate one set of keyword arguments.
            # To simplify later logic, and avoid cases where static analysis might complain that we
            # haven't initialised the "default" handler, we rebind the names so they point to the
            # same object as the chosen method.
            default_method = plugin_method
            default_kwargs = plugin_kwargs
            method_list = [(plugin_method, plugin_kwargs)]
        else:
            # If the method is not the default, we still need to initialise the default plugin's
            # keyword arguments in case we have to fall back on it during the actual run.
            default_method = self.plugins.ext_plugins["default"].obj
            default_kwargs = {}
            method_list = [(plugin_method, plugin_kwargs),
                           (default_method, default_kwargs)]

        for method, kwargs in method_list:
            if method.supports_basis_gates:
                kwargs["basis_gates"] = self._basis_gates
            if method.supports_coupling_map:
                dag_bit_indices = dag_bit_indices or {
                    bit: i
                    for i, bit in enumerate(dag.qubits)
                }
            if method.supports_natural_direction:
                kwargs["natural_direction"] = self._natural_direction
            if method.supports_pulse_optimize:
                kwargs["pulse_optimize"] = self._pulse_optimize
            if method.supports_gate_lengths:
                _gate_lengths = _gate_lengths or _build_gate_lengths(
                    self._backend_props, self._target)
                kwargs["gate_lengths"] = _gate_lengths
            if method.supports_gate_errors:
                _gate_errors = _gate_errors or _build_gate_errors(
                    self._backend_props, self._target)
                kwargs["gate_errors"] = _gate_errors
            supported_bases = method.supported_bases
            if supported_bases is not None:
                kwargs["matched_basis"] = _choose_bases(
                    self._basis_gates, supported_bases)
            if method.supports_target:
                kwargs["target"] = self._target

        # Handle approximation degree as a special case for backwards compatibility, it's
        # not part of the plugin interface and only something needed for the default
        # pass.
        default_method._approximation_degree = self._approximation_degree
        if self.method == "default":
            plugin_method._approximation_degree = self._approximation_degree

        for node in dag.named_nodes(*self._synth_gates):
            if self._min_qubits is not None and len(
                    node.qargs) < self._min_qubits:
                continue
            synth_dag = None
            unitary = node.op.to_matrix()
            n_qubits = len(node.qargs)
            if (plugin_method.max_qubits is not None
                    and n_qubits > plugin_method.max_qubits) or (
                        plugin_method.min_qubits is not None
                        and n_qubits < plugin_method.min_qubits):
                method, kwargs = default_method, default_kwargs
            else:
                method, kwargs = plugin_method, plugin_kwargs
            if method.supports_coupling_map:
                kwargs["coupling_map"] = (
                    self._coupling_map,
                    [dag_bit_indices[x] for x in node.qargs],
                )
            synth_dag = method.run(unitary, **kwargs)
            if synth_dag is not None:
                if isinstance(synth_dag, tuple):
                    dag.substitute_node_with_dag(node,
                                                 synth_dag[0],
                                                 wires=synth_dag[1])
                else:
                    dag.substitute_node_with_dag(node, synth_dag)
        return dag