Skip to content

yilibinbin/Wigsym

Repository files navigation

Wigsym

简体中文 → · 中文文档目录 · Quick start · Algorithm tutorial · Changelog

中文用户请从 README.zh-CN.md快速上手 开始;所有中文入口汇总在 docs/README.zh-CN.md

Symbolic simplifier for graphs of Wigner 3j / 6j / 9j angular-momentum symbols. Takes a coupling diagram as input — either a .3js file of 3j tuples or a .braket file of nested bra-kets — applies bubble-cancellation and cycle-breaking rewrites, and emits a minimal symbolic expression together with an interactive step-by-step graph history.

A built-in Wigner symbol calculator evaluates 3j / 6j / 9j numerically to any sympy-precision rational form, with one-click "Copy as Symbolic / LaTeX / Numeric / MathML" for any field.

For an end-to-end walkthrough of the algorithm — what each frame of the reduction tree means, which Wigner identity each rule represents, and how to read the GraphPane sidebar — see docs/algorithm.md. The walkthrough cites Edmonds 1957, Varshalovich 1988, and Yutsis-Levinson-Vanagas 1962 for every rewrite.

Download (no Python needed)

Platform Asset Notes
macOS arm64 Wigsym-v2.0.7.dmg Open the dmg, drag Wigsym into Applications, eject. First launch may show "unidentified developer" — right-click → Open.
Windows x64 Wigsym-v2.0.7-windows-x64.zip Unzip anywhere; double-click Wigsym.exe. The folder is self-contained — no installer.

Latest releases: https://github.com/yilibinbin/Wigsym/releases.

Features

  • Structured input editor — type into all_3j / powers / factor_sqrt rows directly, or open a .3js / .braket file and edit in place. The source file is never written until you click Save as….
  • Threaded solver — runs in a background thread; the UI stays responsive on heavy 9j and braket cases.
  • Interactive reduction tree — Cytoscape-rendered graph with Prev/Next stepping, Re-layout, and a sidebar where every frame is labelled with the rewrite rule that produced it (Bubble cancel, Break graph, etc.).
  • MathJax-rendered output — input and result both typeset as proper Wigner brackets. Right-click any block for "Copy as".
  • Wigner 3j/6j/9j calculator — selectable symbol type, input grid shaped like the actual matrix (3j and 6j → 2×3, 9j → 3×3), exact sympy evaluation.
  • Cross-platform dark mode — follows the OS theme by default, Ctrl+Shift+D toggles. MathJax math and Cytoscape graph respect the theme without a white flash.
  • Bilingual UI — switch English / 简体中文 at runtime via View → Language; all Qt widgets and HTML shells reload immediately.

Install from source

Requires Python 3.11 or newer (3.13 tested).

git clone https://github.com/yilibinbin/Wigsym
cd Wigsym
python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
python -m wigsym

Run

python -m wigsym
# or, after install
wigsym

Open a testcases/*.3js or *.braket from the left pane, click Solve. The result pane shows:

  • the input rendered as a product of 3j matrices (top),
  • the simplified expression typeset with MathJax (middle),
  • the raw text form (a single-line ASCII expression),
  • the step-by-step rewrite log.

The graph pane shows each intermediate graph G0 → G1 → … with zoom and pan, and a navigable reduction tree in the sidebar where every frame carries the rule that produced it (e.g. G2 Bubble cancel).

Input formats

.3js — three labelled lines:

all_3j=(j1,j2,j3)(j1,j4,j5)(j2,j4,j6)(j3,j5,j6)
powers=-m1,-m2,j3,-m3,-m4,-m5,j6,-m6
factor_sqrt=j3,j6

Shorthand: (j1, j2, -j3) expands to (j1, j2, j3, mj1, mj2, -mj3). Names starting with z or mz are reserved for synthetic intermediate momenta the solver introduces during graph breaking.

.braket — a single nested bra-ket like <((j1,j2)j5,(j3,j4)j6)j7|(j1,((j2,j3)j8,j4)j9)j7>.

The format-hint button (?) in the editor pane has these examples available inline.

Testing

pytest                                    # unit + regression suite
pytest wigsym/tests/test_regression.py  # strict regression bar + drift xfails
ruff check wigsym/                      # lint

The regression harness runs every testcases/*.3js / *.braket through the solver and compares to the committed .out. Cases that permute 6j label positions or synthetic-edge (z*) names compare equal via a Weisfeiler-Lehman-style canonicalizer. A small number of complex multi-stage decompositions produce algebraically-equivalent outputs through a different decomposition path; these are xfail-annotated as known drift — see CORRECTNESS.md for the per-case status matrix and the four-level verification taxonomy (structural / legacy parity / numerical equivalence / literature parity).

Build a standalone app

# macOS — produces dist/Wigsym.app + a versioned dist/Wigsym-vX.Y.Z.dmg
VERSION=2.0.7
pip install -e ".[build]"
pyinstaller mac.spec --clean
dmgbuild -s dmg.py "Wigsym" "dist/Wigsym-v${VERSION}.dmg"

# Windows (run on Windows) — produces dist/Wigsym/Wigsym.exe
$version = "2.0.7"
pip install -e ".[build]"
pyinstaller win.spec --clean
Compress-Archive -Path dist/Wigsym/* -DestinationPath "dist/Wigsym-v$version-windows-x64.zip"

See BUILD.md for the cross-machine workflow used to package both platforms.

Architecture

wigsym/
├── core/                 # pure Python, no Qt — safe in worker threads
│   ├── state.py          # SolverState
│   ├── parser.py         # parse_3js_file / parse_braket / parse_text
│   ├── recognize.py      # is_6j / is_9j / show_6j / show_9j
│   ├── layout.py         # snapshot_graph / recognize_and_emit
│   ├── rewrites.py       # cancel_bubbles / break_graph / simplified
│   ├── solver.py         # solve() orchestrator
│   ├── canonical.py      # SolveMode.CANONICAL: lex-smallest 6j/9j + phase mod 4
│   ├── yutsis.py         # SolveMode.YUTSIS: Regge cycling outer loop
│   ├── be_rewriter.py    # Biedenharn-Elliott pentagon detector
│   ├── rendering.py      # Solution dataclass + render() — text + LaTeX + graph JSON
│   └── equivalence.py    # canonicalize() for regression comparison
├── ui/                   # PySide6 — never imports core globals
│   ├── app.py            # QApplication bootstrap
│   ├── mainwindow.py     # MainWindow with threaded solver + Help menu
│   ├── input_pane.py     # Left: structured input form + Wigner calculator
│   ├── editor_backend.py
│   ├── calculator_backend.py
│   ├── result_pane.py    # Top-right: MathJax via QWebEngineView
│   ├── result_backend.py
│   ├── graph_pane.py     # Bottom-right: Cytoscape via QWebEngineView
│   ├── web_pane.py       # Shared webview + QWebChannel setup
│   ├── bridge.py         # UiBridge — fans JSON payloads to all three shells
│   └── theme.py          # Light/dark QSS + system-theme follower
├── assets/
│   ├── editor.qml             # QML editor + parsed-fields panel
│   ├── calculator_inputs.qml  # QML symbol selector + j/m grid
│   ├── result_shell.html      # MathJax shell — solutionReady subscriber
│   ├── calculator_shell.html  # MathJax shell — calculatorPayloadChanged subscriber
│   ├── graph_shell.html       # Cytoscape shell — graphHistoryReady subscriber
│   ├── shell_common.js        # Shared HTML-shell helpers
│   ├── mathjax/               # vendored MathJax 3.2.2
│   ├── cytoscape/             # vendored Cytoscape.js 3.33 + cose-bilkent
│   └── icons/
└── tests/                     # unit + regression + canonical

The core never imports Qt; the UI never touches core globals. This means wigsym.core can be embedded in a Jupyter notebook or driven from a non-GUI CLI without the PySide6 dependency.

Known limitations

  • A subset of complex .braket testcases produces a symbolically equivalent output along a different decomposition path. The number and label-set of 6j/9j symbols is preserved; only phase simplifications that rely on (-1)^(2j+1) identities may differ. See the test_regression_matches_canonical xfail list.
  • UI smoke tests are skipped by default on Python 3.13 because PySide6 6.10 + QtTest segfaults at pytest fixture-setup. The app itself runs fine when launched directly.

License

MIT. Includes original code by Xiang, Shao-Hui (2019) Mendeley dataset under BSD-3-Clause; that attribution is preserved in LICENSE.

About

Symbolic Wigner 3j/6j/9j angular-momentum simplifier with PySide6 UI

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors