def test_no_state_modification_circuit(self) -> None: """ We apply Sabre on a circuit which doesn't modify the initial state (|0^n> here) and we verify Sabre circuit modifications don't modify the state. """ for nbqbit in range(min_nbqbit, max_nbqbit): prog = Program() qbits = prog.qalloc(nbqbit) random_angles = [ rd.random() * 2 * np.pi for _ in range(3 * nbqbit) ] for i in range(len(qbits)): prog.apply(RX(random_angles[3 * i]), qbits[i]) prog.apply(RX(random_angles[3 * i + 1]), qbits[i]) prog.apply(RX(random_angles[3 * i + 2]), qbits[i]) prog.apply(QFT(nbqbit), qbits) prog.apply(QFT(nbqbit).dag(), qbits) for i in range(len(qbits)): prog.apply(RX(random_angles[3 * i]).dag(), qbits[i]) prog.apply(RX(random_angles[3 * i + 1]).dag(), qbits[i]) prog.apply(RX(random_angles[3 * i + 2]).dag(), qbits[i]) circuit = prog.to_circ(inline=True) for topology in generate_custom_topologies(nbqbit): qpu = Sabre() | (QuameleonPlugin(topology=topology) | PyLinalg()) result = qpu.submit(circuit.to_job()) assert result.raw_data[0].state.int == 0
def test_gate_more_two_qubits(self) -> None: """ Checks Sabre raises PluginException if there is a circuit containing a gate with more than two qubits. """ with pytest.raises(PluginException): circuit = generate_qft_circuit(max_nbqbit, inline=False) qpu = Sabre() | (QuameleonPlugin(topology=Topology( type=TopologyType.LNN)) | PyLinalg()) qpu.submit(circuit.to_job())
def test_custom_topology_without_graph(self) -> None: """ Checks Sabre raises PluginException if TopologyType is CUSTOM but no graph is provided. """ with pytest.raises(PluginException): circuit = generate_qft_circuit(max_nbqbit) qpu = Sabre() | (QuameleonPlugin(topology=Topology( type=TopologyType.CUSTOM)) | PyLinalg()) qpu.submit(circuit.to_job())
def test_unknown_topology_type(self) -> None: """ Checks Sabre raises PluginException for an unknown topology type. """ with pytest.raises(PluginException): circuit = generate_qft_circuit(max_nbqbit) qpu = Sabre() | (QuameleonPlugin(topology=Topology(type=-5)) | PyLinalg()) qpu.submit(circuit.to_job())
def test_too_much_qubits(self) -> None: """ Checks Sabre raises PluginException if there are more qubits in the circuit than in the topology. """ with pytest.raises(PluginException): circuit = generate_qft_circuit(max_nbqbit) qpu = Sabre() | (QuameleonPlugin(topology=Topology( type=TopologyType.CUSTOM, graph={ 0: [1], 1: [0] })) | PyLinalg()) qpu.submit(circuit.to_job())
def test_all_to_all_topology(self) -> None: """ Checks that Sabre doesn't modify the circuit if the topology is of type ALL_TO_ALL. """ for nbqbit in range(min_nbqbit, max_nbqbit): circuit = generate_random_circuit(nbqbit) sabre = Sabre() batch = Batch(jobs=[circuit.to_job()]) hardware_specs = HardwareSpecs() batch_result = sabre.compile(batch, hardware_specs) computed_circuit = batch_result.jobs[0].circuit check_circuits_equality(circuit, computed_circuit)
def test_lnn_topology(self) -> None: """ Tests Sabre on common circuit for LNN topologies for different number of qubits. """ for nbqbit in range(2 * min_nbqbit, max_nbqbit): circuit = generate_random_circuit(rd.randint(nbqbit // 2, nbqbit)) qpu_1 = PyLinalg() result_1 = qpu_1.submit(circuit.to_job()) qpu_2 = Sabre() | (QuameleonPlugin(topology=Topology( type=TopologyType.LNN)) | PyLinalg()) result_2 = qpu_2.submit(circuit.to_job()) check_results_equality(result_1, result_2)
def test_qft_lnn(self) -> None: """ Tests Sabre on a QFT for LNN topologies for different number of qubits. """ for nbqbit in range(3, max_nbqbit): circuit = generate_qft_circuit(nbqbit) qpu_1 = PyLinalg() result_1 = qpu_1.submit(circuit.to_job()) qpu_2 = Sabre() | (QuameleonPlugin(topology=Topology( type=TopologyType.LNN)) | PyLinalg()) result_2 = qpu_2.submit(circuit.to_job()) check_results_equality(result_1, result_2)
def test_qft_custom_usual_topologies(self) -> None: """ Tests Sabre on a QFT for some usual custom topologies for different number of qubits. """ for nbqbit in range(5, max_nbqbit): circuit = generate_qft_circuit(nbqbit) qpu_1 = PyLinalg() result_1 = qpu_1.submit(circuit.to_job()) for topology in generate_custom_topologies(nbqbit): print('Number of qubits : ', nbqbit) print('Current topology : ', topology) qpu_2 = Sabre() | (QuameleonPlugin(topology=topology) | PyLinalg()) result_2 = qpu_2.submit(circuit.to_job()) check_results_equality(result_1, result_2)
def test_lnn_topology(self) -> None: """ Tests Sabre on common circuit for LNN topologies for different number of qubits. """ for nbqbit in range(2 * min_nbqbit, max_nbqbit): nbqbit_circuit = rd.randint(nbqbit // 2, nbqbit) circuit = generate_random_circuit(nbqbit_circuit) observable = generate_random_observable(nbqbit_circuit) qpu_1 = PyLinalg() measure_1 = qpu_1.submit( circuit.to_job("OBS", observable=observable)) qpu_2 = Sabre() | (QuameleonPlugin(topology=Topology( type=TopologyType.LNN)) | PyLinalg()) measure_2 = qpu_2.submit( circuit.to_job("OBS", observable=observable)) check_measures_equality(measure_1, measure_2)
def test_custom_usual_topologies(self) -> None: """ Tests Sabre on common circuit for some usual custom topologies for different number of qubits. """ for nbqbit in range(2 * min_nbqbit, max_nbqbit): nbqbit_circuit = rd.randint(nbqbit // 2, nbqbit) circuit = generate_random_circuit(nbqbit_circuit) observable = generate_random_observable(nbqbit_circuit) qpu_1 = PyLinalg() measure_1 = qpu_1.submit( circuit.to_job("OBS", observable=observable, nbshots=5)) for topology in generate_custom_topologies(nbqbit): qpu_2 = Sabre() | (QuameleonPlugin(topology=topology) | PyLinalg()) measure_2 = qpu_2.submit( circuit.to_job("OBS", observable=observable, nbshots=5)) check_measures_equality(measure_1, measure_2) if nbqbit % 2 == 0: topology = Topology.from_nx( nx.grid_2d_graph(nbqbit // 2, nbqbit // 2)) qpu_2 = Sabre() | (QuameleonPlugin(topology=topology) | PyLinalg()) measure_2 = qpu_2.submit( circuit.to_job("OBS", observable=observable, nbshots=5)) check_measures_equality(measure_1, measure_2)
def test_custom_usual_topologies(self) -> None: """ Tests Sabre on common circuit for some usual custom topologies for different number of qubits. """ for nbqbit in range(2 * min_nbqbit, max_nbqbit): nbqbit_circuit = rd.randint(nbqbit // 2, nbqbit) circuit = generate_random_circuit(nbqbit_circuit) nb_measured_qubits = rd.randint(1, nbqbit_circuit) measured_qubits = rd.sample(range(nbqbit_circuit), nb_measured_qubits) measured_qubits.sort() qpu_1 = PyLinalg() result_1 = qpu_1.submit(circuit.to_job(qubits=measured_qubits)) for topology in generate_custom_topologies(nbqbit): qpu_2 = Sabre() | (QuameleonPlugin(topology=topology) | PyLinalg()) result_2 = qpu_2.submit(circuit.to_job(qubits=measured_qubits)) check_results_equality(result_1, result_2, amplitude=False) if nbqbit % 2 == 0: topology = Topology.from_nx( nx.grid_2d_graph(nbqbit // 2, nbqbit // 2)) qpu_2 = Sabre() | (QuameleonPlugin(topology=topology) | PyLinalg()) result_2 = qpu_2.submit(circuit.to_job(qubits=measured_qubits)) check_results_equality(result_1, result_2, amplitude=False)
def test_lnn_topology(self) -> None: """ Tests Sabre on common circuit for LNN topologies for different number of qubits. """ for nbqbit in range(2 * min_nbqbit, max_nbqbit): nbqbit_circuit = rd.randint(nbqbit // 2, nbqbit) circuit = generate_random_circuit(nbqbit_circuit) nb_measured_qubits = rd.randint(1, nbqbit_circuit) measured_qubits = rd.sample(range(nbqbit_circuit), nb_measured_qubits) measured_qubits.sort() qpu_1 = PyLinalg() result_1 = qpu_1.submit(circuit.to_job(qubits=measured_qubits)) qpu_2 = Sabre() | (QuameleonPlugin(topology=Topology( type=TopologyType.LNN)) | PyLinalg()) result_2 = qpu_2.submit(circuit.to_job(qubits=measured_qubits)) check_results_equality(result_1, result_2, amplitude=False)
def test_already_executable_circuit(self) -> None: """ Tests Sabre on a fully executable circuit which means all gates are applied on qubits which are connected on the hardware. """ for nbqbit in range(min_nbqbit, max_nbqbit): prog = Program() qbits = prog.qalloc(nbqbit) for i in range(len(qbits) - 1): prog.apply(H, qbits[i]) prog.apply(Z, qbits[i]) prog.apply(X.ctrl(), qbits[i + 1], qbits[i]) circuit = prog.to_circ(inline=True) sabre = Sabre() batch = Batch(jobs=[circuit.to_job()]) hardware_specs = HardwareSpecs() batch_result = sabre.compile(batch, hardware_specs) computed_circuit = batch_result.jobs[0].circuit check_circuits_equality(circuit, computed_circuit)