This project is a computer search for Dunwoody tracks (via chord diagrams) using a configurable BFS, on specific types of 'marked surfaces' constructed in a niche way.
- Open
exhaustive_search.pyand edit the config block near the top. - Run:
python3 exhaustive_search.pyYou’ll see an ASCII diagram for each surface, search progress, and a result summary.
All configuration is done via constants at the top of exhaustive_search.py.
SIGNATURE: Klein signature string (e.g."I R V H I R").SURFACE:"annulus"or"strip".DIRECTED_MODE:Trueto use directed surfaces,Falsefor undirected.
UNIQUE: ifTrue, deduplicate by symmetry:- undirected annulus: dihedral symmetry
- undirected strip: reflection symmetry
- directed annulus: cyclic symmetry
- directed strip: reflection symmetry
EXCLUDE_ADJACENT_I: filter permutations with adjacentIentries (ignored in directed mode).PREFIX_PRUNING: enable the prefix-pruning search strategy.START_PREFIX_LENGTH: initial prefix length for prefix pruning.
These toggle which closed tracks are accepted as solutions.
REQUIRE_DY_NONZEROREQUIRE_DX_INFEASIBLE: whenTrue, may return 'complete candidate sets' rather than a single solution.REQUIRE_EVEN_TURNINGREQUIRE_EVEN_OR_PAIRSDOMINANT_DIR_ONLY: only move along dominant x-direction (free first horizontal move).LIMIT_INTERIOR_CROSSINGS: cap interior crossings to one.REJECT_ALL_INTERIOR_USED: reject solutions that use every interior edge.
MAX_NODESMAX_CANDIDATESMAX_PORTS_PER_EDGEMINIMIZE_SEEDMAX_MINIMIZE_SIZE
SHOW_PROGRESS,PROGRESS_INTERVALDEBUG_UNSOLVED,DEBUG_UNSOLVED_MAXDEBUG_TRACE_BFS,DEBUG_TRACE_BFS_MAXDEBUG_BFS_STEPS,DEBUG_BFS_STEPS_MAX
Each case prints in three phases:
- Header + diagram (blue)
- Progress bar while the BFS runs
- Result (solution, complete candidate set, or unsolved)
At the end, a diagnostics table summarizes results per stage and totals.
Annulus [25 / 36]
MarkedAnnulus(N=6)
C↻ D↻ E↻ C↻ D↻ E↻
+----------->-----------+----------->-----------+----------->-----------+-----------<-----------+-----------<-----------+-----------<-----------+
| | | | | | |
| | | | | | |
| | | | | | |
V | | | | | V
V | | | | | V
V | | | | | V
| | | | | | |
| | | | | | |
| | | | | | |
+-----------------------+----------->-----------+----------->-----------+----------->-----------+----------->-----------+-----------------------+
A B A B
start 1/6 [################--------] 3400/5000 queue 28 seen 33999
start 2/6 [########################] 5000/5000 queue 639 seen 4999
start 3/6 [#######################-] 4800/5000 queue 26 seen 47999
start 4/6 [#######################-] 4800/5000 queue 27 seen 47999
start 5/6 [########################] 5000/5000 queue 639 seen 4999
start 6/6 [################--------] 3400/5000 queue 28 seen 33999
Complete candidate set found (size 2).
[1] dy: -4 dx: -x_3 + x_4 + x_5 - x_6
C↻ D↻ E↻ C↻ D↻ E↻
+-----------0-----------+---5-------4-------3---+---B------->-------A---+-----------0-----------+---3-------4-------5---+---A-------<-------B---+
| ** | * * * | * * | * | * * * | * * |
| *** | * * * | * * | * | * * * | * * |
| ** | * * * | * * | * | * * * | * * |
V *** | * * * | * * | * | * * * | * * V
V** | * * * | * * *|* * *|* * * *|* *V
V | * * * | * * * | * * * | * * * | V
| | * * * | * * * | * * * | * * * | |
| | * * * | * * * | * * * | * * * | |
| | * * * | * * * | * * * | * * * | |
+-----------------------+---7-------8-------9---+---D-------E-------F---+---7-------8-------9---+---D-------E-------F---+-----------------------+
A B A B
[2] dy: 4 dx: -2 - x_2 - x_3 + x_4 - x_6
C↻ D↻ E↻ C↻ D↻ E↻
+-----------0-----------+---4------->-------3---+-----------7---@-------+-----------0-----------+---3-------<-------4---+-----------7-----------+
| ** | * * | ** | ** | * * | ** |
| *** | * * | *** | *** | * * | *** |
| ** | * * | ** | ** | * * | ** |
V *** | * * | *** | *** | * * | *** V
V** | * *|** **|** **|* * | **V
V | * | *** | *** | * | V
| | * | ** | ** | * | |
| | * | *** | *** | * | |
| | * | ** | ** | * | |
+-----------------------+-----------6-----------+-----------9-----------+-----------6-----------+-----------9-----------+-----------------------+
A B A B
- Each row of squares is rendered as a contiguous ASCII strip.
- Marked edge labels appear above and below the strip.
- Direction arrows appear near the right end of edges in directed mode.
- OP/OR markers (
>/<) appear along marked edges.
If a simple shortcut is found, the track diagram is printed with its dy and
linear dx expression. If no shortcut is found and REQUIRE_DX_INFEASIBLE is
enabled, a minimized complete candidate set is printed instead.
edge.py: edges with ordered portssquare.py: oriented squares with top/bottom/left/right edgeschords.py: chords and crossing logicchord_diagram.py: square + chords with ASCII renderstrips.py: strips/annuli and adjacencymarked_strips.py: marked strips/annuli with identifications and renderdirected_marked_strips.py: directed variants with per-edge in/out/undirectedpattern.py: chord diagrams across a surfacetrack_state.py: BFS state and move generationtrack_bfs.py: BFS search utilities and wrappersklein_signature_generator.py: undirected surface generationdirected_klein_signature_generator.py: directed surface generationshortcut_completeness.py: LP-based completeness checksexhaustive_search.py: main executable script
- Python 3.11+
scipy(for linear infeasibility checks inshortcut_completeness.py)
Install:
python3 -m pip install scipy