1use graph_sp::{Graph, Linspace};
12use std::collections::HashMap;
13
14fn main() {
15 println!("═══════════════════════════════════════════════════════════");
16 println!(" Graph-SP Comprehensive Demo");
17 println!(" Pure Rust Graph Execution Engine");
18 println!("═══════════════════════════════════════════════════════════\n");
19
20 demo_simple_pipeline();
22 demo_branching();
23 demo_merging();
24 demo_variants();
25 demo_complex_graph();
26}
27
28fn demo_simple_pipeline() {
29 println!("─────────────────────────────────────────────────────────");
30 println!("Demo 1: Simple Sequential Pipeline");
31 println!("─────────────────────────────────────────────────────────");
32
33 let mut graph = Graph::new();
34
35 graph.add(
37 |_: &HashMap<String, String>, _| {
38 let mut result = HashMap::new();
39 result.insert("value".to_string(), "42".to_string());
40 result
41 },
42 Some("DataSource"),
43 None, Some(vec![("value", "data")]) );
46
47 graph.add(
49 |inputs: &HashMap<String, String>, _| {
50 let mut result = HashMap::new();
51 if let Some(val) = inputs.get("x").and_then(|s| s.parse::<i32>().ok()) {
52 result.insert("doubled".to_string(), (val * 2).to_string());
53 }
54 result
55 },
56 Some("Multiply"),
57 Some(vec![("data", "x")]), Some(vec![("doubled", "result")]) );
60
61 graph.add(
63 |inputs: &HashMap<String, String>, _| {
64 let mut result = HashMap::new();
65 if let Some(val) = inputs.get("num").and_then(|s| s.parse::<i32>().ok()) {
66 result.insert("sum".to_string(), (val + 10).to_string());
67 }
68 result
69 },
70 Some("AddTen"),
71 Some(vec![("result", "num")]),
72 Some(vec![("sum", "final")])
73 );
74
75 let dag = graph.build();
76 println!("\n📊 Execution:");
77 let context = dag.execute(false, None);
78
79 println!(" Input: data = {}", context.get("data").unwrap());
80 println!(" Step 1: result = {} (data * 2)", context.get("result").unwrap());
81 println!(" Step 2: final = {} (result + 10)", context.get("final").unwrap());
82
83 println!("\n📈 DAG Statistics:");
84 let stats = dag.stats();
85 println!("{}", stats.summary());
86
87 println!("\n🔍 Mermaid Visualization:");
88 println!("{}", dag.to_mermaid());
89 println!();
90}
91
92fn demo_branching() {
93 println!("─────────────────────────────────────────────────────────");
94 println!("Demo 2: Parallel Branching (Fan-Out)");
95 println!("─────────────────────────────────────────────────────────");
96
97 let mut graph = Graph::new();
98
99 graph.add(
101 |_: &HashMap<String, String>, _| {
102 let mut result = HashMap::new();
103 result.insert("dataset".to_string(), "100".to_string());
104 result
105 },
106 Some("Source"),
107 None,
108 Some(vec![("dataset", "data")])
109 );
110
111 let mut branch_a = Graph::new();
113 branch_a.add(
114 |inputs: &HashMap<String, String>, _| {
115 let mut result = HashMap::new();
116 if let Some(val) = inputs.get("input") {
117 result.insert("stats".to_string(), format!("Mean: {}", val));
118 }
119 result
120 },
121 Some("Statistics"),
122 Some(vec![("data", "input")]),
123 Some(vec![("stats", "stats_result")])
124 );
125
126 let mut branch_b = Graph::new();
128 branch_b.add(
129 |inputs: &HashMap<String, String>, _| {
130 let mut result = HashMap::new();
131 if let Some(val) = inputs.get("input") {
132 result.insert("model".to_string(), format!("Model trained on {}", val));
133 }
134 result
135 },
136 Some("MLModel"),
137 Some(vec![("data", "input")]),
138 Some(vec![("model", "model_result")])
139 );
140
141 let mut branch_c = Graph::new();
143 branch_c.add(
144 |inputs: &HashMap<String, String>, _| {
145 let mut result = HashMap::new();
146 if let Some(val) = inputs.get("input") {
147 result.insert("plot".to_string(), format!("Plot of {}", val));
148 }
149 result
150 },
151 Some("Visualization"),
152 Some(vec![("data", "input")]),
153 Some(vec![("plot", "viz_result")])
154 );
155
156 graph.branch(branch_a);
157 graph.branch(branch_b);
158 graph.branch(branch_c);
159
160 let dag = graph.build();
161 println!("\n📊 Execution:");
162 let context = dag.execute(false, None);
163
164 println!(" Source: data = {}", context.get("data").unwrap());
165 println!(" Branch A (Stats): {}", context.get("stats_result").unwrap());
166 println!(" Branch B (Model): {}", context.get("model_result").unwrap());
167 println!(" Branch C (Viz): {}", context.get("viz_result").unwrap());
168
169 println!("\n📈 DAG Statistics:");
170 let stats = dag.stats();
171 println!("{}", stats.summary());
172 println!(" ⚡ All 3 branches can execute in parallel!");
173
174 println!("\n🔍 Mermaid Visualization:");
175 println!("{}", dag.to_mermaid());
176 println!();
177}
178
179fn demo_merging() {
180 println!("─────────────────────────────────────────────────────────");
181 println!("Demo 3: Branching + Merging (Fan-Out + Fan-In)");
182 println!("─────────────────────────────────────────────────────────");
183
184 let mut graph = Graph::new();
185
186 graph.add(
188 |_: &HashMap<String, String>, _| {
189 let mut result = HashMap::new();
190 result.insert("value".to_string(), "50".to_string());
191 result
192 },
193 Some("Source"),
194 None,
195 Some(vec![("value", "data")])
196 );
197
198 let mut branch_a = Graph::new();
200 branch_a.add(
201 |inputs: &HashMap<String, String>, _| {
202 let mut result = HashMap::new();
203 if let Some(val) = inputs.get("x").and_then(|s| s.parse::<i32>().ok()) {
204 result.insert("output".to_string(), (val + 10).to_string());
205 }
206 result
207 },
208 Some("PathA (+10)"),
209 Some(vec![("data", "x")]),
210 Some(vec![("output", "result")]) );
212
213 let mut branch_b = Graph::new();
215 branch_b.add(
216 |inputs: &HashMap<String, String>, _| {
217 let mut result = HashMap::new();
218 if let Some(val) = inputs.get("x").and_then(|s| s.parse::<i32>().ok()) {
219 result.insert("output".to_string(), (val + 20).to_string());
220 }
221 result
222 },
223 Some("PathB (+20)"),
224 Some(vec![("data", "x")]),
225 Some(vec![("output", "result")]) );
227
228 let branch_a_id = graph.branch(branch_a);
229 let branch_b_id = graph.branch(branch_b);
230
231 graph.merge(
233 |inputs: &HashMap<String, String>, _| {
234 let mut result = HashMap::new();
235 let a = inputs.get("from_a").and_then(|s| s.parse::<i32>().ok()).unwrap_or(0);
236 let b = inputs.get("from_b").and_then(|s| s.parse::<i32>().ok()).unwrap_or(0);
237 result.insert("combined".to_string(), format!("{} + {} = {}", a, b, a + b));
238 result
239 },
240 Some("Merge"),
241 vec![
242 (branch_a_id, "result", "from_a"), (branch_b_id, "result", "from_b") ],
245 Some(vec![("combined", "final")])
246 );
247
248 let dag = graph.build();
249 println!("\n📊 Execution:");
250 let context = dag.execute(false, None);
251
252 println!(" Source: data = {}", context.get("data").unwrap());
253 println!(" Branch A: 50 + 10 = 60");
254 println!(" Branch B: 50 + 20 = 70");
255 println!(" Merged: {}", context.get("final").unwrap());
256
257 println!("\n📈 DAG Statistics:");
258 let stats = dag.stats();
259 println!("{}", stats.summary());
260
261 println!("\n🔍 Mermaid Visualization:");
262 println!("{}", dag.to_mermaid());
263 println!();
264}
265
266fn demo_variants() {
267 println!("─────────────────────────────────────────────────────────");
268 println!("Demo 4: Parameter Sweep with Variants");
269 println!("─────────────────────────────────────────────────────────");
270
271 let mut graph = Graph::new();
272
273 graph.add(
275 |_: &HashMap<String, String>, _| {
276 let mut result = HashMap::new();
277 result.insert("base_value".to_string(), "10.0".to_string());
278 result
279 },
280 Some("DataSource"),
281 None,
282 Some(vec![("base_value", "data")])
283 );
284
285 fn make_scaler(learning_rate: f64) -> impl Fn(&HashMap<String, String>, &HashMap<String, String>) -> HashMap<String, String> {
287 move |inputs: &HashMap<String, String>, _| {
288 let mut result = HashMap::new();
289 if let Some(val) = inputs.get("input").and_then(|s| s.parse::<f64>().ok()) {
290 let scaled = val * learning_rate;
291 result.insert("scaled_value".to_string(), format!("{:.2}", scaled));
292 }
293 result
294 }
295 }
296
297 graph.variant(
299 make_scaler,
300 vec![0.001, 0.01, 0.1, 1.0],
301 Some("ScaleLR"),
302 Some(vec![("data", "input")]),
303 Some(vec![("scaled_value", "result")])
304 );
305
306 let dag = graph.build();
307 println!("\n📊 Execution:");
308 let context = dag.execute(false, None);
309
310 println!(" Source: data = {}", context.get("data").unwrap());
311 println!(" Variants created for learning rates: [0.001, 0.01, 0.1, 1.0]");
312 println!(" (Each variant computes: data * learning_rate)");
313
314 println!("\n📈 DAG Statistics:");
315 let stats = dag.stats();
316 println!("{}", stats.summary());
317 println!(" ⚡ All {} variants can execute in parallel!", stats.variant_count);
318
319 println!("\n🔍 Mermaid Visualization:");
320 println!("{}", dag.to_mermaid());
321 println!();
322}
323
324fn demo_complex_graph() {
325 println!("─────────────────────────────────────────────────────────");
326 println!("Demo 5: Complex Graph (All Features Combined)");
327 println!("─────────────────────────────────────────────────────────");
328
329 let mut graph = Graph::new();
330
331 graph.add(
333 |_: &HashMap<String, String>, _| {
334 let mut result = HashMap::new();
335 result.insert("raw_data".to_string(), "1000".to_string());
336 result
337 },
338 Some("Ingest"),
339 None,
340 Some(vec![("raw_data", "data")])
341 );
342
343 graph.add(
345 |inputs: &HashMap<String, String>, _| {
346 let mut result = HashMap::new();
347 if let Some(val) = inputs.get("raw").and_then(|s| s.parse::<i32>().ok()) {
348 result.insert("cleaned".to_string(), (val / 10).to_string());
349 }
350 result
351 },
352 Some("Preprocess"),
353 Some(vec![("data", "raw")]),
354 Some(vec![("cleaned", "clean_data")])
355 );
356
357 let mut stats_branch = Graph::new();
359 stats_branch.add(
360 |inputs: &HashMap<String, String>, _| {
361 let mut result = HashMap::new();
362 if let Some(val) = inputs.get("data") {
363 result.insert("stats".to_string(), format!("Stats({})", val));
364 }
365 result
366 },
367 Some("Stats"),
368 Some(vec![("clean_data", "data")]),
369 Some(vec![("stats", "statistics")])
370 );
371
372 let mut ml_branch = Graph::new();
373 ml_branch.add(
374 |inputs: &HashMap<String, String>, _| {
375 let mut result = HashMap::new();
376 if let Some(val) = inputs.get("data") {
377 result.insert("prediction".to_string(), format!("Pred({})", val));
378 }
379 result
380 },
381 Some("ML"),
382 Some(vec![("clean_data", "data")]),
383 Some(vec![("prediction", "ml_result")])
384 );
385
386 let stats_id = graph.branch(stats_branch);
387 let ml_id = graph.branch(ml_branch);
388
389 graph.merge(
391 |inputs: &HashMap<String, String>, _| {
392 let mut result = HashMap::new();
393 let stats = inputs.get("stats_in").cloned().unwrap_or_default();
394 let ml = inputs.get("ml_in").cloned().unwrap_or_default();
395 result.insert("report".to_string(), format!("{} & {}", stats, ml));
396 result
397 },
398 Some("Combine"),
399 vec![
400 (stats_id, "statistics", "stats_in"),
401 (ml_id, "ml_result", "ml_in")
402 ],
403 Some(vec![("report", "final_report")])
404 );
405
406 graph.add(
408 |inputs: &HashMap<String, String>, _| {
409 let mut result = HashMap::new();
410 if let Some(report) = inputs.get("report") {
411 result.insert("formatted".to_string(), format!("[FINAL] {}", report));
412 }
413 result
414 },
415 Some("Format"),
416 Some(vec![("final_report", "report")]),
417 Some(vec![("formatted", "output")])
418 );
419
420 let dag = graph.build();
421 println!("\n📊 Execution:");
422 let context = dag.execute(false, None);
423
424 println!(" Step 1: Ingest → data = {}", context.get("data").unwrap());
425 println!(" Step 2: Preprocess → clean_data = {}", context.get("clean_data").unwrap());
426 println!(" Step 3: Branch A → statistics = {}", context.get("statistics").unwrap());
427 println!(" Branch B → ml_result = {}", context.get("ml_result").unwrap());
428 println!(" Step 4: Merge → final_report = {}", context.get("final_report").unwrap());
429 println!(" Step 5: Format → output = {}", context.get("output").unwrap());
430
431 println!("\n📈 DAG Statistics:");
432 let stats = dag.stats();
433 println!("{}", stats.summary());
434
435 println!("\n📋 Execution Order:");
436 for (level_idx, level) in dag.execution_levels().iter().enumerate() {
437 println!(" Level {}: {} nodes", level_idx, level.len());
438 for &node_id in level {
439 let node = dag.nodes().iter().find(|n| n.id == node_id).unwrap();
440 println!(" - {}", node.display_name());
441 }
442 }
443
444 println!("\n🔍 Mermaid Visualization:");
445 println!("{}", dag.to_mermaid());
446 println!();
447
448 println!("═══════════════════════════════════════════════════════════");
449 println!(" Demo Complete!");
450 println!("═══════════════════════════════════════════════════════════");
451}