zigzag-engine/examples/inspect_half_braid.rs
Maximus Gorog c51e3274f9 Stage 2 complete: Construction 17 validated on real 3D data
Zigzag engine (6802 lines, 184 tests):
- Construction 17 normalisation: working through dimension 3+
- Import from homotopy-rs JSON: working (scalar, two_scalars, half_braid)
- Piece extraction via Embedding/restrict_diagram: working
- Type checking pipeline: working (Eckmann-Hilton half_braid passes)
- Essential identity detection: validated with full 2-diagram test

Bugs found and fixed:
- assemble_factorisations losing cospan legs during reassembly
- RewriteN::slice() using source offsets instead of target indices
- singular_preimage() not handling passthrough heights
- restrict_rewrite() not accounting for accumulated cone offsets
- Embedding::preimage() using regular_preimage for Singular case

Added vis-engine-spec.md: visualization engine specification
- 6-layer architecture from math primitives to scene graph
- SVG renderer for 2D, WebGL2 for 3D, custom hit testing
- Spring constraint integration point for semiotic rendering
- No external dependencies - game engine approach

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-09 05:26:15 -06:00

94 lines
3.5 KiB
Rust

//! Inspect the categorical structure of half_braid.json
//!
//! Run with: cargo run --example inspect_half_braid
use std::fs;
use zigzag_engine::diagram::Diagram;
use zigzag_engine::import::load_homotopy_diagram_n;
fn describe_diagram(d: &Diagram, indent: usize) -> String {
let prefix = " ".repeat(indent);
match d {
Diagram::Diagram0(g) => {
format!("{}0-diagram: generator id={}, dim={}", prefix, g.id, g.dimension)
}
Diagram::DiagramN(dn) => {
let dim = d.dimension();
let mut lines = vec![format!(
"{}{}-diagram with {} cospans:",
prefix,
dim,
dn.cospans.len()
)];
lines.push(format!("{} source:", prefix));
lines.push(describe_diagram(dn.source(), indent + 2));
if !dn.cospans.is_empty() {
lines.push(format!("{} target:", prefix));
lines.push(describe_diagram(&dn.target(), indent + 2));
}
lines.join("\n")
}
}
}
fn main() {
let json = fs::read_to_string("fixtures/half_braid.json")
.expect("Failed to read half_braid.json");
let half_braid = load_homotopy_diagram_n(&json)
.expect("Failed to parse");
let half_braid_d = Diagram::DiagramN(half_braid.clone());
println!("=== HALF_BRAID CATEGORICAL STRUCTURE ===\n");
// The half_braid itself is a 3-diagram
println!("half_braid is a {}-diagram with {} cospans\n",
half_braid_d.dimension(), half_braid.cospans.len());
// Its source (a 2-diagram)
let source_2d = half_braid.source();
println!("SOURCE of half_braid (the 2-diagram it transforms FROM):");
println!("{}\n", describe_diagram(source_2d, 1));
// Its target (a 2-diagram)
let target_2d = half_braid.target();
println!("TARGET of half_braid (the 2-diagram it transforms TO):");
println!("{}\n", describe_diagram(&target_2d, 1));
// Are source and target the same?
println!("Are source and target equal? {}\n", source_2d == &target_2d);
// Look at the source 2-diagram structure
if let Diagram::DiagramN(src) = source_2d {
println!("=== SOURCE 2-DIAGRAM SLICES ===");
println!("This 2-diagram has {} cospans (singular heights)\n", src.cospans.len());
// Regular slices
for i in 0..=src.cospans.len() {
if let Some(slice) = src.regular_slice(i) {
println!("Regular slice r{}: {}", i, describe_diagram(&slice, 0));
}
}
println!();
// Singular slices
for i in 0..src.cospans.len() {
if let Some(slice) = src.singular_slice(i) {
println!("Singular slice s{}: {}", i, describe_diagram(&slice, 0));
}
}
}
println!("\n=== INTERPRETATION ===");
println!("Generator 0 (dim=0): The base object x");
println!("Generator 1 (dim=2): The scalar s (a 2-cell: id_x → id_x)");
println!();
println!("The SOURCE 2-diagram is 'two scalars stacked':");
println!(" - 2 cospans means 2 singular heights (s0, s1)");
println!(" - Each singular height is where a scalar (2-cell) lives");
println!();
println!("The half_braid 3-diagram is the Eckmann-Hilton homotopy:");
println!(" - It shows the two scalars 'sliding past' each other");
println!(" - Source = target (as 2-diagrams, they're the same configuration)");
println!(" - But the 3-diagram is NON-trivial: it's the braiding coherence");
}