From 27e21f72e30feae2f142b78ab0dec5942b2ce10c Mon Sep 17 00:00:00 2001 From: John Garvin Date: Thu, 28 Sep 2023 14:05:00 -0500 Subject: [PATCH 1/2] Add initial routing code. --- pytket/phir/routing.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 pytket/phir/routing.py diff --git a/pytket/phir/routing.py b/pytket/phir/routing.py new file mode 100644 index 0000000..eaabb46 --- /dev/null +++ b/pytket/phir/routing.py @@ -0,0 +1,34 @@ +# 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 + + +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): + raise ValueError(f"List contains element not in range: {elem}") + if inv[elem] != -1: + raise ValueError(f"List contains duplicate elements: {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 ValueError( + f"init and goal lists have different lengths: {len(init)} vs. {len(goal)}" + ) + n_swaps = max(abs(g - i) for (i, g) in zip(inverse(init), inverse(goal))) + return n_swaps * swap_cost From e77b33b1c67d3b9f393b5e7392a9617e7f2b8d7f Mon Sep 17 00:00:00 2001 From: John Garvin Date: Thu, 28 Sep 2023 14:51:43 -0500 Subject: [PATCH 2/2] Correct mypy and pylint errors. --- pytket/phir/routing.py | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/pytket/phir/routing.py b/pytket/phir/routing.py index eaabb46..f2d94f1 100644 --- a/pytket/phir/routing.py +++ b/pytket/phir/routing.py @@ -9,17 +9,26 @@ 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): - raise ValueError(f"List contains element not in range: {elem}") - if inv[elem] != -1: - raise ValueError(f"List contains duplicate elements: {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. @@ -27,8 +36,8 @@ def transport_cost(init: list[int], goal: list[int], swap_cost: float) -> float: Transposition Sort, which is the maximum distance that any qubit travels. """ if len(init) != len(goal): - raise ValueError( - f"init and goal lists have different lengths: {len(init)} vs. {len(goal)}" - ) - n_swaps = max(abs(g - i) for (i, g) in zip(inverse(init), inverse(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