Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
load_digraph.H
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 version 2.0.0b
7 https://github.com/lrleon/Aleph-w
8
9 This file is part of Aleph-w library
10
11 Copyright (c) 2002-2026 Leandro Rabindranath Leon
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30*/
31
32
33#ifndef LOAD_DIGRAPH_H
34#define LOAD_DIGRAPH_H
35
83#include <fstream>
84#include <string>
85#include <tpl_graph.H>
86#include <topological_sort.H>
87#include <Tarjan.H>
88
89namespace Aleph
90{
91
93using Info_Nodo = std::pair<std::string, DynDlist<std::string>>;
94
97
100
103
115inline void split(const std::string & text,
116 const std::string & separators,
117 DynDlist<std::string> & words)
118{
119 const size_t n = text.length();
120 size_t start = text.find_first_not_of(separators);
121
122 while (start < n)
123 {
124 size_t stop = text.find_first_of(separators, start);
125 if (stop > n)
126 stop = n;
127 words.append(text.substr(start, stop - start));
128 start = text.find_first_not_of(separators, stop + 1);
129 }
130}
131
136{
142 bool operator()(const Info_Nodo & o1, const Info_Nodo & o2) const
143 {
144 return o1.first == o2.first;
145 }
146};
147
162inline Digrafo::Node * search_node(Digrafo & g, const std::string & s)
163{
164 // Linear search by id
165 for (auto it = g.get_node_it(); it.has_curr(); it.next_ne())
166 {
167 auto *n = it.get_curr();
168 if (n->get_info().first == s)
169 return n;
170 }
171 // Not found -> insert a node with empty fields list
173 return g.insert_node(Info_Nodo(s, empty_fields));
174}
175
177constexpr size_t MIN_NODE_FIELDS = 7;
178
201inline void load_digraph(Digrafo & g,
202 std::istream & nodes_input,
203 std::istream & arcs_input)
204{
205 std::string line;
206
207 // Skip header line if present
208 std::getline(nodes_input, line);
209
210 while (std::getline(nodes_input, line))
211 {
213 split(line, "|", fields);
214 if (fields.size() < MIN_NODE_FIELDS)
215 continue;
216 g.insert_node(Info_Nodo(fields[0], fields));
217 }
218
219 while (std::getline(arcs_input, line))
220 {
222 split(line, " ,", nums);
223 if (nums.size() < 2)
224 continue;
225 g.insert_arc(search_node(g, nums[0]), search_node(g, nums[1]));
226 }
227}
228
241
243inline bool with_power = false;
244
246inline bool with_nes = false;
247
249inline bool only_num = false;
250
252inline bool with_class = false;
253
255inline size_t font_size = 6;
256
258inline bool vertical = true;
259
261
280inline void generate_dot_file(Digrafo & g, std::ostream & output)
281{
282 output << "digraph G {\n"
283 << "fontsize = " << font_size << "\n";
284
285 for (Node_Iterator<Digrafo> it(g); it.has_curr(); it.next_ne())
286 {
287 Digrafo::Node *p = it.get_curr();
288 Info_Nodo & info = p->get_info();
289 output << info.first << " [color=";
290 DynDlist<std::string> & fields = info.second;
291 const std::string & plazo = fields[1];
292 if (plazo == "cp")
293 output << "Green";
294 else if (plazo == "mp")
295 output << "Yellow";
296 else if (plazo == "lp")
297 output << "Red";
298
299 output << " label=\"" << info.first;
300
301 if (not only_num)
302 output << "\\n" << fields[6];
303
304 if (with_power)
305 output << "\\nP=" << fields[5];
306
307 if (with_nes)
308 output << "\\n" << fields[4] << "%";
309
310 output << "\" ";
311
312 if (with_class)
313 {
314 const std::string & clase = fields[2];
315 if (clase == "it")
316 output << " shape = box ";
317 else if (clase == "ef")
318 output << " shape = ellipse ";
319 else if (clase == "pp")
320 output << " shape = hexagon ";
321 }
322
323 output << "]\n";
324 }
325
326 Path<Digrafo> p(g);
328 if (with_cycle)
329 {
330 output << "// WARNING: Cycle detected in ";
331 for (Path<Digrafo>::Iterator it(p); it.has_curr(); it.next_ne())
332 {
333 Info_Nodo & info = it.get_current_node_ne()->get_info();
334 output << "(" << info.first << ")" << info.second[6];
335 if (not it.is_in_last())
336 output << "->";
337 }
338 output << "\n";
339 }
340 else
341 {
343
345
346 for (auto it = ranks.get_it(); it.has_curr(); it.next_ne())
347 {
348 DynList<Digrafo::Node *> & level = it.get_curr();
349 output << "{ rank = same; \n";
350 for (auto ni = level.get_it(); ni.has_curr(); ni.next_ne())
351 output << ni.get_curr()->get_info().first << " ";
352 output << "}\n";
353 }
354 }
355
356 for (Arc_Iterator<Digrafo> it(g); it.has_curr(); it.next_ne())
357 {
358 Digrafo::Arc *a = it.get_curr();
359 output << g.get_src_node(a)->get_info().first << " -> "
360 << g.get_tgt_node(a)->get_info().first << "\n";
361 }
362
363 output << "}\n";
364}
365
366} // end namespace Aleph
367
368// Backward compatibility: expose types and functions at global scope
369using Aleph::Info_Nodo;
370using Aleph::Nodo;
371using Aleph::Arco;
372using Aleph::Digrafo;
373using Aleph::split;
379using Aleph::with_nes;
380using Aleph::only_num;
382using Aleph::font_size;
383using Aleph::vertical;
385
386#endif // LOAD_DIGRAPH_H
Tarjan's algorithm for strongly connected components.
Generic directed graph (digraph) wrapper template.
Definition graph-dry.H:3848
typename BaseGraph::Arc Arc
Definition graph-dry.H:3852
typename BaseGraph::Node Node
Definition graph-dry.H:3851
Dynamic doubly linked list with O(1) size and bidirectional access.
const size_t & size() const noexcept
Return the number of elements (constant time)
T & append(const T &item)
Append a copied item at the end of the list.
Dynamic singly linked list with functional programming support.
Definition htlist.H:1423
void next_ne() noexcept
Advances the iterator to the next filtered element (noexcept version).
size_t size() const noexcept
Count the number of elements of the list.
Definition htlist.H:1319
Filtered iterator on the nodes of a graph.
Definition tpl_graph.H:1206
Iterator on nodes and arcs of a path.
Definition tpl_graph.H:3201
Path on a graph.
Definition tpl_graph.H:2669
size_t length() const noexcept
Count the number of elements of a container.
Definition ah-dry.H:1385
auto get_it() const
Return a properly initialized iterator positioned at the first item on the container.
Definition ah-dry.H:190
bool with_power
Configuration options for DOT file generation.
bool with_class
If true, set node shapes based on class field.
Digrafo::Node * search_node(Digrafo &g, const std::string &s)
Find or create a node by ID.
bool vertical
If true, use vertical layout (default).
void load_digraph(Digrafo &g, std::istream &nodes_input, std::istream &arcs_input)
Load nodes and arcs from streams into the directed graph.
bool only_num
If true, show only the node number, not the full label.
size_t font_size
Font size for the DOT output.
void generate_dot_file(Digrafo &g, std::ostream &output)
Generate a DOT representation of the digraph.
bool with_nes
If true, include NES percentage in node labels.
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
static int search_node(DynArray< typename GT::Node * > &nodes, typename GT::Node *p) noexcept
constexpr size_t MIN_NODE_FIELDS
Minimum expected columns for a node record.
Array< size_t > ranks(const Array< T > &array)
Computes the rank of each element in an Array.
Definition ahSort.H:524
std::pair< std::string, DynDlist< std::string > > Info_Nodo
Node payload: (id, fields) where fields come from the input row.
std::vector< std::string > & split(const std::string &s, const char delim, std::vector< std::string > &elems)
Split a std::string by a single delimiter character.
DynList< T > maps(const C &c, Op op)
Classic map operation.
Filtered iterator on all the arcs of a graph.
Definition tpl_graph.H:1164
Functor to compare nodes by their ID.
bool operator()(const Info_Nodo &o1, const Info_Nodo &o2) const
Compare two node info objects by ID.
Arc of graph implemented with double-linked adjacency lists.
Definition tpl_graph.H:222
Node belonging to a graph implemented with a double linked adjacency list.
Definition tpl_graph.H:121
Topological sorting algorithms for directed acyclic graphs (DAGs).
Generic graph and digraph implementations.
ofstream output
Definition writeHeap.C:213