예제 #1
0
    def test_random_decompose(self):
        """
        Test that random elements are CNOTDihedral
        and to_circuit, to_instruction, _from_circuit, _is_valid methods
        """
        rng = np.random.default_rng(1234)
        samples = 10
        for num_qubits in range(1, 9):
            for _ in range(samples):
                # Test of random_cnotdihedral method
                elem = random_cnotdihedral(num_qubits, seed=rng)
                self.assertIsInstance(
                    elem, CNOTDihedral,
                    "Error: random element is not CNOTDihedral")
                self.assertTrue(elem._is_valid(),
                                "Error: random element is not CNOTDihedral")

                # Test of to_circuit and _from_circuit methods
                test_circ = elem.to_circuit()
                self.assertTrue(
                    test_circ,
                    "Error: cannot decompose a random "
                    "CNOTDihedral element to a circuit",
                )
                test_elem = CNOTDihedral(test_circ)

                self.assertEqual(
                    elem,
                    test_elem,
                    "Error: decomposed circuit is not equal "
                    "to the original circuit",
                )
                # Test that _is_valid fails if linear part is wrong
                test_elem.linear = np.zeros((num_qubits, num_qubits))
                value = test_elem._is_valid()
                self.assertFalse(
                    value, "Error: CNOTDihedral _is_valid is not correct.")

                # Test of to_instruction and _from_circuit methods
                test_gates = elem.to_instruction()
                self.assertIsInstance(
                    test_gates,
                    Gate,
                    "Error: cannot decompose a random "
                    "CNOTDihedral element to a Gate",
                )
                self.assertEqual(
                    test_gates.num_qubits,
                    test_circ.num_qubits,
                    "Error: wrong num_qubits in decomposed gates",
                )
                test_elem1 = CNOTDihedral(test_gates)
                self.assertEqual(
                    elem,
                    test_elem1,
                    "Error: decomposed gates are not equal "
                    "to the original gates",
                )
예제 #2
0
 def test_conjugate(self):
     """Test transpose method"""
     samples = 10
     rng = np.random.default_rng(777)
     for num_qubits in range(1, 5):
         for _ in range(samples):
             circ = random_cnotdihedral_circuit(num_qubits, 5 * num_qubits, seed=rng)
             elem = CNOTDihedral(circ)
             value = elem.conjugate().to_operator()
             target = Operator(circ).conjugate()
             self.assertTrue(target.equiv(value), "Error: conjugate circuit is not the same")
예제 #3
0
 def test_dot_method(self):
     """Test dot method"""
     samples = 10
     rng = np.random.default_rng(222)
     for num_qubits in range(1, 6):
         for _ in range(samples):
             circ1 = random_cnotdihedral_circuit(num_qubits, 5 * num_qubits, seed=rng)
             circ2 = random_cnotdihedral_circuit(num_qubits, 5 * num_qubits, seed=rng)
             elem1 = CNOTDihedral(circ1)
             elem2 = CNOTDihedral(circ2)
             value = elem1.dot(elem2)
             target = CNOTDihedral(circ2.compose(circ1))
             self.assertEqual(target, value, "Error: composed circuit is not the same")
예제 #4
0
    def test_init_circuit_decompose(self):
        """
        Test initialization from circuit and to_circuit, to_instruction methods
        """
        rng = np.random.default_rng(1234)
        samples = 10
        for num_qubits in range(1, 9):
            for _ in range(samples):
                # Test of to_circuit and _from_circuit methods
                circ = random_cnotdihedral_circuit(num_qubits,
                                                   5 * num_qubits,
                                                   seed=rng)
                elem = CNOTDihedral(circ)
                test_circ = elem.to_circuit()
                test_elem = CNOTDihedral(test_circ)
                self.assertEqual(
                    elem,
                    test_elem,
                    "Error: decomposed gates are not equal to the original gates",
                )

                # Test of to_instruction and _from_circuit methods
                circ = random_cnotdihedral_circuit(num_qubits,
                                                   5 * num_qubits,
                                                   seed=rng)
                elem = CNOTDihedral(circ)
                test_circ = elem.to_instruction()
                test_elem = CNOTDihedral(test_circ)
                self.assertEqual(
                    elem,
                    test_elem,
                    "Error: decomposed gates are not equal to the original gates",
                )
예제 #5
0
    def test_barrier_delay_sim(self):
        """Test barrier and delay instructions can be simulated"""
        target_circ = QuantumCircuit(2)
        target_circ.x(0)
        target_circ.cx(0, 1)
        target = CNOTDihedral(target_circ)

        circ = QuantumCircuit(2)
        circ.x(0)
        circ.delay(100, 0)
        circ.barrier([0, 1])
        circ.cx(0, 1)
        value = CNOTDihedral(circ)
        self.assertEqual(value, target)
예제 #6
0
 def test_to_matrix(self):
     """Test to_matrix method"""
     samples = 10
     rng = np.random.default_rng(888)
     for num_qubits in range(1, 5):
         for _ in range(samples):
             circ = random_cnotdihedral_circuit(num_qubits, 5 * num_qubits, seed=rng)
             elem = CNOTDihedral(circ)
             mat = elem.to_matrix()
             self.assertIsInstance(mat, np.ndarray)
             self.assertEqual(mat.shape, 2 * (2**num_qubits,))
             value = Operator(mat)
             target = Operator(circ)
             self.assertTrue(value.equiv(target), "Error: matrix of the circuit is not the same")
예제 #7
0
    def test_expand_method(self):
        """Test expand method"""
        samples = 10
        rng = np.random.default_rng(333)
        for num_qubits_1 in range(1, 5):
            for num_qubits_2 in range(1, 5):
                for _ in range(samples):
                    elem1 = random_cnotdihedral(num_qubits_1, seed=rng)
                    elem2 = random_cnotdihedral(num_qubits_2, seed=rng)
                    circ1 = elem1.to_instruction()
                    circ2 = elem2.to_instruction()
                    value = elem2.expand(elem1)
                    circ = QuantumCircuit(num_qubits_1 + num_qubits_2)
                    qargs = list(range(num_qubits_1))
                    for instr, qregs, _ in circ1.definition:
                        new_qubits = [
                            qargs[circ1.definition.qubits.index(tup)]
                            for tup in qregs
                        ]
                        circ.append(instr, new_qubits)
                    qargs = list(
                        range(num_qubits_1, num_qubits_1 + num_qubits_2))
                    for instr, qregs, _ in circ2.definition:
                        new_qubits = [
                            qargs[circ2.definition.qubits.index(tup)]
                            for tup in qregs
                        ]
                        circ.append(instr, new_qubits)
                    target = CNOTDihedral(circ)

                    self.assertEqual(target, value,
                                     "Error: expand circuit is not the same")
예제 #8
0
 def test_init_from_pauli(self):
     """Test initialization from Pauli"""
     samples = 10
     rng = np.random.default_rng(999)
     for num_qubits in range(1, 5):
         for _ in range(samples):
             pauli = random.random_pauli(num_qubits, seed=rng)
             elem = CNOTDihedral(pauli)
             value = Operator(pauli)
             target = Operator(elem)
             self.assertTrue(value.equiv(target), "Error: Pauli operator is not the same.")
예제 #9
0
    def test_1_qubit_identities(self):
        """Tests identities for 1-qubit gates"""
        # T*X*T = X
        circ1 = QuantumCircuit(1)
        circ1.t(0)
        circ1.x(0)
        circ1.t(0)
        elem1 = CNOTDihedral(circ1)
        elem = CNOTDihedral(XGate())
        self.assertEqual(elem1, elem, "Error: 1-qubit identity does not hold")

        # X*T*X = Tdg
        circ1 = QuantumCircuit(1)
        circ1.x(0)
        circ1.t(0)
        circ1.x(0)
        elem1 = CNOTDihedral(circ1)
        elem = CNOTDihedral(TdgGate())
        self.assertEqual(elem1, elem, "Error: 1-qubit identity does not hold")

        # X*Tdg*X = T
        circ1 = QuantumCircuit(1)
        circ1.x(0)
        circ1.tdg(0)
        circ1.x(0)
        elem1 = CNOTDihedral(circ1)
        elem = CNOTDihedral(TGate())
        self.assertEqual(elem1, elem, "Error: 1-qubit identity does not hold")

        # X*S*X = Sdg
        circ1 = QuantumCircuit(1)
        circ1.x(0)
        circ1.s(0)
        circ1.x(0)
        elem1 = CNOTDihedral(circ1)
        elem = CNOTDihedral(SdgGate())
        self.assertEqual(elem1, elem, "Error: 1-qubit identity does not hold")

        # X*Sdg*X = S
        circ1 = QuantumCircuit(1)
        circ1.x(0)
        circ1.sdg(0)
        circ1.x(0)
        elem1 = CNOTDihedral(circ1)
        elem = CNOTDihedral(SGate())
        self.assertEqual(elem1, elem, "Error: 1-qubit identity does not hold")

        # T*X*Tdg = S*X
        circ1 = QuantumCircuit(1)
        circ1.t(0)
        circ1.x(0)
        circ1.tdg(0)
        circ2 = QuantumCircuit(1)
        circ2.s(0)
        circ2.x(0)
        elem1 = CNOTDihedral(circ1)
        elem2 = CNOTDihedral(circ2)
        self.assertEqual(elem1, elem2, "Error: 1-qubit identity does not hold")
예제 #10
0
    def test_2_qubit_identities(self):
        """Tests identities for 2-qubit gates"""
        # SI * CX * SdgI = CX
        elem = CNOTDihedral(CXGate())
        circ1 = QuantumCircuit(2)
        circ1.s(0)
        circ1.cx(0, 1)
        circ1.sdg(0)
        elem1 = CNOTDihedral(circ1)
        self.assertEqual(elem, elem1,
                         "Error: 2-qubit CX identity does not hold")

        # SI * CZ * SdgI = CZ
        elem = CNOTDihedral(CZGate())
        circ1 = QuantumCircuit(2)
        circ1.s(0)
        circ1.cz(1, 0)
        circ1.sdg(0)
        elem1 = CNOTDihedral(circ1)
        self.assertEqual(elem, elem1,
                         "Error: 2-qubit CZ identity does not hold")

        # SWAP = CX01 * CX10 * CX01 = CX10 * CX01 * CX10
        elem = CNOTDihedral(SwapGate())
        circ1 = QuantumCircuit(2)
        circ1.cx(0, 1)
        circ1.cx(1, 0)
        circ1.cx(0, 1)
        circ2 = QuantumCircuit(2)
        circ2.cx(1, 0)
        circ2.cx(0, 1)
        circ2.cx(1, 0)
        elem1 = CNOTDihedral(circ1)
        elem2 = CNOTDihedral(circ2)
        self.assertEqual(elem, elem1,
                         "Error: 2-qubit SWAP identity does not hold")
        self.assertEqual(elem1, elem2,
                         "Error: 2-qubit SWAP identity does not hold")

        # CS01 = CS10 (symmetric)
        #
        #      ┌───┐
        # q_0: ┤ T ├──■───────────■──
        #      ├───┤┌─┴─┐┌─────┐┌─┴─┐
        # q_1: ┤ T ├┤ X ├┤ Tdg ├┤ X ├
        #      └───┘└───┘└─────┘└───┘
        circ1 = QuantumCircuit(2)
        circ1.t(0)
        circ1.t(1)
        circ1.cx(0, 1)
        circ1.tdg(1)
        circ1.cx(0, 1)

        #      ┌───┐┌───┐┌─────┐┌───┐
        # q_0: ┤ T ├┤ X ├┤ Tdg ├┤ X ├
        #      ├───┤└─┬─┘└─────┘└─┬─┘
        # q_1: ┤ T ├──■───────────■──
        #      └───┘
        circ2 = QuantumCircuit(2)
        circ2.t(1)
        circ2.t(0)
        circ2.cx(1, 0)
        circ2.tdg(0)
        circ2.cx(1, 0)
        elem1 = CNOTDihedral(circ1)
        elem2 = CNOTDihedral(circ2)
        self.assertEqual(elem1, elem2,
                         "Error: 2-qubit CS identity does not hold")

        # TI*CS*TdgI = CS
        #
        #      ┌───┐┌───┐                 ┌─────┐
        # q_0: ┤ T ├┤ T ├──■───────────■──┤ Tdg ├
        #      ├───┤└───┘┌─┴─┐┌─────┐┌─┴─┐└─────┘
        # q_1: ┤ T ├─────┤ X ├┤ Tdg ├┤ X ├───────
        #      └───┘     └───┘└─────┘└───┘
        circ3 = QuantumCircuit(2)
        circ3.t(0)
        circ3.t(0)
        circ3.t(1)
        circ3.cx(0, 1)
        circ3.tdg(1)
        circ3.cx(0, 1)
        circ3.tdg(0)
        elem3 = CNOTDihedral(circ3)
        self.assertEqual(elem1, elem3,
                         "Error: 2-qubit CS identity does not hold")

        # IT*CS*ITdg = CS
        #
        #      ┌───┐
        # q_0: ┤ T ├───────■───────────■─────────
        #      ├───┤┌───┐┌─┴─┐┌─────┐┌─┴─┐┌─────┐
        # q_1: ┤ T ├┤ T ├┤ X ├┤ Tdg ├┤ X ├┤ Tdg ├
        #      └───┘└───┘└───┘└─────┘└───┘└─────┘
        circ4 = QuantumCircuit(2)
        circ4.t(1)
        circ4.t(0)
        circ4.t(1)
        circ4.cx(0, 1)
        circ4.tdg(1)
        circ4.cx(0, 1)
        circ4.tdg(1)
        elem4 = CNOTDihedral(circ4)
        self.assertEqual(elem1, elem4,
                         "Error: 2-qubit CS identity does not hold")

        # XX*CS*XX*SS = CS
        #
        #      ┌───┐┌───┐                 ┌───┐┌───┐
        # q_0: ┤ X ├┤ T ├──■───────────■──┤ X ├┤ S ├
        #      ├───┤├───┤┌─┴─┐┌─────┐┌─┴─┐├───┤├───┤
        # q_1: ┤ X ├┤ T ├┤ X ├┤ Tdg ├┤ X ├┤ X ├┤ S ├
        #      └───┘└───┘└───┘└─────┘└───┘└───┘└───┘
        circ5 = QuantumCircuit(2)
        circ5.x(0)
        circ5.x(1)
        circ5.t(0)
        circ5.t(1)
        circ5.cx(0, 1)
        circ5.tdg(1)
        circ5.cx(0, 1)
        circ5.x(0)
        circ5.x(1)
        circ5.s(0)
        circ5.s(1)
        elem5 = CNOTDihedral(circ5)
        self.assertEqual(elem1, elem5,
                         "Error: 2-qubit CS identity does not hold")

        # CSdg01 = CSdg10 (symmetric)
        #
        #      ┌─────┐
        # q_0: ┤ Tdg ├──■─────────■──
        #      ├─────┤┌─┴─┐┌───┐┌─┴─┐
        # q_1: ┤ Tdg ├┤ X ├┤ T ├┤ X ├
        #      └─────┘└───┘└───┘└───┘
        circ1 = QuantumCircuit(2)
        circ1.tdg(0)
        circ1.tdg(1)
        circ1.cx(0, 1)
        circ1.t(1)
        circ1.cx(0, 1)

        #      ┌─────┐┌───┐┌───┐┌───┐
        # q_0: ┤ Tdg ├┤ X ├┤ T ├┤ X ├
        #      ├─────┤└─┬─┘└───┘└─┬─┘
        # q_1: ┤ Tdg ├──■─────────■──
        #      └─────┘
        circ2 = QuantumCircuit(2)
        circ2.tdg(1)
        circ2.tdg(0)
        circ2.cx(1, 0)
        circ2.t(0)
        circ2.cx(1, 0)
        elem1 = CNOTDihedral(circ1)
        elem2 = CNOTDihedral(circ2)
        self.assertEqual(elem1, elem2,
                         "Error: 2-qubit CSdg identity does not hold")

        # XI*CS*XI*ISdg = CSdg
        #
        #      ┌───┐┌───┐                  ┌───┐
        # q_0: ┤ X ├┤ T ├──■───────────■───┤ X ├─
        #      ├───┤└───┘┌─┴─┐┌─────┐┌─┴─┐┌┴───┴┐
        # q_1: ┤ T ├─────┤ X ├┤ Tdg ├┤ X ├┤ Sdg ├
        #      └───┘     └───┘└─────┘└───┘└─────┘
        circ3 = QuantumCircuit(2)
        circ3.x(0)
        circ3.t(0)
        circ3.t(1)
        circ3.cx(0, 1)
        circ3.tdg(1)
        circ3.cx(0, 1)
        circ3.x(0)
        circ3.sdg(1)
        elem3 = CNOTDihedral(circ3)
        self.assertEqual(elem1, elem3,
                         "Error: 2-qubit CSdg identity does not hold")

        # IX*CS*IX*SdgI = CSdg
        #
        #      ┌───┐                      ┌─────┐
        # q_0: ┤ T ├───────■───────────■──┤ Sdg ├
        #      ├───┤┌───┐┌─┴─┐┌─────┐┌─┴─┐└┬───┬┘
        # q_1: ┤ X ├┤ T ├┤ X ├┤ Tdg ├┤ X ├─┤ X ├─
        #      └───┘└───┘└───┘└─────┘└───┘ └───┘
        circ4 = QuantumCircuit(2)
        circ4.x(1)
        circ4.t(0)
        circ4.t(1)
        circ4.cx(0, 1)
        circ4.tdg(1)
        circ4.cx(0, 1)
        circ4.x(1)
        circ4.sdg(0)
        elem4 = CNOTDihedral(circ4)
        self.assertEqual(elem1, elem4,
                         "Error: 2-qubit CSdg identity does not hold")

        # relations for CZ
        # CZ(0,1) = CZ(1,0)
        elem = CNOTDihedral(CZGate())
        circ1 = QuantumCircuit(2)
        circ1.cz(0, 1)
        circ2 = QuantumCircuit(2)
        circ2.cz(1, 0)
        elem1 = CNOTDihedral(circ1)
        elem2 = CNOTDihedral(circ2)
        self.assertEqual(elem, elem1,
                         "Error: 2-qubit CZ identity does not hold")
        self.assertEqual(elem1, elem2,
                         "Error: 2-qubit CZ identity does not hold")

        # CZ = CS * CS
        #
        #      ┌───┐                 ┌───┐
        # q_0: ┤ T ├──■───────────■──┤ T ├──■───────────■──
        #      ├───┤┌─┴─┐┌─────┐┌─┴─┐├───┤┌─┴─┐┌─────┐┌─┴─┐
        # q_1: ┤ T ├┤ X ├┤ Tdg ├┤ X ├┤ T ├┤ X ├┤ Tdg ├┤ X ├
        #      └───┘└───┘└─────┘└───┘└───┘└───┘└─────┘└───┘
        circ3 = QuantumCircuit(2)
        circ3.t(0)
        circ3.t(1)
        circ3.cx(0, 1)
        circ3.tdg(1)
        circ3.cx(0, 1)
        circ3.t(0)
        circ3.t(1)
        circ3.cx(0, 1)
        circ3.tdg(1)
        circ3.cx(0, 1)
        elem3 = CNOTDihedral(circ3)
        self.assertEqual(elem1, elem3,
                         "Error: 2-qubit CZ identity does not hold")

        # CZ = CSdg * CSdg
        #
        #      ┌─────┐               ┌─────┐
        # q_0: ┤ Tdg ├──■─────────■──┤ Tdg ├──■─────────■──
        #      ├─────┤┌─┴─┐┌───┐┌─┴─┐├─────┤┌─┴─┐┌───┐┌─┴─┐
        # q_1: ┤ Tdg ├┤ X ├┤ T ├┤ X ├┤ Tdg ├┤ X ├┤ T ├┤ X ├
        #      └─────┘└───┘└───┘└───┘└─────┘└───┘└───┘└───┘
        circ4 = QuantumCircuit(2)
        circ4.tdg(0)
        circ4.tdg(1)
        circ4.cx(0, 1)
        circ4.t(1)
        circ4.cx(0, 1)
        circ4.tdg(0)
        circ4.tdg(1)
        circ4.cx(0, 1)
        circ4.t(1)
        circ4.cx(0, 1)
        elem4 = CNOTDihedral(circ4)
        self.assertEqual(elem1, elem4,
                         "Error: 2-qubit CZ identity does not hold")

        # CZ = TdgTdg * CX * T^2I * CX * TdgTdg
        #
        #      ┌─────┐┌───┐┌───┐┌───┐┌───┐┌─────┐
        # q_0: ┤ Tdg ├┤ X ├┤ T ├┤ T ├┤ X ├┤ Tdg ├
        #      ├─────┤└─┬─┘└───┘└───┘└─┬─┘├─────┤
        # q_1: ┤ Tdg ├──■──────────────■──┤ Tdg ├
        #      └─────┘                    └─────┘
        circ5 = QuantumCircuit(2)
        circ5.tdg(0)
        circ5.tdg(1)
        circ5.cx(1, 0)
        circ5.t(0)
        circ5.t(0)
        circ5.cx(1, 0)
        circ5.tdg(0)
        circ5.tdg(1)
        elem5 = CNOTDihedral(circ5)
        self.assertEqual(elem1, elem5,
                         "Error: 2-qubit CZ identity does not hold")

        # relations for CX
        circ1 = QuantumCircuit(2)
        circ1.cx(0, 1)
        elem1 = CNOTDihedral(circ1)

        # TI*CX*TdgI = CX
        #
        #      ┌───┐     ┌─────┐
        # q_0: ┤ T ├──■──┤ Tdg ├
        #      └───┘┌─┴─┐└─────┘
        # q_1: ─────┤ X ├───────
        #           └───┘
        circ2 = QuantumCircuit(2)
        circ2.t(0)
        circ2.cx(0, 1)
        circ2.tdg(0)
        elem2 = CNOTDihedral(circ2)
        self.assertEqual(elem1, elem2,
                         "Error: 2-qubit CX identity does not hold")

        # IZ*CX*ZZ = CX
        #
        #                ┌───┐
        # q_0: ───────■──┤ Z ├
        #      ┌───┐┌─┴─┐├───┤
        # q_1: ┤ Z ├┤ X ├┤ Z ├
        #      └───┘└───┘└───┘
        circ3 = QuantumCircuit(2)
        circ3.z(1)
        circ3.cx(0, 1)
        circ3.z(0)
        circ3.z(1)
        elem3 = CNOTDihedral(circ3)
        self.assertEqual(elem1, elem3,
                         "Error: 2-qubit CX identity does not hold")

        # IX*CX*IX = CX
        #
        # q_0: ───────■───────
        #      ┌───┐┌─┴─┐┌───┐
        # q_1: ┤ X ├┤ X ├┤ X ├
        #      └───┘└───┘└───┘
        circ4 = QuantumCircuit(2)
        circ4.x(1)
        circ4.cx(0, 1)
        circ4.x(1)
        elem4 = CNOTDihedral(circ4)
        self.assertEqual(elem1, elem4,
                         "Error: 2-qubit CX identity does not hold")

        # XI*CX*XX = CX
        #
        #      ┌───┐     ┌───┐
        # q_0: ┤ X ├──■──┤ X ├
        #      └───┘┌─┴─┐├───┤
        # q_1: ─────┤ X ├┤ X ├
        #           └───┘└───┘
        circ5 = QuantumCircuit(2)
        circ5.x(0)
        circ5.cx(0, 1)
        circ5.x(0)
        circ5.x(1)
        elem5 = CNOTDihedral(circ5)
        self.assertEqual(elem1, elem5,
                         "Error: 2-qubit CX identity does not hold")

        # IT*CX01*CX10*TdgI = CX01*CX10
        #
        #           ┌───┐
        # q_0: ──■──┤ X ├
        #      ┌─┴─┐└─┬─┘
        # q_1: ┤ X ├──■──
        #      └───┘
        circ1 = QuantumCircuit(2)
        circ1.cx(0, 1)
        circ1.cx(1, 0)

        #                ┌───┐┌─────┐
        # q_0: ───────■──┤ X ├┤ Tdg ├
        #      ┌───┐┌─┴─┐└─┬─┘└─────┘
        # q_1: ┤ T ├┤ X ├──■─────────
        #      └───┘└───┘
        circ2 = QuantumCircuit(2)
        circ2.t(1)
        circ2.cx(0, 1)
        circ2.cx(1, 0)
        circ2.tdg(0)
        elem1 = CNOTDihedral(circ1)
        elem2 = CNOTDihedral(circ2)
        self.assertEqual(elem1, elem2,
                         "Error: 2-qubit CX01*CX10 identity does not hold")
예제 #11
0
    def test_2_qubit_identities(self):
        """Tests identities for 2-qubit gates"""
        # SI * CX * SdgI = CX
        elem = CNOTDihedral(CXGate())
        circ1 = QuantumCircuit(2)
        circ1.s(0)
        circ1.cx(0, 1)
        circ1.sdg(0)
        elem1 = CNOTDihedral(circ1)
        self.assertEqual(elem, elem1,
                         "Error: 2-qubit CX identity does not hold")

        # SI * CZ * SdgI = CZ
        elem = CNOTDihedral(CZGate())
        circ1 = QuantumCircuit(2)
        circ1.s(0)
        circ1.cz(1, 0)
        circ1.sdg(0)
        elem1 = CNOTDihedral(circ1)
        self.assertEqual(elem, elem1,
                         "Error: 2-qubit CZ identity does not hold")

        # SWAP = CX01 * CX10 * CX01 = CX10 * CX01 * CX10
        elem = CNOTDihedral(SwapGate())
        circ1 = QuantumCircuit(2)
        circ1.cx(0, 1)
        circ1.cx(1, 0)
        circ1.cx(0, 1)
        circ2 = QuantumCircuit(2)
        circ2.cx(1, 0)
        circ2.cx(0, 1)
        circ2.cx(1, 0)
        elem1 = CNOTDihedral(circ1)
        elem2 = CNOTDihedral(circ2)
        self.assertEqual(elem, elem1,
                         "Error: 2-qubit SWAP identity does not hold")
        self.assertEqual(elem1, elem2,
                         "Error: 2-qubit SWAP identity does not hold")

        # CS01 = CS10 (symmetric)
        circ1 = QuantumCircuit(2)
        circ1.t(0)
        circ1.t(1)
        circ1.cx(0, 1)
        circ1.tdg(1)
        circ1.cx(0, 1)
        circ2 = QuantumCircuit(2)
        circ2.t(1)
        circ2.t(0)
        circ2.cx(1, 0)
        circ2.tdg(0)
        circ2.cx(1, 0)
        elem1 = CNOTDihedral(circ1)
        elem2 = CNOTDihedral(circ2)
        self.assertEqual(elem1, elem2,
                         "Error: 2-qubit CS identity does not hold")

        # TI*CS*TdgI = CS
        circ3 = QuantumCircuit(2)
        circ3.t(0)
        circ3.t(0)
        circ3.t(1)
        circ3.cx(0, 1)
        circ3.tdg(1)
        circ3.cx(0, 1)
        circ3.tdg(0)
        elem3 = CNOTDihedral(circ3)
        self.assertEqual(elem1, elem3,
                         "Error: 2-qubit CS identity does not hold")

        # IT*CS*ITdg = CS
        circ4 = QuantumCircuit(2)
        circ4.t(1)
        circ4.t(0)
        circ4.t(1)
        circ4.cx(0, 1)
        circ4.tdg(1)
        circ4.cx(0, 1)
        circ4.tdg(1)
        elem4 = CNOTDihedral(circ4)
        self.assertEqual(elem1, elem4,
                         "Error: 2-qubit CS identity does not hold")

        # XX*CS*XX*SS = CS
        circ5 = QuantumCircuit(2)
        circ5.x(0)
        circ5.x(1)
        circ5.t(0)
        circ5.t(1)
        circ5.cx(0, 1)
        circ5.tdg(1)
        circ5.cx(0, 1)
        circ5.x(0)
        circ5.x(1)
        circ5.s(0)
        circ5.s(1)
        elem5 = CNOTDihedral(circ5)
        self.assertEqual(elem1, elem5,
                         "Error: 2-qubit CS identity does not hold")

        # CSdg01 = CSdg10 (symmetric)
        circ1 = QuantumCircuit(2)
        circ1.tdg(0)
        circ1.tdg(1)
        circ1.cx(0, 1)
        circ1.t(1)
        circ1.cx(0, 1)
        circ2 = QuantumCircuit(2)
        circ2.tdg(1)
        circ2.tdg(0)
        circ2.cx(1, 0)
        circ2.t(0)
        circ2.cx(1, 0)
        elem1 = CNOTDihedral(circ1)
        elem2 = CNOTDihedral(circ2)
        self.assertEqual(elem1, elem2,
                         "Error: 2-qubit CSdg identity does not hold")

        # XI*CS*XI*ISdg = CSdg
        circ3 = QuantumCircuit(2)
        circ3.x(0)
        circ3.t(0)
        circ3.t(1)
        circ3.cx(0, 1)
        circ3.tdg(1)
        circ3.cx(0, 1)
        circ3.x(0)
        circ3.sdg(1)
        elem3 = CNOTDihedral(circ3)
        self.assertEqual(elem1, elem3,
                         "Error: 2-qubit CSdg identity does not hold")

        # IX*CS*IX*SdgI = CSdg
        circ4 = QuantumCircuit(2)
        circ4.x(1)
        circ4.t(0)
        circ4.t(1)
        circ4.cx(0, 1)
        circ4.tdg(1)
        circ4.cx(0, 1)
        circ4.x(1)
        circ4.sdg(0)
        elem4 = CNOTDihedral(circ4)
        self.assertEqual(elem1, elem4,
                         "Error: 2-qubit CSdg identity does not hold")

        # relations for CZ
        # CZ(0,1) = CZ(1,0)
        elem = CNOTDihedral(CZGate())
        circ1 = QuantumCircuit(2)
        circ1.cz(0, 1)
        circ2 = QuantumCircuit(2)
        circ2.cz(1, 0)
        elem1 = CNOTDihedral(circ1)
        elem2 = CNOTDihedral(circ2)
        self.assertEqual(elem, elem1,
                         "Error: 2-qubit CZ identity does not hold")
        self.assertEqual(elem1, elem2,
                         "Error: 2-qubit CZ identity does not hold")

        # CZ = CS * CS
        circ3 = QuantumCircuit(2)
        circ3.t(0)
        circ3.t(1)
        circ3.cx(0, 1)
        circ3.tdg(1)
        circ3.cx(0, 1)
        circ3.t(0)
        circ3.t(1)
        circ3.cx(0, 1)
        circ3.tdg(1)
        circ3.cx(0, 1)
        elem3 = CNOTDihedral(circ3)
        self.assertEqual(elem1, elem3,
                         "Error: 2-qubit CZ identity does not hold")

        # CZ = CSdg * CSdg
        circ4 = QuantumCircuit(2)
        circ4.tdg(0)
        circ4.tdg(1)
        circ4.cx(0, 1)
        circ4.t(1)
        circ4.cx(0, 1)
        circ4.tdg(0)
        circ4.tdg(1)
        circ4.cx(0, 1)
        circ4.t(1)
        circ4.cx(0, 1)
        elem4 = CNOTDihedral(circ4)
        self.assertEqual(elem1, elem4,
                         "Error: 2-qubit CZ identity does not hold")

        # CZ = TdgTdg * CX * T^2I * CX * TdgTdg
        circ5 = QuantumCircuit(2)
        circ5.tdg(0)
        circ5.tdg(1)
        circ5.cx(1, 0)
        circ5.t(0)
        circ5.t(0)
        circ5.cx(1, 0)
        circ5.tdg(0)
        circ5.tdg(1)
        elem5 = CNOTDihedral(circ5)
        self.assertEqual(elem1, elem5,
                         "Error: 2-qubit CZ identity does not hold")

        # relations for CX
        circ1 = QuantumCircuit(2)
        circ1.cx(0, 1)
        elem1 = CNOTDihedral(circ1)

        # TI*CX*TdgI = CX
        circ2 = QuantumCircuit(2)
        circ2.t(0)
        circ2.cx(0, 1)
        circ2.tdg(0)
        elem2 = CNOTDihedral(circ2)
        self.assertEqual(elem1, elem2,
                         "Error: 2-qubit CX identity does not hold")

        # IZ*CX*ZZ = CX
        circ3 = QuantumCircuit(2)
        circ3.z(1)
        circ3.cx(0, 1)
        circ3.z(0)
        circ3.z(1)
        elem3 = CNOTDihedral(circ3)
        self.assertEqual(elem1, elem3,
                         "Error: 2-qubit CX identity does not hold")

        # IX*CX*IX = CX
        circ4 = QuantumCircuit(2)
        circ4.x(1)
        circ4.cx(0, 1)
        circ4.x(1)
        elem4 = CNOTDihedral(circ4)
        self.assertEqual(elem1, elem4,
                         "Error: 2-qubit CX identity does not hold")

        # XI*CX*XX = CX
        circ5 = QuantumCircuit(2)
        circ5.x(0)
        circ5.cx(0, 1)
        circ5.x(0)
        circ5.x(1)
        elem5 = CNOTDihedral(circ5)
        self.assertEqual(elem1, elem5,
                         "Error: 2-qubit CX identity does not hold")

        # IT*CX01*CX10*TdgI = CX01*CX10
        circ1 = QuantumCircuit(2)
        circ1.cx(0, 1)
        circ1.cx(1, 0)
        circ2 = QuantumCircuit(2)
        circ2.t(1)
        circ2.cx(0, 1)
        circ2.cx(1, 0)
        circ2.tdg(0)
        elem1 = CNOTDihedral(circ1)
        elem2 = CNOTDihedral(circ2)
        self.assertEqual(elem1, elem2,
                         "Error: 2-qubit CX01*CX10 identity does not hold")