// Pipeline SVG — the dual-branch DGAC architecture diagram. // Blocks are clickable: clicking jumps to the step they represent. const { useMemo } = React; // KaTeX-rendered sub-text inside SVG via foreignObject. function SubKatex({ x, y, w, h, tex, color }) { const ref = React.useRef(null); React.useEffect(() => { if (!ref.current || !window.katex) return; try { window.katex.render(tex, ref.current, { throwOnError: false, displayMode: false, strict: "ignore", }); } catch(e) { if (ref.current) ref.current.textContent = tex; } }, [tex]); return (
); } function PipeBlock({ x, y, w, h, label, sub, subTex, color, active, dim, onClick, hoverable }) { const stroke = active ? color : "#c8c1b4"; const textFill = active ? color : "#3d3a35"; const subFill = active ? color : "#827d75"; const textOp = active ? 1 : (dim ? 0.55 : 0.9); const rectOp = active ? 1 : (dim ? 0.5 : 0.85); const [hover, setHover] = React.useState(false); const isClickable = !!onClick; const rectStroke = hover && isClickable ? color : stroke; const hasSub = !!(sub || subTex); return ( setHover(true)} onMouseLeave={()=>setHover(false)} > {/* Invisible wider hit area for easier clicking */} {isClickable && ( )} {active && } {label} {subTex ? ( ) : sub && ( {sub} )} ); } function Arrow({ from, to, active, curve=0, color="#9a9388", dashed }) { const [x1,y1]=from, [x2,y2]=to; const mx=(x1+x2)/2, my=(y1+y2)/2 - curve; const op = active?1:0.6; const stroke = active ? color : "#bdb6a8"; return ( ); } function IterBadge({ x, y, active, color, label }){ if (!active) return null; return ( {label} ); } function PipelineDiagram({ activeSet, tweaks, onStepJump }) { const A_T = "oklch(0.55 0.13 250)"; const A_A = "oklch(0.58 0.13 35)"; const A_F = "oklch(0.52 0.13 300)"; const A_C = "oklch(0.55 0.13 150)"; const A_L = "oklch(0.50 0.05 260)"; const w = 1410, h = 320; const on = k => activeSet.has(k); const go = id => onStepJump && onStepJump(id); // X positions for stage columns (graph source + 5 stages + transform) const X = { graph: 20, input: 160, encode: 310, diff: 530, xform: 770, fusion: 930, cprop: 1170 }; // Y bands: top branch (attr), bottom branch (topo), mid (fusion/cprop), loss bar const Y = { attr: 70, topo: 205, mid: 140, loss: 20, col: 278 }; return ( {/* source graph G = (V, E, X) — fans out into X (features) and A (adjacency) */} go("input")}/> {/* input column */} go("input")}/> go("input")}/> {/* encoders — paper has cross-modality init (U from X̄, B from Ã). Sub-labels show the actual source so the arrow visual stays clean (no crossings). */} go("encode")}/> go("encode")}/> {/* diffusion blocks */} go("attribute")}/> go("topology")}/> {/* linear transforms W^(t), W^(a) — paper Eq.14 */} go("fusion")}/> go("fusion")}/> {/* fusion */} go("fusion")}/> {/* kmeans */} go("kmeans")}/> {/* c-prop — paper Eq.16 uses γ (not the branch α) */} go("cprop")}/> {/* output */} go("output")}/> {/* loss bar */} go("loss")}/> {/* arrows — G → (X, A) */} {/* arrows — input → encode (same-row; cross-modality indicated by encoder sub-labels) */} {/* encode → diffusion */} {/* diffusion → transform (W) */} {/* transform → fusion */} {/* fusion → kmeans (vertical) */} {/* kmeans → cprop (diagonal up) */} {/* cprop → output */} {/* loss feedback arrows (dashed) */} {/* iteration badges */} {/* column titles */} GRAPH INPUT ENCODE DIFFUSION (L steps) TRANSFORM (W) FUSION + K-MEANS C-PROP + OUTPUT {/* hint */} 点击任意方块跳到对应步骤 → ); } window.PipelineDiagram = PipelineDiagram;