Current section
4 Versions
Jump to
Current section
4 Versions
Compare versions
32
files changed
+3140
additions
-567
deletions
| @@ -289,9 +289,19 @@ let gdf_string = gdf.serialize_with(node_attr, edge_attr, options, graph) | |
| 289 289 | |
| 290 290 | ### JSON Format |
| 291 291 | |
| 292 | - JSON format export for web visualization libraries and data exchange. Supports multiple format presets for popular visualization tools. |
| 292 | + JSON format export for web visualization libraries and data exchange. Provides multiple format presets for popular visualization tools and supports full bidirectional I/O. |
| 293 293 | |
| 294 | - **Note:** The JSON module is currently write-only. Import/read functionality is not implemented. For bidirectional I/O, consider using GraphML, GDF, TGF, LEDA, or Pajek formats. |
| 294 | + ```gleam |
| 295 | + import yog/model.{Directed} |
| 296 | + import yog_io/json |
| 297 | + import gleam/dynamic/decode |
| 298 | + |
| 299 | + // Export to JSON string |
| 300 | + let json_string = json.to_json(graph, json.default_export_options()) |
| 301 | + |
| 302 | + // Import from JSON string |
| 303 | + let assert Ok(graph) = json.from_json(json_string, decode.string, decode.string) |
| 304 | + ``` |
| 295 305 | |
| 296 306 | ```gleam |
| 297 307 | import yog/model.{Directed} |
| @@ -501,7 +511,7 @@ See [test/examples/multigraph_json_example.gleam](https://github.com/code-shoily | |
| 501 511 | | `yog_io/tgf` | TGF (Trivial Graph Format) serialization and parsing | |
| 502 512 | | `yog_io/leda` | LEDA format with strict validation | |
| 503 513 | | `yog_io/pajek` | Pajek (.net) format for social network analysis | |
| 504 | - | `yog_io/json` | JSON export with multiple format presets and MultiGraph support (WRITE-ONLY) | |
| 514 | + | `yog_io/json` | JSON format support with multiple presets and MultiGraph support | |
| 505 515 | | `yog_io/graphml` | Full GraphML support with custom mappers | |
| 506 516 | | `yog_io/gdf` | Full GDF support with custom mappers | |
| 507 517 | |
| @@ -537,7 +547,7 @@ See [test/examples/multigraph_json_example.gleam](https://github.com/code-shoily | |
| 537 547 | |
| 538 548 | ### JSON |
| 539 549 | |
| 540 | - **Note:** JSON module is currently WRITE-ONLY. Import/read functionality is not implemented. |
| 550 | + JSON module provides comprehensive support for common web-based graph formats with full bidirectional I/O. |
| 541 551 | |
| 542 552 | - âś… Generic format with full metadata |
| 543 553 | - âś… D3.js force-directed format |
| @@ -545,11 +555,11 @@ See [test/examples/multigraph_json_example.gleam](https://github.com/code-shoily | |
| 545 555 | - âś… vis.js network format |
| 546 556 | - âś… NetworkX node-link format |
| 547 557 | - âś… MultiGraph support with unique edge IDs |
| 548 | - - âś… Custom node and edge serializers |
| 558 | + - âś… Custom node and edge serializers/decoders |
| 549 559 | - âś… Generic type support (not limited to String) |
| 550 | - - âś… File write operations |
| 560 | + - âś… File read and write operations |
| 551 561 | - âś… Custom metadata fields |
| 552 | - - ❌ Import/read operations (not implemented) |
| 562 | + - âś… Graph import and deserialization |
| 553 563 | |
| 554 564 | ### GraphML |
| 555 565 | |
| @@ -581,7 +591,7 @@ See [test/examples/multigraph_json_example.gleam](https://github.com/code-shoily | |
| 581 591 | | GraphML | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | |
| 582 592 | | GDF | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | |
| 583 593 | |
| 584 | - **Note:** JSON format is write-only (export only). All other formats support bidirectional read/write operations. |
| 594 | + All formats now support bidirectional read/write operations. |
| 585 595 | |
| 586 596 | ## File Format Examples |
| 587 597 | |
| @@ -701,6 +711,38 @@ Run a specific test function: | |
| 701 711 | ./test_module.sh yog_io/json_test to_json_generic_format_test |
| 702 712 | ``` |
| 703 713 | |
| 714 | + ### Property-Based Tests |
| 715 | + |
| 716 | + In addition to traditional example-based tests, `yog_io` includes property-based tests using [qcheck](https://hex.pm/packages/qcheck). These tests generate random graphs and verify roundtrip invariants: |
| 717 | + |
| 718 | + ```bash |
| 719 | + # Run all tests (including property tests) |
| 720 | + gleam test |
| 721 | + |
| 722 | + # Run specific property test |
| 723 | + gleam test yog_io@property_test.graphml_structural_roundtrip_property_test |
| 724 | + ``` |
| 725 | + |
| 726 | + **Key Properties Verified:** |
| 727 | + |
| 728 | + | Property | Description | |
| 729 | + |----------|-------------| |
| 730 | + | Structural Equality | Complete graph topology preserved (GraphML, JSON) | |
| 731 | + | Node Count | Number of nodes unchanged after roundtrip | |
| 732 | + | Edge Count | Number of edges unchanged after roundtrip | |
| 733 | + | Graph Type | Directed/Undirected property maintained | |
| 734 | + | Undirected Symmetry | For undirected graphs, edge(u,v) implies edge(v,u) | |
| 735 | + |
| 736 | + **Format Limitations:** |
| 737 | + |
| 738 | + Not all formats support complete structural equality: |
| 739 | + |
| 740 | + - **Full Support**: GraphML, JSON (Generic format) |
| 741 | + - **Partial Support**: GDF (empty graphs), TGF (auto-node creation) |
| 742 | + - **No Support**: LEDA, Pajek (node IDs renumbered to 1, 2, 3...) |
| 743 | + |
| 744 | + See [PROPERTY_TESTS.md](PROPERTY_TESTS.md) for detailed documentation on invariants, hypotheses, and limitations. |
| 745 | + |
| 704 746 | ### Running Examples |
| 705 747 | |
| 706 748 | Run all examples at once: |
| @@ -1,8 +1,8 @@ | |
| 1 1 | name = "yog_io" |
| 2 | - version = "1.0.0" |
| 2 | + version = "1.1.0" |
| 3 3 | |
| 4 4 | targets = ["erlang", "javascript"] |
| 5 | - description = "Graph file format I/O for the yog graph library - GraphML, GDF, and JSON support with multiple format presets for web visualization" |
| 5 | + description = "Comprehensive graph file format I/O for the yog graph library - Support for GraphML, GDF, JSON (D3, Cytoscape, VisJs), TGF, LEDA, Pajek, Adjacency List/Matrix, and Matrix Market" |
| 6 6 | licences = ["Apache-2.0"] |
| 7 7 | repository = { type = "github", user = "code-shoily", repo = "yog_io" } |
| 8 8 | links = [{ title = "Website", href = "https://github.com/code-shoily/yog_io" }] |
| @@ -13,10 +13,11 @@ gleam_regexp = ">= 1.0.0 and < 2.0.0" | |
| 13 13 | gleam_json = ">= 3.0.0 and < 4.0.0" |
| 14 14 | simplifile = ">= 1.0.0 and < 3.0.0" |
| 15 15 | xmlm = ">= 1.0.1 and < 2.0.0" |
| 16 | - yog = ">= 5.1.0 and < 6.0.0" |
| 16 | + yog = ">= 5.1.1 and < 6.0.0" |
| 17 17 | |
| 18 18 | [dev_dependencies] |
| 19 19 | gleeunit = ">= 1.0.0 and < 2.0.0" |
| 20 | + qcheck = ">= 1.0.0 and < 2.0.0" |
| 20 21 | |
| 21 22 | [javascript] |
| 22 23 | typescript_declarations = true |
| \ No newline at end of file |
| @@ -1,7 +1,7 @@ | |
| 1 1 | {<<"name">>, <<"yog_io">>}. |
| 2 2 | {<<"app">>, <<"yog_io">>}. |
| 3 | - {<<"version">>, <<"1.0.0">>}. |
| 4 | - {<<"description">>, <<"Graph file format I/O for the yog graph library - GraphML, GDF, and JSON support with multiple format presets for web visualization"/utf8>>}. |
| 3 | + {<<"version">>, <<"1.1.0">>}. |
| 4 | + {<<"description">>, <<"Comprehensive graph file format I/O for the yog graph library - Support for GraphML, GDF, JSON (D3, Cytoscape, VisJs), TGF, LEDA, Pajek, Adjacency List/Matrix, and Matrix Market"/utf8>>}. |
| 5 5 | {<<"licenses">>, [<<"Apache-2.0">>]}. |
| 6 6 | {<<"build_tools">>, [<<"gleam">>]}. |
| 7 7 | {<<"links">>, [ |
| @@ -9,30 +9,30 @@ | |
| 9 9 | {<<"Repository">>, <<"https://github.com/code-shoily/yog_io">>} |
| 10 10 | ]}. |
| 11 11 | {<<"requirements">>, [ |
| 12 | - {<<"gleam_stdlib">>, [ |
| 13 | - {<<"app">>, <<"gleam_stdlib">>}, |
| 14 | - {<<"optional">>, false}, |
| 15 | - {<<"requirement">>, <<">= 0.69.0 and < 1.0.0">>} |
| 16 | - ]}, |
| 17 12 | {<<"yog">>, [ |
| 18 13 | {<<"app">>, <<"yog">>}, |
| 19 14 | {<<"optional">>, false}, |
| 20 | - {<<"requirement">>, <<">= 5.1.0 and < 6.0.0">>} |
| 15 | + {<<"requirement">>, <<">= 5.1.1 and < 6.0.0">>} |
| 21 16 | ]}, |
| 22 17 | {<<"gleam_regexp">>, [ |
| 23 18 | {<<"app">>, <<"gleam_regexp">>}, |
| 24 19 | {<<"optional">>, false}, |
| 25 20 | {<<"requirement">>, <<">= 1.0.0 and < 2.0.0">>} |
| 26 21 | ]}, |
| 22 | + {<<"xmlm">>, [ |
| 23 | + {<<"app">>, <<"xmlm">>}, |
| 24 | + {<<"optional">>, false}, |
| 25 | + {<<"requirement">>, <<">= 1.0.1 and < 2.0.0">>} |
| 26 | + ]}, |
| 27 27 | {<<"gleam_json">>, [ |
| 28 28 | {<<"app">>, <<"gleam_json">>}, |
| 29 29 | {<<"optional">>, false}, |
| 30 30 | {<<"requirement">>, <<">= 3.0.0 and < 4.0.0">>} |
| 31 31 | ]}, |
| 32 | - {<<"xmlm">>, [ |
| 33 | - {<<"app">>, <<"xmlm">>}, |
| 32 | + {<<"gleam_stdlib">>, [ |
| 33 | + {<<"app">>, <<"gleam_stdlib">>}, |
| 34 34 | {<<"optional">>, false}, |
| 35 | - {<<"requirement">>, <<">= 1.0.1 and < 2.0.0">>} |
| 35 | + {<<"requirement">>, <<">= 0.69.0 and < 1.0.0">>} |
| 36 36 | ]}, |
| 37 37 | {<<"simplifile">>, [ |
| 38 38 | {<<"app">>, <<"simplifile">>}, |
| @@ -64,6 +64,19 @@ | |
| 64 64 | <<"include/yog_io@leda_NodeIdOutOfRange.hrl">>, |
| 65 65 | <<"include/yog_io@leda_ReadError.hrl">>, |
| 66 66 | <<"include/yog_io@leda_WriteError.hrl">>, |
| 67 | + <<"include/yog_io@list_ListOptions.hrl">>, |
| 68 | + <<"include/yog_io@list_ParseError.hrl">>, |
| 69 | + <<"include/yog_io@list_ReadError.hrl">>, |
| 70 | + <<"include/yog_io@list_WriteError.hrl">>, |
| 71 | + <<"include/yog_io@matrix_NotSquare.hrl">>, |
| 72 | + <<"include/yog_io@matrix_ReadError.hrl">>, |
| 73 | + <<"include/yog_io@matrix_WriteError.hrl">>, |
| 74 | + <<"include/yog_io@matrix_market_InvalidHeader.hrl">>, |
| 75 | + <<"include/yog_io@matrix_market_InvalidSizeLine.hrl">>, |
| 76 | + <<"include/yog_io@matrix_market_MatrixMarketResult.hrl">>, |
| 77 | + <<"include/yog_io@matrix_market_MissingHeader.hrl">>, |
| 78 | + <<"include/yog_io@matrix_market_ReadError.hrl">>, |
| 79 | + <<"include/yog_io@matrix_market_WriteError.hrl">>, |
| 67 80 | <<"include/yog_io@pajek_InvalidArcLine.hrl">>, |
| 68 81 | <<"include/yog_io@pajek_InvalidNodeId.hrl">>, |
| 69 82 | <<"include/yog_io@pajek_InvalidSectionHeader.hrl">>, |
| @@ -92,12 +105,18 @@ | |
| 92 105 | <<"src/yog_io/graphml.gleam">>, |
| 93 106 | <<"src/yog_io/json.gleam">>, |
| 94 107 | <<"src/yog_io/leda.gleam">>, |
| 108 | + <<"src/yog_io/list.gleam">>, |
| 109 | + <<"src/yog_io/matrix.gleam">>, |
| 110 | + <<"src/yog_io/matrix_market.gleam">>, |
| 95 111 | <<"src/yog_io/pajek.gleam">>, |
| 96 112 | <<"src/yog_io/tgf.gleam">>, |
| 97 113 | <<"src/yog_io@gdf.erl">>, |
| 98 114 | <<"src/yog_io@graphml.erl">>, |
| 99 115 | <<"src/yog_io@json.erl">>, |
| 100 116 | <<"src/yog_io@leda.erl">>, |
| 117 | + <<"src/yog_io@list.erl">>, |
| 118 | + <<"src/yog_io@matrix.erl">>, |
| 119 | + <<"src/yog_io@matrix_market.erl">>, |
| 101 120 | <<"src/yog_io@pajek.erl">>, |
| 102 121 | <<"src/yog_io@tgf.erl">> |
| 103 122 | ]}. |
| @@ -0,0 +1 @@ | |
| 1 | + -record(list_options, {weighted :: boolean(), delimiter :: binary()}). |
| @@ -0,0 +1 @@ | |
| 1 | + -record(parse_error, {line :: integer(), content :: binary()}). |
Loading more files…