tensor-network-visualization 1.4.1__tar.gz → 1.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. {tensor_network_visualization-1.4.1/src/tensor_network_visualization.egg-info → tensor_network_visualization-1.5.0}/PKG-INFO +127 -59
  2. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/README.md +119 -55
  3. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/pyproject.toml +21 -7
  4. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0/src/tensor_network_visualization.egg-info}/PKG-INFO +127 -59
  5. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_visualization.egg-info/SOURCES.txt +30 -3
  6. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_visualization.egg-info/requires.txt +2 -0
  7. tensor_network_visualization-1.5.0/src/tensor_network_viz/__init__.py +59 -0
  8. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/axis_directions.py +10 -0
  9. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/contractions.py +122 -122
  10. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/draw/constants.py +5 -2
  11. tensor_network_visualization-1.5.0/src/tensor_network_viz/_core/draw/contraction_edges.py +149 -0
  12. tensor_network_visualization-1.5.0/src/tensor_network_viz/_core/draw/contraction_scheme.py +282 -0
  13. tensor_network_visualization-1.5.0/src/tensor_network_viz/_core/draw/dangling_self_edges.py +445 -0
  14. tensor_network_visualization-1.5.0/src/tensor_network_viz/_core/draw/edge_labels.py +139 -0
  15. tensor_network_visualization-1.5.0/src/tensor_network_viz/_core/draw/edge_orchestration.py +214 -0
  16. tensor_network_visualization-1.5.0/src/tensor_network_viz/_core/draw/edges.py +16 -0
  17. tensor_network_visualization-1.5.0/src/tensor_network_viz/_core/draw/graph_pipeline.py +275 -0
  18. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/draw/hover.py +412 -250
  19. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/draw/plotter.py +304 -285
  20. tensor_network_visualization-1.5.0/src/tensor_network_viz/_core/draw/render_prep.py +410 -0
  21. tensor_network_visualization-1.5.0/src/tensor_network_viz/_core/draw/scene_state.py +51 -0
  22. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/draw/tensors.py +2 -1
  23. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/draw/viewport_geometry.py +7 -0
  24. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/graph.py +48 -0
  25. tensor_network_visualization-1.5.0/src/tensor_network_viz/_core/layout/body.py +150 -0
  26. tensor_network_visualization-1.5.0/src/tensor_network_viz/_core/layout/direction_common.py +477 -0
  27. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/layout/force_directed.py +7 -5
  28. tensor_network_visualization-1.5.0/src/tensor_network_viz/_core/layout/free_directions_2d.py +493 -0
  29. tensor_network_visualization-1.5.0/src/tensor_network_viz/_core/layout/free_directions_3d.py +250 -0
  30. tensor_network_visualization-1.5.0/src/tensor_network_viz/_core/layout/geometry.py +382 -0
  31. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/layout/parameters.py +20 -0
  32. tensor_network_visualization-1.5.0/src/tensor_network_viz/_core/layout/positions.py +802 -0
  33. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/layout_structure.py +8 -4
  34. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/renderer.py +66 -13
  35. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_registry.py +6 -0
  36. tensor_network_visualization-1.5.0/src/tensor_network_viz/_typing.py +25 -0
  37. tensor_network_visualization-1.5.0/src/tensor_network_viz/config.py +128 -0
  38. tensor_network_visualization-1.5.0/src/tensor_network_viz/contraction_viewer.py +1007 -0
  39. tensor_network_visualization-1.5.0/src/tensor_network_viz/einsum_module/__init__.py +46 -0
  40. tensor_network_visualization-1.5.0/src/tensor_network_viz/einsum_module/_equation.py +332 -0
  41. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/einsum_module/_trace_state.py +72 -44
  42. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/einsum_module/_trace_types.py +15 -2
  43. tensor_network_visualization-1.5.0/src/tensor_network_viz/einsum_module/contraction_cost.py +79 -0
  44. tensor_network_visualization-1.5.0/src/tensor_network_viz/einsum_module/graph.py +309 -0
  45. tensor_network_visualization-1.5.0/src/tensor_network_viz/einsum_module/trace.py +148 -0
  46. tensor_network_visualization-1.5.0/src/tensor_network_viz/interactive_viewer.py +595 -0
  47. tensor_network_visualization-1.5.0/src/tensor_network_viz/quimb/__init__.py +32 -0
  48. tensor_network_visualization-1.5.0/src/tensor_network_viz/tenpy/__init__.py +37 -0
  49. tensor_network_visualization-1.5.0/src/tensor_network_viz/tenpy/explicit.py +73 -0
  50. tensor_network_visualization-1.5.0/src/tensor_network_viz/tenpy/graph.py +184 -0
  51. tensor_network_visualization-1.5.0/src/tensor_network_viz/tensorkrowch/__init__.py +32 -0
  52. tensor_network_visualization-1.5.0/src/tensor_network_viz/tensornetwork/__init__.py +32 -0
  53. tensor_network_visualization-1.5.0/src/tensor_network_viz/viewer.py +224 -0
  54. tensor_network_visualization-1.5.0/tests/test_ci_workflow.py +26 -0
  55. tensor_network_visualization-1.5.0/tests/test_contraction_cost.py +111 -0
  56. tensor_network_visualization-1.5.0/tests/test_contraction_scheme.py +141 -0
  57. tensor_network_visualization-1.5.0/tests/test_contraction_viewer.py +567 -0
  58. tensor_network_visualization-1.5.0/tests/test_demo_cli_scheme.py +270 -0
  59. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/tests/test_draw_performance.py +0 -42
  60. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/tests/test_einsum_autotrace.py +80 -19
  61. tensor_network_visualization-1.5.0/tests/test_einsum_backend.py +400 -0
  62. tensor_network_visualization-1.5.0/tests/test_engine_detection.py +123 -0
  63. tensor_network_visualization-1.5.0/tests/test_engineering_baseline.py +138 -0
  64. tensor_network_visualization-1.5.0/tests/test_examples.py +331 -0
  65. tensor_network_visualization-1.5.0/tests/test_examples_structure.py +38 -0
  66. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/tests/test_layout_core.py +455 -0
  67. tensor_network_visualization-1.5.0/tests/test_lazy_imports.py +40 -0
  68. tensor_network_visualization-1.5.0/tests/test_packaging_metadata.py +29 -0
  69. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/tests/test_plotting.py +504 -16
  70. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/tests/test_public_api.py +24 -2
  71. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/tests/test_quimb_backend.py +16 -6
  72. tensor_network_visualization-1.5.0/tests/test_render_performance_controls.py +162 -0
  73. tensor_network_visualization-1.5.0/tests/test_show_tensor_network_throughput.py +57 -0
  74. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/tests/test_tenpy_backend.py +146 -3
  75. tensor_network_visualization-1.5.0/tests/test_verify_script.py +24 -0
  76. tensor_network_visualization-1.4.1/src/tensor_network_viz/__init__.py +0 -26
  77. tensor_network_visualization-1.4.1/src/tensor_network_viz/_core/draw/edges.py +0 -697
  78. tensor_network_visualization-1.4.1/src/tensor_network_viz/_core/draw/graph_pipeline.py +0 -251
  79. tensor_network_visualization-1.4.1/src/tensor_network_viz/_core/layout/body.py +0 -1108
  80. tensor_network_visualization-1.4.1/src/tensor_network_viz/config.py +0 -89
  81. tensor_network_visualization-1.4.1/src/tensor_network_viz/einsum_module/__init__.py +0 -10
  82. tensor_network_visualization-1.4.1/src/tensor_network_viz/einsum_module/_equation.py +0 -61
  83. tensor_network_visualization-1.4.1/src/tensor_network_viz/einsum_module/graph.py +0 -175
  84. tensor_network_visualization-1.4.1/src/tensor_network_viz/einsum_module/trace.py +0 -100
  85. tensor_network_visualization-1.4.1/src/tensor_network_viz/quimb/__init__.py +0 -9
  86. tensor_network_visualization-1.4.1/src/tensor_network_viz/tenpy/__init__.py +0 -9
  87. tensor_network_visualization-1.4.1/src/tensor_network_viz/tenpy/graph.py +0 -156
  88. tensor_network_visualization-1.4.1/src/tensor_network_viz/tensorkrowch/__init__.py +0 -9
  89. tensor_network_visualization-1.4.1/src/tensor_network_viz/tensornetwork/__init__.py +0 -9
  90. tensor_network_visualization-1.4.1/src/tensor_network_viz/viewer.py +0 -93
  91. tensor_network_visualization-1.4.1/tests/test_einsum_backend.py +0 -155
  92. tensor_network_visualization-1.4.1/tests/test_examples.py +0 -361
  93. tensor_network_visualization-1.4.1/tests/test_integration_quimb.py +0 -41
  94. tensor_network_visualization-1.4.1/tests/test_integration_tenpy.py +0 -55
  95. tensor_network_visualization-1.4.1/tests/test_show_tensor_network_throughput.py +0 -120
  96. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/LICENSE +0 -0
  97. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/setup.cfg +0 -0
  98. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_visualization.egg-info/dependency_links.txt +0 -0
  99. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_visualization.egg-info/top_level.txt +0 -0
  100. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/__init__.py +0 -0
  101. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/_draw_common.py +0 -0
  102. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/_label_format.py +0 -0
  103. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/_nodes_edges_common.py +0 -0
  104. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/curves.py +0 -0
  105. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/draw/__init__.py +0 -0
  106. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/draw/disk_metrics.py +0 -0
  107. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/draw/fonts_and_scale.py +0 -0
  108. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/draw/labels_misc.py +0 -0
  109. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/draw/pick_distance.py +0 -0
  110. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/draw/vectors.py +0 -0
  111. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/graph_cache.py +0 -0
  112. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/graph_utils.py +0 -0
  113. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/layout/__init__.py +0 -0
  114. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_core/layout/types.py +0 -0
  115. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/_engine_specs.py +0 -0
  116. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/einsum_module/_backend.py +0 -0
  117. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/einsum_module/renderer.py +0 -0
  118. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/py.typed +0 -0
  119. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/quimb/graph.py +0 -0
  120. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/quimb/renderer.py +0 -0
  121. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/tenpy/renderer.py +0 -0
  122. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/tensorkrowch/graph.py +0 -0
  123. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/tensorkrowch/renderer.py +0 -0
  124. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/tensornetwork/graph.py +0 -0
  125. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/src/tensor_network_viz/tensornetwork/renderer.py +0 -0
  126. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/tests/test_contraction_groups_once.py +0 -0
  127. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/tests/test_edge_index_label_2d.py +0 -0
  128. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/tests/test_edge_index_label_3d.py +0 -0
  129. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/tests/test_graph_cache.py +0 -0
  130. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/tests/test_integration_einsum.py +0 -0
  131. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/tests/test_integration_tensorkrowch.py +0 -0
  132. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/tests/test_integration_tensornetwork.py +0 -0
  133. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/tests/test_label_draw_metrics_perf.py +0 -0
  134. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/tests/test_label_format.py +0 -0
  135. {tensor_network_visualization-1.4.1 → tensor_network_visualization-1.5.0}/tests/test_node_degrees_perf.py +0 -0
@@ -1,25 +1,29 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tensor-network-visualization
3
- Version: 1.4.1
3
+ Version: 1.5.0
4
4
  Summary: Minimal Matplotlib visualizations for TensorKrowch, TensorNetwork, Quimb, TeNPy, and traced PyTorch/NumPy einsum tensor networks.
5
5
  Author: Alejandro Mata Ali
6
- License: MIT
6
+ License-Expression: MIT
7
7
  Project-URL: Homepage, https://github.com/DOKOS-TAYOS/Tensor-Network-Visualization
8
8
  Project-URL: Documentation, https://github.com/DOKOS-TAYOS/Tensor-Network-Visualization/blob/main/docs/guide.md
9
9
  Project-URL: Changelog, https://github.com/DOKOS-TAYOS/Tensor-Network-Visualization/blob/main/CHANGELOG.md
10
10
  Project-URL: Repository, https://github.com/DOKOS-TAYOS/Tensor-Network-Visualization
11
11
  Project-URL: Issues, https://github.com/DOKOS-TAYOS/Tensor-Network-Visualization/issues
12
12
  Keywords: tensor-network,visualization,pytorch,numpy,tensorkrowch,tensornetwork,quimb,tenpy,einsum,quantum-inspired,matplotlib
13
- Classifier: License :: OSI Approved :: MIT License
14
13
  Classifier: Programming Language :: Python :: 3
15
14
  Classifier: Programming Language :: Python :: 3 :: Only
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
16
18
  Classifier: Topic :: Scientific/Engineering :: Visualization
17
- Requires-Python: >=3.10
19
+ Requires-Python: >=3.11
18
20
  Description-Content-Type: text/markdown
19
21
  License-File: LICENSE
20
22
  Requires-Dist: matplotlib>=3.7
21
23
  Requires-Dist: networkx>=3.0
24
+ Requires-Dist: numpy
22
25
  Provides-Extra: dev
26
+ Requires-Dist: build; extra == "dev"
23
27
  Requires-Dist: pytest; extra == "dev"
24
28
  Requires-Dist: ruff; extra == "dev"
25
29
  Requires-Dist: pyright; extra == "dev"
@@ -62,8 +66,9 @@ PyTorch/NumPy `einsum` tensor networks.
62
66
  Tensor network libraries use different object models and rarely share a single visualization path.
63
67
  This package **normalizes** each backend into one graph description, **lays out** nodes (chains,
64
68
  grids, trees, planar embeddings, or force-directed fallback), and **draws** with Matplotlib in
65
- **2D** (filled disks) or **3D** (lightweight octahedra). There is no custom GUI: you get standard
66
- `Figure` and `Axes` objects for saving, composing subplots, and further styling.
69
+ **2D** (filled disks) or **3D** (lightweight octahedra). The interactive layer stays inside
70
+ standard Matplotlib figures: `show_tensor_network` can add a small control panel, while the return
71
+ value is still a normal `Figure` plus `Axes` object that you can save, embed, or restyle.
67
72
 
68
73
  **Audience:** Researchers who work with tensor networks and want consistent, publication-friendly
69
74
  diagrams across Quimb, TeNPy, TensorNetwork, TensorKrowch, or traced `einsum` contraction graphs.
@@ -72,14 +77,19 @@ diagrams across Quimb, TeNPy, TensorNetwork, TensorKrowch, or traced `einsum` co
72
77
 
73
78
  PyPI package name: `tensor-network-visualization`. Import module: `tensor_network_viz`.
74
79
 
80
+ **Requires Python 3.11 or newer.**
81
+
75
82
  ### Base install
76
83
 
77
84
  ```bash
78
85
  python -m pip install tensor-network-visualization
79
86
  ```
80
87
 
81
- Depends on `matplotlib` and `networkx` only. You can render **`einsum`** traces built from ordered
82
- `pair_tensor` entries without installing PyTorch.
88
+ Base runtime dependencies are `numpy`, `matplotlib`, and `networkx` only. You can **build and
89
+ render** rich **`einsum`** graphs from ordered **`pair_tensor`** / **`einsum_trace_step`** entries
90
+ (ellipsis and repeated indices need shapes in metadata); **`tensor-network-visualization[einsum]`**
91
+ (PyTorch) is only needed to **execute** `tensor_network_viz.einsum(..., trace=...)` and record
92
+ those rows automatically.
83
93
 
84
94
  ### Optional backends (extras)
85
95
 
@@ -89,7 +99,7 @@ Depends on `matplotlib` and `networkx` only. You can render **`einsum`** traces
89
99
  | TensorNetwork | `tensornetwork` | `pip install "tensor-network-visualization[tensornetwork]"` |
90
100
  | Quimb | `quimb` | `pip install "tensor-network-visualization[quimb]"` |
91
101
  | TeNPy | `tenpy` | Resolves to PyPI package **`physics-tenpy`**. |
92
- | Einsum tracing | `einsum` | Adds **PyTorch** for the traced `einsum` helper. |
102
+ | Einsum tracing | `einsum` | Adds **PyTorch** for auto-traced `einsum(..., trace=...)` (layout from `pair_tensor` / `einsum_trace_step` lists with metadata as needed). |
93
103
  | Jupyter widgets| `jupyter` | `ipympl`, widgets, JupyterLab / Notebook 7+ for interactive figures. |
94
104
 
95
105
  Combine extras, for example:
@@ -143,12 +153,19 @@ Everything below maps to real parameters—there are no hidden mode switches.
143
153
 
144
154
  | Concept | Where | Meaning |
145
155
  |--------|--------|---------|
146
- | **View mode** | `show_tensor_network(..., view=...)` | `"2d"` — disk nodes; `"3d"` octahedra. Same normalized graph. |
147
- | **Engine mode** | `engine=...` | Adapter: `"tensorkrowch"`, `"tensornetwork"`, `"quimb"`, `"tenpy"`, `"einsum"`. Invalid `ValueError`. |
156
+ | **View mode** | `show_tensor_network(..., view=...)` | Default is `"2d"`; `"3d"` is available from the same figure controls when widgets are enabled. |
157
+ | **Engine mode** | `engine=...` | Optional override. When omitted, `show_tensor_network` auto-detects `"tensorkrowch"`, `"tensornetwork"`, `"quimb"`, `"tenpy"`, or `"einsum"` from the input. Invalid explicit values still raise `ValueError`. |
148
158
  | **Display mode** | `show=True` / `False` | If `True`: Jupyter **kernel** uses `IPython.display.display(fig)`; otherwise `plt.show()`. If `False`: neither runs—use for `savefig` / batch. |
149
- | **Label policy** | `PlotConfig` + overrides | Defaults: `show_tensor_labels`, `show_index_labels`. Per-call: `show_tensor_network(..., show_tensor_labels=..., show_index_labels=...)`. |
150
- | **Hover labels** | `PlotConfig(hover_labels=True)` | Tensor names and bond labels appear on pointer hover (2D axes hit-test; 3D screen-space distance). Needs an **interactive** Matplotlib window. |
151
- | **Einsum workflow** | `engine="einsum"` | **Auto:** `EinsumTrace` + `tensor_network_viz.einsum`. **Manual:** ordered list of `pair_tensor(...)`. |
159
+ | **Interactive controls** | `interactive_controls=True` | Figure-level Matplotlib widgets for view/hover/label toggles. Set `False` for clean static exports or headless batch rendering. |
160
+ | **Label policy** | `PlotConfig` + overrides | Defaults: `show_tensor_labels=False`, `show_index_labels=False`. Per-call: `show_tensor_network(..., show_tensor_labels=..., show_index_labels=...)`. |
161
+ | **Hover labels** | `PlotConfig(hover_labels=True)` | Default is `True`. Hover tooltips are independent from static labels, so both can stay enabled together in an interactive Matplotlib window. |
162
+ | **Contraction scheme** | `PlotConfig(show_contraction_scheme=True)` | **Einsum:** cumulative per-step highlights from the trace. **Other engines:** set **`contraction_scheme_by_name`**. Compatible figures now add Matplotlib toggles for **Scheme**, **Playback**, and **Cost hover**; if you start with those flags off, the scheme bundle is computed lazily on first use. **2D:** rounded boxes (AABB + pad); colored borders (no fill by default). **3D:** wireframe box. See **`docs/guide.md`**. |
163
+ | **Einsum workflow** | `engine="einsum"` | **Auto:** `EinsumTrace` + `einsum` (binary `pair_tensor`, unary/ternary+ `einsum_trace_step`; implicit `->`, `out=`). **Manual:** ordered `pair_tensor` / `einsum_trace_step` lists when you want a fully explicit trace. See **`examples/run_demo.py`** and **`examples/einsum_demo.py`**. |
164
+
165
+ `show_tensor_network` now creates figure-level Matplotlib widgets by default: a `2d/3d` selector on
166
+ figures it creates itself, plus `Hover`, `Tensor labels`, and `Edge labels` checkboxes. If you
167
+ pass an external `ax`, the same-view checkboxes stay available but the `2d/3d` selector is hidden.
168
+ The default widget state is `Hover=True`, `Tensor labels=False`, `Edge labels=False`.
152
169
 
153
170
  ## Minimal examples
154
171
 
@@ -171,13 +188,16 @@ network = qtn.TensorNetwork(tensors)
171
188
  fig, ax = show_tensor_network(
172
189
  network,
173
190
  engine="quimb",
174
- view="2d",
175
191
  config=PlotConfig(figsize=(8, 6)),
192
+ interactive_controls=False,
176
193
  show=False,
177
194
  )
178
195
  fig.savefig("network.png", bbox_inches="tight")
179
196
  ```
180
197
 
198
+ Use `interactive_controls=False` when you want the saved figure without the Matplotlib control
199
+ panel.
200
+
181
201
  ### Quimb 3D, hide index labels on this call only
182
202
 
183
203
  ```python
@@ -197,12 +217,12 @@ fig, ax = show_tensor_network(
197
217
  fig, ax = show_tensor_network(
198
218
  network,
199
219
  engine="quimb",
200
- view="2d",
201
220
  config=PlotConfig(figsize=(8, 6), hover_labels=True),
202
221
  )
203
222
  ```
204
223
 
205
- No effect for headless `show=False` without a GUI event loop; pair with an interactive backend
224
+ Hover is independent from static labels, so you can also enable tensor or edge labels from the
225
+ figure checkboxes without losing the hover tooltips. This still needs an interactive backend
206
226
  (e.g. `%matplotlib widget` in Jupyter).
207
227
 
208
228
  ### TeNPy finite MPS (sketch)
@@ -216,7 +236,6 @@ from tensor_network_viz import show_tensor_network, PlotConfig
216
236
  fig, ax = show_tensor_network(
217
237
  mps,
218
238
  engine="tenpy",
219
- view="2d",
220
239
  config=PlotConfig(figsize=(8, 6)),
221
240
  show=False,
222
241
  )
@@ -228,25 +247,30 @@ fig, ax = show_tensor_network(
228
247
  show_tensor_network(
229
248
  network,
230
249
  *,
231
- engine: EngineName,
232
- view: ViewName,
250
+ engine: EngineName | None = None,
251
+ view: ViewName | None = None,
233
252
  config: PlotConfig | None = None,
253
+ ax: Axes | Axes3D | None = None,
234
254
  show_tensor_labels: bool | None = None,
235
255
  show_index_labels: bool | None = None,
256
+ interactive_controls: bool = True,
236
257
  show: bool = True,
237
258
  ) -> tuple[Figure, Axes | Axes3D]
238
259
  ```
239
260
 
240
261
  - **`network`:** Backend-native object or iterable (see [guide — supported inputs](docs/guide.md)).
241
- - **`engine`:** `"tensorkrowch"` \| `"tensornetwork"` \| `"quimb"` \| `"tenpy"` \| `"einsum"`.
242
- - **`view`:** `"2d"` \| `"3d"`.
262
+ - **`engine`:** optional explicit override. If omitted, the backend is inferred from `network`.
263
+ - **`view`:** `"2d"` \| `"3d"`; omitted means `"2d"` unless a 3D `ax` is passed.
243
264
  - **`config`:** Styling and layout; defaults to `PlotConfig()` if omitted.
265
+ - **`ax`:** Optional Matplotlib axes. When present, rendering stays on that axes and the `2d/3d` selector is hidden.
244
266
  - **`show_tensor_labels` / `show_index_labels`:** If `None`, use values from `config`; else override for this call only.
267
+ - **`interactive_controls`:** If `True`, attach the view/hover/label widgets when the figure supports them. Set `False` for a static render.
245
268
  - **`show`:** Whether to push the figure to the current UI (`display`/`show`).
246
269
  - **Returns:** `(fig, ax)` for titles, `savefig`, colorbars, or embedding in a subplot.
247
270
 
248
271
  Backend-specific shortcuts (same renderer core) accept **`ax=`** and **`seed=`** for subplots and
249
- reproducible layout; see the [guide](docs/guide.md).
272
+ reproducible layout; they stay fixed-dimension helpers (`plot_*_network_2d` or `plot_*_network_3d`)
273
+ and do not add the `2d/3d` selector. See the [guide](docs/guide.md).
250
274
 
251
275
  ### `PlotConfig` quick reference
252
276
 
@@ -255,17 +279,17 @@ Numeric fields with **`None`** use the corresponding `DEFAULT_*` on the class (s
255
279
 
256
280
  | Field | Default | Role |
257
281
  |-------|---------|------|
258
- | `node_color` | `"#E8E8E8"` | Tensor node fill. |
259
- | `node_edge_color` | `"#2D3748"` | Tensor node outline. |
260
- | `node_color_degree_one` | `"#E8D6D6"` | Fill for tensors with total graph degree 1. |
261
- | `node_edge_color_degree_one` | `"#4A3436"` | Outline for degree-1 tensors. |
262
- | `tensor_label_color` | `"#1A202C"` | Tensor name text. |
263
- | `label_color` | `"#0C1319"` | Index / bond label text. |
264
- | `bond_edge_color` | `"#00008B"` | Contraction edges. |
265
- | `dangling_edge_color` | `"#8B0000"` | Dangling (open) legs. |
282
+ | `node_color` | `"#E8EEF5"` | Tensor node fill. |
283
+ | `node_edge_color` | `"#1E293B"` | Tensor node outline. |
284
+ | `node_color_degree_one` | `"#FEE2E2"` | Fill for tensors with total graph degree 1. |
285
+ | `node_edge_color_degree_one` | `"#7F1D1D"` | Outline for degree-1 tensors. |
286
+ | `tensor_label_color` | `"#0F172A"` | Tensor name text. |
287
+ | `label_color` | `"#334155"` | Index / bond label text. |
288
+ | `bond_edge_color` | `"#0369A1"` | Contraction edges. |
289
+ | `dangling_edge_color` | `"#BE123C"` | Dangling (open) legs. |
266
290
  | `figsize` | `(8, 6)` | `inches`; `None` uses Matplotlib fallback `(14, 10)` when the renderer creates a new figure. |
267
- | `show_tensor_labels` | `True` | Draw tensor names on nodes. |
268
- | `show_index_labels` | `True` | Draw axis names on bonds / stubs. |
291
+ | `show_tensor_labels` | `False` | Draw tensor names on nodes. |
292
+ | `show_index_labels` | `False` | Draw axis names on bonds / stubs. |
269
293
  | `node_radius` | `None` | → `0.08` data units (scaled with layout; multiplies geometric radius). |
270
294
  | `stub_length` | `None` | → `0.16` (dangling stub length scale). |
271
295
  | `self_loop_radius` | `None` | → `0.2` (self-contraction loops). |
@@ -275,7 +299,7 @@ Numeric fields with **`None`** use the corresponding `DEFAULT_*` on the class (s
275
299
  | `positions` | `None` | `dict[int, tuple[float, ...]]` — custom positions keyed by **normalized node id** (`id` of adapter node); partial dicts get layout for missing ids. |
276
300
  | `validate_positions` | `False` | If `True`, warn on unknown keys or short coordinates vs `view`. |
277
301
  | `refine_tensor_labels` | `True` | Extra passes to fit tensor names inside the node marker (2D or 3D); set `False` for speed. |
278
- | `hover_labels` | `False` | Hide labels until hover (interactive only). |
302
+ | `hover_labels` | `True` | Enable hover tooltips independently from static labels (interactive only). |
279
303
 
280
304
  Defaults `0.08`, `0.16`, `0.2`, `0.85`, `0.75`, `220` are also available as
281
305
  `PlotConfig.DEFAULT_NODE_RADIUS`, `DEFAULT_STUB_LENGTH`, `DEFAULT_SELF_LOOP_RADIUS`,
@@ -290,6 +314,7 @@ from tensor_network_viz import (
290
314
  PlotConfig,
291
315
  ViewName,
292
316
  einsum,
317
+ einsum_trace_step,
293
318
  pair_tensor,
294
319
  show_tensor_network,
295
320
  )
@@ -301,10 +326,21 @@ Per-backend plotters (optional; same as `show_tensor_network` internals):
301
326
  from tensor_network_viz.tensorkrowch import plot_tensorkrowch_network_2d, plot_tensorkrowch_network_3d
302
327
  from tensor_network_viz.tensornetwork import plot_tensornetwork_network_2d, plot_tensornetwork_network_3d
303
328
  from tensor_network_viz.quimb import plot_quimb_network_2d, plot_quimb_network_3d
304
- from tensor_network_viz.tenpy import plot_tenpy_network_2d, plot_tenpy_network_3d
305
- from tensor_network_viz.einsum_module import plot_einsum_network_2d, plot_einsum_network_3d
329
+ from tensor_network_viz.tenpy import (
330
+ make_tenpy_tensor_network,
331
+ plot_tenpy_network_2d,
332
+ plot_tenpy_network_3d,
333
+ )
334
+ from tensor_network_viz.einsum_module import (
335
+ parse_einsum_equation,
336
+ parse_equation_for_shapes,
337
+ plot_einsum_network_2d,
338
+ plot_einsum_network_3d,
339
+ )
306
340
  ```
307
341
 
342
+ (`parse_equation_for_shapes` — binary only; `parse_einsum_equation` — any arity, NumPy-validated.)
343
+
308
344
  ## Accepted inputs (summary)
309
345
 
310
346
  | Backend | Input |
@@ -312,42 +348,63 @@ from tensor_network_viz.einsum_module import plot_einsum_network_2d, plot_einsum
312
348
  | tensorkrowch | Network with `nodes` / `leaf_nodes`, or iterable of nodes |
313
349
  | tensornetwork | Iterable of `tensornetwork.Node` |
314
350
  | quimb | `TensorNetwork` or iterable of `Tensor` |
315
- | tenpy | Finite/segment/infinite `MPS`, finite/infinite `MPO` |
316
- | einsum | `EinsumTrace` or ordered iterable of `pair_tensor` |
351
+ | tenpy | `TenPyTensorNetwork` / `make_tenpy_tensor_network` (`npc.Array` + bonds); `MPS`, `MPO`, `MomentumMPS`-like; no stable TeNPy PEPS class (hand-built TN ok) |
352
+ | einsum | `EinsumTrace` or ordered iterable of `pair_tensor` / `einsum_trace_step` (ellipsis / hyperedges in the normalized graph) |
317
353
 
318
354
  Details, subgraph behavior, and Quimb hyperindex hubs are in **[docs/guide.md](docs/guide.md)**.
319
355
 
320
356
  ## Example scripts
321
357
 
322
- Runnable demos live under **`examples/`**. From the repo root with the right extra installed:
358
+ Runnable demos live under **`examples/`** and now share one public launcher:
323
359
 
324
- | Script | Purpose |
360
+ ```bash
361
+ python examples/run_demo.py <engine> <example> [options]
362
+ ```
363
+
364
+ Main files:
365
+
366
+ | File | Purpose |
325
367
  |--------|---------|
326
- | `demo_cli.py` | Shared helpers (`--hover-labels` `PlotConfig(hover_labels=True)`); imported by demos. |
327
- | `tensorkrowch_demo.py` | MPS, MPO, PEPS, weird, disconnected; `--from-list` subset. |
328
- | `tensornetwork_demo.py` | Same topologies with `tensornetwork.Node`. |
329
- | `mera_tree_demo.py` | Large MERA + binary TTN stress test. |
330
- | `cubic_peps_demo.py` | 3D cubic PEPS lattice. |
331
- | `quimb_demo.py` | Includes hyper-index example; `--from-list`. |
332
- | `tenpy_demo.py` | Finite and infinite MPS/MPO. |
333
- | `einsum_demo.py` | Auto trace vs manual `pair_tensor`. |
334
- | `tn_tsp.py` | Larger TensorKrowch TSP construction. |
335
-
336
- Catalog and one-liner commands: **[examples/README.md](examples/README.md)**.
368
+ | `run_demo.py` | Public CLI entry point for every engine and example. |
369
+ | `demo_cli.py` | Shared typed helpers for parsing, save paths, plot config, and topology builders. |
370
+ | `tensorkrowch_demo.py` | TensorKrowch registry: MPS/TT, MPO, ladder, PEPS, cubic PEPS, MERA, MERA+TTN, weird, disconnected. |
371
+ | `tensornetwork_demo.py` | TensorNetwork registry with the same structured graph examples. |
372
+ | `quimb_demo.py` | Quimb registry with the same graph family plus a native hypergraph example. |
373
+ | `tenpy_demo.py` | TeNPy registry: native MPS/MPO/iMPS/iMPO/purification/uniform/excitation plus explicit chain/hub/hyper examples. |
374
+ | `einsum_demo.py` | Einsum registry: network-style traces plus `ellipsis`, `batch`, `trace`, `ternary`, `unary`, `nway`, `implicit_out`. |
375
+ | `run_all_examples.py` | Headless batch runner that calls `run_demo.py` and saves PNGs. |
376
+
377
+ Useful launcher examples:
378
+
379
+ ```bash
380
+ python examples/run_demo.py quimb hyper --view 2d
381
+ python examples/run_demo.py tenpy chain --view 2d --save tenpy_chain.png --no-show
382
+ python examples/run_demo.py einsum ellipsis --view 3d --from-list
383
+ python examples/run_demo.py tensornetwork mera_ttn --view 2d --scheme
384
+ ```
385
+
386
+ Catalog and CLI details: **[examples/README.md](examples/README.md)**.
337
387
 
338
388
  ## Backend notes
339
389
 
340
390
  - Quimb **hyper-indices** (three or more tensors) are drawn via internal virtual hubs.
341
391
  - Infinite TeNPy **MPS/MPO** use one periodic unit cell.
342
392
  - The **einsum** backend visualizes the **fundamental** tensor network, not each intermediate
343
- contraction tensor.
393
+ contraction tensor. Pairwise summed indices are drawn as ordinary bonds; repeated or
394
+ output-carrying indices use **virtual hubs** (layout separates colocated hubs, nudges **2D**
395
+ hubs that attach to **one** tensor only—e.g. **`ii->i`**—off that tensor, and offsets hubs on a
396
+ tensor–tensor chord when a **direct** bond also links that pair).
397
+ - Optional **`contraction_steps`** from **einsum**: **running union** of operand physical lineages
398
+ (each step is a superset of the previous); **`PlotConfig`** draws per-step **AABB** highlights
399
+ (**2D:** rounded rectangles; **3D:** wireframe), colored borders (no fill by default), extra
400
+ padding as steps advance, and later steps underneath.
344
401
  - Passing a **subset** of nodes/tensors shows connections outside the subset as **dangling** legs.
345
402
 
346
403
  ## Quick verification (reviewers)
347
404
 
348
405
  ```bash
349
406
  python -m pip install -e ".[quimb]"
350
- python examples/quimb_demo.py mps 2d --save quimb_mps.png --no-show
407
+ python examples/run_demo.py quimb mps --view 2d --save quimb_mps.png --no-show
351
408
  python -m pytest
352
409
  ```
353
410
 
@@ -361,7 +418,9 @@ Expect `quimb_mps.png` and all tests passing.
361
418
  | `ValueError: Unsupported tensor network engine` / `view` | Use only listed `engine` / `view` literals (see above). |
362
419
  | Blank or double figure in Jupyter | Assign `fig, ax = show_tensor_network(...)`; avoid bare tuple as last line; try `%matplotlib widget` or inline. |
363
420
  | Hover labels do nothing | Requires interactive backend and `show` path that runs a GUI or widget event loop; not for `--no-show` PNG only. |
421
+ | Saved figure includes the control panel | Pass `interactive_controls=False` when exporting a static figure from `show_tensor_network`. |
364
422
  | Huge graphs are slow | `PlotConfig(refine_tensor_labels=False)`; lower `layout_iterations` or pass `positions`. Force layout samples repulsion when node count is large (about 72+; see [guide](docs/guide.md#layout-and-draw-scale)). |
423
+ | Einsum unary trace (`ii->i`) looks odd in 2D | Layout offsets the virtual hub off the tensor in 2D; try `view="3d"` or read [Einsum unary / same-tensor trace in 2D](docs/guide.md#toc-einsum-unary-2d-layout) in the guide. |
365
424
 
366
425
  **Full troubleshooting:** [docs/guide.md — Troubleshooting](docs/guide.md#troubleshooting).
367
426
 
@@ -370,7 +429,7 @@ Expect `quimb_mps.png` and all tests passing.
370
429
  - **[docs/guide.md](docs/guide.md)** — Installation, backends, `PlotConfig` recipes, layout/draw
371
430
  behavior, architecture, **extended troubleshooting**.
372
431
  - **[CHANGELOG.md](CHANGELOG.md)** — Release notes by version.
373
- - **[examples/README.md](examples/README.md)** — CLI examples per script.
432
+ - **[examples/README.md](examples/README.md)** — launcher usage, engine/example matrix, and batch examples.
374
433
  - **[THIRD_PARTY_LICENSES.md](THIRD_PARTY_LICENSES.md)**
375
434
 
376
435
  ## Support and contributing
@@ -382,9 +441,18 @@ Expect `quimb_mps.png` and all tests passing.
382
441
  ## Development
383
442
 
384
443
  ```bash
385
- python -m pip install -e ".[dev]"
386
- ruff check .
387
- ruff format .
388
- pyright
389
- pytest
444
+ python -m venv .venv
445
+ python -m pip install -r requirements.dev.txt
446
+ ```
447
+
448
+ Windows:
449
+
450
+ ```powershell
451
+ .\.venv\Scripts\python scripts\verify.py
452
+ ```
453
+
454
+ Linux/macOS (with the venv activated):
455
+
456
+ ```bash
457
+ python scripts/verify.py
390
458
  ```