Exemple #1
0
    def test_block_spanning_two_regs_different_index(self):
        """blocks spanning wires on different quantum registers work when the wires
        could have conflicting indices. This was raised in #2806 when a CX was applied
        across multiple registers and their indices collided, raising an error."""
        qr0 = QuantumRegister(1, "qr0")
        qr1 = QuantumRegister(2, "qr1")
        qc = QuantumCircuit(qr0, qr1)
        qc.cx(qr0[0], qr1[1])
        dag = circuit_to_dag(qc)

        pass_ = ConsolidateBlocks(force_consolidate=True)
        pass_.property_set["block_list"] = [list(dag.topological_op_nodes())]
        new_dag = pass_.run(dag)

        original_unitary = UnitaryGate(Operator(qc))

        from qiskit.converters import dag_to_circuit

        new_unitary = UnitaryGate(Operator(dag_to_circuit(new_dag)))

        self.assertEqual(original_unitary, new_unitary)
Exemple #2
0
def _transpilation(circuit, backend=None, basis_gates=None, coupling_map=None,
                   initial_layout=None, seed_mapper=None,
                   pass_manager=None):
    """Perform transpilation of a single circuit.

    Args:
        circuit (QuantumCircuit): A circuit to transpile.
        backend (BaseBackend): a backend to compile for
        basis_gates (str): comma-separated basis gate set to compile to
        coupling_map (list): coupling map (perhaps custom) to target in mapping
        initial_layout (list): initial layout of qubits in mapping
        seed_mapper (int): random seed for the swap_mapper
        pass_manager (PassManager): a pass_manager for the transpiler stage

    Returns:
        QuantumCircuit: A transpiled circuit.

    Raises:
        TranspilerError: if args are not complete for transpiler to function.
    """
    dag = circuit_to_dag(circuit)
    if not backend and not initial_layout:
        raise TranspilerError('initial layout not supplied, and cannot '
                              'be inferred from backend.')
    if (initial_layout is None and not backend.configuration().simulator
            and not _matches_coupling_map(dag, coupling_map)):
        initial_layout = _pick_best_layout(dag, backend)

    final_dag, final_layout = transpile_dag(dag, basis_gates=basis_gates,
                                            coupling_map=coupling_map,
                                            initial_layout=initial_layout,
                                            get_layout=True, format='dag',
                                            seed_mapper=seed_mapper,
                                            pass_manager=pass_manager)
    final_dag.layout = [[k, v]
                        for k, v in final_layout.items()] if final_layout else None

    out_circuit = dag_to_circuit(final_dag)

    return out_circuit
def _remap_circuit_faulty_backend(circuit, num_qubits, backend_prop, faulty_qubits_map):
    faulty_qubits = backend_prop.faulty_qubits() if backend_prop else []
    disconnected_qubits = {k for k, v in faulty_qubits_map.items() if v is None}.difference(
        faulty_qubits
    )
    faulty_qubits_map_reverse = {v: k for k, v in faulty_qubits_map.items()}
    if faulty_qubits:
        faulty_qreg = circuit._create_qreg(len(faulty_qubits), "faulty")
    else:
        faulty_qreg = []
    if disconnected_qubits:
        disconnected_qreg = circuit._create_qreg(len(disconnected_qubits), "disconnected")
    else:
        disconnected_qreg = []

    new_layout = Layout()
    faulty_qubit = 0
    disconnected_qubit = 0

    for real_qubit in range(num_qubits):
        if faulty_qubits_map[real_qubit] is not None:
            new_layout[real_qubit] = circuit._layout[faulty_qubits_map[real_qubit]]
        else:
            if real_qubit in faulty_qubits:
                new_layout[real_qubit] = faulty_qreg[faulty_qubit]
                faulty_qubit += 1
            else:
                new_layout[real_qubit] = disconnected_qreg[disconnected_qubit]
                disconnected_qubit += 1
    physical_layout_dict = {}
    for index, qubit in enumerate(circuit.qubits):
        physical_layout_dict[qubit] = faulty_qubits_map_reverse[index]
    for qubit in faulty_qreg[:] + disconnected_qreg[:]:
        physical_layout_dict[qubit] = new_layout[qubit]
    dag_circuit = circuit_to_dag(circuit)
    apply_layout_pass = ApplyLayout()
    apply_layout_pass.property_set["layout"] = Layout(physical_layout_dict)
    circuit = dag_to_circuit(apply_layout_pass.run(dag_circuit))
    circuit._layout = new_layout
    return circuit
 def test_2q_hamiltonian(self):
     """test 2 qubit hamiltonian"""
     qr = QuantumRegister(2)
     cr = ClassicalRegister(2)
     qc = QuantumCircuit(qr, cr)
     matrix = Operator.from_label("XY")
     qc.x(qr[0])
     theta = Parameter("theta")
     uni2q = HamiltonianGate(matrix, theta)
     qc.append(uni2q, [qr[0], qr[1]])
     qc2 = qc.bind_parameters({theta: -np.pi / 2})
     dag = circuit_to_dag(qc2)
     nodes = dag.two_qubit_ops()
     self.assertEqual(len(nodes), 1)
     dnode = nodes[0]
     self.assertIsInstance(dnode.op, HamiltonianGate)
     self.assertEqual(dnode.qargs, [qr[0], qr[1]])
     # Equality based on Pauli exponential identity
     np.testing.assert_array_almost_equal(dnode.op.to_matrix(),
                                          1j * matrix.data)
     qc3 = dag_to_circuit(dag)
     self.assertEqual(qc2, qc3)
    def run(self, circuit):
        """Run all the passes on a QuantumCircuit

        Args:
            circuit (QuantumCircuit): circuit to transform via all the registered passes

        Returns:
            QuantumCircuit: Transformed circuit.
        """
        name = circuit.name
        dag = circuit_to_dag(circuit)
        del circuit
        self.reset()  # Reset passmanager instance before starting

        for passset in self.working_list:
            for pass_ in passset:
                dag = self._do_pass(pass_, dag, passset.options)

        circuit = dag_to_circuit(dag)
        circuit.name = name
        circuit.layout = self.property_set['layout']
        return circuit
Exemple #6
0
    def test_cx_bell_to_crz(self):
        """Verify we can translate a CX bell to CRZ,U."""
        bell = QuantumCircuit(2)
        bell.h(0)
        bell.cx(0, 1)

        in_dag = circuit_to_dag(bell)
        out_dag = BasisTranslator(std_eqlib, ["crz", "u"]).run(in_dag)

        self.assertTrue(set(out_dag.count_ops()).issubset(["crz", "u"]))
        self.assertEqual(Operator(bell), Operator(dag_to_circuit(out_dag)))

        qr = QuantumRegister(2, "q")
        expected = QuantumCircuit(qr)
        expected.u(pi / 2, 0, pi, 0)
        expected.u(0, 0, pi / 2, 0)
        expected.u(pi / 2, 0, pi, 1)
        expected.crz(pi, 0, 1)
        expected.u(pi / 2, 0, pi, 1)
        expected_dag = circuit_to_dag(expected)

        self.assertEqual(out_dag, expected_dag)
            def replace_node(node, instr_map):
                target_params, target_dag = instr_map[node.op.name, node.op.num_qubits]
                if len(node.op.params) != len(target_params):
                    raise TranspilerError(
                        "Translation num_params not equal to op num_params."
                        "Op: {} {} Translation: {}\n{}".format(
                            node.op.params, node.op.name, target_params, target_dag
                        )
                    )

                if node.op.params:
                    # Convert target to circ and back to assign_parameters, since
                    # DAGCircuits won't have a ParameterTable.
                    from qiskit.converters import dag_to_circuit, circuit_to_dag

                    target_circuit = dag_to_circuit(target_dag)

                    target_circuit.assign_parameters(
                        dict(zip_longest(target_params, node.op.params)), inplace=True
                    )

                    bound_target_dag = circuit_to_dag(target_circuit)
                else:
                    bound_target_dag = target_dag

                if len(bound_target_dag.op_nodes()) == 1 and len(
                    bound_target_dag.op_nodes()[0].qargs
                ) == len(node.qargs):
                    dag_op = bound_target_dag.op_nodes()[0].op
                    # dag_op may be the same instance as other ops in the dag,
                    # so if there is a condition, need to copy
                    if node.op.condition:
                        dag_op = dag_op.copy()
                    dag.substitute_node(node, dag_op, inplace=True)

                    if bound_target_dag.global_phase:
                        dag.global_phase += bound_target_dag.global_phase
                else:
                    dag.substitute_node_with_dag(node, bound_target_dag)
    def run(self, dag: DAGCircuit) -> DAGCircuit:
        """Run a preconfigured optimisation pass on the circuit and route for the given
        backend.

        :param dag: The circuit to optimise and route

        :return: The modified circuit
        """
        qc = dag_to_circuit(dag)
        old_parameters = qc.parameters
        circ = qiskit_to_tk(qc)
        self._pass.apply(circ)
        qc = tk_to_qiskit(circ)
        new_param_lookup = {p._symbol_expr: p for p in qc.parameters}
        subs_map = {
            new_param_lookup[p._symbol_expr]: p
            for p in old_parameters
        }
        qc.assign_parameters(subs_map, inplace=True)
        newdag = circuit_to_dag(qc)
        newdag.name = dag.name
        return newdag
Exemple #9
0
 def run(self, circuit:Circuit, shots:int, fit_to_constraints=True, seed:int=None) -> np.ndarray:
     """Run a circuit on Qiskit Aer Qasm simulator.
     
     :param circuit: The circuit to run
     :type circuit: Circuit
     :param shots: Number of shots (repeats) to run
     :type shots: int
     :param fit_to_constraints: Compile the circuit to meet the contstraints of the backend, defaults to True
     :type fit_to_constraints: bool, optional
     :param seed: random seed to for simulator
     :type seed: int
     :return: Table of shot results, each row is a shot, columns are ordered by qubit ordering. Values are 0 or 1, corresponding to qubit basis states.
     :rtype: numpy.ndarray
     """
     c = circuit.copy()
     if fit_to_constraints :
         Transform.RebaseToQiskit().apply(c)
     dag = tk_to_dagcircuit(c)
     qc = dag_to_circuit(dag)
     qobj = assemble(qc, shots=shots, seed_simulator=seed, memory=True)
     job = self._backend.run(qobj, noise_model=self.noise_model)
     return bin_str_2_table(job.result().get_memory(qc))
Exemple #10
0
    def __call__(self, circuit, property_set=None):
        """Runs the pass on circuit.

        Args:
            circuit (QuantumCircuit): the dag on which the pass is run.
            property_set (PropertySet or dict or None): input/output property set. An analysis pass
                might change the property set in-place.

        Returns:
            QuantumCircuit: If on transformation pass, the resulting QuantumCircuit. If analysis
                   pass, the input circuit.
        """
        from qiskit.converters import circuit_to_dag, dag_to_circuit
        from qiskit.dagcircuit.dagcircuit import DAGCircuit

        property_set_ = None
        if isinstance(property_set, dict):  # this includes (dict, PropertySet)
            property_set_ = PropertySet(property_set)

        if isinstance(property_set_, PropertySet):
            self.property_set = property_set_

        result = self.run(circuit_to_dag(circuit))

        result_circuit = circuit

        if isinstance(property_set, dict):  # this includes (dict, PropertySet)
            property_set.clear()
            property_set.update(self.property_set)

        if isinstance(result, DAGCircuit):
            result_circuit = dag_to_circuit(result)
        elif result is None:
            result_circuit = circuit.copy()

        if self.property_set["layout"]:
            result_circuit._layout = self.property_set["layout"]

        return result_circuit
    def test_plugin_configuration(self):
        """Tests plugin with a custom configuration."""
        config = {
            "network_layout": "sequ",
            "connectivity_type": "full",
            "depth": 0,
            "seed": 12345,
            "optimizer": SLSQP(),
        }
        transpiler_pass = UnitarySynthesis(
            basis_gates=["rx", "ry", "rz", "cx"],
            method="aqc",
            plugin_config=config)

        dag = circuit_to_dag(self._qc)
        dag = transpiler_pass.run(dag)

        approx_circuit = dag_to_circuit(dag)
        approx_unitary = Operator(approx_circuit).data

        np.testing.assert_array_almost_equal(self._target_unitary,
                                             approx_unitary, 3)
Exemple #12
0
    def apply(self, operation, wires, par):
        # type: (Any, Sequence[int], List) -> None
        """Apply a quantum operation.

        Args:
            operation (str): name of the operation
            wires (Sequence[int]): subsystems the operation is applied on
            par (tuple): parameters for the operation
        """

        mapped_operation = self._operation_map[operation]

        if isinstance(mapped_operation,
                      BasisState) and not self._first_operation:
            raise DeviceError(
                "Operation {} cannot be used after other Operations have already been applied "
                "on a {} device.".format(operation, self.short_name))
        self._first_operation = False

        qregs = [(self._reg, i) for i in wires]

        if isinstance(mapped_operation, str):
            dag = circuit_to_dag(QuantumCircuit(self._reg, self._creg,
                                                name=''))
            instruction = Instruction(mapped_operation,
                                      par,
                                      qregs, [],
                                      circuit=self._circuit)
            dag.apply_operation_back(instruction)
            qc = dag_to_circuit(dag)
            self._circuit = self._circuit + qc
        elif isinstance(mapped_operation, QiskitInstructions):
            op = mapped_operation  # type: QiskitInstructions
            op.apply(qregs=qregs, param=list(par), circuit=self._circuit)
        else:
            raise ValueError(
                "The operation is not of an expected type. This is a software bug!"
            )
    def apply(self, operation, wires, par):
        mapped_operation = self._operation_map[operation]

        qregs = [self._reg[i] for i in wires]

        if operation == "QubitStateVector":

            if self.backend_name == "unitary_simulator":
                raise QuantumFunctionError(
                    "The QubitStateVector operation is not supported on the unitary simulator backend."
                )

            if len(par[0]) != 2 ** len(wires):
                raise ValueError("State vector must be of length 2**wires.")

            qregs = list(reversed(qregs))

            # TODO: Once a fix is available in Qiskit-Aer, remove the following:
            par = (x.tolist() for x in par if isinstance(x, np.ndarray))

        if operation == "QubitUnitary":

            if len(par[0]) != 2 ** len(wires):
                raise ValueError("Unitary matrix must be of shape (2**wires, 2**wires).")

            qregs = list(reversed(qregs))

        dag = circuit_to_dag(QuantumCircuit(self._reg, self._creg, name=""))
        gate = mapped_operation(*par)

        if operation.endswith(".inv"):
            gate = gate.inverse()

        dag.apply_operation_back(gate, qargs=qregs)
        qc = dag_to_circuit(dag)
        self._circuit = self._circuit + qc
Exemple #14
0
def get_controlled_circuit(circuit,
                           ctl_qubit,
                           tgt_circuit=None,
                           use_basis_gates=True):
    """
    Construct the controlled version of a given circuit.

    Args:
        circuit (QuantumCircuit) : the base circuit
        ctl_qubit (Qubit) : the control qubit to use
        tgt_circuit (QuantumCircuit) : the target controlled circuit to be modified in-place
        use_basis_gates (bool) : boolean flag to indicate whether or not
                                only basis gates should be used

    Return:
        QuantumCircuit: a QuantumCircuit object with the base circuit being controlled by ctl_qubit
    Raises:
        RuntimeError: unexpected operation
    """
    if tgt_circuit is not None:
        qc = tgt_circuit
    else:
        qc = QuantumCircuit()

    # get all the qubits and clbits
    qregs = circuit.qregs
    qubits = []
    for qreg in qregs:
        if not qc.has_register(qreg):
            qc.add_register(qreg)
        qubits.extend(qreg)
    cregs = circuit.cregs
    clbits = []
    for creg in cregs:
        if not qc.has_register(creg):
            qc.add_register(creg)
        clbits.extend(creg)

    # get all operations
    unroller = Unroller(basis=['u', 'p', 'cx'])
    ops = dag_to_circuit(unroller.run(circuit_to_dag(circuit))).data

    # process all basis gates to add control
    if not qc.has_register(ctl_qubit.register):
        qc.add_register(ctl_qubit.register)
    for op in ops:
        if op[0].name == 'id':
            apply_cu(qc,
                     0,
                     0,
                     0,
                     ctl_qubit,
                     op[1][0],
                     use_basis_gates=use_basis_gates)
        elif op[0].name == 'p':
            apply_cp(qc,
                     *op[0].params,
                     ctl_qubit,
                     op[1][0],
                     use_basis_gates=use_basis_gates)
        elif op[0].name == 'u':
            apply_cu(qc,
                     *op[0].params,
                     ctl_qubit,
                     op[1][0],
                     use_basis_gates=use_basis_gates)
        elif op[0].name == 'cx':
            apply_ccx(qc,
                      ctl_qubit,
                      op[1][0],
                      op[1][1],
                      use_basis_gates=use_basis_gates)
        elif op[0].name == 'measure':
            qc.measure(op[1], op[2])
        elif op[0].name == 'barrier':
            qc.barrier(op[1])
        else:
            raise RuntimeError('Unexpected operation {}.'.format(op[0].name))

    return qc
def _compose_transforms(basis_transforms, source_basis, source_dag):
    """Compose a set of basis transforms into a set of replacements.

    Args:
        basis_transforms (List[Tuple[gate_name, params, equiv]]): List of
            transforms to compose.
        source_basis (Set[Tuple[gate_name: str, gate_num_qubits: int]]): Names
            of gates which need to be translated.
        source_dag (DAGCircuit): DAG with example gates from source_basis.
            (Used to determine num_params for gate in source_basis.)

    Returns:
        Dict[gate_name, Tuple(params, dag)]: Dictionary mapping between each gate
            in source_basis and a DAGCircuit instance to replace it. Gates in
            source_basis but not affected by basis_transforms will be included
            as a key mapping to itself.
    """

    example_gates = {(node.op.name, node.op.num_qubits): node.op for node in source_dag.op_nodes()}
    mapped_instrs = {}

    for gate_name, gate_num_qubits in source_basis:
        # Need to grab a gate instance to find num_qubits and num_params.
        # Can be removed following https://github.com/Qiskit/qiskit-terra/pull/3947 .
        example_gate = example_gates[gate_name, gate_num_qubits]
        num_params = len(example_gate.params)

        placeholder_params = ParameterVector(gate_name, num_params)
        placeholder_gate = Gate(gate_name, gate_num_qubits, list(placeholder_params))
        placeholder_gate.params = list(placeholder_params)

        dag = DAGCircuit()
        qr = QuantumRegister(gate_num_qubits)
        dag.add_qreg(qr)
        dag.apply_operation_back(placeholder_gate, qr[:], [])
        mapped_instrs[gate_name, gate_num_qubits] = placeholder_params, dag

    for gate_name, gate_num_qubits, equiv_params, equiv in basis_transforms:
        logger.debug(
            "Composing transform step: %s/%s %s =>\n%s",
            gate_name,
            gate_num_qubits,
            equiv_params,
            equiv,
        )

        for mapped_instr_name, (dag_params, dag) in mapped_instrs.items():
            doomed_nodes = [
                node
                for node in dag.op_nodes()
                if (node.op.name, node.op.num_qubits) == (gate_name, gate_num_qubits)
            ]

            if doomed_nodes and logger.isEnabledFor(logging.DEBUG):
                from qiskit.converters import dag_to_circuit

                logger.debug(
                    "Updating transform for mapped instr %s %s from \n%s",
                    mapped_instr_name,
                    dag_params,
                    dag_to_circuit(dag),
                )

            for node in doomed_nodes:
                from qiskit.converters import circuit_to_dag

                replacement = equiv.assign_parameters(
                    dict(zip_longest(equiv_params, node.op.params))
                )

                replacement_dag = circuit_to_dag(replacement)

                dag.substitute_node_with_dag(node, replacement_dag)

            if doomed_nodes and logger.isEnabledFor(logging.DEBUG):
                from qiskit.converters import dag_to_circuit

                logger.debug(
                    "Updated transform for mapped instr %s %s to\n%s",
                    mapped_instr_name,
                    dag_params,
                    dag_to_circuit(dag),
                )

    return mapped_instrs
Exemple #16
0
 def reverser(self, dag):
     circuit = dag_to_circuit(dag)
     return circuit
def _circuit_from_qasm(qasm):
    from qiskit.converters import ast_to_dag
    from qiskit.converters import dag_to_circuit
    ast = qasm.parse()
    dag = ast_to_dag(ast)
    return dag_to_circuit(dag)
    def run(self, dag):
        """Translate an input DAGCircuit to the target basis.

        Args:
            dag (DAGCircuit): input dag

        Raises:
            TranspilerError: if the target basis cannot be reached

        Returns:
            DAGCircuit: translated circuit.
        """

        if self._target_basis is None:
            return dag

        # Names of instructions assumed to supported by any backend.
        basic_instrs = ['measure', 'reset', 'barrier', 'snapshot']

        target_basis = set(self._target_basis).union(basic_instrs)

        source_basis = set()
        for node in dag.op_nodes():
            name = node.op.name
            qubit_params = (tuple([node.qargs[0].index]), tuple(node.op.params))
            if (dag.calibrations and name in dag.calibrations
                    and qubit_params in dag.calibrations[name]):
                pass
            else:
                source_basis.add((name, node.op.num_qubits))

        logger.info('Begin BasisTranslator from source basis %s to target '
                    'basis %s.', source_basis, target_basis)

        # Search for a path from source to target basis.

        search_start_time = time.time()
        basis_transforms = _basis_search(self._equiv_lib, source_basis,
                                         target_basis, _basis_heuristic)
        search_end_time = time.time()
        logger.info('Basis translation path search completed in %.3fs.',
                    search_end_time - search_start_time)

        if basis_transforms is None:
            raise TranspilerError(
                'Unable to map source basis {} to target basis {} '
                'over library {}.'.format(
                    source_basis, target_basis, self._equiv_lib))

        # Compose found path into a set of instruction substitution rules.

        compose_start_time = time.time()
        instr_map = _compose_transforms(basis_transforms, source_basis, dag)

        compose_end_time = time.time()
        logger.info('Basis translation paths composed in %.3fs.',
                    compose_end_time - compose_start_time)

        # Replace source instructions with target translations.

        replace_start_time = time.time()
        for node in dag.op_nodes():
            if node.name in target_basis:
                continue

            if dag.calibrations and node.name in dag.calibrations:
                qubit = tuple([node.qargs[0].index])
                params = tuple(node.op.params)
                if (qubit, params) in dag.calibrations[node.name]:
                    continue

            if (node.op.name, node.op.num_qubits) in instr_map:
                target_params, target_dag = instr_map[node.op.name, node.op.num_qubits]

                if len(node.op.params) != len(target_params):
                    raise TranspilerError(
                        'Translation num_params not equal to op num_params.'
                        'Op: {} {} Translation: {}\n{}'.format(
                            node.op.params, node.op.name,
                            target_params, target_dag))

                if node.op.params:
                    # Convert target to circ and back to assign_parameters, since
                    # DAGCircuits won't have a ParameterTable.
                    from qiskit.converters import dag_to_circuit, circuit_to_dag
                    target_circuit = dag_to_circuit(target_dag)

                    target_circuit.assign_parameters(
                        dict(zip_longest(target_params, node.op.params)),
                        inplace=True)

                    bound_target_dag = circuit_to_dag(target_circuit)
                else:
                    bound_target_dag = target_dag

                if (len(bound_target_dag.op_nodes()) == 1
                        and len(bound_target_dag.op_nodes()[0].qargs) == len(node.qargs)):
                    dag.substitute_node(node, bound_target_dag.op_nodes()[0].op, inplace=True)
                else:
                    dag.substitute_node_with_dag(node, bound_target_dag)
            else:
                raise TranspilerError('BasisTranslator did not map {}.'.format(node.name))

        replace_end_time = time.time()
        logger.info('Basis translation instructions replaced in %.3fs.',
                    replace_end_time - replace_start_time)

        return dag
def _partition_circuit(circuit):
    dag = circuit_to_dag(circuit)
    dag_layers = ([i['graph'] for i in dag.serial_layers()])
    num_qubits = circuit.num_qubits
    layers = list(
        zip(dag_layers, [{x: False
                          for x in range(0, num_qubits)}
                         for layer in dag_layers]))

    # initialize the ledger
    # The ledger tracks which qubits in each layer are available to have
    # gates from subsequent layers shifted backward.
    # The idea being that all parameterized gates should have
    # no descendants within their layer
    for i, (layer, ledger) in enumerate(layers):
        op_node = layer.op_nodes()[0]
        is_param = op_node.op.is_parameterized()
        qargs = op_node.qargs
        indices = [qarg.index for qarg in qargs]
        if is_param:
            for index in indices:
                ledger[index] = True

    def apply_node_op(node, dag, back=True):
        op = copy.copy(node.op)
        qargs = copy.copy(node.qargs)
        cargs = copy.copy(node.cargs)
        condition = copy.copy(node.condition)
        if back:
            dag.apply_operation_back(op, qargs, cargs, condition)
        else:
            dag.apply_operation_front(op, qargs, cargs, condition)

    converged = False

    for _ in range(dag.depth() + 1):
        if converged:
            break

        converged = True

        for i, (layer, ledger) in enumerate(layers):
            if i == len(layers) - 1:
                continue

            (next_layer, next_ledger) = layers[i + 1]
            for next_node in next_layer.op_nodes():
                is_param = next_node.op.is_parameterized()
                qargs = next_node.qargs
                indices = [qarg.index for qarg in qargs]

                # If the next_node can be moved back a layer without
                # without becoming the descendant of a parameterized gate,
                # then do it.
                if not any([ledger[x] for x in indices]):

                    apply_node_op(next_node, layer)
                    next_layer.remove_op_node(next_node)

                    if is_param:
                        for index in indices:
                            ledger[index] = True
                            next_ledger[index] = False

                    converged = False

            # clean up empty layers left behind.
            if len(next_layer.op_nodes()) == 0:
                layers.pop(i + 1)

    partitioned_circs = [dag_to_circuit(layer[0]) for layer in layers]
    return partitioned_circs
def _transpilation(circuit,
                   basis_gates=None,
                   coupling_map=None,
                   initial_layout=None,
                   seed_mapper=None,
                   pass_manager=None):
    """Perform transpilation of a single circuit.

    Args:
        circuit (QuantumCircuit): A circuit to transpile.
        basis_gates (list[str]): list of basis gate names supported by the
            target. Default: ['u1','u2','u3','cx','id']
        coupling_map (CouplingMap): coupling map (perhaps custom) to target in mapping
        initial_layout (Layout): initial layout of qubits in mapping
        seed_mapper (int): random seed for the swap_mapper
        pass_manager (PassManager): a pass_manager for the transpiler stage

    Returns:
        QuantumCircuit: A transpiled circuit.

    Raises:
        TranspilerError: If the Layout does not matches the circuit
    """
    if initial_layout is not None and set(
            circuit.qregs) != initial_layout.get_registers():
        raise TranspilerError(
            'The provided initial layout does not match the registers in '
            'the circuit "%s"' % circuit.name)

    if pass_manager and not pass_manager.working_list:
        return circuit

    dag = circuit_to_dag(circuit)
    del circuit

    # if the circuit and layout already satisfy the coupling_constraints, use that layout
    # if there's no layout but the circuit is compatible, use a trivial layout
    # otherwise layout on the most densely connected physical qubit subset
    # FIXME: this should be simplified once it is ported to a PassManager
    if coupling_map:
        cm_object = CouplingMap(coupling_map)
        check_map = CheckMap(cm_object, initial_layout)
        check_map.run(dag)
        if check_map.property_set['is_swap_mapped']:
            if not initial_layout:
                trivial_layout = TrivialLayout(cm_object)
                trivial_layout.run(dag)
                initial_layout = trivial_layout.property_set['layout']
        else:
            dense_layout = DenseLayout(cm_object)
            dense_layout.run(dag)
            initial_layout = dense_layout.property_set['layout']

    final_dag = transpile_dag(dag,
                              basis_gates=basis_gates,
                              coupling_map=coupling_map,
                              initial_layout=initial_layout,
                              seed_mapper=seed_mapper,
                              pass_manager=pass_manager)

    out_circuit = dag_to_circuit(final_dag)

    return out_circuit
    def run(self, dag):
        """Translate an input DAGCircuit to the target basis.

        Args:
            dag (DAGCircuit): input dag

        Raises:
            TranspilerError: if the target basis cannot be reached

        Returns:
            DAGCircuit: translated circuit.
        """

        if self._target_basis is None:
            return dag

        # Names of instructions assumed to supported by any backend.
        basic_instrs = ["measure", "reset", "barrier", "snapshot", "delay"]

        target_basis = set(self._target_basis).union(basic_instrs)

        source_basis = set()
        for node in dag.op_nodes():
            if not dag.has_calibration_for(node):
                source_basis.add((node.name, node.op.num_qubits))

        logger.info(
            "Begin BasisTranslator from source basis %s to target " "basis %s.",
            source_basis,
            target_basis,
        )

        # Search for a path from source to target basis.

        search_start_time = time.time()
        basis_transforms = _basis_search(
            self._equiv_lib, source_basis, target_basis, _basis_heuristic
        )
        search_end_time = time.time()
        logger.info(
            "Basis translation path search completed in %.3fs.", search_end_time - search_start_time
        )

        if basis_transforms is None:
            raise TranspilerError(
                "Unable to map source basis {} to target basis {} "
                "over library {}.".format(source_basis, target_basis, self._equiv_lib)
            )

        # Compose found path into a set of instruction substitution rules.

        compose_start_time = time.time()
        instr_map = _compose_transforms(basis_transforms, source_basis, dag)

        compose_end_time = time.time()
        logger.info(
            "Basis translation paths composed in %.3fs.", compose_end_time - compose_start_time
        )

        # Replace source instructions with target translations.

        replace_start_time = time.time()
        for node in dag.op_nodes():
            if node.name in target_basis:
                continue

            if dag.has_calibration_for(node):
                continue

            if (node.op.name, node.op.num_qubits) in instr_map:
                target_params, target_dag = instr_map[node.op.name, node.op.num_qubits]

                if len(node.op.params) != len(target_params):
                    raise TranspilerError(
                        "Translation num_params not equal to op num_params."
                        "Op: {} {} Translation: {}\n{}".format(
                            node.op.params, node.op.name, target_params, target_dag
                        )
                    )

                if node.op.params:
                    # Convert target to circ and back to assign_parameters, since
                    # DAGCircuits won't have a ParameterTable.
                    from qiskit.converters import dag_to_circuit, circuit_to_dag

                    target_circuit = dag_to_circuit(target_dag)

                    target_circuit.assign_parameters(
                        dict(zip_longest(target_params, node.op.params)), inplace=True
                    )

                    bound_target_dag = circuit_to_dag(target_circuit)
                else:
                    bound_target_dag = target_dag

                if len(bound_target_dag.op_nodes()) == 1 and len(
                    bound_target_dag.op_nodes()[0].qargs
                ) == len(node.qargs):
                    dag_op = bound_target_dag.op_nodes()[0].op
                    # dag_op may be the same instance as other ops in the dag,
                    # so if there is a condition, need to copy
                    if node.op.condition:
                        dag_op = dag_op.copy()
                    dag.substitute_node(node, dag_op, inplace=True)

                    if bound_target_dag.global_phase:
                        dag.global_phase += bound_target_dag.global_phase
                else:
                    dag.substitute_node_with_dag(node, bound_target_dag)
            else:
                raise TranspilerError(f"BasisTranslator did not map {node.name}.")

        replace_end_time = time.time()
        logger.info(
            "Basis translation instructions replaced in %.3fs.",
            replace_end_time - replace_start_time,
        )

        return dag
Exemple #22
0
def _transpilation(circuit,
                   basis_gates=None,
                   coupling_map=None,
                   initial_layout=None,
                   seed_mapper=None,
                   pass_manager=None):
    """Perform transpilation of a single circuit.

    Args:
        circuit (QuantumCircuit): A circuit to transpile.
        basis_gates (list[str]): list of basis gate names supported by the
            target. Default: ['u1','u2','u3','cx','id']
        coupling_map (list): coupling map (perhaps custom) to target in mapping
        initial_layout (list): initial layout of qubits in mapping
        seed_mapper (int): random seed for the swap_mapper
        pass_manager (PassManager): a pass_manager for the transpiler stage

    Returns:
        QuantumCircuit: A transpiled circuit.

    Raises:
        TranspilerError: if args are not complete for transpiler to function.
    """
    if pass_manager and not pass_manager.working_list:
        return circuit

    dag = circuit_to_dag(circuit)
    del circuit

    # pick a trivial layout if the circuit already satisfies the coupling constraints
    # else layout on the most densely connected physical qubit subset
    # FIXME: this should be simplified once it is ported to a PassManager
    if coupling_map and initial_layout is None:
        cm_object = CouplingMap(coupling_map)
        check_cnot_direction = CheckCnotDirection(cm_object)
        check_cnot_direction.run(dag)
        if check_cnot_direction.property_set['is_direction_mapped']:
            trivial_layout = TrivialLayout(cm_object)
            trivial_layout.run(dag)
            initial_layout = trivial_layout.property_set['layout']
        else:
            dense_layout = DenseLayout(cm_object)
            dense_layout.run(dag)
            initial_layout = dense_layout.property_set['layout']

    # temporarily build old-style layout dict
    # (TODO: remove after transition to StochasticSwap pass)
    if isinstance(initial_layout, Layout):
        layout = initial_layout.copy()
        virtual_qubits = layout.get_virtual_bits()
        initial_layout = {(v[0].name, v[1]): ('q', layout[v])
                          for v in virtual_qubits}

    final_dag = transpile_dag(dag,
                              basis_gates=basis_gates,
                              coupling_map=coupling_map,
                              initial_layout=initial_layout,
                              seed_mapper=seed_mapper,
                              pass_manager=pass_manager)

    out_circuit = dag_to_circuit(final_dag)

    return out_circuit
Exemple #23
0
def _qiskit_ansatz(num_params, num_qubits, wires, tape):
    """Transform a quantum tape from PennyLane to a Qiskit circuit.

    Args:
        num_params (int): Number of parameters.
        num_qubits (int): Number of qubits.
        wires (qml.wire.Wires): Wires used in the tape and Hamiltonian.
        tape (qml.tape.QuantumTape): The quantum tape of the circuit ansatz in PennyLane.

    Returns:
        QuantumCircuit: Qiskit quantum circuit.

    """
    consecutive_wires = qml.wires.Wires(range(num_qubits))
    wires_map = OrderedDict(zip(wires, consecutive_wires))
    # From here: Create the Qiskit ansatz circuit
    params_vector = ParameterVector("p", num_params)

    reg = QuantumRegister(num_qubits, "q")
    circuit_ansatz = QuantumCircuit(reg, name="vqe")

    circuits = []

    j = 0
    for operation in tape.operations:
        wires = operation.wires.map(wires_map)
        par = operation.parameters
        operation = operation.name
        mapped_operation = QiskitDevice._operation_map[operation]

        qregs = [reg[i] for i in wires.labels]

        if operation.split(".inv")[0] in ("QubitUnitary", "QubitStateVector"):
            # Need to revert the order of the quantum registers used in
            # Qiskit such that it matches the PennyLane ordering
            qregs = list(reversed(qregs))

        dag = circuit_to_dag(QuantumCircuit(reg, name=""))

        if operation in ("QubitUnitary", "QubitStateVector"):
            # Parameters are matrices
            gate = mapped_operation(par[0])
        else:
            # Parameters for the operation
            if par and qml.math.requires_grad(par[0]):
                op_num_params = len(par)
                par = []
                for num in range(op_num_params):
                    par.append(params_vector[j + num])
                j += op_num_params

            gate = mapped_operation(*par)

        if operation.endswith(".inv"):
            gate = gate.inverse()

        dag.apply_operation_back(gate, qargs=qregs)
        circuit = dag_to_circuit(dag)
        circuits.append(circuit)

    for circuit in circuits:
        circuit_ansatz &= circuit

    return circuit_ansatz
 def decompose_non_standard_non_unitary_gates_return(self) -> Tuple[QuantumCircuit, DAGCircuit]:
     decomposer = Decomposer()
     dag = decomposer.decompose_non_standard_non_unitary_gates(self.dag)
     circuit = dag_to_circuit(dag)
     return (circuit, dag)
Exemple #25
0
 def time_dag_to_circuit(self, *_):
     converters.dag_to_circuit(self.dag)
Exemple #26
0
    def test_compose_permuted(self):
        """Composing two dags of the same width, permuted wires.
                        ┌───┐
         lqr_1_0: |0>───┤ H ├───      rqr_0: |0>──■───────
                        ├───┤                     │  ┌───┐
         lqr_1_1: |0>───┤ X ├───      rqr_1: |0>──┼──┤ X ├
                     ┌──┴───┴──┐                  │  ├───┤
         lqr_1_2: |0>┤ U1(0.1) ├      rqr_2: |0>──┼──┤ Y ├
                     └─────────┘                ┌─┴─┐└───┘
         lqr_2_0: |0>─────■─────  +   rqr_3: |0>┤ X ├─────   =
                        ┌─┴─┐                   └───┘┌───┐
         lqr_2_1: |0>───┤ X ├───      rqr_4: |0>─────┤ Z ├
                        └───┘                        └───┘
         lcr_0: 0 ══════════════

         lcr_1: 0 ══════════════

                        ┌───┐   ┌───┐
         lqr_1_0: |0>───┤ H ├───┤ Z ├
                        ├───┤   ├───┤
         lqr_1_1: |0>───┤ X ├───┤ X ├
                     ┌──┴───┴──┐├───┤
         lqr_1_2: |0>┤ U1(0.1) ├┤ Y ├
                     └─────────┘└───┘
         lqr_2_0: |0>─────■───────■──
                        ┌─┴─┐   ┌─┴─┐
         lqr_2_1: |0>───┤ X ├───┤ X ├
                        └───┘   └───┘
         lcr_0: 0 ═══════════════════

         lcr_1: 0 ═══════════════════
        """
        qreg = QuantumRegister(5, 'rqr')
        right_qubit0 = qreg[0]
        right_qubit1 = qreg[1]
        right_qubit2 = qreg[2]
        right_qubit3 = qreg[3]
        right_qubit4 = qreg[4]

        circuit_right = QuantumCircuit(qreg)
        circuit_right.cx(qreg[0], qreg[3])
        circuit_right.x(qreg[1])
        circuit_right.y(qreg[2])
        circuit_right.z(qreg[4])

        dag_left = circuit_to_dag(self.circuit_left)
        dag_right = circuit_to_dag(circuit_right)

        # permuted wiring
        dag_left.compose(dag_right, edge_map={right_qubit0: self.left_qubit3,
                                              right_qubit1: self.left_qubit1,
                                              right_qubit2: self.left_qubit2,
                                              right_qubit3: self.left_qubit4,
                                              right_qubit4: self.left_qubit0})
        circuit_composed = dag_to_circuit(dag_left)

        circuit_expected = self.circuit_left.copy()
        circuit_expected.z(self.left_qubit0)
        circuit_expected.x(self.left_qubit1)
        circuit_expected.y(self.left_qubit2)
        circuit_expected.cx(self.left_qubit3, self.left_qubit4)

        self.assertEqual(circuit_composed, circuit_expected)
Exemple #27
0
def transpile_dag(dag,
                  basis_gates=None,
                  coupling_map=None,
                  initial_layout=None,
                  seed_mapper=None,
                  pass_manager=None):
    """Deprecated - Use qiskit.compiler.transpile for transpiling from
    circuits to circuits.
    Transform a dag circuit into another dag circuit
    (transpile), through consecutive passes on the dag.

    Args:
        dag (DAGCircuit): dag circuit to transform via transpilation
        basis_gates (list[str]): list of basis gate names supported by the
            target. Default: ['u1','u2','u3','cx','id']
        coupling_map (list): A graph of coupling::

            [
             [control0(int), target0(int)],
             [control1(int), target1(int)],
            ]

            eg. [[0, 2], [1, 2], [1, 3], [3, 4]}

        initial_layout (Layout or None): A layout object
        seed_mapper (int): random seed_mapper for the swap mapper
        pass_manager (PassManager): pass manager instance for the transpilation process
            If None, a default set of passes are run.
            Otherwise, the passes defined in it will run.
            If contains no passes in it, no dag transformations occur.

    Returns:
        DAGCircuit: transformed dag
    """
    warnings.warn(
        "transpile_dag has been deprecated and will be removed in the "
        "0.9 release. Circuits can be transpiled directly to other "
        "circuits with the transpile function.", DeprecationWarning)

    if basis_gates is None:
        basis_gates = ['u1', 'u2', 'u3', 'cx', 'id']

    if pass_manager is None:
        # default set of passes

        # if a coupling map is given compile to the map
        if coupling_map:
            pass_manager = default_pass_manager(basis_gates,
                                                CouplingMap(coupling_map),
                                                initial_layout,
                                                seed_transpiler=seed_mapper)
        else:
            pass_manager = default_pass_manager_simulator(basis_gates)

    # run the passes specified by the pass manager
    # TODO return the property set too. See #1086
    name = dag.name
    circuit = dag_to_circuit(dag)
    circuit = pass_manager.run(circuit)
    dag = circuit_to_dag(circuit)
    dag.name = name

    return dag
 def unroll(self, gates: List[str]) -> QuantumCircuit:
     unroll_pass = Unroller(gates)
     self.decompose_non_standard_non_unitary_gates()
     self.dag = unroll_pass.run(self.dag)
     self.circuit = dag_to_circuit(self.dag)
     return self.circuit
Exemple #29
0
    def test_compose_classical(self):
        """Composing on classical bits.

                       ┌───┐                       ┌─────┐┌─┐
        lqr_1_0: |0>───┤ H ├───     rqr_0: |0>──■──┤ Tdg ├┤M├
                       ├───┤                  ┌─┴─┐└─┬─┬─┘└╥┘
        lqr_1_1: |0>───┤ X ├───     rqr_1: |0>┤ X ├──┤M├───╫─
                    ┌──┴───┴──┐               └───┘  └╥┘   ║
        lqr_1_2: |0>┤ U1(0.1) ├  +   rcr_0: 0 ════════╬════╩═  =
                    └─────────┘                       ║
        lqr_2_0: |0>─────■─────      rcr_1: 0 ════════╩══════
                       ┌─┴─┐
        lqr_2_1: |0>───┤ X ├───
                       └───┘
        lcr_0: 0 ══════════════

        lcr_1: 0 ══════════════

                       ┌───┐
        lqr_1_0: |0>───┤ H ├──────────────────
                       ├───┤        ┌─────┐┌─┐
        lqr_1_1: |0>───┤ X ├─────■──┤ Tdg ├┤M├
                    ┌──┴───┴──┐  │  └─────┘└╥┘
        lqr_1_2: |0>┤ U1(0.1) ├──┼──────────╫─
                    └─────────┘  │          ║
        lqr_2_0: |0>─────■───────┼──────────╫─
                       ┌─┴─┐   ┌─┴─┐  ┌─┐   ║
        lqr_2_1: |0>───┤ X ├───┤ X ├──┤M├───╫─
                       └───┘   └───┘  └╥┘   ║
           lcr_0: 0 ═══════════════════╩════╬═
                                            ║
           lcr_1: 0 ════════════════════════╩═
        """
        qreg = QuantumRegister(2, 'rqr')
        creg = ClassicalRegister(2, 'rcr')
        right_qubit0 = qreg[0]
        right_qubit1 = qreg[1]
        right_clbit0 = creg[0]
        right_clbit1 = creg[1]

        circuit_right = QuantumCircuit(qreg, creg)
        circuit_right.cx(qreg[0], qreg[1])
        circuit_right.tdg(qreg[0])
        circuit_right.measure(qreg, creg)

        dag_left = circuit_to_dag(self.circuit_left)
        dag_right = circuit_to_dag(circuit_right)

        # permuted subset of qubits and clbits
        dag_left.compose(dag_right, edge_map={right_qubit0: self.left_qubit1,
                                              right_qubit1: self.left_qubit4,
                                              right_clbit0: self.left_clbit1,
                                              right_clbit1: self.left_clbit0})
        circuit_composed = dag_to_circuit(dag_left)

        circuit_expected = self.circuit_left.copy()
        circuit_expected.cx(self.left_qubit1, self.left_qubit4)
        circuit_expected.tdg(self.left_qubit1)
        circuit_expected.measure(self.left_qubit4, self.left_clbit0)
        circuit_expected.measure(self.left_qubit1, self.left_clbit1)

        self.assertEqual(circuit_composed, circuit_expected)
    def test_unroll_all_instructions(self):
        """Test unrolling a circuit containing all standard instructions.
        """

        qr = QuantumRegister(3, 'qr')
        cr = ClassicalRegister(3, 'cr')
        circuit = QuantumCircuit(qr, cr)
        circuit.crx(0.5, qr[1], qr[2])
        circuit.cry(0.5, qr[1], qr[2])
        circuit.ccx(qr[0], qr[1], qr[2])
        circuit.ch(qr[0], qr[2])
        circuit.crz(0.5, qr[1], qr[2])
        circuit.cswap(qr[1], qr[0], qr[2])
        circuit.append(CU1Gate(0.1), [qr[0], qr[2]])
        circuit.append(CU3Gate(0.2, 0.1, 0.0), [qr[1], qr[2]])
        circuit.cx(qr[1], qr[0])
        circuit.cy(qr[1], qr[2])
        circuit.cz(qr[2], qr[0])
        circuit.h(qr[1])
        circuit.i(qr[0])
        circuit.rx(0.1, qr[0])
        circuit.ry(0.2, qr[1])
        circuit.rz(0.3, qr[2])
        circuit.rzz(0.6, qr[1], qr[0])
        circuit.s(qr[0])
        circuit.sdg(qr[1])
        circuit.swap(qr[1], qr[2])
        circuit.t(qr[2])
        circuit.tdg(qr[0])
        circuit.append(U1Gate(0.1), [qr[1]])
        circuit.append(U2Gate(0.2, -0.1), [qr[0]])
        circuit.append(U3Gate(0.3, 0.0, -0.1), [qr[2]])
        circuit.x(qr[2])
        circuit.y(qr[1])
        circuit.z(qr[0])
        # circuit.snapshot('0')
        # circuit.measure(qr, cr)
        dag = circuit_to_dag(circuit)
        pass_ = UnrollCustomDefinitions(std_eqlib, ['u3', 'cx', 'id'])
        dag = pass_.run(dag)

        pass_ = BasisTranslator(std_eqlib, ['u3', 'cx', 'id'])
        unrolled_dag = pass_.run(dag)

        ref_circuit = QuantumCircuit(qr, cr)
        ref_circuit.append(U3Gate(0, 0, pi / 2), [qr[2]])
        ref_circuit.cx(qr[1], qr[2])
        ref_circuit.append(U3Gate(-0.25, 0, 0), [qr[2]])
        ref_circuit.cx(qr[1], qr[2])
        ref_circuit.append(U3Gate(0.25, -pi / 2, 0), [qr[2]])
        ref_circuit.append(U3Gate(0.25, 0, 0), [qr[2]])
        ref_circuit.cx(qr[1], qr[2])
        ref_circuit.append(U3Gate(-0.25, 0, 0), [qr[2]])
        ref_circuit.cx(qr[1], qr[2])
        ref_circuit.append(U3Gate(pi / 2, 0, pi), [qr[2]])
        ref_circuit.cx(qr[1], qr[2])
        ref_circuit.append(U3Gate(0, 0, -pi / 4), [qr[2]])
        ref_circuit.cx(qr[0], qr[2])
        ref_circuit.append(U3Gate(0, 0, pi / 4), [qr[2]])
        ref_circuit.cx(qr[1], qr[2])
        ref_circuit.append(U3Gate(0, 0, pi / 4), [qr[1]])
        ref_circuit.append(U3Gate(0, 0, -pi / 4), [qr[2]])
        ref_circuit.cx(qr[0], qr[2])
        ref_circuit.cx(qr[0], qr[1])
        ref_circuit.append(U3Gate(0, 0, pi / 4), [qr[0]])
        ref_circuit.append(U3Gate(0, 0, -pi / 4), [qr[1]])
        ref_circuit.cx(qr[0], qr[1])
        ref_circuit.append(U3Gate(0, 0, pi / 4), [qr[2]])
        ref_circuit.append(U3Gate(pi / 2, 0, pi), [qr[2]])
        ref_circuit.append(U3Gate(0, 0, pi / 2), [qr[2]])
        ref_circuit.append(U3Gate(pi / 2, 0, pi), [qr[2]])
        ref_circuit.append(U3Gate(0, 0, pi / 4), [qr[2]])
        ref_circuit.cx(qr[0], qr[2])
        ref_circuit.append(U3Gate(0, 0, -pi / 4), [qr[2]])
        ref_circuit.append(U3Gate(pi / 2, 0, pi), [qr[2]])
        ref_circuit.append(U3Gate(0, 0, -pi / 2), [qr[2]])
        ref_circuit.append(U3Gate(0, 0, 0.25), [qr[2]])
        ref_circuit.cx(qr[1], qr[2])
        ref_circuit.append(U3Gate(0, 0, -0.25), [qr[2]])
        ref_circuit.cx(qr[1], qr[2])
        ref_circuit.cx(qr[2], qr[0])
        ref_circuit.append(U3Gate(pi / 2, 0, pi), [qr[2]])
        ref_circuit.cx(qr[0], qr[2])
        ref_circuit.append(U3Gate(0, 0, -pi / 4), [qr[2]])
        ref_circuit.cx(qr[1], qr[2])
        ref_circuit.append(U3Gate(0, 0, pi / 4), [qr[2]])
        ref_circuit.cx(qr[0], qr[2])
        ref_circuit.append(U3Gate(0, 0, pi / 4), [qr[0]])
        ref_circuit.append(U3Gate(0, 0, -pi / 4), [qr[2]])
        ref_circuit.cx(qr[1], qr[2])
        ref_circuit.cx(qr[1], qr[0])
        ref_circuit.append(U3Gate(0, 0, -pi / 4), [qr[0]])
        ref_circuit.append(U3Gate(0, 0, pi / 4), [qr[1]])
        ref_circuit.cx(qr[1], qr[0])
        ref_circuit.append(U3Gate(0, 0, 0.05), [qr[1]])
        ref_circuit.append(U3Gate(0, 0, pi / 4), [qr[2]])
        ref_circuit.append(U3Gate(pi / 2, 0, pi), [qr[2]])
        ref_circuit.cx(qr[2], qr[0])
        ref_circuit.append(U3Gate(0, 0, 0.05), [qr[0]])
        ref_circuit.cx(qr[0], qr[2])
        ref_circuit.append(U3Gate(0, 0, -0.05), [qr[2]])
        ref_circuit.cx(qr[0], qr[2])
        ref_circuit.append(U3Gate(0, 0, 0.05), [qr[2]])
        ref_circuit.append(U3Gate(0, 0, -0.05), [qr[2]])
        ref_circuit.cx(qr[1], qr[2])
        ref_circuit.append(U3Gate(-0.1, 0, -0.05), [qr[2]])
        ref_circuit.cx(qr[1], qr[2])
        ref_circuit.cx(qr[1], qr[0])
        ref_circuit.append(U3Gate(pi / 2, 0, pi), [qr[0]])
        ref_circuit.append(U3Gate(0.1, 0.1, 0), [qr[2]])
        ref_circuit.append(U3Gate(0, 0, -pi / 2), [qr[2]])
        ref_circuit.cx(qr[1], qr[2])
        ref_circuit.append(U3Gate(pi / 2, 0, pi), [qr[1]])
        ref_circuit.append(U3Gate(0.2, 0, 0), [qr[1]])
        ref_circuit.append(U3Gate(0, 0, pi / 2), [qr[2]])
        ref_circuit.cx(qr[2], qr[0])
        ref_circuit.append(U3Gate(pi / 2, 0, pi), [qr[0]])
        ref_circuit.i(qr[0])
        ref_circuit.append(U3Gate(0.1, -pi / 2, pi / 2), [qr[0]])
        ref_circuit.cx(qr[1], qr[0])
        ref_circuit.append(U3Gate(0, 0, 0.6), [qr[0]])
        ref_circuit.cx(qr[1], qr[0])
        ref_circuit.append(U3Gate(0, 0, pi / 2), [qr[0]])
        ref_circuit.append(U3Gate(0, 0, -pi / 4), [qr[0]])
        ref_circuit.append(U3Gate(pi / 2, 0.2, -0.1), [qr[0]])
        ref_circuit.append(U3Gate(0, 0, pi), [qr[0]])
        ref_circuit.append(U3Gate(0, 0, -pi / 2), [qr[1]])
        ref_circuit.append(U3Gate(0, 0, 0.3), [qr[2]])
        ref_circuit.cx(qr[1], qr[2])
        ref_circuit.cx(qr[2], qr[1])
        ref_circuit.cx(qr[1], qr[2])
        ref_circuit.append(U3Gate(0, 0, 0.1), [qr[1]])
        ref_circuit.append(U3Gate(pi, pi / 2, pi / 2), [qr[1]])
        ref_circuit.append(U3Gate(0, 0, pi / 4), [qr[2]])
        ref_circuit.append(U3Gate(0.3, 0.0, -0.1), [qr[2]])
        ref_circuit.append(U3Gate(pi, 0, pi), [qr[2]])
        # ref_circuit.snapshot('0')
        # ref_circuit.measure(qr, cr)
        # ref_dag = circuit_to_dag(ref_circuit)

        self.assertTrue(
            Operator(dag_to_circuit(unrolled_dag)).equiv(ref_circuit))