//! Trace the merge topology of half_braid //! //! Run with: cargo run --example trace_merge use std::fs; use zigzag_engine::diagram::Diagram; use zigzag_engine::import::load_homotopy_diagram_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"); println!("=== MERGE TOPOLOGY ANALYSIS ===\n"); // Source 2-diagram structure if let Diagram::DiagramN(src) = half_braid.source() { println!("SOURCE 2-diagram ({} cospans):", src.cospans.len()); println!("Heights: r0, s0, r1, s1, r2"); println!(); // Print y-coordinates for each height println!("Height mappings (using layout_coords logic):"); for i in 0..=src.cospans.len() { let y = (i as f64) - 1.0; println!(" r{}: y = {:.1}", i, y); if i < src.cospans.len() { let y_sing = i as f64; println!(" s{}: y = {:.1} ← SCALAR HERE", i, y_sing); } } println!(); } // Target 2-diagram structure let target = half_braid.target(); if let Diagram::DiagramN(tgt) = &target { println!("TARGET 2-diagram ({} cospans):", tgt.cospans.len()); println!("Heights: r0, s0, r1"); println!(); println!("Height mappings:"); for i in 0..=tgt.cospans.len() { let y = (i as f64) - 1.0; println!(" r{}: y = {:.1}", i, y); if i < tgt.cospans.len() { let y_sing = i as f64; println!(" s{}: y = {:.1} ← MERGED SCALAR HERE", i, y_sing); } } println!(); } println!("=== VISIBLE ELEMENT ANALYSIS ===\n"); println!("The 2 VERTICES (geom_dim=0) are the TWO INPUT SCALARS:"); println!(" vertex (s0,s0,s0): z=-0.5, the FIRST scalar from source s0"); println!(" vertex (s1,s0,s0): z=+0.5, the SECOND scalar from source s1"); println!(); println!("The 3 WIRES (geom_dim=1) are the BOUNDARIES between regions:"); println!(" wire (r0,s0,s0): z=-1.0, LEFT boundary (below both scalars)"); println!(" wire (r1,s0,s0): z= 0.0, MIDDLE boundary (between the two scalars)"); println!(" wire (r2,s0,s0): z=+1.0, RIGHT boundary (above both scalars)"); println!(); println!("=== Y-SHAPE TOPOLOGY ===\n"); println!("The MERGE contracts source heights r0,s0,r1,s1,r2 into target heights r0,s0,r1"); println!(); println!("Mapping:"); println!(" Source r0 (y=-1) → Target r0 (y=-1) [PRESERVED]"); println!(" Source s0 (y= 0) → Target s0 (y= 0) [MERGED INTO]"); println!(" Source r1 (y= 0) → Target s0 (y= 0) [ABSORBED]"); println!(" Source s1 (y= 1) → Target s0 (y= 0) [MERGED INTO]"); println!(" Source r2 (y=+1) → Target r1 (y= 0) [CONTRACTED DOWN]"); println!(); println!("For the 3 visible wires:"); println!(); println!("Wire r0 (z=-1, LEFT EDGE):"); println!(" Source endpoint (x=-1): y=-1 (at source height r0)"); println!(" Merge waypoint (x= 0): y= 0 (at merge height s0)"); println!(" Target endpoint (x=+1): y=-1 (at target height r0)"); println!(" → This wire DIPS DOWN to the merge then back up"); println!(); println!("Wire r1 (z=0, MIDDLE/STEM):"); println!(" Source endpoint (x=-1): y= 0 (at source height r1, between s0 and s1)"); println!(" Merge waypoint (x= 0): y= 0 (at merge height s0)"); println!(" Target endpoint (x=+1): y= 0 (at target height s0)"); println!(" → This is the STEM - stays at y=0 throughout"); println!(); println!("Wire r2 (z=+1, RIGHT EDGE):"); println!(" Source endpoint (x=-1): y=+1 (at source height r2)"); println!(" Merge waypoint (x= 0): y= 0 (at merge height s0)"); println!(" Target endpoint (x=+1): y= 0 (at target height r1)"); println!(" → This wire comes DOWN from above into the merge"); println!(); println!("=== THE Y-SHAPE ===\n"); println!("Looking at y-z plane (height vs depth) at different x (time) slices:\n"); println!("At SOURCE (x=-1): At MERGE (x=0): At TARGET (x=+1):"); println!(" "); println!("y=+1 ──●r2── y=+1 y=+1 "); println!(" │ ╲ "); println!(" │ ╲ "); println!("y= 0 ──●r1── ←s1 scalar y= 0 ●●● (merge) y= 0 ──●r1,r2── "); println!(" │ ╱ ↑ ↑ "); println!(" │ ╱ vertices merged "); println!("y=-1 ──●r0── ←s0 scalar y=-1 y=-1 ──●r0── "); println!(" "); println!(" z: -1 0 +1 -1 0 +1 -1 0 +1 "); }