pub struct ExecutionResult {
pub context: ExecutionContext,
pub node_outputs: HashMap<NodeId, HashMap<String, String>>,
pub branch_outputs: HashMap<usize, HashMap<String, String>>,
}Expand description
Execution result that tracks outputs per node and per branch
Fields§
§context: ExecutionContextGlobal execution context (all variables accessible by broadcast name)
node_outputs: HashMap<NodeId, HashMap<String, String>>Outputs per node (node_id -> HashMap of output variables)
branch_outputs: HashMap<usize, HashMap<String, String>>Outputs per branch (branch_id -> HashMap of output variables)
Implementations§
Source§impl ExecutionResult
impl ExecutionResult
Sourcepub fn get(&self, key: &str) -> Option<&String>
pub fn get(&self, key: &str) -> Option<&String>
Get a value from the global context
Examples found in repository?
examples/per_node_output_access.rs (line 285)
225fn demo_variant_per_node_access() {
226 println!("─────────────────────────────────────────────────────────");
227 println!("Demo 3: Variant Outputs with Per-Node Tracking");
228 println!("─────────────────────────────────────────────────────────\n");
229
230 let mut graph = Graph::new();
231
232 // Source node
233 graph.add(
234 |_: &HashMap<String, String>, _| {
235 let mut result = HashMap::new();
236 result.insert("base_value".to_string(), "10".to_string());
237 result
238 },
239 Some("Source"),
240 None,
241 Some(vec![("base_value", "data")])
242 );
243
244 // Variant factory for scaling
245 fn make_scaler(factor: f64) -> impl Fn(&HashMap<String, String>, &HashMap<String, String>) -> HashMap<String, String> {
246 move |inputs: &HashMap<String, String>, _| {
247 let value = inputs.get("input_data").unwrap().parse::<f64>().unwrap();
248 let mut result = HashMap::new();
249 result.insert("scaled_value".to_string(), (value * factor).to_string());
250 result
251 }
252 }
253
254 // Create variants with unique output names to preserve all results
255 graph.variant(
256 make_scaler,
257 vec![2.0, 3.0, 5.0],
258 Some("Scale"),
259 Some(vec![("data", "input_data")]),
260 Some(vec![("scaled_value", "result")]) // Note: will overwrite in global context
261 );
262
263 let dag = graph.build();
264 let result = dag.execute_detailed(false, None);
265
266 println!("🌍 Global Context (note: 'result' contains last variant's output):");
267 for (key, value) in &result.context {
268 println!(" {} = {}", key, value);
269 }
270
271 println!("\n📦 Per-Node Outputs (each variant tracked separately):");
272
273 // Node 0 is the source
274 // Nodes 1, 2, 3 are the variant nodes (2x, 3x, 5x scalers)
275 for node_id in 1..=3 {
276 println!("\nNode {} (Variant Scaler) outputs:", node_id);
277 if let Some(outputs) = result.get_node_outputs(node_id) {
278 for (key, value) in outputs {
279 println!(" {} = {}", key, value);
280 }
281 }
282 }
283
284 println!("\n💡 Key Insight:");
285 println!(" - Global context has 'result' = {} (last variant overwrites)", result.get("result").unwrap());
286 println!(" - But per-node outputs preserve ALL variant results:");
287 println!(" Node 1 (2x): result = {}", result.get_from_node(1, "result").unwrap());
288 println!(" Node 2 (3x): result = {}", result.get_from_node(2, "result").unwrap());
289 println!(" Node 3 (5x): result = {}", result.get_from_node(3, "result").unwrap());
290
291 println!();
292}Sourcepub fn get_node_outputs(
&self,
node_id: NodeId,
) -> Option<&HashMap<String, String>>
pub fn get_node_outputs( &self, node_id: NodeId, ) -> Option<&HashMap<String, String>>
Get all outputs from a specific node
Examples found in repository?
examples/per_node_output_access.rs (line 80)
24fn demo_per_node_access() {
25 println!("─────────────────────────────────────────────────────────");
26 println!("Demo 1: Per-Node Output Access");
27 println!("─────────────────────────────────────────────────────────\n");
28
29 let mut graph = Graph::new();
30
31 // Node 0: Source
32 graph.add(
33 |_: &HashMap<String, String>, _| {
34 let mut result = HashMap::new();
35 result.insert("value".to_string(), "10".to_string());
36 result
37 },
38 Some("Source"),
39 None,
40 Some(vec![("value", "initial_data")])
41 );
42
43 // Node 1: Double
44 graph.add(
45 |inputs: &HashMap<String, String>, _| {
46 let value = inputs.get("in").unwrap().parse::<i32>().unwrap();
47 let mut result = HashMap::new();
48 result.insert("doubled".to_string(), (value * 2).to_string());
49 result
50 },
51 Some("Double"),
52 Some(vec![("initial_data", "in")]),
53 Some(vec![("doubled", "doubled_data")])
54 );
55
56 // Node 2: Add Ten
57 graph.add(
58 |inputs: &HashMap<String, String>, _| {
59 let value = inputs.get("in").unwrap().parse::<i32>().unwrap();
60 let mut result = HashMap::new();
61 result.insert("added".to_string(), (value + 10).to_string());
62 result
63 },
64 Some("AddTen"),
65 Some(vec![("doubled_data", "in")]),
66 Some(vec![("added", "final_result")])
67 );
68
69 // Execute and get detailed results
70 let dag = graph.build();
71 let result = dag.execute_detailed(false, None);
72
73 println!("🌍 Global Context (all variables):");
74 for (key, value) in &result.context {
75 println!(" {} = {}", key, value);
76 }
77
78 println!("\n📦 Per-Node Outputs:");
79 println!("\nNode 0 (Source) outputs:");
80 if let Some(outputs) = result.get_node_outputs(0) {
81 for (key, value) in outputs {
82 println!(" {} = {}", key, value);
83 }
84 }
85
86 println!("\nNode 1 (Double) outputs:");
87 if let Some(outputs) = result.get_node_outputs(1) {
88 for (key, value) in outputs {
89 println!(" {} = {}", key, value);
90 }
91 }
92
93 println!("\nNode 2 (AddTen) outputs:");
94 if let Some(outputs) = result.get_node_outputs(2) {
95 for (key, value) in outputs {
96 println!(" {} = {}", key, value);
97 }
98 }
99
100 println!("\n🎯 Accessing specific node outputs:");
101 if let Some(value) = result.get_from_node(0, "initial_data") {
102 println!(" Node 0 'initial_data': {}", value);
103 }
104 if let Some(value) = result.get_from_node(1, "doubled_data") {
105 println!(" Node 1 'doubled_data': {}", value);
106 }
107 if let Some(value) = result.get_from_node(2, "final_result") {
108 println!(" Node 2 'final_result': {}", value);
109 }
110
111 println!();
112}
113
114fn demo_per_branch_access() {
115 println!("─────────────────────────────────────────────────────────");
116 println!("Demo 2: Per-Branch Output Access");
117 println!("─────────────────────────────────────────────────────────\n");
118
119 let mut graph = Graph::new();
120
121 // Main graph: Source node
122 graph.add(
123 |_: &HashMap<String, String>, _| {
124 let mut result = HashMap::new();
125 result.insert("dataset".to_string(), "100".to_string());
126 result
127 },
128 Some("Source"),
129 None,
130 Some(vec![("dataset", "data")])
131 );
132
133 // Branch A: Statistics
134 let mut branch_a = Graph::new();
135 branch_a.add(
136 |inputs: &HashMap<String, String>, _| {
137 let value = inputs.get("input").unwrap();
138 let mut result = HashMap::new();
139 result.insert("stat_result".to_string(), format!("Mean of {}", value));
140 result
141 },
142 Some("Statistics"),
143 Some(vec![("data", "input")]),
144 Some(vec![("stat_result", "statistics")])
145 );
146
147 // Branch B: Model Training
148 let mut branch_b = Graph::new();
149 branch_b.add(
150 |inputs: &HashMap<String, String>, _| {
151 let value = inputs.get("input").unwrap();
152 let mut result = HashMap::new();
153 result.insert("model_result".to_string(), format!("Model trained on {}", value));
154 result
155 },
156 Some("ModelTraining"),
157 Some(vec![("data", "input")]),
158 Some(vec![("model_result", "trained_model")])
159 );
160
161 // Branch C: Visualization
162 let mut branch_c = Graph::new();
163 branch_c.add(
164 |inputs: &HashMap<String, String>, _| {
165 let value = inputs.get("input").unwrap();
166 let mut result = HashMap::new();
167 result.insert("viz_result".to_string(), format!("Plot of {}", value));
168 result
169 },
170 Some("Visualization"),
171 Some(vec![("data", "input")]),
172 Some(vec![("viz_result", "plot")])
173 );
174
175 let branch_a_id = graph.branch(branch_a);
176 let branch_b_id = graph.branch(branch_b);
177 let branch_c_id = graph.branch(branch_c);
178
179 // Execute and get detailed results
180 let dag = graph.build();
181 let result = dag.execute_detailed(false, None);
182
183 println!("🌍 Global Context:");
184 for (key, value) in &result.context {
185 println!(" {} = {}", key, value);
186 }
187
188 println!("\n🌿 Per-Branch Outputs:");
189
190 println!("\nBranch {} (Statistics) outputs:", branch_a_id);
191 if let Some(outputs) = result.get_branch_outputs(branch_a_id) {
192 for (key, value) in outputs {
193 println!(" {} = {}", key, value);
194 }
195 }
196
197 println!("\nBranch {} (Model Training) outputs:", branch_b_id);
198 if let Some(outputs) = result.get_branch_outputs(branch_b_id) {
199 for (key, value) in outputs {
200 println!(" {} = {}", key, value);
201 }
202 }
203
204 println!("\nBranch {} (Visualization) outputs:", branch_c_id);
205 if let Some(outputs) = result.get_branch_outputs(branch_c_id) {
206 for (key, value) in outputs {
207 println!(" {} = {}", key, value);
208 }
209 }
210
211 println!("\n🎯 Accessing specific branch outputs:");
212 if let Some(value) = result.get_from_branch(branch_a_id, "statistics") {
213 println!(" Branch {} 'statistics': {}", branch_a_id, value);
214 }
215 if let Some(value) = result.get_from_branch(branch_b_id, "trained_model") {
216 println!(" Branch {} 'trained_model': {}", branch_b_id, value);
217 }
218 if let Some(value) = result.get_from_branch(branch_c_id, "plot") {
219 println!(" Branch {} 'plot': {}", branch_c_id, value);
220 }
221
222 println!();
223}
224
225fn demo_variant_per_node_access() {
226 println!("─────────────────────────────────────────────────────────");
227 println!("Demo 3: Variant Outputs with Per-Node Tracking");
228 println!("─────────────────────────────────────────────────────────\n");
229
230 let mut graph = Graph::new();
231
232 // Source node
233 graph.add(
234 |_: &HashMap<String, String>, _| {
235 let mut result = HashMap::new();
236 result.insert("base_value".to_string(), "10".to_string());
237 result
238 },
239 Some("Source"),
240 None,
241 Some(vec![("base_value", "data")])
242 );
243
244 // Variant factory for scaling
245 fn make_scaler(factor: f64) -> impl Fn(&HashMap<String, String>, &HashMap<String, String>) -> HashMap<String, String> {
246 move |inputs: &HashMap<String, String>, _| {
247 let value = inputs.get("input_data").unwrap().parse::<f64>().unwrap();
248 let mut result = HashMap::new();
249 result.insert("scaled_value".to_string(), (value * factor).to_string());
250 result
251 }
252 }
253
254 // Create variants with unique output names to preserve all results
255 graph.variant(
256 make_scaler,
257 vec![2.0, 3.0, 5.0],
258 Some("Scale"),
259 Some(vec![("data", "input_data")]),
260 Some(vec![("scaled_value", "result")]) // Note: will overwrite in global context
261 );
262
263 let dag = graph.build();
264 let result = dag.execute_detailed(false, None);
265
266 println!("🌍 Global Context (note: 'result' contains last variant's output):");
267 for (key, value) in &result.context {
268 println!(" {} = {}", key, value);
269 }
270
271 println!("\n📦 Per-Node Outputs (each variant tracked separately):");
272
273 // Node 0 is the source
274 // Nodes 1, 2, 3 are the variant nodes (2x, 3x, 5x scalers)
275 for node_id in 1..=3 {
276 println!("\nNode {} (Variant Scaler) outputs:", node_id);
277 if let Some(outputs) = result.get_node_outputs(node_id) {
278 for (key, value) in outputs {
279 println!(" {} = {}", key, value);
280 }
281 }
282 }
283
284 println!("\n💡 Key Insight:");
285 println!(" - Global context has 'result' = {} (last variant overwrites)", result.get("result").unwrap());
286 println!(" - But per-node outputs preserve ALL variant results:");
287 println!(" Node 1 (2x): result = {}", result.get_from_node(1, "result").unwrap());
288 println!(" Node 2 (3x): result = {}", result.get_from_node(2, "result").unwrap());
289 println!(" Node 3 (5x): result = {}", result.get_from_node(3, "result").unwrap());
290
291 println!();
292}Sourcepub fn get_branch_outputs(
&self,
branch_id: usize,
) -> Option<&HashMap<String, String>>
pub fn get_branch_outputs( &self, branch_id: usize, ) -> Option<&HashMap<String, String>>
Get all outputs from a specific branch
Examples found in repository?
examples/per_node_output_access.rs (line 191)
114fn demo_per_branch_access() {
115 println!("─────────────────────────────────────────────────────────");
116 println!("Demo 2: Per-Branch Output Access");
117 println!("─────────────────────────────────────────────────────────\n");
118
119 let mut graph = Graph::new();
120
121 // Main graph: Source node
122 graph.add(
123 |_: &HashMap<String, String>, _| {
124 let mut result = HashMap::new();
125 result.insert("dataset".to_string(), "100".to_string());
126 result
127 },
128 Some("Source"),
129 None,
130 Some(vec![("dataset", "data")])
131 );
132
133 // Branch A: Statistics
134 let mut branch_a = Graph::new();
135 branch_a.add(
136 |inputs: &HashMap<String, String>, _| {
137 let value = inputs.get("input").unwrap();
138 let mut result = HashMap::new();
139 result.insert("stat_result".to_string(), format!("Mean of {}", value));
140 result
141 },
142 Some("Statistics"),
143 Some(vec![("data", "input")]),
144 Some(vec![("stat_result", "statistics")])
145 );
146
147 // Branch B: Model Training
148 let mut branch_b = Graph::new();
149 branch_b.add(
150 |inputs: &HashMap<String, String>, _| {
151 let value = inputs.get("input").unwrap();
152 let mut result = HashMap::new();
153 result.insert("model_result".to_string(), format!("Model trained on {}", value));
154 result
155 },
156 Some("ModelTraining"),
157 Some(vec![("data", "input")]),
158 Some(vec![("model_result", "trained_model")])
159 );
160
161 // Branch C: Visualization
162 let mut branch_c = Graph::new();
163 branch_c.add(
164 |inputs: &HashMap<String, String>, _| {
165 let value = inputs.get("input").unwrap();
166 let mut result = HashMap::new();
167 result.insert("viz_result".to_string(), format!("Plot of {}", value));
168 result
169 },
170 Some("Visualization"),
171 Some(vec![("data", "input")]),
172 Some(vec![("viz_result", "plot")])
173 );
174
175 let branch_a_id = graph.branch(branch_a);
176 let branch_b_id = graph.branch(branch_b);
177 let branch_c_id = graph.branch(branch_c);
178
179 // Execute and get detailed results
180 let dag = graph.build();
181 let result = dag.execute_detailed(false, None);
182
183 println!("🌍 Global Context:");
184 for (key, value) in &result.context {
185 println!(" {} = {}", key, value);
186 }
187
188 println!("\n🌿 Per-Branch Outputs:");
189
190 println!("\nBranch {} (Statistics) outputs:", branch_a_id);
191 if let Some(outputs) = result.get_branch_outputs(branch_a_id) {
192 for (key, value) in outputs {
193 println!(" {} = {}", key, value);
194 }
195 }
196
197 println!("\nBranch {} (Model Training) outputs:", branch_b_id);
198 if let Some(outputs) = result.get_branch_outputs(branch_b_id) {
199 for (key, value) in outputs {
200 println!(" {} = {}", key, value);
201 }
202 }
203
204 println!("\nBranch {} (Visualization) outputs:", branch_c_id);
205 if let Some(outputs) = result.get_branch_outputs(branch_c_id) {
206 for (key, value) in outputs {
207 println!(" {} = {}", key, value);
208 }
209 }
210
211 println!("\n🎯 Accessing specific branch outputs:");
212 if let Some(value) = result.get_from_branch(branch_a_id, "statistics") {
213 println!(" Branch {} 'statistics': {}", branch_a_id, value);
214 }
215 if let Some(value) = result.get_from_branch(branch_b_id, "trained_model") {
216 println!(" Branch {} 'trained_model': {}", branch_b_id, value);
217 }
218 if let Some(value) = result.get_from_branch(branch_c_id, "plot") {
219 println!(" Branch {} 'plot': {}", branch_c_id, value);
220 }
221
222 println!();
223}Sourcepub fn get_from_node(&self, node_id: NodeId, key: &str) -> Option<&String>
pub fn get_from_node(&self, node_id: NodeId, key: &str) -> Option<&String>
Get a specific variable from a node
Examples found in repository?
examples/per_node_output_access.rs (line 101)
24fn demo_per_node_access() {
25 println!("─────────────────────────────────────────────────────────");
26 println!("Demo 1: Per-Node Output Access");
27 println!("─────────────────────────────────────────────────────────\n");
28
29 let mut graph = Graph::new();
30
31 // Node 0: Source
32 graph.add(
33 |_: &HashMap<String, String>, _| {
34 let mut result = HashMap::new();
35 result.insert("value".to_string(), "10".to_string());
36 result
37 },
38 Some("Source"),
39 None,
40 Some(vec![("value", "initial_data")])
41 );
42
43 // Node 1: Double
44 graph.add(
45 |inputs: &HashMap<String, String>, _| {
46 let value = inputs.get("in").unwrap().parse::<i32>().unwrap();
47 let mut result = HashMap::new();
48 result.insert("doubled".to_string(), (value * 2).to_string());
49 result
50 },
51 Some("Double"),
52 Some(vec![("initial_data", "in")]),
53 Some(vec![("doubled", "doubled_data")])
54 );
55
56 // Node 2: Add Ten
57 graph.add(
58 |inputs: &HashMap<String, String>, _| {
59 let value = inputs.get("in").unwrap().parse::<i32>().unwrap();
60 let mut result = HashMap::new();
61 result.insert("added".to_string(), (value + 10).to_string());
62 result
63 },
64 Some("AddTen"),
65 Some(vec![("doubled_data", "in")]),
66 Some(vec![("added", "final_result")])
67 );
68
69 // Execute and get detailed results
70 let dag = graph.build();
71 let result = dag.execute_detailed(false, None);
72
73 println!("🌍 Global Context (all variables):");
74 for (key, value) in &result.context {
75 println!(" {} = {}", key, value);
76 }
77
78 println!("\n📦 Per-Node Outputs:");
79 println!("\nNode 0 (Source) outputs:");
80 if let Some(outputs) = result.get_node_outputs(0) {
81 for (key, value) in outputs {
82 println!(" {} = {}", key, value);
83 }
84 }
85
86 println!("\nNode 1 (Double) outputs:");
87 if let Some(outputs) = result.get_node_outputs(1) {
88 for (key, value) in outputs {
89 println!(" {} = {}", key, value);
90 }
91 }
92
93 println!("\nNode 2 (AddTen) outputs:");
94 if let Some(outputs) = result.get_node_outputs(2) {
95 for (key, value) in outputs {
96 println!(" {} = {}", key, value);
97 }
98 }
99
100 println!("\n🎯 Accessing specific node outputs:");
101 if let Some(value) = result.get_from_node(0, "initial_data") {
102 println!(" Node 0 'initial_data': {}", value);
103 }
104 if let Some(value) = result.get_from_node(1, "doubled_data") {
105 println!(" Node 1 'doubled_data': {}", value);
106 }
107 if let Some(value) = result.get_from_node(2, "final_result") {
108 println!(" Node 2 'final_result': {}", value);
109 }
110
111 println!();
112}
113
114fn demo_per_branch_access() {
115 println!("─────────────────────────────────────────────────────────");
116 println!("Demo 2: Per-Branch Output Access");
117 println!("─────────────────────────────────────────────────────────\n");
118
119 let mut graph = Graph::new();
120
121 // Main graph: Source node
122 graph.add(
123 |_: &HashMap<String, String>, _| {
124 let mut result = HashMap::new();
125 result.insert("dataset".to_string(), "100".to_string());
126 result
127 },
128 Some("Source"),
129 None,
130 Some(vec![("dataset", "data")])
131 );
132
133 // Branch A: Statistics
134 let mut branch_a = Graph::new();
135 branch_a.add(
136 |inputs: &HashMap<String, String>, _| {
137 let value = inputs.get("input").unwrap();
138 let mut result = HashMap::new();
139 result.insert("stat_result".to_string(), format!("Mean of {}", value));
140 result
141 },
142 Some("Statistics"),
143 Some(vec![("data", "input")]),
144 Some(vec![("stat_result", "statistics")])
145 );
146
147 // Branch B: Model Training
148 let mut branch_b = Graph::new();
149 branch_b.add(
150 |inputs: &HashMap<String, String>, _| {
151 let value = inputs.get("input").unwrap();
152 let mut result = HashMap::new();
153 result.insert("model_result".to_string(), format!("Model trained on {}", value));
154 result
155 },
156 Some("ModelTraining"),
157 Some(vec![("data", "input")]),
158 Some(vec![("model_result", "trained_model")])
159 );
160
161 // Branch C: Visualization
162 let mut branch_c = Graph::new();
163 branch_c.add(
164 |inputs: &HashMap<String, String>, _| {
165 let value = inputs.get("input").unwrap();
166 let mut result = HashMap::new();
167 result.insert("viz_result".to_string(), format!("Plot of {}", value));
168 result
169 },
170 Some("Visualization"),
171 Some(vec![("data", "input")]),
172 Some(vec![("viz_result", "plot")])
173 );
174
175 let branch_a_id = graph.branch(branch_a);
176 let branch_b_id = graph.branch(branch_b);
177 let branch_c_id = graph.branch(branch_c);
178
179 // Execute and get detailed results
180 let dag = graph.build();
181 let result = dag.execute_detailed(false, None);
182
183 println!("🌍 Global Context:");
184 for (key, value) in &result.context {
185 println!(" {} = {}", key, value);
186 }
187
188 println!("\n🌿 Per-Branch Outputs:");
189
190 println!("\nBranch {} (Statistics) outputs:", branch_a_id);
191 if let Some(outputs) = result.get_branch_outputs(branch_a_id) {
192 for (key, value) in outputs {
193 println!(" {} = {}", key, value);
194 }
195 }
196
197 println!("\nBranch {} (Model Training) outputs:", branch_b_id);
198 if let Some(outputs) = result.get_branch_outputs(branch_b_id) {
199 for (key, value) in outputs {
200 println!(" {} = {}", key, value);
201 }
202 }
203
204 println!("\nBranch {} (Visualization) outputs:", branch_c_id);
205 if let Some(outputs) = result.get_branch_outputs(branch_c_id) {
206 for (key, value) in outputs {
207 println!(" {} = {}", key, value);
208 }
209 }
210
211 println!("\n🎯 Accessing specific branch outputs:");
212 if let Some(value) = result.get_from_branch(branch_a_id, "statistics") {
213 println!(" Branch {} 'statistics': {}", branch_a_id, value);
214 }
215 if let Some(value) = result.get_from_branch(branch_b_id, "trained_model") {
216 println!(" Branch {} 'trained_model': {}", branch_b_id, value);
217 }
218 if let Some(value) = result.get_from_branch(branch_c_id, "plot") {
219 println!(" Branch {} 'plot': {}", branch_c_id, value);
220 }
221
222 println!();
223}
224
225fn demo_variant_per_node_access() {
226 println!("─────────────────────────────────────────────────────────");
227 println!("Demo 3: Variant Outputs with Per-Node Tracking");
228 println!("─────────────────────────────────────────────────────────\n");
229
230 let mut graph = Graph::new();
231
232 // Source node
233 graph.add(
234 |_: &HashMap<String, String>, _| {
235 let mut result = HashMap::new();
236 result.insert("base_value".to_string(), "10".to_string());
237 result
238 },
239 Some("Source"),
240 None,
241 Some(vec![("base_value", "data")])
242 );
243
244 // Variant factory for scaling
245 fn make_scaler(factor: f64) -> impl Fn(&HashMap<String, String>, &HashMap<String, String>) -> HashMap<String, String> {
246 move |inputs: &HashMap<String, String>, _| {
247 let value = inputs.get("input_data").unwrap().parse::<f64>().unwrap();
248 let mut result = HashMap::new();
249 result.insert("scaled_value".to_string(), (value * factor).to_string());
250 result
251 }
252 }
253
254 // Create variants with unique output names to preserve all results
255 graph.variant(
256 make_scaler,
257 vec![2.0, 3.0, 5.0],
258 Some("Scale"),
259 Some(vec![("data", "input_data")]),
260 Some(vec![("scaled_value", "result")]) // Note: will overwrite in global context
261 );
262
263 let dag = graph.build();
264 let result = dag.execute_detailed(false, None);
265
266 println!("🌍 Global Context (note: 'result' contains last variant's output):");
267 for (key, value) in &result.context {
268 println!(" {} = {}", key, value);
269 }
270
271 println!("\n📦 Per-Node Outputs (each variant tracked separately):");
272
273 // Node 0 is the source
274 // Nodes 1, 2, 3 are the variant nodes (2x, 3x, 5x scalers)
275 for node_id in 1..=3 {
276 println!("\nNode {} (Variant Scaler) outputs:", node_id);
277 if let Some(outputs) = result.get_node_outputs(node_id) {
278 for (key, value) in outputs {
279 println!(" {} = {}", key, value);
280 }
281 }
282 }
283
284 println!("\n💡 Key Insight:");
285 println!(" - Global context has 'result' = {} (last variant overwrites)", result.get("result").unwrap());
286 println!(" - But per-node outputs preserve ALL variant results:");
287 println!(" Node 1 (2x): result = {}", result.get_from_node(1, "result").unwrap());
288 println!(" Node 2 (3x): result = {}", result.get_from_node(2, "result").unwrap());
289 println!(" Node 3 (5x): result = {}", result.get_from_node(3, "result").unwrap());
290
291 println!();
292}
293
294fn demo_execution_history_tracking() {
295 println!("─────────────────────────────────────────────────────────");
296 println!("Demo 4: Execution History Tracking");
297 println!("─────────────────────────────────────────────────────────\n");
298
299 let mut graph = Graph::new();
300
301 // Multi-stage pipeline
302 graph.add(
303 |_: &HashMap<String, String>, _| {
304 let mut result = HashMap::new();
305 result.insert("raw".to_string(), "5".to_string());
306 result
307 },
308 Some("Load"),
309 None,
310 Some(vec![("raw", "input")])
311 );
312
313 graph.add(
314 |inputs: &HashMap<String, String>, _| {
315 let value = inputs.get("x").unwrap().parse::<i32>().unwrap();
316 let mut result = HashMap::new();
317 result.insert("cleaned".to_string(), (value + 1).to_string());
318 result
319 },
320 Some("Clean"),
321 Some(vec![("input", "x")]),
322 Some(vec![("cleaned", "clean_data")])
323 );
324
325 graph.add(
326 |inputs: &HashMap<String, String>, _| {
327 let value = inputs.get("x").unwrap().parse::<i32>().unwrap();
328 let mut result = HashMap::new();
329 result.insert("normalized".to_string(), (value * 10).to_string());
330 result
331 },
332 Some("Normalize"),
333 Some(vec![("clean_data", "x")]),
334 Some(vec![("normalized", "norm_data")])
335 );
336
337 graph.add(
338 |inputs: &HashMap<String, String>, _| {
339 let value = inputs.get("x").unwrap().parse::<i32>().unwrap();
340 let mut result = HashMap::new();
341 result.insert("transformed".to_string(), format!("FINAL_{}", value));
342 result
343 },
344 Some("Transform"),
345 Some(vec![("norm_data", "x")]),
346 Some(vec![("transformed", "output")])
347 );
348
349 let dag = graph.build();
350 let result = dag.execute_detailed(false, None);
351
352 println!("📊 Execution History (Data Flow Tracking):");
353 println!();
354 println!("Step-by-step transformation:");
355 println!(" 1. Load: input = {}", result.get_from_node(0, "input").unwrap());
356 println!(" 2. Clean: clean_data = {}", result.get_from_node(1, "clean_data").unwrap());
357 println!(" 3. Normalize: norm_data = {}", result.get_from_node(2, "norm_data").unwrap());
358 println!(" 4. Transform: output = {}", result.get_from_node(3, "output").unwrap());
359
360 println!("\n🔍 Debugging: Inspect any intermediate result:");
361 println!(" Need to debug the normalization step?");
362 println!(" Just check Node 2: {}", result.get_from_node(2, "norm_data").unwrap());
363
364 println!("\n✅ Benefits of Per-Node Access:");
365 println!(" ✓ Track data transformations step-by-step");
366 println!(" ✓ Debug issues by inspecting intermediate values");
367 println!(" ✓ Validate each processing stage independently");
368 println!(" ✓ Preserve all variant outputs even with name collisions");
369
370 println!();
371}Sourcepub fn get_from_branch(&self, branch_id: usize, key: &str) -> Option<&String>
pub fn get_from_branch(&self, branch_id: usize, key: &str) -> Option<&String>
Get a specific variable from a branch
Examples found in repository?
examples/per_node_output_access.rs (line 212)
114fn demo_per_branch_access() {
115 println!("─────────────────────────────────────────────────────────");
116 println!("Demo 2: Per-Branch Output Access");
117 println!("─────────────────────────────────────────────────────────\n");
118
119 let mut graph = Graph::new();
120
121 // Main graph: Source node
122 graph.add(
123 |_: &HashMap<String, String>, _| {
124 let mut result = HashMap::new();
125 result.insert("dataset".to_string(), "100".to_string());
126 result
127 },
128 Some("Source"),
129 None,
130 Some(vec![("dataset", "data")])
131 );
132
133 // Branch A: Statistics
134 let mut branch_a = Graph::new();
135 branch_a.add(
136 |inputs: &HashMap<String, String>, _| {
137 let value = inputs.get("input").unwrap();
138 let mut result = HashMap::new();
139 result.insert("stat_result".to_string(), format!("Mean of {}", value));
140 result
141 },
142 Some("Statistics"),
143 Some(vec![("data", "input")]),
144 Some(vec![("stat_result", "statistics")])
145 );
146
147 // Branch B: Model Training
148 let mut branch_b = Graph::new();
149 branch_b.add(
150 |inputs: &HashMap<String, String>, _| {
151 let value = inputs.get("input").unwrap();
152 let mut result = HashMap::new();
153 result.insert("model_result".to_string(), format!("Model trained on {}", value));
154 result
155 },
156 Some("ModelTraining"),
157 Some(vec![("data", "input")]),
158 Some(vec![("model_result", "trained_model")])
159 );
160
161 // Branch C: Visualization
162 let mut branch_c = Graph::new();
163 branch_c.add(
164 |inputs: &HashMap<String, String>, _| {
165 let value = inputs.get("input").unwrap();
166 let mut result = HashMap::new();
167 result.insert("viz_result".to_string(), format!("Plot of {}", value));
168 result
169 },
170 Some("Visualization"),
171 Some(vec![("data", "input")]),
172 Some(vec![("viz_result", "plot")])
173 );
174
175 let branch_a_id = graph.branch(branch_a);
176 let branch_b_id = graph.branch(branch_b);
177 let branch_c_id = graph.branch(branch_c);
178
179 // Execute and get detailed results
180 let dag = graph.build();
181 let result = dag.execute_detailed(false, None);
182
183 println!("🌍 Global Context:");
184 for (key, value) in &result.context {
185 println!(" {} = {}", key, value);
186 }
187
188 println!("\n🌿 Per-Branch Outputs:");
189
190 println!("\nBranch {} (Statistics) outputs:", branch_a_id);
191 if let Some(outputs) = result.get_branch_outputs(branch_a_id) {
192 for (key, value) in outputs {
193 println!(" {} = {}", key, value);
194 }
195 }
196
197 println!("\nBranch {} (Model Training) outputs:", branch_b_id);
198 if let Some(outputs) = result.get_branch_outputs(branch_b_id) {
199 for (key, value) in outputs {
200 println!(" {} = {}", key, value);
201 }
202 }
203
204 println!("\nBranch {} (Visualization) outputs:", branch_c_id);
205 if let Some(outputs) = result.get_branch_outputs(branch_c_id) {
206 for (key, value) in outputs {
207 println!(" {} = {}", key, value);
208 }
209 }
210
211 println!("\n🎯 Accessing specific branch outputs:");
212 if let Some(value) = result.get_from_branch(branch_a_id, "statistics") {
213 println!(" Branch {} 'statistics': {}", branch_a_id, value);
214 }
215 if let Some(value) = result.get_from_branch(branch_b_id, "trained_model") {
216 println!(" Branch {} 'trained_model': {}", branch_b_id, value);
217 }
218 if let Some(value) = result.get_from_branch(branch_c_id, "plot") {
219 println!(" Branch {} 'plot': {}", branch_c_id, value);
220 }
221
222 println!();
223}Sourcepub fn contains_key(&self, key: &str) -> bool
pub fn contains_key(&self, key: &str) -> bool
Check if a variable exists in global context
Trait Implementations§
Source§impl Clone for ExecutionResult
impl Clone for ExecutionResult
Source§fn clone(&self) -> ExecutionResult
fn clone(&self) -> ExecutionResult
Returns a duplicate of the value. Read more
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
Performs copy-assignment from
source. Read moreAuto Trait Implementations§
impl Freeze for ExecutionResult
impl RefUnwindSafe for ExecutionResult
impl Send for ExecutionResult
impl Sync for ExecutionResult
impl Unpin for ExecutionResult
impl UnwindSafe for ExecutionResult
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more