Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Transpiler refactor #1500

Merged
merged 37 commits into from
Nov 27, 2024
Merged
Changes from 1 commit
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
2c7190e
fix: update connectivity in default transpiler
Oct 17, 2024
e1e769a
fix: remove initial_layout & use wire_names & update test files
Oct 22, 2024
2a888ad
fix: update code-examples
Oct 23, 2024
05b6f68
fix: update comparison in test_bell_state_3q
Oct 23, 2024
876b79c
feat: circuit draw with int qubit names
Oct 23, 2024
02e9945
fix: placer.py coverage
Oct 23, 2024
05f36e7
fix: circuit.py coverage
Oct 23, 2024
01b667d
fix: router.py coverage
Oct 23, 2024
4e21132
fix: remove dead codes
Oct 24, 2024
12bf8b0
fix: refactor connectivity graphs in test files
Oct 24, 2024
36c1348
fix: return type of a router
Oct 24, 2024
f19dc6e
fix: minor changes
Oct 25, 2024
7534ef2
fix: remove add_nodes_from when setting backend
Oct 25, 2024
67fae1f
fix: Circuit remove default wire_names / dict wire_names
Oct 28, 2024
2ac1a85
fix: wire_names update docstrings
Oct 28, 2024
788fd06
fix: line connectivity remove fixture
Oct 28, 2024
4e3dbce
fix: test files default qubit
Oct 28, 2024
d4e507c
fix: refactor assert functions
Oct 28, 2024
5cf75b5
fix: refactor assert funcs
Oct 28, 2024
942991a
fix: pandoc update result draw()
Oct 28, 2024
25d8788
fix: pandoc update
Oct 28, 2024
93ac772
feat: Circuit __init__ int/list first arg init
Oct 28, 2024
41f5eff
fix: Circuit._parse -> _resolve_qubits
Oct 28, 2024
a4f2092
fix: minor updates / update docstring of qibo.Circuit
Oct 30, 2024
10be459
fix: update test files _resolve_qubits / wire_names setter
Oct 30, 2024
a1d3302
fix: combine similar assert func to assert_placement
Oct 30, 2024
0851eeb
fix: minor test files update
Oct 30, 2024
ec37f34
Merge branch 'master' into transpiler_refactor
Nov 4, 2024
32c9ac2
Merge branch 'master' into transpiler_refactor
csookim Nov 8, 2024
ff89c58
Merge branch 'master' into transpiler_refactor
Nov 19, 2024
824bb76
passes move connectivity check to __call__
Nov 21, 2024
214a4ea
fix: remove Trivial and Custom
Nov 22, 2024
abed4b9
fix: remove default star transpiler / enforce connectivity
Nov 22, 2024
ad079de
fix: modify is_satisfied
Nov 22, 2024
1f55f3c
fix: revert, make connectivity optiona
Nov 22, 2024
797331e
fix: type errors, Preprocessor connectivity check, utils.py -> assert…
Nov 25, 2024
049ff01
fix: utils -> asserts
Nov 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fix: refactor assert funcs
  • Loading branch information
changsookim committed Oct 28, 2024
commit 5cf75b59fbfd05a277a14f3e8e3ca38d6048f576
9 changes: 7 additions & 2 deletions src/qibo/transpiler/placer.py
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@
from qibo.transpiler._exceptions import PlacementError
from qibo.transpiler.abstract import Placer, Router
from qibo.transpiler.router import _find_connected_qubit
from qibo.transpiler.utils import assert_placement
from qibo.transpiler.utils import assert_placement, assert_qubit_match


def _find_gates_qubits_pairs(circuit: Circuit):
@@ -66,7 +66,7 @@ def __call__(self, circuit: Circuit):
circuit (:class:`qibo.models.circuit.Circuit`): The original Qibo circuit to transform.
Only single qubit gates and two qubits gates are supported by the router.
"""

assert_qubit_match(circuit, self.connectivity)
middle_qubit_idx = circuit.wire_names.index(self.middle_qubit)
wire_names = circuit.wire_names.copy()

@@ -109,6 +109,7 @@ def __call__(self, circuit: Circuit = None):
Args:
circuit (:class:`qibo.models.circuit.Circuit`): circuit to be transpiled.
"""
assert_qubit_match(circuit, self.connectivity)
return


@@ -131,6 +132,7 @@ def __call__(self, circuit: Circuit):
Args:
circuit (:class:`qibo.models.circuit.Circuit`): circuit to be transpiled.
"""
assert_qubit_match(circuit, self.connectivity)
if isinstance(self.initial_map, dict):
circuit.wire_names = sorted(self.initial_map, key=self.initial_map.get)
elif isinstance(self.initial_map, list):
@@ -162,6 +164,7 @@ def __call__(self, circuit: Circuit):
Args:
circuit (:class:`qibo.models.circuit.Circuit`): circuit to be transpiled.
"""
assert_qubit_match(circuit, self.connectivity)
gates_qubits_pairs = _find_gates_qubits_pairs(circuit)
if len(gates_qubits_pairs) < 3:
raise_error(
@@ -220,6 +223,7 @@ def __call__(self, circuit):
Args:
circuit (:class:`qibo.models.circuit.Circuit`): Circuit to be transpiled.
"""
assert_qubit_match(circuit, self.connectivity)
_, local_state = _check_backend_and_local_state(self.seed, backend=None)
gates_qubits_pairs = _find_gates_qubits_pairs(circuit)
nodes = self.connectivity.number_of_nodes()
@@ -305,6 +309,7 @@ def __call__(self, circuit: Circuit):
Args:
circuit (:class:`qibo.models.circuit.Circuit`): circuit to be transpiled.
"""
assert_qubit_match(circuit, self.connectivity)
self.routing_algorithm.connectivity = self.connectivity
new_circuit = self._assemble_circuit(circuit)
self._routing_step(new_circuit)
5 changes: 4 additions & 1 deletion src/qibo/transpiler/router.py
Original file line number Diff line number Diff line change
@@ -11,6 +11,7 @@
from qibo.transpiler._exceptions import ConnectivityError
from qibo.transpiler.abstract import Router
from qibo.transpiler.blocks import Block, CircuitBlocks
from qibo.transpiler.utils import assert_qubit_match


class StarConnectivityRouter(Router):
@@ -48,7 +49,7 @@ def __call__(self, circuit: Circuit):
circuit (:class:`qibo.models.circuit.Circuit`): The original Qibo circuit to transform.
Only single qubit gates and two qubits gates are supported by the router.
"""

assert_qubit_match(circuit, self.connectivity)
middle_qubit_idx = circuit.wire_names.index(self.middle_qubit)
nqubits = circuit.nqubits
new = Circuit(nqubits=nqubits, wire_names=circuit.wire_names)
@@ -334,6 +335,7 @@ def __call__(self, circuit: Circuit):
(:class:`qibo.models.circuit.Circuit`, dict): circut mapped to hardware topology,
and final physical-to-logical qubit mapping.
"""
assert_qubit_match(circuit, self.connectivity)
self._preprocessing(circuit=circuit)
while self._dag.number_of_nodes() != 0:
execute_block_list = self._check_execution()
@@ -624,6 +626,7 @@ def __call__(self, circuit: Circuit):
Returns:
(:class:`qibo.models.circuit.Circuit`, dict): routed circuit and final layout.
"""
assert_qubit_match(circuit, self.connectivity)
self._preprocessing(circuit=circuit)
longest_path = np.max(self._dist_matrix)

14 changes: 14 additions & 0 deletions src/qibo/transpiler/utils.py
Original file line number Diff line number Diff line change
@@ -18,6 +18,20 @@
from qibo.transpiler.unroller import NativeGates


def assert_qubit_match(circuit: Circuit, connectivity: nx.Graph):
"""Check if the number of qubits in the circuit matches the connectivity graph.

Args:
circuit (:class:`qibo.models.circuit.Circuit`): Circuit model to check.
connectivity (:class:`networkx.Graph`): Chip connectivity.
"""
if circuit.nqubits != len(connectivity.nodes):
raise_error(
TranspilerPipelineError,
"Number of qubits in the circuit does not match the connectivity graph.",
)


def assert_transpiling(
original_circuit: Circuit,
transpiled_circuit: Circuit,
32 changes: 0 additions & 32 deletions tests/test_transpiler_pipeline.py
Original file line number Diff line number Diff line change
@@ -85,38 +85,6 @@ def test_pipeline_default(ngates, names, star_connectivity):
)


def test_assert_circuit_equivalence_equal():
circ1 = Circuit(2)
circ2 = Circuit(2)
circ1.add(gates.X(0))
circ1.add(gates.CZ(0, 1))
circ2.add(gates.X(0))
circ2.add(gates.CZ(0, 1))
final_map = {0: 0, 1: 1}
assert_circuit_equivalence(circ1, circ2, final_map=final_map)


def test_assert_circuit_equivalence_swap():
circ1 = Circuit(2)
circ2 = Circuit(2)
circ1.add(gates.X(0))
circ2.add(gates.SWAP(0, 1))
circ2.add(gates.X(1))
final_map = {0: 1, 1: 0}
assert_circuit_equivalence(circ1, circ2, final_map=final_map)


def test_assert_circuit_equivalence_false():
circ1 = Circuit(2)
circ2 = Circuit(2)
circ1.add(gates.X(0))
circ2.add(gates.SWAP(0, 1))
circ2.add(gates.X(1))
final_map = {0: 0, 1: 1}
with pytest.raises(TranspilerPipelineError):
assert_circuit_equivalence(circ1, circ2, final_map=final_map)


def test_int_qubit_names_default(star_connectivity):
names = [1244, 1532, 2315, 6563, 8901]
circ = Circuit(5, wire_names=names)
56 changes: 3 additions & 53 deletions tests/test_transpiler_placer.py
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@

from qibo import gates
from qibo.models import Circuit
from qibo.transpiler._exceptions import PlacementError
from qibo.transpiler._exceptions import PlacementError, TranspilerPipelineError
from qibo.transpiler.pipeline import restrict_connectivity_qubits
from qibo.transpiler.placer import (
Custom,
@@ -15,7 +15,7 @@
_find_gates_qubits_pairs,
)
from qibo.transpiler.router import ShortestPaths
from qibo.transpiler.utils import assert_mapping_consistency, assert_placement
from qibo.transpiler.utils import assert_placement


def star_circuit(names=["q0", "q1", "q2", "q3", "q4"]):
@@ -25,56 +25,6 @@ def star_circuit(names=["q0", "q1", "q2", "q3", "q4"]):
return circuit


def test_assert_placement_true(star_connectivity):
circuit = Circuit(5)
assert_placement(circuit, connectivity=star_connectivity())


@pytest.mark.parametrize(
"qubits, names", [(5, ["A", "B", "C", "D", "F"]), (3, ["A", "B", "C"])]
)
def test_assert_placement_false(qubits, names, star_connectivity):
connectivity = star_connectivity()
circuit = Circuit(qubits, wire_names=names)
with pytest.raises(PlacementError):
assert_placement(circuit, connectivity)


@pytest.mark.parametrize("qubits", [10, 1])
def test_assert_placement_error(qubits, star_connectivity):
connectivity = star_connectivity()
circuit = Circuit(qubits)
with pytest.raises(PlacementError):
assert_placement(circuit, connectivity)


@pytest.mark.parametrize("names", [["A", "B", "C", "D", "E"], [0, 1, 2, 3, 4]])
def test_mapping_consistency(names, star_connectivity):
assert_mapping_consistency(names, star_connectivity(names))


def test_mapping_consistency_error(star_connectivity):
with pytest.raises(PlacementError):
assert_mapping_consistency(["A", "B", "C", "D", "F"], star_connectivity())


@pytest.mark.parametrize("names", [["A", "B", "C", "D", "E"], [0, 1, 2, 3, 4]])
def test_mapping_consistency_restricted(names, star_connectivity):
connectivity = star_connectivity(names)
on_qubit = [names[0], names[2]]
restricted_connectivity = restrict_connectivity_qubits(connectivity, on_qubit)
assert_mapping_consistency(on_qubit, restricted_connectivity)


@pytest.mark.parametrize("names", [["A", "B", "C", "D", "E"], [0, 1, 2, 3, 4]])
def test_mapping_consistency_restricted_error(names, star_connectivity):
connectivity = star_connectivity(names)
on_qubit = [names[0], names[2]]
restricted_connectivity = restrict_connectivity_qubits(connectivity, on_qubit)
with pytest.raises(PlacementError):
assert_mapping_consistency([names[3], names[4]], restricted_connectivity)


def test_gates_qubits_pairs():
circuit = Circuit(5)
circuit.add(gates.CNOT(0, 1))
@@ -152,7 +102,7 @@ def test_custom_error_circuit(star_connectivity):
custom_layout = [4, 3, 2, 1, 0]
connectivity = star_connectivity(names=custom_layout)
placer = Custom(connectivity=connectivity, initial_map=custom_layout)
with pytest.raises(ValueError):
with pytest.raises(TranspilerPipelineError):
placer(circuit)


30 changes: 6 additions & 24 deletions tests/test_transpiler_router.py
Original file line number Diff line number Diff line change
@@ -93,25 +93,6 @@ def matched_circuit(names):
return circuit


def test_assert_connectivity(star_connectivity):
names = ["A", "B", "C", "D", "E"]
assert_connectivity(star_connectivity(names), matched_circuit(names))


def test_assert_connectivity_false(star_connectivity):
circuit = Circuit(5)
circuit.add(gates.CZ(0, 1))
with pytest.raises(ConnectivityError):
assert_connectivity(star_connectivity(), circuit)


def test_assert_connectivity_3q(star_connectivity):
circuit = Circuit(5)
circuit.add(gates.TOFFOLI(0, 1, 2))
with pytest.raises(ConnectivityError):
assert_connectivity(star_connectivity(), circuit)


def test_bell_state_3q():
circuit = Circuit(3)
circuit.add(gates.H(0))
@@ -407,7 +388,7 @@ def test_sabre_matched(names, star_connectivity):
connectivity = star_connectivity(names=names)
circuit = matched_circuit(names)
original_circuit = circuit.copy()
placer = Trivial()
placer = Trivial(connectivity=connectivity)
router = Sabre(connectivity=connectivity)

placer(circuit)
@@ -428,7 +409,7 @@ def test_sabre_simple(seed, star_connectivity):
circ = Circuit(5)
circ.add(gates.CZ(0, 1))
original_circuit = circ.copy()
placer = Trivial()
placer = Trivial(connectivity=connectivity)
router = Sabre(connectivity=connectivity, seed=seed)

placer(circ)
@@ -506,10 +487,11 @@ def test_sabre_random_circuits_grid(


def test_sabre_memory_map(star_connectivity):
placer = Trivial()
connectivity = star_connectivity()
placer = Trivial(connectivity=connectivity)
layout_circ = Circuit(5)
placer(layout_circ)
router = Sabre(connectivity=star_connectivity())
router = Sabre(connectivity=connectivity)
router._preprocessing(circuit=star_circuit())
router._memory_map = [[1, 0, 2, 3, 4]]
value = router._compute_cost((0, 1))
@@ -554,7 +536,7 @@ def test_restrict_qubits(router_algorithm, star_connectivity):


def test_star_error_multi_qubit(star_connectivity):
circuit = Circuit(3)
circuit = Circuit(5)
circuit.add(gates.TOFFOLI(0, 1, 2))
connectivity = star_connectivity(middle_qubit_idx=2)
transpiler = StarConnectivityRouter(connectivity)
1 change: 0 additions & 1 deletion tests/test_transpiler_unitary_decompositions.py
Original file line number Diff line number Diff line change
@@ -3,7 +3,6 @@
from scipy.linalg import expm

from qibo import Circuit, gates, matrices
from qibo.config import PRECISION_TOL
from qibo.quantum_info.linalg_operations import partial_trace
from qibo.quantum_info.metrics import purity
from qibo.quantum_info.random_ensembles import random_unitary
30 changes: 0 additions & 30 deletions tests/test_transpiler_unroller.py
Original file line number Diff line number Diff line change
@@ -39,36 +39,6 @@ def test_translate_gate_error_2q():
translate_gate(gates.CZ(0, 1), natives)


def test_assert_decomposition():
circuit = Circuit(2)
circuit.add(gates.CZ(0, 1))
circuit.add(gates.Z(0))
circuit.add(gates.M(1))
assert_decomposition(circuit, native_gates=NativeGates.default())


def test_assert_decomposition_fail_1q():
circuit = Circuit(1)
circuit.add(gates.X(0))
with pytest.raises(DecompositionError):
assert_decomposition(circuit, native_gates=NativeGates.default())


@pytest.mark.parametrize("gate", [gates.CNOT(0, 1), gates.iSWAP(0, 1)])
def test_assert_decomposition_fail_2q(gate):
circuit = Circuit(2)
circuit.add(gate)
with pytest.raises(DecompositionError):
assert_decomposition(circuit, native_gates=NativeGates.default())


def test_assert_decomposition_fail_3q():
circuit = Circuit(3)
circuit.add(gates.TOFFOLI(0, 1, 2))
with pytest.raises(DecompositionError):
assert_decomposition(circuit, native_gates=NativeGates.default())


@pytest.mark.parametrize(
"natives_2q",
[NativeGates.CZ, NativeGates.iSWAP, NativeGates.CZ | NativeGates.iSWAP],
Loading