Example #1
0
    def test_from_circuit_constructor_reverse_user_specified_layout(self):
        """Test initialization from a circuit with a user specified reverse layout."""
        # Test tensor product of 1-qubit gates
        circuit = QuantumCircuit(3)
        circuit.h(2)
        circuit.x(1)
        circuit.ry(np.pi / 2, 0)
        layout = Layout({circuit.qubits[2]: 0, circuit.qubits[1]: 1, circuit.qubits[0]: 2})
        op = Operator.from_circuit(circuit, layout=layout)
        y90 = (1 / np.sqrt(2)) * np.array([[1, -1], [1, 1]])
        target = np.kron(y90, np.kron(self.UX, self.UH))
        global_phase_equivalent = matrix_equal(op.data, target, ignore_phase=True)
        self.assertTrue(global_phase_equivalent)

        # Test decomposition of Controlled-Phase gate
        lam = np.pi / 4
        circuit = QuantumCircuit(2)
        circuit.cp(lam, 1, 0)
        layout = Layout({circuit.qubits[1]: 0, circuit.qubits[0]: 1})
        op = Operator.from_circuit(circuit, layout=layout)
        target = np.diag([1, 1, 1, np.exp(1j * lam)])
        global_phase_equivalent = matrix_equal(op.data, target, ignore_phase=True)
        self.assertTrue(global_phase_equivalent)

        # Test decomposition of controlled-H gate
        circuit = QuantumCircuit(2)
        circuit.ch(1, 0)
        layout = Layout({circuit.qubits[1]: 0, circuit.qubits[0]: 1})
        op = Operator.from_circuit(circuit, layout=layout)
        target = np.kron(self.UI, np.diag([1, 0])) + np.kron(self.UH, np.diag([0, 1]))
        global_phase_equivalent = matrix_equal(op.data, target, ignore_phase=True)
        self.assertTrue(global_phase_equivalent)
Example #2
0
    def run(self, dag):
        """Run the SabreLayout pass on `dag`.

        Args:
            dag (DAGCircuit): DAG to find layout for.

        Raises:
            TranspilerError: if dag wider than self.coupling_map
        """
        if len(dag.qubits) > self.coupling_map.size():
            raise TranspilerError("More virtual qubits exist than physical.")

        # Choose a random initial_layout.
        if self.seed is None:
            self.seed = np.random.randint(0, np.iinfo(np.int32).max)
        rng = np.random.default_rng(self.seed)

        physical_qubits = rng.choice(self.coupling_map.size(),
                                     len(dag.qubits),
                                     replace=False)
        physical_qubits = rng.permutation(physical_qubits)
        initial_layout = Layout(
            {q: dag.qubits[i]
             for i, q in enumerate(physical_qubits)})

        if self.routing_pass is None:
            self.routing_pass = SabreSwap(self.coupling_map,
                                          "decay",
                                          seed=self.seed,
                                          fake_run=True)
        else:
            self.routing_pass.fake_run = True

        # Do forward-backward iterations.
        circ = dag_to_circuit(dag)
        rev_circ = circ.reverse_ops()
        for _ in range(self.max_iterations):
            for _ in ("forward", "backward"):
                pm = self._layout_and_route_passmanager(initial_layout)
                new_circ = pm.run(circ)

                # Update initial layout and reverse the unmapped circuit.
                pass_final_layout = pm.property_set["final_layout"]
                final_layout = self._compose_layouts(
                    initial_layout,
                    pass_final_layout,
                    new_circ.qregs  # pylint: disable=no-member
                )
                initial_layout = final_layout
                circ, rev_circ = rev_circ, circ

            # Diagnostics
            logger.info("new initial layout")
            logger.info(initial_layout)

        for qreg in dag.qregs.values():
            initial_layout.add_register(qreg)

        self.property_set["layout"] = initial_layout
        self.routing_pass.fake_run = False
Example #3
0
    def test_layout_add(self):
        """add() method"""
        layout = Layout()
        layout[self.qr[0]] = 0
        layout.add(self.qr[1])

        self.assertEqual(layout[self.qr[1]], 1)
Example #4
0
    def test_layout_from_intlist(self):
        """Create a layout from a list of integers.
        virtual  physical
         q1_0  ->  4
         q2_0  ->  5
         q2_1  ->  6
         q3_0  ->  8
         q3_1  ->  9
         q3_2  ->  10
        """
        qr1 = QuantumRegister(1, 'qr1')
        qr2 = QuantumRegister(2, 'qr2')
        qr3 = QuantumRegister(3, 'qr3')
        intlist_layout = [4, 5, 6, 8, 9, 10]
        layout = Layout.from_intlist(intlist_layout, qr1, qr2, qr3)

        expected = Layout({
            4: qr1[0],
            5: qr2[0],
            6: qr2[1],
            8: qr3[0],
            9: qr3[1],
            10: qr3[2]
        })
        self.assertDictEqual(layout._p2v, expected._p2v)
        self.assertDictEqual(layout._v2p, expected._v2p)
Example #5
0
 def test_layout_get_bits(self):
     """Get the map from the (qu)bits view"""
     layout_dict = {(self.qr, 0): 0,
                    (self.qr, 1): 1,
                    (self.qr, 2): 2}
     layout = Layout(layout_dict)
     self.assertDictEqual(layout_dict, layout.get_virtual_bits())
Example #6
0
    def test_layout_from_intlist_short(self):
        """If the intlist is longer that your quantum register, map them to None.
        virtual  physical
         q1_0  ->  4
         q2_0  ->  5
         q2_1  ->  6
         None  ->  8
         None  ->  9
         None  ->  10
        """
        qr1 = QuantumRegister(1, 'qr1')
        qr2 = QuantumRegister(2, 'qr2')

        intlist_layout = [4, 5, 6, 8, 9, 10]
        layout = Layout.from_intlist(intlist_layout, qr1, qr2)

        expected = Layout({
            4: qr1[0],
            5: qr2[0],
            6: qr2[1],
            8: None,
            9: None,
            10: None
        })
        self.assertDictEqual(layout._p2v, expected._p2v)
        self.assertDictEqual(layout._v2p, expected._v2p)
Example #7
0
 def test_layout_get_physical_bits(self):
     """Get the map from the physical bits view"""
     layout = Layout({self.qr[0]: 0, self.qr[1]: 1, self.qr[2]: 2})
     self.assertDictEqual(layout.get_physical_bits(), {
         0: self.qr[0],
         1: self.qr[1],
         2: self.qr[2]
     })
Example #8
0
    def test_layout_repr_with_holes(self):
        """A non-bijective Layout repr reproduces layout"""
        qr = QuantumRegister(5, 'qr')
        layout = Layout({qr[0]: 0, qr[1]: 3, qr[2]: 4, qr[3]: 5, qr[4]: 6})

        repr_layout = eval(layout.__repr__())  # pylint: disable=eval-used
        self.assertDictEqual(layout._p2v, repr_layout._p2v)
        self.assertDictEqual(layout._v2p, repr_layout._v2p)
Example #9
0
    def test_layout_add(self):
        """add() method"""
        layout = Layout()
        layout[(self.qr, 0)] = 0
        layout.add((self.qr, 1))

        self.assertEqual(layout[(self.qr, 1)], 1)
        self.assertEqual(layout[1], (self.qr, 1))
Example #10
0
 def test_layout_get_physical_bits(self):
     """Get the map from the physical bits view"""
     layout = Layout({(self.qr, 0): 0, (self.qr, 1): 1, (self.qr, 2): 2})
     self.assertDictEqual(layout.get_physical_bits(), {
         0: (self.qr, 0),
         1: (self.qr, 1),
         2: (self.qr, 2)
     })
Example #11
0
    def run(self, dag):
        """Run the SabreLayout pass on `dag`.

        Args:
            dag (DAGCircuit): DAG to find layout for.

        Raises:
            TranspilerError: if dag wider than self.coupling_map
        """
        if len(dag.qubits) > self.coupling_map.size():
            raise TranspilerError('More virtual qubits exist than physical.')

        # Choose a random initial_layout.
        if self.seed is None:
            self.seed = np.random.randint(0, np.iinfo(np.int32).max)
        rng = np.random.default_rng(self.seed)

        physical_qubits = rng.choice(self.coupling_map.size(),
                                     len(dag.qubits),
                                     replace=False)
        physical_qubits = rng.permutation(physical_qubits)
        initial_layout = Layout(
            {q: dag.qubits[i]
             for i, q in enumerate(physical_qubits)})

        if self.routing_pass is None:
            self.routing_pass = SabreSwap(self.coupling_map,
                                          'decay',
                                          seed=self.seed)

        # Do forward-backward iterations.
        circ = dag_to_circuit(dag)
        for i in range(self.max_iterations):
            for _ in ('forward', 'backward'):
                pm = self._layout_and_route_passmanager(initial_layout)
                new_circ = pm.run(circ)

                # Update initial layout and reverse the unmapped circuit.
                pass_final_layout = pm.property_set['final_layout']
                final_layout = self._compose_layouts(initial_layout,
                                                     pass_final_layout,
                                                     new_circ.qregs)  # pylint: disable=no-member
                initial_layout = final_layout
                circ = circ.reverse_ops()

            # Diagnostics
            logger.info('After round %d, num_swaps: %d', i + 1,
                        new_circ.count_ops().get('swap', 0))  # pylint: disable=no-member

            logger.info('new initial layout')
            logger.info(initial_layout)

        for qreg in dag.qregs.values():
            initial_layout.add_register(qreg)

        self.property_set['layout'] = initial_layout
Example #12
0
    def test_layout_contains(self):
        """Verify Layouts support __contains__."""
        qr = QuantumRegister(2, 'qr')
        layout = Layout()
        layout.add(qr[0], 0)

        self.assertIn(qr[0], layout)
        self.assertIn(0, layout)
        self.assertNotIn(qr[1], layout)
        self.assertNotIn(1, layout)
Example #13
0
    def test_layout_add_register(self):
        """add_register() method"""
        layout = Layout()
        qr0 = QuantumRegister(2, 'q0')
        qr1 = QuantumRegister(1, 'qr1')
        layout.add_register(qr0)
        layout.add_register(qr1)

        self.assertEqual(layout[qr0[0]], 0)
        self.assertEqual(layout[qr0[1]], 1)
        self.assertEqual(layout[qr1[0]], 2)
    def test_layout_from_intlist_numpy(self):
        """Create a layout from a list of numpy integers. See #3097"""
        qr1 = QuantumRegister(1, "qr1")
        qr2 = QuantumRegister(2, "qr2")
        qr3 = QuantumRegister(3, "qr3")
        intlist_layout = numpy.array([0, 1, 2, 3, 4, 5])
        layout = Layout.from_intlist(intlist_layout, qr1, qr2, qr3)

        expected = Layout.generate_trivial_layout(qr1, qr2, qr3)
        self.assertDictEqual(layout._p2v, expected._p2v)
        self.assertDictEqual(layout._v2p, expected._v2p)
Example #15
0
    def test_layout_repr(self):
        """Layout repr reproduces layout"""
        qr = QuantumRegister(5, 'qr')
        layout = Layout({(qr, 0): 2,
                         (qr, 1): 4,
                         (qr, 2): 3,
                         (qr, 3): 0,
                         (qr, 4): 1,
                         })

        repr_layout = eval(layout.__repr__())  # pylint: disable=eval-used
        self.assertDictEqual(layout._p2v, repr_layout._p2v)
        self.assertDictEqual(layout._v2p, repr_layout._v2p)
    def test_layout_add_register(self):
        """add_register() method"""
        layout = Layout()
        qr0 = QuantumRegister(2, "q0")
        qr1 = QuantumRegister(1, "qr1")
        layout.add_register(qr0)
        layout.add_register(qr1)

        self.assertEqual(layout[qr0[0]], 0)
        self.assertEqual(layout[qr0[1]], 1)
        self.assertEqual(layout[qr1[0]], 2)
        self.assertIn(qr0, layout.get_registers())
        self.assertIn(qr1, layout.get_registers())
Example #17
0
    def test_layout_combine(self):
        """combine_into_edge_map() method"""
        layout = Layout()
        layout.add((self.qr, 0))
        layout.add((self.qr, 1))
        another_layout = Layout()
        another_layout.add((self.qr, 1))
        another_layout.add((self.qr, 0))

        edge_map = layout.combine_into_edge_map(another_layout)
        self.assertDictEqual(edge_map, {(self.qr, 0): (self.qr, 1), (self.qr, 1): (self.qr, 0)})
Example #18
0
    def test_layout_combine(self):
        """combine_into_edge_map() method"""
        layout = Layout()
        layout.add(self.qr[0])
        layout.add(self.qr[1])
        another_layout = Layout()
        another_layout.add(self.qr[1])
        another_layout.add(self.qr[0])

        edge_map = layout.combine_into_edge_map(another_layout)
        self.assertDictEqual(edge_map, {self.qr[0]: self.qr[1], self.qr[1]: self.qr[0]})
Example #19
0
    def run(self, dag):
        """
        Run the StochasticSwap pass on `dag`.

        Args:
            dag (DAGCircuit): DAG to map.

        Returns:
            DAGCircuit: A mapped DAG.

        Raises:
            TranspilerError: if the coupling map or the layout are not
            compatible with the DAG
        """

        if len(dag.qregs) != 1 or dag.qregs.get('q', None) is None:
            raise TranspilerError('Basic swap runs on physical circuits only')

        if len(dag.qubits()) > len(self.coupling_map.physical_qubits):
            raise TranspilerError(
                'The layout does not match the amount of qubits in the DAG')

        canonical_register = dag.qregs['q']
        self.trivial_layout = Layout.generate_trivial_layout(
            canonical_register)

        self.qregs = dag.qregs
        if self.seed is None:
            self.seed = np.random.randint(0, np.iinfo(np.int32).max)
        self.rng = np.random.RandomState(self.seed)
        logger.debug("StochasticSwap RandomState seeded with seed=%s",
                     self.seed)

        new_dag = self._mapper(dag, self.coupling_map, trials=self.trials)
        return new_dag
Example #20
0
    def run(self, dag):
        """Run the CXDirection pass on `dag`.

        Flips the cx nodes to match the directed coupling map. Modifies the
        input dag.

        Args:
            dag (DAGCircuit): DAG to map.

        Returns:
            DAGCircuit: The rearranged dag for the coupling map

        Raises:
            TranspilerError: If the circuit cannot be mapped just by flipping the
                cx nodes.
        """
        cmap_edges = set(self.coupling_map.get_edges())

        if len(dag.qregs) > 1:
            raise TranspilerError(
                'CXDirection expects a single qreg input DAG,'
                'but input DAG had qregs: {}.'.format(dag.qregs))

        trivial_layout = Layout.generate_trivial_layout(*dag.qregs.values())

        for cnot_node in dag.named_nodes('cx', 'CX'):
            control = cnot_node.qargs[0]
            target = cnot_node.qargs[1]

            physical_q0 = trivial_layout[control]
            physical_q1 = trivial_layout[target]

            if self.coupling_map.distance(physical_q0, physical_q1) != 1:
                raise TranspilerError(
                    'The circuit requires a connection between physical '
                    'qubits %s and %s' % (physical_q0, physical_q1))

            if (physical_q0, physical_q1) not in cmap_edges:
                # A flip needs to be done

                # Create the replacement dag and associated register.
                sub_dag = DAGCircuit()
                sub_qr = QuantumRegister(2)
                sub_dag.add_qreg(sub_qr)

                # Add H gates before
                sub_dag.apply_operation_back(U2Gate(0, pi), [sub_qr[0]], [])
                sub_dag.apply_operation_back(U2Gate(0, pi), [sub_qr[1]], [])

                # Flips the cx
                sub_dag.apply_operation_back(CXGate(), [sub_qr[1], sub_qr[0]],
                                             [])

                # Add H gates after
                sub_dag.apply_operation_back(U2Gate(0, pi), [sub_qr[0]], [])
                sub_dag.apply_operation_back(U2Gate(0, pi), [sub_qr[1]], [])

                dag.substitute_node_with_dag(cnot_node, sub_dag)

        return dag
Example #21
0
 def test_layout_avoid_dangling_virtual(self):
     """ No dangling pointers for virtual qubits."""
     layout = Layout({self.qr[0]: 0})
     self.assertEqual(layout[0], self.qr[0])
     layout[0] = self.qr[1]
     with self.assertRaises(KeyError):
         _ = layout[self.qr[0]]
Example #22
0
    def test_virtual_keyerror(self):
        """When asking for an unexistant virtual qubit, KeyError"""
        layout = Layout()
        layout[self.qr[0]] = 1

        with self.assertRaises(KeyError):
            _ = layout[self.qr[1]]
Example #23
0
 def test_from_circuit_constructor_ghz_out_of_order_layout(self):
     """Test an out of order ghz state with a layout set."""
     circuit = QuantumCircuit(5)
     circuit.h(3)
     circuit.cx(3, 4)
     circuit.cx(3, 2)
     circuit.cx(3, 0)
     circuit.cx(3, 1)
     circuit._layout = Layout(
         {
             circuit.qubits[3]: 0,
             circuit.qubits[4]: 1,
             circuit.qubits[2]: 2,
             circuit.qubits[0]: 3,
             circuit.qubits[1]: 4,
         }
     )
     result = Operator.from_circuit(circuit)
     expected = QuantumCircuit(5)
     expected.h(0)
     expected.cx(0, 1)
     expected.cx(0, 2)
     expected.cx(0, 3)
     expected.cx(0, 4)
     expected_op = Operator(expected)
     self.assertTrue(expected_op.equiv(result))
Example #24
0
    def test_physical_keyerror(self):
        """When asking for an unexistant physical qubit, KeyError"""
        layout = Layout()
        layout[(self.qr, 0)] = 1

        with self.assertRaises(KeyError):
            _ = layout[0]
Example #25
0
 def test_layout_avoid_dangling_virtual(self):
     """ No dangling pointers for virtual qubits."""
     layout = Layout({(self.qr, 0): 0})
     self.assertEqual(layout[0], (self.qr, 0))
     layout[0] = (self.qr, 1)
     with self.assertRaises(KeyError):
         _ = layout[(self.qr, 0)]
Example #26
0
def remap_compact_virtual_qubit_registers(circuit: QuantumCircuit, coupling_map: CouplingMap) -> \
        Optional[Tuple[QuantumCircuit, int]]:
    dag = circuit_to_dag(circuit)
    if not check_dag_circuit_compatible(dag, coupling_map):
        return

    qreg = dag.qregs['q']
    num_physical_qubits = len(coupling_map.physical_qubits)
    device_register = QuantumRegister(num_physical_qubits)
    qubit_index_counter = 0
    virtual_qubit_remap_layout = Layout.generate_trivial_layout(device_register)
    idle_wires = [wire for wire in dag.idle_wires()]
    for i in range(len(qreg)):
        qubit = qreg[i]
        if qubit not in idle_wires:
            virtual_qubit_remap_layout.add(qubit, qubit_index_counter)
            qubit_index_counter += 1

    for i, wire in enumerate(idle_wires):
        virtual_qubit_remap_layout.add(wire, qubit_index_counter + i)
    logger.debug("Compact circuit layout: {}".format(virtual_qubit_remap_layout))
    remap_pass_manager = PassManager()
    remap_pass_manager.append(SetLayout(virtual_qubit_remap_layout))
    remap_pass_manager.append(ApplyLayout())
    remap_circuit = remap_pass_manager.run(circuit)
    return remap_circuit, qubit_index_counter
    def run(self, dag):
        """
        If `dag` is mapped and the direction is correct the property
        `is_direction_mapped` is set to True (or to False otherwise).

        Args:
            dag (DAGCircuit): DAG to check.
        """
        if self.layout is None:
            if self.property_set["layout"]:
                self.layout = self.property_set["layout"]
            else:
                self.layout = Layout.generate_trivial_layout(*dag.qregs.values())

        self.property_set['is_direction_mapped'] = True
        edges = self.coupling_map.get_edges()

        for gate in dag.twoQ_gates():
            physical_q0 = self.layout[gate.qargs[0]]
            physical_q1 = self.layout[gate.qargs[1]]

            if isinstance(gate.op, (CXBase, CnotGate)) and (
                    physical_q0, physical_q1) not in edges:
                self.property_set['is_direction_mapped'] = False
                return
Example #28
0
def layout_test():
    q0 = QuantumRegister(1, name='x')
    q1 = QuantumRegister(1, name='y')
    q2 = QuantumRegister(1, name='z')
    q3 = QuantumRegister(1, name='h')
    cr = ClassicalRegister(4)
    qc = QuantumCircuit(q0, q1, q2, q3, cr)
    qc.x(q0[0])
    qc.y(q1[0])
    qc.z(q2[0])
    qc.h(q3[0])
    qc.measure(q0, cr[0])
    # qc = random_circuit(4, 1, measure=True)
    print(qc)
    q = qc.qubits
    print(q)
    input_dict = {}
    input_dict[q0[0]] = 3
    input_dict[q1[0]] = 2
    input_dict[q2[0]] = 1
    input_dict[q3[0]] = 0
    # input_dict[q[0]] = 3
    # input_dict[q[1]] = 2
    # input_dict[q[2]] = 1
    # input_dict[q[3]] = 0
    layout = Layout(input_dict=input_dict)
    print(layout)
    qc._layout = layout
    print(qc)
    print(qc._layout)
    def run(self, dag):
        """Run the CheckGateDirection pass on `dag`.

        If `dag` is mapped and the direction is correct the property
        `is_direction_mapped` is set to True (or to False otherwise).

        Args:
            dag (DAGCircuit): DAG to check.
        """
        self.property_set["is_direction_mapped"] = True
        edges = self.coupling_map.get_edges()
        trivial_layout = Layout.generate_trivial_layout(*dag.qregs.values())
        if self.target is None:
            for gate in dag.two_qubit_ops():
                physical_q0 = trivial_layout[gate.qargs[0]]
                physical_q1 = trivial_layout[gate.qargs[1]]

                if (physical_q0, physical_q1) not in edges:
                    self.property_set["is_direction_mapped"] = False
                    return
        else:
            for gate in dag.two_qubit_ops():
                physical_q0 = trivial_layout[gate.qargs[0]]
                physical_q1 = trivial_layout[gate.qargs[1]]

                if (physical_q0, physical_q1) not in self.target[gate.op.name]:
                    self.property_set["is_direction_mapped"] = False
                    return
    def run(self, dag):
        """Run the StochasticSwap pass on `dag`.

        Args:
            dag (DAGCircuit): DAG to map.

        Returns:
            DAGCircuit: A mapped DAG.

        Raises:
            TranspilerError: if the coupling map or the layout are not
            compatible with the DAG
        """

        if len(dag.qregs) != 1 or dag.qregs.get("q", None) is None:
            raise TranspilerError("StochasticSwap runs on physical circuits only")

        if len(dag.qubits) > len(self.coupling_map.physical_qubits):
            raise TranspilerError("The layout does not match the amount of qubits in the DAG")

        canonical_register = dag.qregs["q"]
        self.trivial_layout = Layout.generate_trivial_layout(canonical_register)
        self._qubit_indices = {bit: idx for idx, bit in enumerate(dag.qubits)}

        self.qregs = dag.qregs
        if self.seed is None:
            self.seed = np.random.randint(0, np.iinfo(np.int32).max)
        self.rng = np.random.default_rng(self.seed)
        logger.debug("StochasticSwap default_rng seeded with seed=%s", self.seed)
        self.coupling_map.compute_distance_matrix()
        new_dag = self._mapper(dag, self.coupling_map, trials=self.trials)
        return new_dag