33 cout <<
"=== Graph Serialization: Educational Examples ===\n\n";
39 cout <<
"--- Example 1: Saving Graph to File ---\n\n";
44 cout <<
"Building directed graph (workflow):\n";
45 cout <<
" Start -> Process1 -> Process2 -> End\n";
46 cout <<
" Process1 -> Process3 -> End\n\n";
48 auto start = g.insert_node({
"start", {
"Start",
"Node",
"Type:Source"}});
49 auto p1 = g.insert_node({
"p1", {
"Process1",
"CPU-Intensive"}});
50 auto p2 = g.insert_node({
"p2", {
"Process2",
"I/O-Intensive"}});
51 auto p3 = g.insert_node({
"p3", {
"Process3",
"Memory-Intensive"}});
52 auto end = g.insert_node({
"end", {
"End",
"Node",
"Type:Sink"}});
54 g.insert_arc(start, p1,
"trigger");
55 g.insert_arc(p1, p2,
"pass_data");
56 g.insert_arc(p1, p3,
"parallel");
57 g.insert_arc(p2, end,
"complete");
58 g.insert_arc(p3, end,
"complete");
60 cout <<
"Graph created: " << g.get_num_nodes() <<
" nodes, "
61 << g.get_num_arcs() <<
" arcs\n\n";
64 cout <<
"Saving to files...\n";
66 ofstream
nodes_file(
"/tmp/workflow_nodes.txt");
67 ofstream
arcs_file(
"/tmp/workflow_arcs.txt");
72 auto node = it.get_curr();
73 auto&
info = node->get_info();
84 auto arc = it.get_curr();
85 auto src = g.get_src_node(arc);
86 auto tgt = g.get_tgt_node(arc);
89 << tgt->get_info().first;
90 if (!arc->get_info().empty())
98 cout <<
" Nodes saved to: /tmp/workflow_nodes.txt\n";
99 cout <<
" Arcs saved to: /tmp/workflow_arcs.txt\n\n";
101 cout <<
"FILE CONTENTS:\n";
102 cout <<
"Nodes file:\n";
103 cout <<
" start|Start|Node|Type:Source\n";
104 cout <<
" p1|Process1|CPU-Intensive\n";
106 cout <<
"Arcs file:\n";
107 cout <<
" start p1 trigger\n";
108 cout <<
" p1 p2 pass_data\n";
116 cout <<
"--- Example 2: Loading Graph from File ---\n\n";
119 ifstream
nodes_file(
"/tmp/workflow_nodes.txt");
120 ifstream
arcs_file(
"/tmp/workflow_arcs.txt");
124 cout <<
"ERROR: Could not open saved files\n";
125 cout <<
"Make sure Example 1 ran successfully\n\n";
132 cout <<
"Loading graph from files...\n";
139 cout <<
"Loaded nodes:\n";
142 auto node = it.get_curr();
143 auto&
info = node->get_info();
145 cout <<
" ID: " <<
info.first <<
", Fields: ";
146 for (
size_t i = 0; i <
info.second.
size(); ++i)
148 if (i > 0)
cout <<
", ";
154 cout <<
"\nKEY INSIGHT: Graph structure perfectly preserved\n";
155 cout <<
" All nodes, arcs, and data restored\n\n";
163 cout <<
"--- Example 3: Round-Trip Test (Save → Load → Verify) ---\n\n";
167 auto n1 =
original.insert_node({
"1", {
"Node",
"One"}});
168 auto n2 =
original.insert_node({
"2", {
"Node",
"Two"}});
169 auto n3 =
original.insert_node({
"3", {
"Node",
"Three"}});
171 original.insert_arc(n1, n2,
"arc12");
172 original.insert_arc(n2, n3,
"arc23");
173 original.insert_arc(n3, n1,
"arc31");
175 cout <<
"Original graph: " <<
original.get_num_nodes() <<
" nodes, "
176 <<
original.get_num_arcs() <<
" arcs\n";
183 auto node = it.get_curr();
184 auto&
info = node->get_info();
193 auto arc = it.get_curr();
194 auto src =
original.get_src_node(arc);
195 auto tgt =
original.get_tgt_node(arc);
197 << tgt->get_info().first <<
" "
198 << arc->get_info() <<
"\n";
205 cout <<
"Loaded graph: " <<
loaded.get_num_nodes() <<
" nodes, "
206 <<
loaded.get_num_arcs() <<
" arcs\n\n";
213 cout <<
"✓ VERIFICATION PASSED: Structure preserved\n";
215 cout <<
"✗ VERIFICATION FAILED: Structure mismatch\n";
217 cout <<
"\nIMPORTANT: This format preserves:\n";
218 cout <<
" ✓ Node IDs and attributes\n";
219 cout <<
" ✓ Arc connectivity\n";
220 cout <<
" ✓ Arc labels/weights\n";
221 cout <<
" ✓ Directed graph structure\n\n";
228 cout <<
"--- Example 4: Error Handling ---\n\n";
230 cout <<
"COMMON ERRORS AND SOLUTIONS:\n\n";
232 cout <<
"1. File Not Found:\n";
233 cout <<
" ifstream file(\"nonexistent.txt\");\n";
234 cout <<
" if (!file) {\n";
235 cout <<
" cerr << \"ERROR: Cannot open file\\n\";\n";
236 cout <<
" return 1;\n";
239 cout <<
"2. Invalid Arc (node ID not found):\n";
240 cout <<
" Arc references node that doesn't exist\n";
241 cout <<
" Solution: Validate node IDs before loading arcs\n\n";
243 cout <<
"3. Malformed Data:\n";
244 cout <<
" Missing delimiters, incorrect format\n";
245 cout <<
" Solution: Use try-catch around load_digraph()\n\n";
247 cout <<
"4. Encoding Issues:\n";
248 cout <<
" Non-ASCII characters in node names\n";
249 cout <<
" Solution: Use UTF-8 encoding consistently\n\n";
256 cout <<
"--- Example 5: Performance Tips ---\n\n";
258 cout <<
"FOR LARGE GRAPHS:\n\n";
260 cout <<
"1. STREAMING:\n";
261 cout <<
" Don't load entire file into memory\n";
262 cout <<
" Process line by line\n\n";
264 cout <<
"2. BINARY FORMAT:\n";
265 cout <<
" Text files: human-readable but large\n";
266 cout <<
" Binary: compact but not portable\n";
267 cout <<
" Trade-off based on use case\n\n";
269 cout <<
"3. COMPRESSION:\n";
270 cout <<
" Use gzip for text files\n";
271 cout <<
" Can reduce size by 80-90%\n";
272 cout <<
" Read/write through compression library\n\n";
274 cout <<
"4. CHUNKING:\n";
275 cout <<
" Save/load in chunks for very large graphs\n";
276 cout <<
" Process incrementally\n\n";
279 cout <<
"=== SUMMARY: Graph Serialization Best Practices ===\n";
280 cout <<
"\n1. FILE FORMAT CHOICE:\n";
281 cout <<
" Text: Human-readable, easy to debug, larger files\n";
282 cout <<
" Binary: Compact, fast, not human-readable\n";
283 cout <<
" Choose based on needs (debugging vs production)\n";
284 cout <<
"\n2. ALWAYS VERIFY:\n";
285 cout <<
" After loading, check node/arc counts\n";
286 cout <<
" Validate graph properties (connectivity, etc.)\n";
287 cout <<
" Round-trip test: save → load → compare\n";
288 cout <<
"\n3. ERROR HANDLING:\n";
289 cout <<
" Check file open success\n";
290 cout <<
" Validate node IDs before creating arcs\n";
291 cout <<
" Use try-catch for parsing errors\n";
292 cout <<
"\n4. METADATA:\n";
293 cout <<
" Include version info in file header\n";
294 cout <<
" Add timestamp, graph name, etc.\n";
295 cout <<
" Document file format in comments\n";
296 cout <<
"\n5. LARGE GRAPHS:\n";
297 cout <<
" Use streaming for memory efficiency\n";
298 cout <<
" Consider compression (gzip)\n";
299 cout <<
" Chunk processing for huge graphs\n";
300 cout <<
"\n6. APPLICATIONS:\n";
301 cout <<
" * Checkpoint long-running algorithms\n";
302 cout <<
" * Share datasets between researchers\n";
303 cout <<
" * Version control for graph evolution\n";
304 cout <<
" * Backup and disaster recovery\n";
Generic directed graph (digraph) wrapper template.
void next()
Advances the iterator to the next filtered element.
size_t size() const noexcept
Count the number of elements of the list.
Filtered iterator on the nodes of a graph.
void load_digraph(Digrafo &g, std::istream &nodes_input, std::istream &arcs_input)
Load nodes and arcs from streams into the directed graph.
Utilities for loading directed graphs from pipe-separated files.
Main namespace for Aleph-w library functions.
DynList< T > maps(const C &c, Op op)
Classic map operation.
Filtered iterator on all the arcs of a graph.