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

Refactor greedy pauli simp #1611

Merged
merged 63 commits into from
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
00f3ef3
Initial refactor
yao-cqc Jul 8, 2024
8d3f9f3
Refactor node types
yao-cqc Sep 24, 2024
4c41f1c
Move nodes definition into a new file
yao-cqc Sep 24, 2024
0fa70b8
Refactor synthesis
yao-cqc Sep 25, 2024
7f690ea
Cleanup
yao-cqc Sep 25, 2024
0fcca68
More refactoring
yao-cqc Sep 25, 2024
7a32bd1
Refactor pauli graph converters
yao-cqc Sep 25, 2024
b8071a7
Initial implementation of GPGraph
yao-cqc Oct 2, 2024
48c8b2c
Migrate to GPGraph
yao-cqc Oct 2, 2024
5aef873
Ignore global phase
yao-cqc Oct 3, 2024
cd4411f
Add supports for conditional gates
yao-cqc Oct 4, 2024
388873d
Add support for classical ops
yao-cqc Oct 4, 2024
ef7d0b6
flatten_registers should only rename qubits and bits
yao-cqc Oct 4, 2024
9e9a2fd
Replace unsigned with Bit
yao-cqc Oct 4, 2024
77a1522
Revert "Replace unsigned with Bit"
yao-cqc Oct 4, 2024
54d3e89
Manually check if qubits and bits can be flattened since ``is_simple(…
yao-cqc Oct 4, 2024
83ec4ac
Consistent enum names
yao-cqc Oct 4, 2024
090ab69
Add support for mid-circuit measurement
yao-cqc Oct 4, 2024
6083f1d
Rename variables
yao-cqc Oct 6, 2024
bbc43e5
Add support for resets
yao-cqc Oct 7, 2024
00c6aca
Update docstrings
yao-cqc Oct 7, 2024
30d483b
Update pass predicate
yao-cqc Oct 7, 2024
7e1eee5
Add more tests
yao-cqc Oct 7, 2024
431404e
Merge branch 'main' into refactor-greedy-pauli-simp
yao-cqc Oct 8, 2024
9d8094d
bump tket version
yao-cqc Oct 8, 2024
b98cb8a
Add changelog entry
yao-cqc Oct 8, 2024
dc2dc1d
Fix docs errors
yao-cqc Oct 8, 2024
c5e18d7
Merge branch 'main' into refactor-greedy-pauli-simp
yao-cqc Oct 8, 2024
a8d3288
bump tket version
yao-cqc Oct 8, 2024
8ac2da5
Remove unused headers
yao-cqc Oct 8, 2024
354ce1f
bump tket version in pytket
yao-cqc Oct 8, 2024
64eebbb
uncomment lines
yao-cqc Oct 10, 2024
664cf10
remove consts in SQ_CLIFF_DAGGER
yao-cqc Oct 10, 2024
4fdfbec
Merge branch 'main' into refactor-greedy-pauli-simp
yao-cqc Oct 10, 2024
f5138f1
Merging conditionals
yao-cqc Oct 10, 2024
21f806f
Revert "Merging conditionals"
yao-cqc Oct 10, 2024
5423b71
Optimise conditional handling
yao-cqc Oct 11, 2024
6e14c7d
remove ConditionalPauliRotation
yao-cqc Oct 11, 2024
e3b85a3
Remove clifford reduction and pass parameters when synthesis conditio…
yao-cqc Oct 11, 2024
0b46746
Seeded tie breaking
yao-cqc Oct 11, 2024
1bfca5a
Add limits to the search space
yao-cqc Oct 14, 2024
c5b778d
Allowing ZZPhase gates
yao-cqc Oct 15, 2024
273349b
update binder and serialisation
yao-cqc Oct 15, 2024
eafa42c
Add test for ops handling in python
yao-cqc Oct 15, 2024
1f91c29
add note for AC node cost
yao-cqc Oct 15, 2024
3a6cef5
Merge branch 'main' into refactor-greedy-pauli-simp
yao-cqc Oct 15, 2024
102ea5b
bump tket version
yao-cqc Oct 15, 2024
fd5e552
update changelog
yao-cqc Oct 15, 2024
d6186d9
fix changelog format
yao-cqc Oct 15, 2024
3f1d65a
add missing prams in docstrings
yao-cqc Oct 15, 2024
faa0536
cast size_t to unsigned
yao-cqc Oct 15, 2024
e31abde
remove nondeterminism from test
yao-cqc Oct 15, 2024
488429c
Remove more nondeterminism
yao-cqc Oct 15, 2024
0def7b5
regen stubs
yao-cqc Oct 15, 2024
e5030e2
Add debug info
yao-cqc Oct 16, 2024
65ee40b
Revert "Add debug info"
yao-cqc Oct 16, 2024
38d3c6f
Replace implicit wire swaps in optimised conditional circuits
yao-cqc Oct 22, 2024
7f1c680
Merge branch 'main' into refactor-greedy-pauli-simp
yao-cqc Oct 23, 2024
a9f148e
re-organise changelog
yao-cqc Oct 23, 2024
08eb8c8
Bump tket version
yao-cqc Oct 23, 2024
92462fc
fix bug in sign correction
yao-cqc Oct 24, 2024
b1b93eb
Add more tests
yao-cqc Oct 24, 2024
2c47c1f
Merge branch 'main' into refactor-greedy-pauli-simp
yao-cqc Oct 24, 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
13 changes: 12 additions & 1 deletion pytket/binders/passes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -927,8 +927,19 @@ PYBIND11_MODULE(passes, m) {
"\n\n:param discount_rate: Rate used to discount the cost impact from "
"gadgets that are further away. Default to 0.7."
"\n:param depth_weight: Degree of depth optimisation. Default to 0.3."
"\n:param max_tqe_candidates: Maximum number of 2-qubit Clifford "
"gate candidates to evaluate at each step. Default to 500."
"\n:param max_lookahead: Maximum lookahead when evaluating each "
"Clifford gate candidate. Default to 500."
"\n:param seed: Unsigned integer seed used for sampling candidates "
"and tie breaking. Default to 0."
"\n:param allow_zzphase: If set to True, allows the algorithm to "
"implement 2-qubit rotations using ZZPhase gates when deemed "
"optimal. Defaults to False."
"\n:return: a pass to perform the simplification",
py::arg("discount_rate") = 0.7, py::arg("depth_weight") = 0.3);
py::arg("discount_rate") = 0.7, py::arg("depth_weight") = 0.3,
py::arg("max_lookahead") = 500, py::arg("max_tqe_candidates") = 500,
py::arg("seed") = 0, py::arg("allow_zzphase") = false);
m.def(
"PauliSquash", &PauliSquash,
"Applies :py:meth:`PauliSimp` followed by "
Expand Down
13 changes: 12 additions & 1 deletion pytket/binders/transform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -431,8 +431,19 @@ PYBIND11_MODULE(transform, m) {
"gadgets that are further away. Default to 0.7."
"\n:param depth_weight: Degree of depth optimisation. Default to "
"0.3."
"\n:param max_tqe_candidates: Maximum number of 2-qubit Clifford "
"gate candidates to evaluate at each step. Default to 500."
"\n:param max_lookahead: Maximum lookahead when evaluating each "
"Clifford gate candidate. Default to 500."
"\n:param seed: Unsigned integer seed used for sampling candidates "
"and tie breaking. Default to 0."
"\n:param allow_zzphase: If set to True, allows the algorithm to "
"implement 2-qubit rotations using ZZPhase gates when deemed "
"optimal. Defaults to False."
"\n:return: a pass to perform the simplification",
py::arg("discount_rate") = 0.7, py::arg("depth_weight") = 0.3)
py::arg("discount_rate") = 0.7, py::arg("depth_weight") = 0.3,
py::arg("max_tqe_candidates") = 500, py::arg("max_lookahead") = 500,
py::arg("seed") = 0, py::arg("allow_zzphase") = false)
.def_static(
"ZZPhaseToRz", &Transforms::ZZPhase_to_Rz,
"Fixes all ZZPhase gate angles to [-1, 1) half turns.")
Expand Down
2 changes: 1 addition & 1 deletion pytket/conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def requirements(self):
self.requires("pybind11_json/0.2.14")
self.requires("symengine/0.12.0")
self.requires("tkassert/0.3.4@tket/stable")
self.requires("tket/1.3.34@tket/stable")
self.requires("tket/1.3.35@tket/stable")
self.requires("tklog/0.3.3@tket/stable")
self.requires("tkrng/0.3.3@tket/stable")
self.requires("tktokenswap/0.3.9@tket/stable")
Expand Down
12 changes: 12 additions & 0 deletions pytket/docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,18 @@ Features:

* Add new `ClExprOp` operation type as an alternative to `ClassicalExpBox`; add
option to use this when converting from QASM.
* Several updates to `GreedyPauliSimp`:

* Support for mid-circuit measurements, resets, conditionals,
and classical gates.

* New parameters `max_lookahead` and `max_tqe_candidates` are added
to limit the search space.

* New parameter `seed` is added to support random sampling and tie breaking.

* New parameter `allow_zzphase` allows the algorithm to implement 2-qubit rotations
using ZZPhase gates when deemed optimal.

Fixes:

Expand Down
6 changes: 5 additions & 1 deletion pytket/pytket/_tket/passes.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -440,12 +440,16 @@ def GlobalisePhasedX(squash: bool = True) -> BasePass:
It is not recommended to use this pass with symbolic expressions, as in certain cases a blow-up in symbolic expression sizes may occur.
"""
def GreedyPauliSimp(discount_rate: float = 0.7, depth_weight: float = 0.3) -> BasePass:
def GreedyPauliSimp(discount_rate: float = 0.7, depth_weight: float = 0.3, max_lookahead: int = 500, max_tqe_candidates: int = 500, seed: int = 0, allow_zzphase: bool = False) -> BasePass:
"""
Construct a pass that converts a circuit into a graph of Pauli gadgets to account for commutation and phase folding, and resynthesises them using a greedy algorithm adapted from arxiv.org/abs/2103.08602. The method for synthesising the final Clifford operator is adapted from arxiv.org/abs/2305.10966.
:param discount_rate: Rate used to discount the cost impact from gadgets that are further away. Default to 0.7.
:param depth_weight: Degree of depth optimisation. Default to 0.3.
:param max_tqe_candidates: Maximum number of 2-qubit Clifford gate candidates to evaluate at each step. Default to 500.
:param max_lookahead: Maximum lookahead when evaluating each Clifford gate candidate. Default to 500.
:param seed: Unsigned integer seed used for sampling candidates and tie breaking. Default to 0.
:param allow_zzphase: If set to True, allows the algorithm to implement 2-qubit rotations using ZZPhase gates when deemed optimal. Defaults to False.
:return: a pass to perform the simplification
"""
def GuidedPauliSimp(strat: pytket._tket.transform.PauliSynthStrat = pytket._tket.transform.PauliSynthStrat.Sets, cx_config: pytket._tket.circuit.CXConfigType = pytket._tket.circuit.CXConfigType.Snake) -> BasePass:
Expand Down
6 changes: 5 additions & 1 deletion pytket/pytket/_tket/transform.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -165,12 +165,16 @@ class Transform:
It is not recommended to use this transformation with symbolic expressions, as in certain cases a blow-up in symbolic expression sizes may occur.
"""
@staticmethod
def GreedyPauliSimp(discount_rate: float = 0.7, depth_weight: float = 0.3) -> Transform:
def GreedyPauliSimp(discount_rate: float = 0.7, depth_weight: float = 0.3, max_tqe_candidates: int = 500, max_lookahead: int = 500, seed: int = 0, allow_zzphase: bool = False) -> Transform:
"""
Convert a circuit into a graph of Pauli gadgets to account for commutation and phase folding, and resynthesises them using a greedy algorithm adapted from arxiv.org/abs/2103.08602. The method for synthesising the final Clifford operator is adapted from arxiv.org/abs/2305.10966.
:param discount_rate: Rate used to discount the cost impact from gadgets that are further away. Default to 0.7.
:param depth_weight: Degree of depth optimisation. Default to 0.3.
:param max_tqe_candidates: Maximum number of 2-qubit Clifford gate candidates to evaluate at each step. Default to 500.
:param max_lookahead: Maximum lookahead when evaluating each Clifford gate candidate. Default to 500.
:param seed: Unsigned integer seed used for sampling candidates and tie breaking. Default to 0.
:param allow_zzphase: If set to True, allows the algorithm to implement 2-qubit rotations using ZZPhase gates when deemed optimal. Defaults to False.
:return: a pass to perform the simplification
"""
@staticmethod
Expand Down
10 changes: 9 additions & 1 deletion pytket/tests/passes_serialisation_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,15 @@ def nonparam_predicate_dict(name: str) -> Dict[str, Any]:
{"name": "RoundAngles", "n": 6, "only_zeros": False}
),
"GreedyPauliSimp": standard_pass_dict(
{"name": "GreedyPauliSimp", "discount_rate": 0.4, "depth_weight": 0.5}
{
"name": "GreedyPauliSimp",
"discount_rate": 0.4,
"depth_weight": 0.5,
"max_lookahead": 100,
"max_tqe_candidates": 100,
"seed": 2,
"allow_zzphase": True,
}
),
# lists must be sorted by OpType value
"AutoSquash": standard_pass_dict(
Expand Down
52 changes: 49 additions & 3 deletions pytket/tests/predicates_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
UnitID,
Conditional,
Bit,
RangePredicateOp,
SetBitsOp,
MultiBitOp,
)
from pytket.circuit.named_types import ParamType, RenameUnitsMap
from pytket.pauli import Pauli
Expand Down Expand Up @@ -1020,18 +1023,61 @@ def test_clifford_push_through_measures() -> None:
assert coms[7].op.type == OpType.CopyBits


def greedy_pauli_synth() -> None:
circ = Circuit(4, name="test")
def test_greedy_pauli_synth() -> None:
circ = Circuit(name="test")
rega = circ.add_q_register("a", 2)
regb = circ.add_q_register("b", 2)
d = circ.copy()
circ.Rz(0, rega[0]).H(regb[1]).CX(rega[0], rega[1]).Ry(0.3, rega[0]).S(regb[1]).CZ(
rega[0], regb[0]
).SWAP(regb[1], rega[0])
d = circ.copy()
pss = GreedyPauliSimp(0.5, 0.5)
assert pss.apply(d)
assert np.allclose(circ.get_unitary(), d.get_unitary())
assert d.name == "test"
# test gateset
range_predicate = RangePredicateOp(3, 0, 6)
set_bits = SetBitsOp([True, True])
multi_bit = MultiBitOp(set_bits, 2)
exp = Bit(2) & Bit(3)
eq_pred_values = [True, False, False, True]
and_values = [bool(i) for i in [0, 0, 0, 1]]
pg1 = PauliExpBox([Pauli.X, Pauli.Z], 0.3)
circ = Circuit(4, 4, name="test")
circ.add_pauliexpbox(pg1, [0, 1])
circ.add_gate(multi_bit, [0, 1, 2, 3])
circ.add_gate(range_predicate, [0, 1, 2, 3])
circ.add_classicalexpbox_bit(exp, [Bit(0)])
circ.add_c_predicate(eq_pred_values, [0, 1], 2, "EQ")
circ.add_c_modifier(and_values, [1], 2)
circ._add_wasm("funcname", "wasmfileuid", [1, 1], [], [Bit(0), Bit(1)], [0])
circ.measure_all()
circ.Reset(0)
circ.add_pauliexpbox(pg1, [2, 3])
assert GreedyPauliSimp(0.5, 0.5, 100, 100, 0, True).apply(circ)
# PauliExpBoxes implemented using ZZPhase
d = Circuit(4, 4, name="test")
d.H(0)
d.ZZPhase(0.3, 0, 1)
d.H(0)
d.add_gate(multi_bit, [0, 1, 2, 3])
d.add_gate(range_predicate, [0, 1, 2, 3])
d.add_classicalexpbox_bit(exp, [Bit(0)])
d.add_c_predicate(eq_pred_values, [0, 1], 2, "EQ")
d.add_c_modifier(and_values, [1], 2)
d._add_wasm("funcname", "wasmfileuid", [1, 1], [], [Bit(0), Bit(1)], [0])
d.measure_all()
d.Reset(0)
d.H(2)
d.ZZPhase(0.3, 2, 3)
d.H(2)
assert circ == d
# test barrier
circ = Circuit(1).add_barrier([0])
with pytest.raises(RuntimeError) as e:
GreedyPauliSimp().apply(circ)
err_msg = "Predicate requirements are not satisfied"
assert err_msg in str(e.value)


def test_auto_rebase_deprecation(recwarn: Any) -> None:
Expand Down
24 changes: 22 additions & 2 deletions schemas/compiler_pass_v1.json
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,22 @@
"depth_weight": {
"type": "number",
"definition": "parameter controlling the degree of depth optimisation in \"GreedyPauliSimp\""
},
"max_lookahead": {
"type": "number",
"definition": "parameter controlling the lookahead when evaluating candidates in \"GreedyPauliSimp\""
},
"max_tqe_candidates": {
"type": "number",
"definition": "parameter controlling the number of candidates to evaluate in \"GreedyPauliSimp\""
},
"seed": {
"type": "number",
"definition": "parameter controlling the random sampling and tie breaking in \"GreedyPauliSimp\""
},
"allow_zzphase": {
"type": "boolean",
"definition": "parameter controlling the use of ZZPhase gates in \"GreedyPauliSimp\""
}
},
"required": [
Expand Down Expand Up @@ -883,9 +899,13 @@
"then": {
"required": [
"discount_rate",
"depth_weight"
"depth_weight",
"max_lookahead",
"max_tqe_candidates",
"seed",
"allow_zzphase"
],
"maxProperties": 3
"maxProperties": 7
}
},
{
Expand Down
2 changes: 2 additions & 0 deletions tket/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,8 @@ target_sources(tket
src/Transformations/ContextualReduction.cpp
src/Transformations/Decomposition.cpp
src/Transformations/GreedyPauliOptimisation.cpp
src/Transformations/GreedyPauliConverters.cpp
src/Transformations/GreedyPauliOps.cpp
src/Transformations/MeasurePass.cpp
src/Transformations/OptimisationPass.cpp
src/Transformations/PauliOptimisation.cpp
Expand Down
2 changes: 1 addition & 1 deletion tket/conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

class TketConan(ConanFile):
name = "tket"
version = "1.3.34"
version = "1.3.35"
package_type = "library"
license = "Apache 2"
homepage = "https://github.com/CQCL/tket"
Expand Down
9 changes: 8 additions & 1 deletion tket/include/tket/Predicates/PassGenerators.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -350,9 +350,16 @@ PassPtr gen_special_UCC_synthesis(
*
* @param discount_rate
* @param depth_weight
* @param max_lookahead
* @param max_tqe_candidates
* @param seed
* @param allow_zzphase
* @return PassPtr
*/
PassPtr gen_greedy_pauli_simp(double discount_rate, double depth_weight);
PassPtr gen_greedy_pauli_simp(
double discount_rate = 0.7, double depth_weight = 0.3,
unsigned max_lookahead = 500, unsigned max_tqe_candidates = 500,
unsigned seed = 0, bool allow_zzphase = false);

/**
* Generate a pass to simplify the circuit where it acts on known basis states.
Expand Down
Loading
Loading