zxcalc / pyzx

Python library for quantum circuit rewriting and optimisation using the ZX-calculus
Apache License 2.0
364 stars 109 forks source link

Clarification on applying individual transformations #238

Open rcasjimenez opened 2 weeks ago

rcasjimenez commented 2 weeks ago

My goal is to apply a single transformation to a graph that satisfies the 'graph-like' precondition.

First approach

I tried to apply the following transformations mentioned in #199 (to_gh and spider_simp):

fname = os.path.join('..','circuits','Fast', 'mod5_4_before')
circ = zx.Circuit.load(fname).to_basic_gates()
x = circ.to_graph() # We first have to convert the circuit into a ZX-graph
initial_graph = copy.deepcopy(x)

# turn all red spiders into green spiders
zx.to_gh(initial_graph)

# simplify: remove excess HAD's, fuse along non-HAD edges, remove parallel edges and self-loops
zx.simplify.spider_simp(initial_graph, quiet=True)
# checking transformed graph
print(f'zx.simplify.is_graph_like:{zx.simplify.is_graph_like(initial_graph)}')  

Output:

zx.simplify.is_graph_like:False

But the graph was not 'graph-like'.

Second approach

My second approach was using specific functions to convert to 'graph-like'.

I converted the 'mod5_4_before' circuit to a graph, and later to a 'graph-like' graph using the 'to_graph_like' function. I have to say that to_graph_like function appears in a code block with a note: "#The functions below haven't been updated in a while. Use at your own risk.", although the function appears to implement the requirements necessary for a graph to satisfy the 'graph-like' condition according to 'Hybrid quantum-classical circuit simplification with the ZX-calculus'. (page 6). After this, I applied the transformation 'zx.rules.remove_ids' to the graph of type 'graph-like', and checked the type of graph using the 'is_graph_like' function, this function returned False -> so, it was not a graph of type 'graph-like'.

fname = os.path.join('.','circuits','Fast', 'mod5_4_before')
circ = zx.Circuit.load(fname).to_basic_gates()
x = circ.to_graph() # We first have to convert the circuit into a ZX-graph
graph = copy.deepcopy(x)
print('--------------------------------------')
graph_aux = copy.deepcopy(graph)
zx.simplify.to_graph_like(graph_aux)
print(f'zx.simplify.is_graph_like(graph_aux):{zx.simplify.is_graph_like(graph_aux)}')
print('--------------------------------------')
zx.draw(graph_aux, labels=True)
print('--------------------------------------')
matcher_params = zx.rules.match_ids_parallel(graph_aux)
print(f'matcher_params[0]:{matcher_params[0]}')
print('--------------------------------------')
zx.rules.apply_rule(graph_aux, zx.rules.remove_ids,[matcher_params[0]])  
zx.draw(graph_aux, labels=True)
print(f'zx.simplify.is_graph_like:{zx.simplify.is_graph_like(graph_aux)}')

Output:

image

As I said at the beginning of this comment, my goal is to apply a transform to a circuit. In this case, I tested the 'zx.rules.remove_ids' transformation, and the result does not seem to be satisfactory.

I am very confused, please:

jvdwetering commented 2 weeks ago

The first thing seems to be a bug, potentially in the is_graph_like function. The second one is because removing an identity breaks the graph being graph like. You can see this in your last picture: there is a regular edge between vertices 38 and 48. If you want to make it graph like then you should fuse the spiders again.

jvdwetering commented 2 weeks ago

I've now changed the default behaviour to is_graph_like so that it makes sense here. The old behaviour you can get by setting the new parameter strict=True.

rcasjimenez commented 2 weeks ago

Thanks @jvdwetering.

  1. In the first case, the result is now a "graph-like" (strict=False) graph according to the default behavior of the modified function.

  2. In the second case, yes, if I only fuse the spiders again, the resulting graph is 'graph-like', as indicated by the is_graph_like function.

Taking these results into account:

jvdwetering commented 2 weeks ago

It depends on what you want to do with your graph-like diagram. But yes, fusing all spiders is definitely a necessity.

rcasjimenez commented 1 week ago

What I would like to do with my graph-type diagram is to be able to apply a set of transformations to a circuit, making sure that I do not modify the functionality/semantics of the graph corresponding to the circuit.

So this is my question, taking into account the new parameter in the function I can apply to a circuit:

Which one should I apply?