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

Export morphisms to JSON #8

Merged
merged 10 commits into from
Sep 28, 2023
Merged

Export morphisms to JSON #8

merged 10 commits into from
Sep 28, 2023

Conversation

TKuh
Copy link
Contributor

@TKuh TKuh commented Aug 25, 2023

This is very rudimentary right now.

A problem is, that the annotations in the JSON format are not optional:
https://github.com/Quantomatic/pyzx/blob/18e0a4d3004f5972afcb4a33de7d325df6c539f7/pyzx/graph/jsonparser.py#L62
(Even though it's stated in their documentation to be optional, it's probably too old...)

And this is a reason for failure:

gap tst/CategoryOfZXDiagrams.tst 

gap> ExportAsQGraph( H, "H" );

Produces a file H.qgraph:

{
  "node_vertices": {
    "0": {
      "data": {
        "type": "input"
      }
    },
    "1": {
      "data": {
        "type": "H"
      }
    },
    "2": {
      "data": {
        "type": "output"
      }
    }
  },
  "undir_edges": {
    "E01": {
      "src": 0,
      "tgt": 1
    },
    "E12": {
      "src": 1,
      "tgt": 2
    }
  }
}

Trying to load it in Python:

>>> import pyzx as zx
>>> with open("H.qgraph") as file:
...     json = file.read()
... 
>>> zx.Graph.from_json(json)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/tom/Software/Python/lib/python3.11/site-packages/pyzx/graph/base.py", line 474, in from_json
    return json_to_graph(js,cls.backend)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/tom/Software/Python/lib/python3.11/site-packages/pyzx/graph/jsonparser.py", line 62, in json_to_graph
    c = attr['annotation']['coord']
        ~~~~^^^^^^^^^^^^^^
KeyError: 'annotation'

I have not tested setting the annotations to a fixed value (or something else), because I don't know if this is even desirable.
Also, I barely understand the various node/vertex types and which ones have to be chosen for the JSON. Right now, I'm only making a guess from examples I've found.

We have to talk about this in person next week, I would rather not have to dig through the ZX-Calculus, because that likely takes too much time.

@zickgraf
Copy link
Member

Thanks for the progress so far, this already looks very promising :-)

@TKuh
Copy link
Contributor Author

TKuh commented Sep 1, 2023

Some things I noticed:

  1. Hadamard nodes can have an attribute is_edge (see here)
  2. There are also W_input/W_output node vertices. (see here)

I don't know if this is important, I just wanted to point this out to you.

Other than that, the JSON's of the morphisms from CategoryOfZXDiagrams.tst are all accepted by PyZX. :)

gap> ExportAsQGraph( H, "H" );
gap> ExportAsQGraph( X_1_1, "X" );
gap> ExportAsQGraph( Z_1_1, "Z" );

gap> precomp := PreCompose( ev, coev );
gap> pre2 := PreCompose( coev, ev );
gap> ExportAsQGraph( precomp, "precomp" );
gap> ExportAsQGraph( pre2, "precomp2" );
import pyzx as zx

for name in [ "X.qgraph", "Z.qgraph", "H.qgraph", "precomp.qgraph", "precomp2.qgraph" ]:
     with open( name ) as file:
          json = file.read()
          zx.Graph.from_json(json)

@TKuh TKuh marked this pull request as ready for review September 1, 2023 13:52
Copy link
Member

@zickgraf zickgraf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, that already looks very nice :-) Some code comments below. A functional comment will follow below.

gap/Tools.gi Outdated Show resolved Hide resolved
gap/Tools.gi Outdated Show resolved Hide resolved
gap/Tools.gi Outdated Show resolved Hide resolved
@zickgraf
Copy link
Member

zickgraf commented Sep 8, 2023

  • Hadamard nodes can have an attribute is_edge (see here)

I just played with this a bit and now I know what it does: Hadamard nodes are always connected to exactly two edges. So for visualization, instead of drawing a Hadamard node, sometimes a single blue edge is printed. This is what this flag does. We do not need it.

  • There are also W_input/W_output node vertices. (see here)

That's an extension of the ZX-calculus which we currently do not need.

All of this already seems to work quite well, but PyZX has a weird autodetection of inputs and outputs from the coordinates (input nodes are drawn on the left, output nodes on the right). This autodetection seems to kick in when using the json import, and then the information about inputs and outputs is lost. You can see this with print(zx.Graph.from_json(json).to_json()).

Maybe you can have a look at the code and see if one can avoid this automatic detection? Or we simply draw all inputs to the left and all outputs to the right. Then it would also be nice to spread out the nodes a bit (a simple counter for the y-coordinate should suffice).

Thanks for the work :-)

gap/Tools.gi Show resolved Hide resolved
gap/Tools.gi Outdated Show resolved Hide resolved
@TKuh TKuh force-pushed the export branch 2 times, most recently from 8dd9925 to 80770fd Compare September 16, 2023 09:13
@TKuh
Copy link
Contributor Author

TKuh commented Sep 16, 2023

All of this already seems to work quite well, but PyZX has a weird autodetection of inputs and outputs from the coordinates (input nodes are drawn on the left, output nodes on the right). This autodetection seems to kick in when using the json import, and then the information about inputs and outputs is lost.

It turned out that this information is not read, because json_to_graph expects the input/output field to be inside the annotation field. Now it's imported correctly. If you prefer, I can also adjust the coordinates.

Another thing is this:

gap ./tst/CategoryOfZXDiagrams.tst

gap> precomp := PreCompose( ev, coev );
gap> ExportAsQGraph( precomp, "precomp" );

The above gives the following edges:

"undir_edges": {
    "e0": {
      "src": "0",
      "tgt": "5"
    },
    "e1": {
      "src": "1",
      "tgt": "4"
    },
    "e2": {
      "src": "2",
      "tgt": "3"
    },
    "e3": {
      "src": "6",
      "tgt": "11"
    },
    "e4": {
      "src": "7",
      "tgt": "10"
    },
    "e5": {
      "src": "8",
      "tgt": "9"
    }
  },

After print(zx.Graph.from_json(json).to_json()) some edges have their sources and targets swapped:

"undir_edges": {
    "e0": {
      "src": "0",
      "tgt": "5"
    },
    "e1": {
      "src": "1",
      "tgt": "4"
    },
    "e2": {
      "src": "10",
      "tgt": "7"
    },
    "e3": {
      "src": "11",
      "tgt": "6"
    },
    "e4": {
      "src": "2",
      "tgt": "3"
    },
    "e5": {
      "src": "8",
      "tgt": "9"
    }
  },

I suspect it's because of this call
https://github.com/Quantomatic/pyzx/blob/a215056115e7103c5bc492cef1d21bc121ff1dad/pyzx/graph/jsonparser.py#L152

From the documentation of ‎add_edge_table‎: "[...] The method selectively adds or removes edges to produce that ZX diagram which would result from adding (#edges, #h-edges), and then removing all parallel edges using Hopf/spider laws."

Copy link
Member

@zickgraf zickgraf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It turned out that this information is not read, because json_to_graph expects the input/output field to be inside the annotation field. Now it's imported correctly. If you prefer, I can also adjust the coordinates.

Perfect, then we do not need the coordinates.

After print(zx.Graph.from_json(json).to_json()) some edges have their sources and targets swapped:

The semantics do not care about the direction of edges, so that should be fine.

gap/Tools.gi Show resolved Hide resolved
gap/Tools.gd Show resolved Hide resolved
gap/Tools.gi Outdated Show resolved Hide resolved
@zickgraf
Copy link
Member

Ah, the CI does not run because you are a first-time contributor. Usually there is a button to trigger the CI manually, but I cannot find it. Please make sure make ci-test succeeds.

@TKuh
Copy link
Contributor Author

TKuh commented Sep 18, 2023

Ah, the CI does not run because you are a first-time contributor. Usually there is a button to trigger the CI manually, but I cannot find it. Please make sure make ci-test succeeds.

I get this Julia error at the end:

git clone https://github.com/zickgraf/ZXCalculusForCAP.jl.git ~/.julia/dev/ZXCalculusForCAP
Cloning into '/home/tom/.julia/dev/ZXCalculusForCAP'...
remote: Enumerating objects: 24, done.
remote: Counting objects: 100% (24/24), done.
remote: Compressing objects: 100% (21/21), done.
remote: Total 24 (delta 1), reused 24 (delta 1), pack-reused 0
Receiving objects: 100% (24/24), 21.28 KiB | 807.00 KiB/s, done.
Resolving deltas: 100% (1/1), done.
~/.gap/pkg/PackageJanitor/gap_to_julia CAP
rm: cannot remove '/home/tom/.julia/dev/CAP/docs/src/cap20.tst.autogen.md': No such file or directory
make: *** [makefile:71: test-gap_to_julia] Error 1

@zickgraf
Copy link
Member

I think I will take over at this point: I will push some cleanups and then work on some subtleties for PyZX. PyZX has more quirks then expected, and fixing them on the fly is more efficient than communicating back and forth.

Thanks a lot for the work!

Tom Kuhmichel and others added 7 commits September 28, 2023 12:00
This reverts commit 11cd1a9.

The constructed morphism does not define a ZX diagram.
IsWellDefinedForMorphisms has to be reworked.
just like PyZX does
In the ZX calculus, Z always comes first.
@codecov
Copy link

codecov bot commented Sep 28, 2023

Codecov Report

Attention: 3 lines in your changes are missing coverage. Please review.

Files Coverage Δ
PackageInfo.g 100.00% <100.00%> (ø)
gap/CategoryOfZXDiagrams.gd 100.00% <100.00%> (ø)
gap/Tools.gd 100.00% <100.00%> (ø)
init.g 100.00% <100.00%> (ø)
read.g 100.00% <100.00%> (ø)
gap/Tools.gi 97.87% <97.87%> (ø)
gap/CategoryOfZXDiagrams.gi 90.19% <96.42%> (+5.06%) ⬆️

📢 Thoughts on this report? Let us know!.

@zickgraf zickgraf merged commit 9be22d3 into homalg-project:master Sep 28, 2023
4 checks passed
@TKuh TKuh deleted the export branch September 28, 2023 13:43
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