Skip to content

Commit

Permalink
Merge pull request #190 from CQCL/release/0.20
Browse files Browse the repository at this point in the history
Release/0.20
  • Loading branch information
cqc-alec authored Aug 8, 2023
2 parents 1909191 + 5819aca commit cfdeae2
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 11 deletions.
2 changes: 1 addition & 1 deletion _metadata.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
__extension_version__ = "0.19.0"
__extension_version__ = "0.20.0"
__extension_name__ = "pytket-quantinuum"
12 changes: 12 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
Changelog
~~~~~~~~~

0.20.0 (August 2023)
--------------------

* Update pytket version requirement to 1.18.
* Add ``implicit_swaps`` option to
``QuantinuumBackend.rebase_pass``, which
can use implicit wire swaps (represented in the circuit qubit permutation)
to help implement some gates when chosen. Defaults to ``False``.
* Add ``implicit_swaps`` option to
``QuantinuumBackend.default_compilation_pass``, which
is used in the rebase step. Defaults to ``True``.

0.19.0 (August 2023)
--------------------

Expand Down
34 changes: 28 additions & 6 deletions pytket/extensions/quantinuum/backends/quantinuum.py
Original file line number Diff line number Diff line change
Expand Up @@ -372,10 +372,32 @@ def required_predicates(self) -> List[Predicate]:

return preds

def rebase_pass(self) -> BasePass:
return auto_rebase_pass(self._gate_set)
def rebase_pass(self, implicit_swaps: bool = False) -> BasePass:
"""
:param implicit_swaps: If true, allows rebasing of Circuit via TK2 gates
to use implicit wire swaps in circuit construction if it reduces
the total 2qb qate count.
:type implicit_swaps: bool
:return: Compilation pass for rebasing circuits
:rtype: BasePass
"""
return auto_rebase_pass(self._gate_set, implicit_swaps)

def default_compilation_pass(self, optimisation_level: int = 2) -> BasePass:
def default_compilation_pass(
self, optimisation_level: int = 2, implicit_swaps: bool = True
) -> BasePass:
"""
:param optimisation_level: Allows values of 0,1 or 2, with higher values
prompting more computationally heavy optimising compilation that
can lead to reduced gate count in circuits.
:type optimisation_level: int
:param implicit_swaps: If true, allows rebasing of Circuit via TK2 gates
to use implicit wire swaps in circuit construction if it reduces
the total 2qb qate count.
:type implicit_swaps: bool
:return: Compilation pass for compiling circuits to Quantinuum devices
:rtype: BasePass
"""
assert optimisation_level in range(3)
passlist = [
DecomposeBoxes(),
Expand All @@ -399,14 +421,14 @@ def default_compilation_pass(self, optimisation_level: int = 2) -> BasePass:
# https://cqcl.github.io/pytket-quantinuum/api/index.html#default-compilation
# Edit this docs source file -> pytket-quantinuum/docs/intro.txt
if optimisation_level == 0:
passlist.append(self.rebase_pass())
passlist.append(self.rebase_pass(implicit_swaps=implicit_swaps))
elif optimisation_level == 1:
passlist.extend(
[
SynthesiseTK(),
NormaliseTK2(),
DecomposeTK2(**fidelities),
self.rebase_pass(),
self.rebase_pass(implicit_swaps=implicit_swaps),
ZZPhaseToRz(),
RemoveRedundancies(),
squash,
Expand All @@ -421,7 +443,7 @@ def default_compilation_pass(self, optimisation_level: int = 2) -> BasePass:
FullPeepholeOptimise(target_2qb_gate=OpType.TK2),
NormaliseTK2(),
DecomposeTK2(**fidelities),
self.rebase_pass(),
self.rebase_pass(implicit_swaps=implicit_swaps),
RemoveRedundancies(),
squash,
SimplifyInitial(
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
packages=find_namespace_packages(include=["pytket.*"]),
include_package_data=True,
install_requires=[
"pytket ~= 1.17",
"pytket ~= 1.18",
"requests >= 2.2",
"types-requests",
"websockets >= 7.0",
Expand Down
83 changes: 80 additions & 3 deletions tests/unit/convert_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

import pytest

from pytket.circuit import Circuit, OpType, reg_eq # type: ignore
from pytket.circuit import Circuit, OpType, Qubit, reg_eq # type: ignore
from pytket._tket.circuit import _TEMP_BIT_NAME, _TEMP_BIT_REG_BASE # type: ignore
from pytket.extensions.quantinuum import QuantinuumBackend
from pytket.extensions.quantinuum.backends.quantinuum import scratch_reg_resize_pass
Expand All @@ -29,7 +29,7 @@ def test_convert() -> None:
circ.add_barrier([2])
circ.measure_all()

QuantinuumBackend("", machine_debug=True).rebase_pass().apply(circ)
QuantinuumBackend("", machine_debug=True).rebase_pass(False).apply(circ)
circ_quum = circuit_to_qasm_str(circ, header="hqslib1")
qasm_str = circ_quum.split("\n")[6:-1]
assert all(
Expand All @@ -46,7 +46,7 @@ def test_convert_rzz() -> None:
circ.add_gate(OpType.ZZMax, [2, 3])
circ.measure_all()

QuantinuumBackend("", machine_debug=True).rebase_pass().apply(circ)
QuantinuumBackend("", machine_debug=True).rebase_pass(False).apply(circ)
circ_quum = circuit_to_qasm_str(circ, header="hqslib1")
qasm_str = circ_quum.split("\n")[6:-1]
assert all(
Expand Down Expand Up @@ -121,3 +121,80 @@ def test_resize_scratch_registers() -> None:
c_compiled = circ.copy()
scratch_reg_resize_pass(10).apply(c_compiled)
assert circ == c_compiled


def test_implicit_swap_removal() -> None:
b = QuantinuumBackend("", machine_debug=True)
c = Circuit(2).ISWAPMax(0, 1)
compiled = b.get_compiled_circuit(c, 0)
assert compiled.n_gates_of_type(OpType.ZZMax) == 1
assert compiled.n_gates_of_type(OpType.ZZPhase) == 0
iqp = compiled.implicit_qubit_permutation()
assert iqp[Qubit(0)] == Qubit(1)
assert iqp[Qubit(1)] == Qubit(0)
c = Circuit(2).ISWAPMax(0, 1)
b.rebase_pass(False).apply(c)
assert c.n_gates_of_type(OpType.ZZMax) == 2
assert c.n_gates_of_type(OpType.ZZPhase) == 0

c = Circuit(2).Sycamore(0, 1)
compiled = b.get_compiled_circuit(c, 0)
assert compiled.n_gates_of_type(OpType.ZZMax) == 2
assert compiled.n_gates_of_type(OpType.ZZPhase) == 0
iqp = compiled.implicit_qubit_permutation()
assert iqp[Qubit(0)] == Qubit(1)
assert iqp[Qubit(1)] == Qubit(0)
c = Circuit(2).Sycamore(0, 1)
b.rebase_pass(False).apply(c)
assert c.n_gates_of_type(OpType.ZZMax) == 3
assert c.n_gates_of_type(OpType.ZZPhase) == 0

c = Circuit(2).ISWAP(0.3, 0, 1)
compiled = b.get_compiled_circuit(c, 0)
assert compiled.n_gates_of_type(OpType.ZZMax) == 2
assert compiled.n_gates_of_type(OpType.ZZPhase) == 0
iqp = compiled.implicit_qubit_permutation()
assert iqp[Qubit(0)] == Qubit(0)
assert iqp[Qubit(1)] == Qubit(1)
c = Circuit(2).ISWAP(0.3, 0, 1)
b.rebase_pass(False).apply(c)
assert c.n_gates_of_type(OpType.ZZMax) == 2
assert c.n_gates_of_type(OpType.ZZPhase) == 0

c = Circuit(2).ISWAPMax(0, 1).ISWAPMax(1, 0)
compiled = b.get_compiled_circuit(c, 0)
assert compiled.n_gates_of_type(OpType.ZZMax) == 2
assert compiled.n_gates_of_type(OpType.ZZPhase) == 0
iqp = compiled.implicit_qubit_permutation()
assert iqp[Qubit(0)] == Qubit(0)
assert iqp[Qubit(1)] == Qubit(1)
c = Circuit(2).ISWAPMax(0, 1).ISWAPMax(1, 0)
compiled = b.get_compiled_circuit(c, 1)
assert compiled.n_gates_of_type(OpType.ZZMax) == 0
assert compiled.n_gates_of_type(OpType.ZZPhase) == 0
iqp = compiled.implicit_qubit_permutation()
assert iqp[Qubit(0)] == Qubit(0)
c = Circuit(2).ISWAPMax(0, 1).ISWAPMax(1, 0)
b.rebase_pass(False).apply(c)
assert c.n_gates_of_type(OpType.ZZMax) == 4
assert c.n_gates_of_type(OpType.ZZPhase) == 0

c = Circuit(2).SWAP(0, 1)
compiled = b.get_compiled_circuit(c, 0)
assert compiled.n_gates_of_type(OpType.ZZMax) == 0
assert compiled.n_gates_of_type(OpType.ZZPhase) == 0
iqp = compiled.implicit_qubit_permutation()
assert iqp[Qubit(0)] == Qubit(1)
assert iqp[Qubit(1)] == Qubit(0)
c = Circuit(2).SWAP(0, 1)
b.rebase_pass(False).apply(c)
assert c.n_gates_of_type(OpType.ZZMax) == 3
assert c.n_gates_of_type(OpType.ZZPhase) == 0

c = Circuit(2).ZZMax(0, 1)
compiled = b.get_compiled_circuit(c, 0)
assert compiled.n_gates == 1


if __name__ == "__main__":
test_implicit_swap_removal()

0 comments on commit cfdeae2

Please sign in to comment.