diff --git a/pytket/phir/routing.py b/pytket/phir/routing.py new file mode 100644 index 0000000..f2d94f1 --- /dev/null +++ b/pytket/phir/routing.py @@ -0,0 +1,43 @@ +# Copyright (c) 2023 Quantinuum LLC. +# INSERT LICENSE HERE +""" +Routing functions. For simulation we don't need to create a sequence of +transport operations; we are only interested in the time cost to transport from +one state to another. +""" + +from __future__ import annotations + + +class TransportError(Exception): + def __init__(self, a: list[int], b: list[int]): + super().__init__(f"Traps different sizes: {len(a)} vs. {len(b)}") + + +class PermutationError(Exception): + def __init__(self, lst: list[int]): + super().__init__(f"List {lst} is not a permutation of range({len(lst)})") + + +def inverse(lst: list[int]) -> list[int]: + """Inverse of a permutation list. If a[i] = x, then inverse(a)[x] = i.""" + inv = [-1] * len(lst) + for i, elem in enumerate(lst): + if not 0 <= elem < len(lst) or inv[elem] != -1: + raise PermutationError(lst) + inv[elem] = i + return inv + + +def transport_cost(init: list[int], goal: list[int], swap_cost: float) -> float: + """Cost of transport from init to goal. + + This is based on the number of parallel swaps performed by Odd-Even + Transposition Sort, which is the maximum distance that any qubit travels. + """ + if len(init) != len(goal): + raise TransportError(init, goal) + n_swaps = max( + abs(g - i) for (i, g) in zip(inverse(init), inverse(goal)) # noqa: B905 + ) + return n_swaps * swap_cost