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

W node support #128

Merged
merged 23 commits into from
Aug 18, 2023
Merged

W node support #128

merged 23 commits into from
Aug 18, 2023

Conversation

RazinShaikh
Copy link
Contributor

@RazinShaikh RazinShaikh commented Aug 13, 2023

This PR adds basic support for W nodes in PyZX. It allows for creating diagrams with W, saving/loading them, and implements a W fusion rule.

@jvdwetering
Copy link
Collaborator

It looks like you didn't add the functionality for drawing W spiders in PyZX itself. So if you were to call zx.draw(g) on a graph containing a W it would probably crash. I know you are adding this to support it in ZXLive, but it feels kinda weird to have a new feature which then does not work with some of the other basic things, like drawing, that exist in PyZX.

@RazinShaikh
Copy link
Contributor Author

Alright, I will do something about the drawing. What are the other basic things that need to be accounted for?

@jvdwetering
Copy link
Collaborator

Thanks! I think exporting to the json format, although this is not super important. Support for calculating the tensor is pretty useful (this will be useful in ZXLive anyway). For the drawing ideally it would support both the matplotlib backend, and the d3 backend.
I'm pretty sure all the rewrites already check all the types, and they will hence just not apply if there is a W, so that should be fine I think.

In generate.py there is a function spider() that generates a diagram containing a single spider. This is useful when you build a diagram programmatically by tensor products and compositions. So maybe you want to add support for W here?

@RazinShaikh
Copy link
Contributor Author

RazinShaikh commented Aug 14, 2023

I had already implemented import/export from json and tikz because that's necessary for saving zxlive diagrams. Regarding the d3 backend, can you point me to where I need to add the code for W node?

@jvdwetering
Copy link
Collaborator

The relevant changes to the d3 backend should probably be made in js/zx_viewer.inline.js.

@RazinShaikh
Copy link
Contributor Author

I have implemented everything except calculating the tensor. I am confused about how to convert W to tensor so I would appreciate any help there.

@jvdwetering
Copy link
Collaborator

jvdwetering commented Aug 15, 2023

So for the tensor, is it true that we can view the 'output' node of the W-spider as a NOT gate and the 'input' node as something flexsymmetric? Because if so, then it shouldn't be too hard to extend the tensor function to this. I think I should be able to do that quite easily in that case.
(I'm talking strictly about the qubit case here of course)

@RazinShaikh
Copy link
Contributor Author

Yes, for qubits the W_INPUT is a NOT gate and W_OUTPUT is a W state which is flexsymmetric.

@jvdwetering
Copy link
Collaborator

So here's the idea:
In tensor.py you add the following function:

def W_to_tensor(arity: int) -> np.ndarray:
    m = np.zeros([2]*arity,dtype=complex)
    if arity == 0: # not sure what this should be
        return m # Maybe just a zero scalar?
    for i in range(arity):
        index = (0,)*n
        index[i] = 1
        m[index] = 1
    return m

This should be giving the tensor of the flexsymmetric W-spider (double-check that the 0-arity one should be the zero scalar).
Then in the function tensorfy we need to make sure it understands what to do with W-spiders (this is untested code so might not actually work).

You see the part where it says:

if types[v] == 1:
    t = Z_to_tensor(d,phase)
elif types[v] == 2:
    t = X_to_tensor(d,phase)
elif types[v] == 3:
    t = H_to_tensor(d,phase)

You just add the case here for W_to_tensor for the W_OUTPUT.
Then the best way to deal with W_INPUT is I think to treat it as an identity spider (and hence add it to the special case above as a Z_to_tensor with a phase of zero), and then do special behaviour for the W_EDGE that is in between them (namely, to interpret this edge as the NOT instead of W_INPUT). This special behaviour could be implemented at the lines

for n in nn:
    if ety[n] == EdgeType.HADAMARD:
        t = np.tensordot(t,had,(0,0)) # Hadamard edges are moved to the last index of t

If we define a tensor not = np.array([[0,1],[1,0]]), we can just a special case here for if ety[n] == EdgeType.W_EDGE, and it should just work I think?

You probably also want to include some sanity checks, like making sure the arity of W_INPUT is 2, and that its phase is zero, and also that the phase of the W_OUTPUT is zero.

Does that all make sense?

@RazinShaikh
Copy link
Contributor Author

Thanks, the strategy makes sense. I don't fully understand the W_to_tensor method. Can you clarify what n is in the code below?

def W_to_tensor(arity: int) -> np.ndarray:
    m = np.zeros([2]*arity,dtype=complex)
    if arity == 0: # not sure what this should be
        return m # Maybe just a zero scalar?
    for i in range(arity):
        index = (0,)*n # What is n?
        index[i] = 1
        m[index] = 1
    return m

@jvdwetering
Copy link
Collaborator

Oh woops, that n should be arity. This method essentially builds the state vector of the W, which is a superposition of all the |00..100> states, so at that index we need to put a 1 into the tensor.

@RazinShaikh
Copy link
Contributor Author

great, that makes sense

@RazinShaikh
Copy link
Contributor Author

RazinShaikh commented Aug 15, 2023

Also, I realized that W with one input and one output is just a NOT gate. So, it makes sense to use the same method for W_INPUT and W_OUTPUT.

image

@RazinShaikh
Copy link
Contributor Author

Just pushed W_to_tensor and verified that it gives the right answer.

@jvdwetering
Copy link
Collaborator

Nice! So do you think everything is implemented and working now? If it is not too much bother, you could also make a Jupyter notebook in the demos folder demonstrating how the W-spider works. In any case at some points the docs should be updated, because this is yet again a feature that does not appear anywhere in the docs.

pyzx/rules.py Outdated Show resolved Hide resolved
@RazinShaikh
Copy link
Contributor Author

RazinShaikh commented Aug 17, 2023

Yeah, everything is now implemented. I want to implement more rules such as ZW bialgebra, trialgebra, WW (almost) bialgebra, and Z copying through W but I would prefer to do that gradually. For now, there isn't too much to show in a demo jupyter notebook. I can create a notebook that shows how to build diagrams with W and demonstrate the fusion rule.

@RazinShaikh
Copy link
Contributor Author

I have added a demo notebook and also made the drawing slightly better.

@RazinShaikh
Copy link
Contributor Author

RazinShaikh commented Aug 18, 2023

I added w fusion to basicrules.py, which means we can drag and drop w nodes in zxlive to fuse them.

@jvdwetering
Copy link
Collaborator

Alright, so is this ready to merge now?

@RazinShaikh
Copy link
Contributor Author

Yes, looks good to me

@jvdwetering jvdwetering merged commit 41b8be2 into zxcalc:master Aug 18, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants