def test_gate_types(): import collections c = Circuit(3) c.add(gates.H(0)) c.add(gates.H(1)) c.add(gates.X(2)) c.add(gates.CNOT(0, 2)) c.add(gates.CNOT(1, 2)) c.add(gates.TOFFOLI(0, 1, 2)) target_counter = collections.Counter({"h": 2, "x": 1, "cx": 2, "ccx": 1}) assert c.ngates == 6 assert c.gate_types == target_counter
def test_summary(): c = Circuit(3) c.add(gates.H(0)) c.add(gates.H(1)) c.add(gates.CNOT(0, 2)) c.add(gates.CNOT(1, 2)) c.add(gates.TOFFOLI(0, 1, 2)) c.add(gates.H(2)) target_summary = "\n".join([ "Circuit depth = 5", "Total number of gates = 6", "Number of qubits = 3", "Most common gates:", "h: 3", "cx: 2", "ccx: 1" ]) assert c.summary() == target_summary
def test_circuit_add_iterable(): c = Circuit(2) # adding list gatelist = [gates.H(0), gates.H(1), gates.CNOT(0, 1)] c.add(gatelist) assert c.depth == 2 assert c.ngates == 3 assert list(c.queue) == gatelist # adding tuple gatetuple = (gates.H(0), gates.H(1), gates.CNOT(0, 1)) c.add(gatetuple) assert c.depth == 4 assert c.ngates == 6 assert isinstance(c.queue[-1], gates.CNOT)
def test_gates_of_type(): c = Circuit(3) c.add(gates.H(0)) c.add(gates.H(1)) c.add(gates.CNOT(0, 2)) c.add(gates.X(1)) c.add(gates.CNOT(1, 2)) c.add(gates.TOFFOLI(0, 1, 2)) c.add(gates.H(2)) h_gates = c.gates_of_type(gates.H) cx_gates = c.gates_of_type("cx") assert h_gates == [(0, c.queue[0]), (1, c.queue[1]), (6, c.queue[6])] assert cx_gates == [(2, c.queue[2]), (4, c.queue[4])] with pytest.raises(TypeError): c.gates_of_type(5)
def test_cnot_and_cz_init(): gate = gates.CNOT(0, 1) assert gate.target_qubits == (1,) assert gate.control_qubits == (0,) gate = gates.CZ(3, 2) assert gate.target_qubits == (2,) assert gate.control_qubits == (3,)
def test_circuit_copy_with_measurements(): c1 = Circuit(4) c1.add([gates.H(0), gates.H(3), gates.CNOT(0, 2)]) c1.add(gates.M(0, 1, register_name="a")) c1.add(gates.M(3, register_name="b")) c2 = c1.copy() assert c2.measurement_gate is c1.measurement_gate assert c2.measurement_tuples == {"a": (0, 1), "b": (3, )}
def test_queue_class(): from qibo.abstractions.circuit import _Queue queue = _Queue(4) gatelist = [gates.H(0), gates.H(1), gates.X(0), gates.H(2), gates.CNOT(1, 2), gates.Y(3)] for g in gatelist: queue.append(g) assert queue.moments == [[gatelist[0], gatelist[1], gatelist[3], gatelist[5]], [gatelist[2], gatelist[4], gatelist[4], None]]
def test_circuit_add(): c = Circuit(2) g1, g2, g3 = gates.H(0), gates.H(1), gates.CNOT(0, 1) c.add(g1) c.add(g2) c.add(g3) assert c.depth == 2 assert c.ngates == 3 assert list(c.queue) == [g1, g2, g3]
def test_fused_gate(): gate = gates.FusedGate(0, 1) gate.append(gates.H(0)) gate.append(gates.CNOT(0, 1)) assert len(gate.gates) == 2 gate.prepend(gates.TOFFOLI(0, 1, 2)) assert gate.qubits == (0, 1, 2) assert len(gate.gates) == 3 assert isinstance(gate.gates[0], gates.TOFFOLI)
def test_circuit_copy(deep): c1 = Circuit(2) c1.add([gates.H(0), gates.H(1), gates.CNOT(0, 1)]) c2 = c1.copy(deep) assert c2.depth == c1.depth assert c2.ngates == c1.ngates assert c2.nqubits == c1.nqubits for g1, g2 in zip(c1.queue, c2.queue): if deep: assert g1.__class__ == g2.__class__ assert g1.target_qubits == g2.target_qubits assert g1.control_qubits == g2.control_qubits else: assert g1 is g2
def test_controlled_by(): gate = gates.RX(0, 0.1234).controlled_by(1, 2, 3) assert gate.target_qubits == (0,) assert gate.control_qubits == (1, 2, 3) assert gate.is_controlled_by assert isinstance(gate, gates.RX) with pytest.raises(RuntimeError): gate = gates.CNOT(0, 1).controlled_by(2) gate = gates.RY(0, 0.1234) gate.nqubits = 5 with pytest.raises(RuntimeError): gate = gate.controlled_by(2)
def test_circuit_with_noise(measurements, noise_map): c = Circuit(2) c.add([gates.H(0), gates.H(1), gates.CNOT(0, 1)]) if measurements: c.add(gates.M(0, 1)) noisyc = c.with_noise(noise_map) if not isinstance(noise_map, dict): noise_map = {0: noise_map, 1: noise_map} targetc = Circuit(2) targetc.add(gates.H(0)) targetc.add(gates.PauliNoiseChannel(0, *noise_map[0])) targetc.add(gates.H(1)) targetc.add(gates.PauliNoiseChannel(1, *noise_map[1])) targetc.add(gates.CNOT(0, 1)) targetc.add(gates.PauliNoiseChannel(0, *noise_map[0])) targetc.add(gates.PauliNoiseChannel(1, *noise_map[1])) for g1, g2 in zip(noisyc.queue, targetc.queue): assert isinstance(g1, g2.__class__) assert g1.target_qubits == g2.target_qubits assert g1.control_qubits == g2.control_qubits if measurements: assert noisyc.measurement_gate.target_qubits == (0, 1) assert noisyc.measurement_tuples == {"register0": (0, 1)}
def test_circuit_on_qubits(): c = Circuit(3) c.add([gates.H(0), gates.X(1), gates.Y(2)]) c.add([gates.CNOT(0, 1), gates.CZ(1, 2)]) c.add(gates.H(1).controlled_by(0, 2)) new_gates = list(c.on_qubits(2, 5, 4)) assert new_gates[0].target_qubits == (2, ) assert new_gates[1].target_qubits == (5, ) assert new_gates[2].target_qubits == (4, ) assert new_gates[3].target_qubits == (5, ) assert new_gates[3].control_qubits == (2, ) assert new_gates[4].target_qubits == (4, ) assert new_gates[4].control_qubits == (5, ) assert new_gates[5].target_qubits == (5, ) assert new_gates[5].control_qubits == (2, 4)
def test_gates_commute(): assert gates.H(0).commutes(gates.X(1)) assert gates.H(0).commutes(gates.H(1)) assert gates.H(0).commutes(gates.H(0)) assert not gates.H(0).commutes(gates.Y(0)) assert not gates.CNOT(0, 1).commutes(gates.SWAP(1, 2)) assert not gates.CNOT(0, 1).commutes(gates.H(1)) assert not gates.CNOT(0, 1).commutes(gates.Y(0).controlled_by(2)) assert not gates.CNOT(2, 3).commutes(gates.CNOT(3, 0)) assert gates.CNOT(0, 1).commutes(gates.Y(2).controlled_by(0))
def test_circuit_invert(measurements): c = Circuit(3) gatelist = [gates.H(0), gates.X(1), gates.Y(2), gates.CNOT(0, 1), gates.CZ(1, 2)] c.add(gatelist) if measurements: c.add(gates.M(0, 2)) invc = c.invert() for g1, g2 in zip(invc.queue, gatelist[::-1]): g2 = g2.dagger() assert isinstance(g1, g2.__class__) assert g1.target_qubits == g2.target_qubits assert g1.control_qubits == g2.control_qubits if measurements: assert invc.measurement_gate.target_qubits == (0, 2) assert invc.measurement_tuples == {"register0": (0, 2)}
def test_multiqubit_gates(): c = Circuit(2) c.add(gates.H(0)) c.add(gates.CNOT(0, 1)) c.add(gates.X(1)) c.add(gates.SWAP(0, 1)) c.add(gates.X(0).controlled_by(1)) # `controlled_by` here falls back to CNOT and should work target = f"""// Generated by QIBO {__version__} OPENQASM 2.0; include "qelib1.inc"; qreg q[2]; h q[0]; cx q[0],q[1]; x q[1]; swap q[0],q[1]; cx q[1],q[0];""" assert_strings_equal(c.to_qasm(), target)
def test_circuit_decompose(measurements): c = Circuit(4) c.add([gates.H(0), gates.X(1), gates.Y(2)]) c.add([gates.CZ(0, 1), gates.CNOT(2, 3), gates.TOFFOLI(0, 1, 3)]) if measurements: c.add(gates.M(0, 2)) decompc = c.decompose() dgates = [] for gate in c.queue: dgates.extend(gate.decompose()) for g1, g2 in zip(decompc.queue, dgates): assert isinstance(g1, g2.__class__) assert g1.target_qubits == g2.target_qubits assert g1.control_qubits == g2.control_qubits if measurements: assert decompc.measurement_gate.target_qubits == (0, 2) assert decompc.measurement_tuples == {"register0": (0, 2)}
def test_circuit_addition(measurements): c1 = Circuit(2) g1, g2 = gates.H(0), gates.CNOT(0, 1) c1.add(g1) c1.add(g2) if measurements: c1.add(gates.M(0, register_name="a")) c2 = Circuit(2) g3 = gates.H(1) c2.add(g3) if measurements: c2.add(gates.M(1, register_name="b")) c3 = c1 + c2 assert c3.depth == 3 assert list(c3.queue) == [g1, g2, g3] if measurements: assert c3.measurement_tuples == {"a": (0, ), "b": (1, )} assert c3.measurement_gate.target_qubits == (0, 1)
def test_circuit_draw_callbacks(legend): """Check that callbacks are drawn correcly""" from qibo.callbacks import EntanglementEntropy entropy = EntanglementEntropy([0]) c = Circuit(2) c.add(gates.CallbackGate(entropy)) c.add(gates.H(0)) c.add(gates.CallbackGate(entropy)) c.add(gates.CNOT(0, 1)) c.add(gates.CallbackGate(entropy)) ref = 'q0: ─EE─H─EE─o─EE─\n' \ 'q1: ─EE───EE─X─EE─' if legend: ref += '\n\n Legend for callbacks and channels: \n' \ '| Gate | Symbol |\n'\ '|---------------------+----------|\n'\ '| EntanglementEntropy | EE |' assert c.draw(legend=legend) == ref
def test_circuit_draw_channels(legend): """Check that channels are drawn correctly""" from qibo.models import Circuit as circuit c = circuit(2, density_matrix=True) c.add(gates.H(0)) c.add(gates.PauliNoiseChannel(0, 0.1, 0.0, 0.2)) c.add(gates.H(1)) c.add(gates.PauliNoiseChannel(1, 0.0, 0.2, 0.1)) c.add(gates.CNOT(0, 1)) c.add(gates.PauliNoiseChannel(0, 0.1, 0.0, 0.2)) c.add(gates.PauliNoiseChannel(1, 0.0, 0.2, 0.1)) ref = 'q0: ─H─PN─o─PN─\n' \ 'q1: ─H─PN─X─PN─' if legend: ref += '\n\n Legend for callbacks and channels: \n' \ '| Gate | Symbol |\n' \ '|-------------------+----------|\n' \ '| PauliNoiseChannel | PN |' assert c.draw(legend=legend) == ref
def test_fused_gate(): gate = gates.FusedGate(0, 1) gate.add(gates.H(0)) gate.add(gates.CNOT(0, 1)) with pytest.raises(ValueError): gate.add(gates.CZ(1, 2))
def test_on_qubits(): gate = gates.CNOT(0, 1)._on_qubits(2, 3) assert gate.target_qubits == (3,) assert gate.control_qubits == (2,) assert isinstance(gate, gates.CNOT)
def gen(): yield gates.H(0) yield gates.H(1) yield gates.CNOT(0, 1)