-
Notifications
You must be signed in to change notification settings - Fork 116
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
Causal flow preserving circuit optimisation #189
base: master
Are you sure you want to change the base?
Conversation
This looks great Calum. It also makes quite some changes to the API and where the circuits are stored so I need to make sure first this doesn't break anything in some other place, so it might be a while before I can actually approve this. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the improvements, Calum.
It would also be nice to add unit tests for each added/modified functionality, and especially to have an end-to-end regression test, for example using a circuit from your paper, to demonstrate/verify the result of teleport_reduce
with store = True
.
(The demo notebooks and benchmarks aren't run by GitHub as part of its continuous integration, so it would be good to be able to catch future breaking changes with a test as otherwise the demos and benchmarks may break or change their behaviour without anyone noticing.)
I've realised that some of the other demo notebooks may now not run with the changes to where circuits are stored, I'll go through and update these also. |
Sure, I'll add some tests for everything! |
With these new commits, is this now ready for merging? |
I suppose he's waiting for an answer about testing |
I had already fixed the bug in to_graph_like that you fixed in the recent commit (although have now updated the vertex alignments). I also just added a check that the graph initially contains no H-boxes - previously it just treated a boundary H-box correctly, but really the graph should contain no H-boxes at all, otherwise to_gh() and spider_simp() won't work properly for removing hadamard pairs etc. Running |
Yes, I think it is fine to raise an exception in that case. Though the circular import could be prevented by doing a local import inside the function |
@jvdwetering Can we try to resolve the conflicts and merge this before more PRs are merged which will cause this to diverge further? |
@RazinShaikh is currently in the middle of a PR spree that updates many of the rewrites to work with multigraphs. This is a really big PR and I currently have no overview on all the things it touches. So I think after all the multigraph changes have been made we can revisit how much of this PR still makes sense. |
Causal flow preserving optimisation of quantum circuits
Implements various functions and changes used for optimising quantum circuits (https://arxiv.org/abs/2312.02793).
circuits/benchmarking_circuits/
Reorganised benchmarking circuits to be clearer which circuit is optimised by which function, and enable easier integration with the new updated
Benchmark
class.demos/circuit_optimisation/
Added new demo notebooks demonstrating the use of the new
Benchmark
class for circuit optimisation (benchmarking.ipynb
) as well as effective optimisation of QFT circuits (qft-opt.ipynb
). Also includes stored benchmarking metadata demonstrating how it can be saved, rather than having to rerun optimisations each time.benchmarking.py
Implements the new
Benchmark
class for comparing circuit optimisation strategies, replacingbenchmark.py
. This allows you to store the data so that routines don't need to be rerun, automatically verifies circuits, and automatically produces a more visually appealing output. Demonstrated indemos/circuit_optimisation/benchmarking.ipynb
.Benchmark.load_circuits
enables loading directories containing unoptimised circuits as well as directories containing circuits pre-optimised by a specific routine.Benchmark.add_simplification_func
allows you to add any optimisation function which accepts a circuit and outputs an optimised circuit.Benchmark.df
generates a dataframe containing desired results, outputting a stylised version of this.Benchmark.Pt_graphs
automatically produces graphs comparing results on randomly generated circuits with varying T-gate probabilitypyzx/flow.py
Replaced file
gflow.py
withflow.py
, implementing the following functions:gflow
is the same function as before (although marginally optimised), implementing the gflow algorithm from dx.doi.org/10.1007/978-3-540-70575-8_70.cflow
implements the causal flow algorithm from the same paper. If phase gadgets are desired to be included then this points tofull_cflow
.full_cflow
implements the causal flow algorithm from https://doi.org/10.48550/arXiv.quant-ph/0603072, which calculates the full partial order. It also checks for cflow with phase gadgets (which can then be extracted via phase polynomial synthesis).pyzx/extract.py
Updated the
extract_simple
function:phase_poly_synth
function, implementing the algorithm from https://arxiv.org/abs/2004.06052.func: teleport_reduce
Reimplemented phase teleportation in
pyzx/simplify.py
,pyzx/graph/base.py
andpyzx/graph/graph_s.py
in order to track all potential vertices which phases can be fused on, as well as allow phase jumping between these variables throughout simplification. The basic use ofteleport_reduce
with the parameterstore = False
(default) is identical to before.The new objects stored in
BaseGraph
are as follows:phase_tracking
denotes whether the graph is tracking phases, either when the diagram is being simplified initially to find fused phase variables or afterwards when the diagram is being simplified and phases variables are not yet placed on the graph, or phase jumping is allowed.phase_teleporter
points to an instance ofpyzx/simplify.PhaseTeleporter
. This is only used for the initial simplification when finding phase variables which fuse together. In post-simplification all metadata about the variables is then stored on the graph in the following variables, and this is set toNone
:parent_vertex
points a vertex to the original vertex containing the phase variable on the graphvertex_groups
indexes a vertex to which vertex group it is ingroup_data
stores the list of vertices remaining (i.e. not placed on the graph yet) in each group of fused variables.phase_sum
stores the total phase sum of each group which remains to be added to the graph on one of the variables. If only one variable remains it the phase will be automatically placed and the group removed.phase_mult
stores any phase multipliers for vertices (if -1 then the phase sum needs to be subtracted from the graph on that variable rather than added) - i.e. the result of the functionphase_negate
when gadgets are negated.vertex_rank
stores the ordering of how vertices were fused together in the initial simplification process.vertices_to_update
stores any vertices which have been modified by fixing other phases (i.e. if it was the last in the group), such that potential matches involving these can be updated/removed - used inflow_2Q_simp
.In
pyzx/simplify.PhaseTeleporter
fused phase variables are now stored in a disjoint set. Thisparent
function is not the same as theparent_vertex
inBaseGraph
, but rather the parent in the disjoint set.pyzx/simplify.py
Modified some functions and added new functions for selective simplification
simp
now includes an additional parameternum
which limits the number of rewrites applied. It also implements rules usingapply_rule
rather than separately within the functionbasic_simp
iteratively applies justid_simp
andspider_simp
flow_2Q_simp
is the main optimisation function, selectively applying the transformation which reduces the two-qubit gate count the most (if causal flow is chosen to be preserved).selective_simp
,match_score_2Q_simp
andupdate_2Q_simp_matches
are all helper functions used for this.to_graph_like
andis_graph_like
were updated, including an optionalassert_bound_connections
parameter if the input/output connection conditions are not required to be modified.pyzx/rules.py
The following modifications to existing functions are made:
allow_interacting_matches
parameter was added, used when the matches are not all going to be applied at once (such as inflow_2Q_simp
).MatchPivotType
andMatchLcompType
are modified to use tuples rather than lists, so that they are now immutable and can be used as keys in a dictionary.match_pivot_gadget
,match_pivot_boundary
andmatch_phase_gadgets
were updated such that they no longer modify the graph at all, with all modifications being moved to the respective rewrite functions. The structure of the MatchTypes for each of these are also modified accordingly.pivot_gadget
is the new rewrite function for bothmatch_pivot_gadget
andmatch_pivot_boundary
, using a helper functiongadgetize
which infuses the relevant spiders into phase gadgets before, before applying the usualpivot
rewrite function.Then the following functions were added:
match_id_fuse
,id_fuse
implement identity fusion (i.e. identity removal followed by immediate fusion).match_lcomp_unfuse
,lcomp_unfuse
implement local complementation including prior applications of neighbour unfusion.match_pivot_unfuse
,pivot_unfuse
implement local complementation including prior applications of neighbour unfusion.match_2Q_simp
,rewrite_2Q_simp
finds all matches ofid_fuse
,lcomp_unfuse
andpivot_unfuse
.pyzx/heuristics.py
Module which enables the calculation of statistics and heuristics for various matches, used in
flow_2Q_simp