Example #1
0
def random_cnotdihedral_circuit(num_qubits, num_gates, gates="all", seed=None):
    """Generate a pseudo random CNOTDihedral circuit."""

    if gates == "all":
        if num_qubits == 1:
            gates = ["i", "x", "y", "z", "t", "tdg", "s", "sdg"]
        else:
            gates = [
                "i", "x", "y", "z", "t", "tdg", "s", "sdg", "cx", "cz", "swap"
            ]

    instructions = {
        "i": (IGate(), 1),
        "x": (XGate(), 1),
        "y": (YGate(), 1),
        "z": (ZGate(), 1),
        "s": (SGate(), 1),
        "sdg": (SdgGate(), 1),
        "t": (TGate(), 1),
        "tdg": (TdgGate(), 1),
        "cx": (CXGate(), 2),
        "cz": (CZGate(), 2),
        "swap": (SwapGate(), 2),
    }

    if isinstance(seed, np.random.Generator):
        rng = seed
    else:
        rng = np.random.default_rng(seed)

    samples = rng.choice(gates, num_gates)

    circ = QuantumCircuit(num_qubits)

    for name in samples:
        gate, nqargs = instructions[name]
        qargs = rng.choice(range(num_qubits), nqargs, replace=False).tolist()
        circ.append(gate, qargs)

    return circ
Example #2
0
def random_cnotdihedral_circuit(num_qubits, num_gates, gates='all', seed=None):
    """Generate a pseudo random CNOTDihedral circuit."""

    if gates == 'all':
        if num_qubits == 1:
            gates = ['i', 'x', 'y', 'z', 't', 'tdg', 's', 'sdg']
        else:
            gates = [
                'i', 'x', 'y', 'z', 't', 'tdg', 's', 'sdg', 'cx', 'cz', 'swap'
            ]

    instructions = {
        'i': (IGate(), 1),
        'x': (XGate(), 1),
        'y': (YGate(), 1),
        'z': (ZGate(), 1),
        's': (SGate(), 1),
        'sdg': (SdgGate(), 1),
        't': (TGate(), 1),
        'tdg': (TdgGate(), 1),
        'cx': (CXGate(), 2),
        'cz': (CZGate(), 2),
        'swap': (SwapGate(), 2)
    }

    if isinstance(seed, np.random.Generator):
        rng = seed
    else:
        rng = np.random.default_rng(seed)

    samples = rng.choice(gates, num_gates)

    circ = QuantumCircuit(num_qubits)

    for name in samples:
        gate, nqargs = instructions[name]
        qargs = rng.choice(range(num_qubits), nqargs, replace=False).tolist()
        circ.append(gate, qargs)

    return circ
    def test_user_style(self):
        """Tests loading a user style"""
        circuit = QuantumCircuit(7)
        circuit.h(0)
        circuit.append(HGate(label="H2"), [1])
        circuit.x(0)
        circuit.cx(0, 1)
        circuit.ccx(0, 1, 2)
        circuit.swap(0, 1)
        circuit.cswap(0, 1, 2)
        circuit.append(SwapGate().control(2), [0, 1, 2, 3])
        circuit.dcx(0, 1)
        circuit.append(DCXGate().control(1), [0, 1, 2])
        circuit.append(DCXGate().control(2), [0, 1, 2, 3])
        circuit.z(4)
        circuit.append(SGate(label="S1"), [4])
        circuit.sdg(4)
        circuit.t(4)
        circuit.tdg(4)
        circuit.p(pi / 2, 4)
        circuit.cz(5, 6)
        circuit.cp(pi / 2, 5, 6)
        circuit.y(5)
        circuit.rx(pi / 3, 5)
        circuit.rzx(pi / 2, 5, 6)
        circuit.u(pi / 2, pi / 2, pi / 2, 5)
        circuit.barrier(5, 6)
        circuit.reset(5)

        self.circuit_drawer(
            circuit,
            style={
                "name": "user_style",
                "displaytext": {"H2": "H_2"},
                "displaycolor": {"H2": ("#EEDD00", "#FF0000")},
            },
            filename="user_style.png",
        )
Example #4
0
class TestRBUtilities(QiskitExperimentsTestCase):
    """
    A test class for additional functionality provided by the StandardRB
    class.
    """

    instructions = {
        "i": IGate(),
        "x": XGate(),
        "y": YGate(),
        "z": ZGate(),
        "h": HGate(),
        "s": SGate(),
        "sdg": SdgGate(),
        "cx": CXGate(),
        "cz": CZGate(),
        "swap": SwapGate(),
    }
    seed = 42

    @data(
        [1, {((0,), "x"): 3, ((0,), "y"): 2, ((0,), "h"): 1}],
        [5, {((1,), "x"): 3, ((4,), "y"): 2, ((1,), "h"): 1, ((1, 4), "cx"): 7}],
    )
    @unpack
    def test_count_ops(self, num_qubits, expected_counts):
        """Testing the count_ops utility function
        this function receives a circuit and counts the number of gates
        in it, counting gates for different qubits separately"""
        circuit = QuantumCircuit(num_qubits)
        gates_to_add = []
        for gate, count in expected_counts.items():
            gates_to_add += [gate for _ in range(count)]
        rng = np.random.default_rng(self.seed)
        rng.shuffle(gates_to_add)
        for qubits, gate in gates_to_add:
            circuit.append(self.instructions[gate], qubits)
        counts = rb.RBUtils.count_ops(circuit)
        self.assertDictEqual(expected_counts, counts)

    def test_calculate_1q_epg(self):
        """Testing the calculation of 1 qubit error per gate
        The EPG is computed based on the error per clifford determined
        in the RB experiment, the gate counts, and an estimate about the
        relations between the errors of different gate types
        """
        epc_1_qubit = FitVal(0.0037, 0)
        qubits = [0]
        gate_error_ratio = {((0,), "id"): 1, ((0,), "rz"): 0, ((0,), "sx"): 1, ((0,), "x"): 1}
        gates_per_clifford = {((0,), "rz"): 10.5, ((0,), "sx"): 8.15, ((0,), "x"): 0.25}
        epg = rb.RBUtils.calculate_1q_epg(epc_1_qubit, qubits, gate_error_ratio, gates_per_clifford)
        error_dict = {
            ((0,), "rz"): FitVal(0, 0),
            ((0,), "sx"): FitVal(0.0004432101747785104, 0),
            ((0,), "x"): FitVal(0.0004432101747785104, 0),
        }

        for gate in ["x", "sx", "rz"]:
            expected_epg = error_dict[((0,), gate)]
            actual_epg = epg[(0,)][gate]
            self.assertTrue(np.allclose(expected_epg.value, actual_epg.value, atol=0.001))
            self.assertTrue(np.allclose(expected_epg.stderr, actual_epg.stderr, atol=0.001))

    def test_calculate_2q_epg(self):
        """Testing the calculation of 2 qubit error per gate
        The EPG is computed based on the error per clifford determined
        in the RB experiment, the gate counts, and an estimate about the
        relations between the errors of different gate types
        """
        epc_2_qubit = FitVal(0.034184849962675984, 0)
        qubits = [1, 4]
        gate_error_ratio = {
            ((1,), "id"): 1,
            ((4,), "id"): 1,
            ((1,), "rz"): 0,
            ((4,), "rz"): 0,
            ((1,), "sx"): 1,
            ((4,), "sx"): 1,
            ((1,), "x"): 1,
            ((4,), "x"): 1,
            ((4, 1), "cx"): 1,
            ((1, 4), "cx"): 1,
        }
        gates_per_clifford = {
            ((1, 4), "barrier"): 1.032967032967033,
            ((1,), "rz"): 15.932967032967033,
            ((1,), "sx"): 12.382417582417583,
            ((4,), "rz"): 18.681946624803768,
            ((4,), "sx"): 14.522605965463109,
            ((1, 4), "cx"): 1.0246506515936569,
            ((4, 1), "cx"): 0.5212064090480678,
            ((4,), "x"): 0.24237661112857592,
            ((1,), "measure"): 0.01098901098901099,
            ((4,), "measure"): 0.01098901098901099,
            ((1,), "x"): 0.2525918944392083,
        }
        epg_1_qubit = [
            AnalysisResultData("EPG_rz", 0.0, device_components=[1]),
            AnalysisResultData("EPG_rz", 0.0, device_components=[4]),
            AnalysisResultData("EPG_sx", 0.00036207066403884814, device_components=[1]),
            AnalysisResultData("EPG_sx", 0.0005429962529239195, device_components=[4]),
            AnalysisResultData("EPG_x", 0.00036207066403884814, device_components=[1]),
            AnalysisResultData("EPG_x", 0.0005429962529239195, device_components=[4]),
        ]
        epg = rb.RBUtils.calculate_2q_epg(
            epc_2_qubit, qubits, gate_error_ratio, gates_per_clifford, epg_1_qubit
        )

        error_dict = {
            ((1, 4), "cx"): FitVal(0.012438847900902494, 0),
        }

        expected_epg = error_dict[((1, 4), "cx")]
        actual_epg = epg[(1, 4)]["cx"]
        self.assertTrue(np.allclose(expected_epg.value, actual_epg.value, atol=0.001))
        self.assertTrue(np.allclose(expected_epg.stderr, actual_epg.stderr, atol=0.001))

    def test_coherence_limit(self):
        """Test coherence_limit."""
        t1 = 100.0
        t2 = 100.0
        gate_2_qubits = 0.5
        gate_1_qubit = 0.1
        twoq_coherence_err = rb.RBUtils.coherence_limit(2, [t1, t1], [t2, t2], gate_2_qubits)

        oneq_coherence_err = rb.RBUtils.coherence_limit(1, [t1], [t2], gate_1_qubit)

        self.assertAlmostEqual(oneq_coherence_err, 0.00049975, 6, "Error: 1Q Coherence Limit")

        self.assertAlmostEqual(twoq_coherence_err, 0.00597, 5, "Error: 2Q Coherence Limit")

    def test_clifford_1_qubit_generation(self):
        """Verify 1-qubit clifford indeed generates the correct group"""
        clifford_dicts = [
            {"stabilizer": ["+Z"], "destabilizer": ["+X"]},
            {"stabilizer": ["+X"], "destabilizer": ["+Z"]},
            {"stabilizer": ["+Y"], "destabilizer": ["+X"]},
            {"stabilizer": ["+X"], "destabilizer": ["+Y"]},
            {"stabilizer": ["+Z"], "destabilizer": ["+Y"]},
            {"stabilizer": ["+Y"], "destabilizer": ["+Z"]},
            {"stabilizer": ["-Z"], "destabilizer": ["+X"]},
            {"stabilizer": ["+X"], "destabilizer": ["-Z"]},
            {"stabilizer": ["-Y"], "destabilizer": ["+X"]},
            {"stabilizer": ["+X"], "destabilizer": ["-Y"]},
            {"stabilizer": ["-Z"], "destabilizer": ["-Y"]},
            {"stabilizer": ["-Y"], "destabilizer": ["-Z"]},
            {"stabilizer": ["-Z"], "destabilizer": ["-X"]},
            {"stabilizer": ["-X"], "destabilizer": ["-Z"]},
            {"stabilizer": ["+Y"], "destabilizer": ["-X"]},
            {"stabilizer": ["-X"], "destabilizer": ["+Y"]},
            {"stabilizer": ["-Z"], "destabilizer": ["+Y"]},
            {"stabilizer": ["+Y"], "destabilizer": ["-Z"]},
            {"stabilizer": ["+Z"], "destabilizer": ["-X"]},
            {"stabilizer": ["-X"], "destabilizer": ["+Z"]},
            {"stabilizer": ["-Y"], "destabilizer": ["-X"]},
            {"stabilizer": ["-X"], "destabilizer": ["-Y"]},
            {"stabilizer": ["+Z"], "destabilizer": ["-Y"]},
            {"stabilizer": ["-Y"], "destabilizer": ["+Z"]},
        ]
        cliffords = [Clifford.from_dict(i) for i in clifford_dicts]
        utils = rb.CliffordUtils()
        for n in range(24):
            clifford = utils.clifford_1_qubit(n)
            self.assertEqual(clifford, cliffords[n])

    def test_clifford_2_qubit_generation(self):
        """Verify 2-qubit clifford indeed generates the correct group"""
        utils = rb.CliffordUtils()
        pauli_free_elements = [
            0,
            1,
            2,
            3,
            4,
            5,
            6,
            7,
            8,
            9,
            10,
            11,
            12,
            13,
            14,
            15,
            16,
            17,
            18,
            19,
            20,
            21,
            22,
            23,
            24,
            25,
            26,
            27,
            28,
            29,
            30,
            31,
            32,
            33,
            34,
            35,
            576,
            577,
            578,
            579,
            580,
            581,
            582,
            583,
            584,
            585,
            586,
            587,
            588,
            589,
            590,
            591,
            592,
            593,
            594,
            595,
            596,
            597,
            598,
            599,
            600,
            601,
            602,
            603,
            604,
            605,
            606,
            607,
            608,
            609,
            610,
            611,
            612,
            613,
            614,
            615,
            616,
            617,
            618,
            619,
            620,
            621,
            622,
            623,
            624,
            625,
            626,
            627,
            628,
            629,
            630,
            631,
            632,
            633,
            634,
            635,
            636,
            637,
            638,
            639,
            640,
            641,
            642,
            643,
            644,
            645,
            646,
            647,
            648,
            649,
            650,
            651,
            652,
            653,
            654,
            655,
            656,
            657,
            658,
            659,
            660,
            661,
            662,
            663,
            664,
            665,
            666,
            667,
            668,
            669,
            670,
            671,
            672,
            673,
            674,
            675,
            676,
            677,
            678,
            679,
            680,
            681,
            682,
            683,
            684,
            685,
            686,
            687,
            688,
            689,
            690,
            691,
            692,
            693,
            694,
            695,
            696,
            697,
            698,
            699,
            700,
            701,
            702,
            703,
            704,
            705,
            706,
            707,
            708,
            709,
            710,
            711,
            712,
            713,
            714,
            715,
            716,
            717,
            718,
            719,
            720,
            721,
            722,
            723,
            724,
            725,
            726,
            727,
            728,
            729,
            730,
            731,
            732,
            733,
            734,
            735,
            736,
            737,
            738,
            739,
            740,
            741,
            742,
            743,
            744,
            745,
            746,
            747,
            748,
            749,
            750,
            751,
            752,
            753,
            754,
            755,
            756,
            757,
            758,
            759,
            760,
            761,
            762,
            763,
            764,
            765,
            766,
            767,
            768,
            769,
            770,
            771,
            772,
            773,
            774,
            775,
            776,
            777,
            778,
            779,
            780,
            781,
            782,
            783,
            784,
            785,
            786,
            787,
            788,
            789,
            790,
            791,
            792,
            793,
            794,
            795,
            796,
            797,
            798,
            799,
            800,
            801,
            802,
            803,
            804,
            805,
            806,
            807,
            808,
            809,
            810,
            811,
            812,
            813,
            814,
            815,
            816,
            817,
            818,
            819,
            820,
            821,
            822,
            823,
            824,
            825,
            826,
            827,
            828,
            829,
            830,
            831,
            832,
            833,
            834,
            835,
            836,
            837,
            838,
            839,
            840,
            841,
            842,
            843,
            844,
            845,
            846,
            847,
            848,
            849,
            850,
            851,
            852,
            853,
            854,
            855,
            856,
            857,
            858,
            859,
            860,
            861,
            862,
            863,
            864,
            865,
            866,
            867,
            868,
            869,
            870,
            871,
            872,
            873,
            874,
            875,
            876,
            877,
            878,
            879,
            880,
            881,
            882,
            883,
            884,
            885,
            886,
            887,
            888,
            889,
            890,
            891,
            892,
            893,
            894,
            895,
            896,
            897,
            898,
            899,
            5760,
            5761,
            5762,
            5763,
            5764,
            5765,
            5766,
            5767,
            5768,
            5769,
            5770,
            5771,
            5772,
            5773,
            5774,
            5775,
            5776,
            5777,
            5778,
            5779,
            5780,
            5781,
            5782,
            5783,
            5784,
            5785,
            5786,
            5787,
            5788,
            5789,
            5790,
            5791,
            5792,
            5793,
            5794,
            5795,
            5796,
            5797,
            5798,
            5799,
            5800,
            5801,
            5802,
            5803,
            5804,
            5805,
            5806,
            5807,
            5808,
            5809,
            5810,
            5811,
            5812,
            5813,
            5814,
            5815,
            5816,
            5817,
            5818,
            5819,
            5820,
            5821,
            5822,
            5823,
            5824,
            5825,
            5826,
            5827,
            5828,
            5829,
            5830,
            5831,
            5832,
            5833,
            5834,
            5835,
            5836,
            5837,
            5838,
            5839,
            5840,
            5841,
            5842,
            5843,
            5844,
            5845,
            5846,
            5847,
            5848,
            5849,
            5850,
            5851,
            5852,
            5853,
            5854,
            5855,
            5856,
            5857,
            5858,
            5859,
            5860,
            5861,
            5862,
            5863,
            5864,
            5865,
            5866,
            5867,
            5868,
            5869,
            5870,
            5871,
            5872,
            5873,
            5874,
            5875,
            5876,
            5877,
            5878,
            5879,
            5880,
            5881,
            5882,
            5883,
            5884,
            5885,
            5886,
            5887,
            5888,
            5889,
            5890,
            5891,
            5892,
            5893,
            5894,
            5895,
            5896,
            5897,
            5898,
            5899,
            5900,
            5901,
            5902,
            5903,
            5904,
            5905,
            5906,
            5907,
            5908,
            5909,
            5910,
            5911,
            5912,
            5913,
            5914,
            5915,
            5916,
            5917,
            5918,
            5919,
            5920,
            5921,
            5922,
            5923,
            5924,
            5925,
            5926,
            5927,
            5928,
            5929,
            5930,
            5931,
            5932,
            5933,
            5934,
            5935,
            5936,
            5937,
            5938,
            5939,
            5940,
            5941,
            5942,
            5943,
            5944,
            5945,
            5946,
            5947,
            5948,
            5949,
            5950,
            5951,
            5952,
            5953,
            5954,
            5955,
            5956,
            5957,
            5958,
            5959,
            5960,
            5961,
            5962,
            5963,
            5964,
            5965,
            5966,
            5967,
            5968,
            5969,
            5970,
            5971,
            5972,
            5973,
            5974,
            5975,
            5976,
            5977,
            5978,
            5979,
            5980,
            5981,
            5982,
            5983,
            5984,
            5985,
            5986,
            5987,
            5988,
            5989,
            5990,
            5991,
            5992,
            5993,
            5994,
            5995,
            5996,
            5997,
            5998,
            5999,
            6000,
            6001,
            6002,
            6003,
            6004,
            6005,
            6006,
            6007,
            6008,
            6009,
            6010,
            6011,
            6012,
            6013,
            6014,
            6015,
            6016,
            6017,
            6018,
            6019,
            6020,
            6021,
            6022,
            6023,
            6024,
            6025,
            6026,
            6027,
            6028,
            6029,
            6030,
            6031,
            6032,
            6033,
            6034,
            6035,
            6036,
            6037,
            6038,
            6039,
            6040,
            6041,
            6042,
            6043,
            6044,
            6045,
            6046,
            6047,
            6048,
            6049,
            6050,
            6051,
            6052,
            6053,
            6054,
            6055,
            6056,
            6057,
            6058,
            6059,
            6060,
            6061,
            6062,
            6063,
            6064,
            6065,
            6066,
            6067,
            6068,
            6069,
            6070,
            6071,
            6072,
            6073,
            6074,
            6075,
            6076,
            6077,
            6078,
            6079,
            6080,
            6081,
            6082,
            6083,
            10944,
            10945,
            10946,
            10947,
            10948,
            10949,
            10950,
            10951,
            10952,
            10953,
            10954,
            10955,
            10956,
            10957,
            10958,
            10959,
            10960,
            10961,
            10962,
            10963,
            10964,
            10965,
            10966,
            10967,
            10968,
            10969,
            10970,
            10971,
            10972,
            10973,
            10974,
            10975,
            10976,
            10977,
            10978,
            10979,
        ]
        cliffords = []
        for n in pauli_free_elements:
            clifford = utils.clifford_2_qubit(n)
            phase = clifford.table.phase
            for i in range(4):
                self.assertFalse(phase[i])
            for other_clifford in cliffords:
                self.assertNotEqual(clifford, other_clifford)
            cliffords.append(clifford)

        pauli_check_elements_list = [
            [0, 36, 72, 108, 144, 180, 216, 252, 288, 324, 360, 396, 432, 468, 504, 540],
            [
                576,
                900,
                1224,
                1548,
                1872,
                2196,
                2520,
                2844,
                3168,
                3492,
                3816,
                4140,
                4464,
                4788,
                5112,
                5436,
            ],
            [
                5760,
                6084,
                6408,
                6732,
                7056,
                7380,
                7704,
                8028,
                8352,
                8676,
                9000,
                9324,
                9648,
                9972,
                10296,
                10620,
            ],
            [
                10944,
                10980,
                11016,
                11052,
                11088,
                11124,
                11160,
                11196,
                11232,
                11268,
                11304,
                11340,
                11376,
                11412,
                11448,
                11484,
            ],
        ]
        for pauli_check_elements in pauli_check_elements_list:
            phases = []
            table = None
            for n in pauli_check_elements:
                clifford = utils.clifford_2_qubit(n)
                if table is None:
                    table = clifford.table.array
                else:
                    self.assertTrue(np.all(table == clifford.table.array))
                phase = tuple(clifford.table.phase)
                for other_phase in phases:
                    self.assertNotEqual(phase, other_phase)
                phases.append(phase)
Example #5
0
def make_immutable(obj):
    """ Delete the __setattr__ property to make the object mostly immutable. """

    # TODO figure out how to get correct error message
    # def throw_immutability_exception(self, *args):
    #     raise OpflowError('Operator convenience globals are immutable.')

    obj.__setattr__ = None
    return obj


# 1-Qubit Paulis
X = make_immutable(PauliOp(Pauli('X')))
Y = make_immutable(PauliOp(Pauli('Y')))
Z = make_immutable(PauliOp(Pauli('Z')))
I = make_immutable(PauliOp(Pauli('I')))

# Clifford+T, and some other common non-parameterized gates
CX = make_immutable(CircuitOp(CXGate()))
S = make_immutable(CircuitOp(SGate()))
H = make_immutable(CircuitOp(HGate()))
T = make_immutable(CircuitOp(TGate()))
Swap = make_immutable(CircuitOp(SwapGate()))
CZ = make_immutable(CircuitOp(CZGate()))

# 1-Qubit Paulis
Zero = make_immutable(StateFn('0'))
One = make_immutable(StateFn('1'))
Plus = make_immutable(H.compose(Zero))
Minus = make_immutable(H.compose(X).compose(Zero))
Example #6
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")
class TestPauli(QiskitTestCase):
    """Tests for Pauli operator class."""
    @data(*pauli_group_labels(2))
    def test_conjugate(self, label):
        """Test conjugate method."""
        value = Pauli(label).conjugate()
        target = operator_from_label(label).conjugate()
        self.assertEqual(Operator(value), target)

    @data(*pauli_group_labels(2))
    def test_transpose(self, label):
        """Test transpose method."""
        value = Pauli(label).transpose()
        target = operator_from_label(label).transpose()
        self.assertEqual(Operator(value), target)

    @data(*pauli_group_labels(2))
    def test_adjoint(self, label):
        """Test adjoint method."""
        value = Pauli(label).adjoint()
        target = operator_from_label(label).adjoint()
        self.assertEqual(Operator(value), target)

    @data(*pauli_group_labels(2))
    def test_inverse(self, label):
        """Test inverse method."""
        pauli = Pauli(label)
        value = pauli.inverse()
        target = pauli.adjoint()
        self.assertEqual(value, target)

    @data(*it.product(pauli_group_labels(2, full_group=False), repeat=2))
    @unpack
    def test_dot(self, label1, label2):
        """Test dot method."""
        p1 = Pauli(label1)
        p2 = Pauli(label2)
        value = Operator(p1.dot(p2))
        op1 = operator_from_label(label1)
        op2 = operator_from_label(label2)
        target = op1.dot(op2)
        self.assertEqual(value, target)

    @data(*pauli_group_labels(1))
    def test_dot_qargs(self, label2):
        """Test dot method with qargs."""
        label1 = '-iXYZ'
        p1 = Pauli(label1)
        p2 = Pauli(label2)
        qargs = [0]
        value = Operator(p1.dot(p2, qargs=qargs))
        op1 = operator_from_label(label1)
        op2 = operator_from_label(label2)
        target = op1.dot(op2, qargs=qargs)
        self.assertEqual(value, target)

    @data(*it.product(pauli_group_labels(2, full_group=False), repeat=2))
    @unpack
    def test_compose(self, label1, label2):
        """Test compose method."""
        p1 = Pauli(label1)
        p2 = Pauli(label2)
        value = Operator(p1.compose(p2))
        op1 = operator_from_label(label1)
        op2 = operator_from_label(label2)
        target = op1.compose(op2)
        self.assertEqual(value, target)

    @data(*pauli_group_labels(1))
    def test_compose_qargs(self, label2):
        """Test compose method with qargs."""
        label1 = '-XYZ'
        p1 = Pauli(label1)
        p2 = Pauli(label2)
        qargs = [0]
        value = Operator(p1.compose(p2, qargs=qargs))
        op1 = operator_from_label(label1)
        op2 = operator_from_label(label2)
        target = op1.compose(op2, qargs=qargs)
        self.assertEqual(value, target)

    @data(*it.product(pauli_group_labels(1, full_group=False), repeat=2))
    @unpack
    def test_tensor(self, label1, label2):
        """Test tensor method."""
        p1 = Pauli(label1)
        p2 = Pauli(label2)
        value = Operator(p1.tensor(p2))
        op1 = operator_from_label(label1)
        op2 = operator_from_label(label2)
        target = op1.tensor(op2)
        self.assertEqual(value, target)

    @data(*it.product(pauli_group_labels(1, full_group=False), repeat=2))
    @unpack
    def test_expand(self, label1, label2):
        """Test expand method."""
        p1 = Pauli(label1)
        p2 = Pauli(label2)
        value = Operator(p1.expand(p2))
        op1 = operator_from_label(label1)
        op2 = operator_from_label(label2)
        target = op1.expand(op2)
        self.assertEqual(value, target)

    @data('II', 'XI', 'YX', 'ZZ', 'YZ')
    def test_power(self, label):
        """Test power method."""
        iden = Pauli('II')
        op = Pauli(label)
        self.assertTrue(op**2, iden)

    @data(1, 1.0, -1, -1.0, 1j, -1j)
    def test_multiply(self, val):
        """Test multiply method."""
        op = val * Pauli(([True, True], [False, False], 0))
        phase = (-1j)**op.phase
        self.assertEqual(phase, val)

    def test_multiply_except(self):
        """Test multiply method raises exceptions."""
        op = Pauli('XYZ')
        self.assertRaises(QiskitError, op._multiply, 2)

    @data(0, 1, 2, 3)
    def test_negate(self, phase):
        """Test negate method"""
        op = Pauli(([False], [True], phase))
        neg = -op
        self.assertTrue(op.equiv(neg))
        self.assertEqual(neg.phase, (op.phase + 2) % 4)

    @data(*it.product(pauli_group_labels(1, False), repeat=2))
    @unpack
    def test_commutes(self, p1, p2):
        """Test commutes method"""
        P1 = Pauli(p1)
        P2 = Pauli(p2)
        self.assertEqual(P1.commutes(P2), P1.dot(P2) == P2.dot(P1))

    @data(*it.product(pauli_group_labels(1, False), repeat=2))
    @unpack
    def test_anticommutes(self, p1, p2):
        """Test anticommutes method"""
        P1 = Pauli(p1)
        P2 = Pauli(p2)
        self.assertEqual(P1.anticommutes(P2), P1.dot(P2) == -P2.dot(P1))

    @data(*it.product(
        (IGate(), XGate(), YGate(), ZGate(), HGate(), SGate(), SdgGate()),
        pauli_group_labels(1, False)))
    @unpack
    def test_evolve_clifford1(self, gate, label):
        """Test evolve method for 1-qubit Clifford gates."""
        cliff = Clifford(gate)
        op = Operator(gate)
        pauli = Pauli(label)
        value = Operator(pauli.evolve(cliff))
        target = op.adjoint().dot(pauli).dot(op)
        self.assertEqual(value, target)

    @data(*it.product((CXGate(), CYGate(), CZGate(), SwapGate()),
                      pauli_group_labels(2, False)))
    @unpack
    def test_evolve_clifford2(self, gate, label):
        """Test evolve method for 2-qubit Clifford gates."""
        cliff = Clifford(gate)
        op = Operator(gate)
        pauli = Pauli(label)
        value = Operator(pauli.evolve(cliff))
        target = op.adjoint().dot(pauli).dot(op)
        self.assertEqual(value, target)

    def test_evolve_clifford_qargs(self):
        """Test evolve method for random Clifford"""
        cliff = random_clifford(3, seed=10)
        op = Operator(cliff)
        pauli = random_pauli(5, seed=10)
        qargs = [3, 0, 1]
        value = Operator(pauli.evolve(cliff, qargs=qargs))
        target = Operator(pauli).compose(op.adjoint(),
                                         qargs=qargs).dot(op, qargs=qargs)
        self.assertEqual(value, target)
Example #8
0
def make_immutable(obj):
    """ Delete the __setattr__ property to make the object mostly immutable. """

    # TODO figure out how to get correct error message
    # def throw_immutability_exception(self, *args):
    #     raise AquaError('Operator convenience globals are immutable.')

    obj.__setattr__ = None
    return obj


# 1-Qubit Paulis
X = make_immutable(PauliOp(Pauli('X')))
Y = make_immutable(PauliOp(Pauli('Y')))
Z = make_immutable(PauliOp(Pauli('Z')))
I = make_immutable(PauliOp(Pauli('I')))

# Clifford+T, and some other common non-parameterized gates
CX = make_immutable(PrimitiveOp(CXGate()))
S = make_immutable(PrimitiveOp(SGate()))
H = make_immutable(PrimitiveOp(HGate()))
T = make_immutable(PrimitiveOp(TGate()))
Swap = make_immutable(PrimitiveOp(SwapGate()))
CZ = make_immutable(PrimitiveOp(CZGate()))

# 1-Qubit Paulis
Zero = make_immutable(StateFn('0'))
One = make_immutable(StateFn('1'))
Plus = make_immutable(H.compose(Zero))
Minus = make_immutable(H.compose(X).compose(Zero))
 def test_controlled_swap(self):
     """Test creation of controlled swap gate"""
     self.assertEqual(SwapGate().control(), CSwapGate())
 def test_swap_definition_specification(self):
     """Test the instantiation of a controlled swap gate with explicit definition."""
     swap = SwapGate()
     cswap = ControlledGate('cswap', 3, [], num_ctrl_qubits=1,
                            definition=swap.definition)
     self.assertEqual(swap.definition, cswap.definition)
Example #11
0
class TestPauli(QiskitTestCase):
    """Tests for Pauli operator class."""
    @data(*pauli_group_labels(2))
    def test_conjugate(self, label):
        """Test conjugate method."""
        value = Pauli(label).conjugate()
        target = operator_from_label(label).conjugate()
        self.assertEqual(Operator(value), target)

    @data(*pauli_group_labels(2))
    def test_transpose(self, label):
        """Test transpose method."""
        value = Pauli(label).transpose()
        target = operator_from_label(label).transpose()
        self.assertEqual(Operator(value), target)

    @data(*pauli_group_labels(2))
    def test_adjoint(self, label):
        """Test adjoint method."""
        value = Pauli(label).adjoint()
        target = operator_from_label(label).adjoint()
        self.assertEqual(Operator(value), target)

    @data(*pauli_group_labels(2))
    def test_inverse(self, label):
        """Test inverse method."""
        pauli = Pauli(label)
        value = pauli.inverse()
        target = pauli.adjoint()
        self.assertEqual(value, target)

    @data(*it.product(pauli_group_labels(2, full_group=False), repeat=2))
    @unpack
    def test_dot(self, label1, label2):
        """Test dot method."""
        p1 = Pauli(label1)
        p2 = Pauli(label2)
        value = Operator(p1.dot(p2))
        op1 = operator_from_label(label1)
        op2 = operator_from_label(label2)
        target = op1.dot(op2)
        self.assertEqual(value, target)

    @data(*pauli_group_labels(1))
    def test_dot_qargs(self, label2):
        """Test dot method with qargs."""
        label1 = "-iXYZ"
        p1 = Pauli(label1)
        p2 = Pauli(label2)
        qargs = [0]
        value = Operator(p1.dot(p2, qargs=qargs))
        op1 = operator_from_label(label1)
        op2 = operator_from_label(label2)
        target = op1.dot(op2, qargs=qargs)
        self.assertEqual(value, target)

    @data(*it.product(pauli_group_labels(2, full_group=False), repeat=2))
    @unpack
    def test_compose(self, label1, label2):
        """Test compose method."""
        p1 = Pauli(label1)
        p2 = Pauli(label2)
        value = Operator(p1.compose(p2))
        op1 = operator_from_label(label1)
        op2 = operator_from_label(label2)
        target = op1.compose(op2)
        self.assertEqual(value, target)

    @data(*pauli_group_labels(1))
    def test_compose_qargs(self, label2):
        """Test compose method with qargs."""
        label1 = "-XYZ"
        p1 = Pauli(label1)
        p2 = Pauli(label2)
        qargs = [0]
        value = Operator(p1.compose(p2, qargs=qargs))
        op1 = operator_from_label(label1)
        op2 = operator_from_label(label2)
        target = op1.compose(op2, qargs=qargs)
        self.assertEqual(value, target)

    @data(*it.product(pauli_group_labels(1, full_group=False), repeat=2))
    @unpack
    def test_tensor(self, label1, label2):
        """Test tensor method."""
        p1 = Pauli(label1)
        p2 = Pauli(label2)
        value = Operator(p1.tensor(p2))
        op1 = operator_from_label(label1)
        op2 = operator_from_label(label2)
        target = op1.tensor(op2)
        self.assertEqual(value, target)

    @data(*it.product(pauli_group_labels(1, full_group=False), repeat=2))
    @unpack
    def test_expand(self, label1, label2):
        """Test expand method."""
        p1 = Pauli(label1)
        p2 = Pauli(label2)
        value = Operator(p1.expand(p2))
        op1 = operator_from_label(label1)
        op2 = operator_from_label(label2)
        target = op1.expand(op2)
        self.assertEqual(value, target)

    @data("II", "XI", "YX", "ZZ", "YZ")
    def test_power(self, label):
        """Test power method."""
        iden = Pauli("II")
        op = Pauli(label)
        self.assertTrue(op**2, iden)

    @data(1, 1.0, -1, -1.0, 1j, -1j)
    def test_multiply(self, val):
        """Test multiply method."""
        op = val * Pauli(([True, True], [False, False], 0))
        phase = (-1j)**op.phase
        self.assertEqual(phase, val)

    def test_multiply_except(self):
        """Test multiply method raises exceptions."""
        op = Pauli("XYZ")
        self.assertRaises(QiskitError, op._multiply, 2)

    @data(0, 1, 2, 3)
    def test_negate(self, phase):
        """Test negate method"""
        op = Pauli(([False], [True], phase))
        neg = -op
        self.assertTrue(op.equiv(neg))
        self.assertEqual(neg.phase, (op.phase + 2) % 4)

    @data(*it.product(pauli_group_labels(1, False), repeat=2))
    @unpack
    def test_commutes(self, p1, p2):
        """Test commutes method"""
        P1 = Pauli(p1)
        P2 = Pauli(p2)
        self.assertEqual(P1.commutes(P2), P1.dot(P2) == P2.dot(P1))

    @data(*it.product(pauli_group_labels(1, False), repeat=2))
    @unpack
    def test_anticommutes(self, p1, p2):
        """Test anticommutes method"""
        P1 = Pauli(p1)
        P2 = Pauli(p2)
        self.assertEqual(P1.anticommutes(P2), P1.dot(P2) == -P2.dot(P1))

    @data(*it.product(
        (IGate(), XGate(), YGate(), ZGate(), HGate(), SGate(), SdgGate()),
        pauli_group_labels(1, False),
    ))
    @unpack
    def test_evolve_clifford1(self, gate, label):
        """Test evolve method for 1-qubit Clifford gates."""
        op = Operator(gate)
        pauli = Pauli(label)
        value = Operator(pauli.evolve(gate))
        value_h = Operator(pauli.evolve(gate, frame="h"))
        value_s = Operator(pauli.evolve(gate, frame="s"))
        value_inv = Operator(pauli.evolve(gate.inverse()))
        target = op.adjoint().dot(pauli).dot(op)
        self.assertEqual(value, target)
        self.assertEqual(value, value_h)
        self.assertEqual(value_inv, value_s)

    @data(*it.product((CXGate(), CYGate(), CZGate(), SwapGate()),
                      pauli_group_labels(2, False)))
    @unpack
    def test_evolve_clifford2(self, gate, label):
        """Test evolve method for 2-qubit Clifford gates."""
        op = Operator(gate)
        pauli = Pauli(label)
        value = Operator(pauli.evolve(gate))
        value_h = Operator(pauli.evolve(gate, frame="h"))
        value_s = Operator(pauli.evolve(gate, frame="s"))
        value_inv = Operator(pauli.evolve(gate.inverse()))
        target = op.adjoint().dot(pauli).dot(op)
        self.assertEqual(value, target)
        self.assertEqual(value, value_h)
        self.assertEqual(value_inv, value_s)

    def test_evolve_clifford_qargs(self):
        """Test evolve method for random Clifford"""
        cliff = random_clifford(3, seed=10)
        op = Operator(cliff)
        pauli = random_pauli(5, seed=10)
        qargs = [3, 0, 1]
        value = Operator(pauli.evolve(cliff, qargs=qargs))
        value_h = Operator(pauli.evolve(cliff, qargs=qargs, frame="h"))
        value_s = Operator(pauli.evolve(cliff, qargs=qargs, frame="s"))
        value_inv = Operator(pauli.evolve(cliff.adjoint(), qargs=qargs))
        target = Operator(pauli).compose(op.adjoint(),
                                         qargs=qargs).dot(op, qargs=qargs)
        self.assertEqual(value, target)
        self.assertEqual(value, value_h)
        self.assertEqual(value_inv, value_s)

    def test_barrier_delay_sim(self):
        """Test barrier and delay instructions can be simulated"""
        target_circ = QuantumCircuit(2)
        target_circ.x(0)
        target_circ.y(1)
        target = Pauli(target_circ)

        circ = QuantumCircuit(2)
        circ.x(0)
        circ.delay(100, 0)
        circ.barrier([0, 1])
        circ.y(1)
        value = Pauli(circ)
        self.assertEqual(value, target)
Example #12
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")