Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
graph_coloring_graphviz_example.cc
Go to the documentation of this file.
1/*
2 Aleph_w
3
4 Data structures & Algorithms
5 version 2.0.0b
6 https://github.com/lrleon/Aleph-w
7
8 This file is part of Aleph-w library
9
10 Copyright (c) 2002-2026 Leandro Rabindranath Leon
11
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files (the "Software"), to deal
14 in the Software without restriction, including without limitation the rights
15 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be included in all
20 copies or substantial portions of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 SOFTWARE.
29*/
30
56#include <fstream>
57#include <iostream>
58#include <string>
59
60#include <ah-errors.H>
61#include <Graph_Coloring.H>
62#include <tpl_graph.H>
63
64using namespace Aleph;
65using namespace std;
66
70
71static constexpr size_t Crown_Size = 5;
72
73static const char *fill_palette[] = {"#f94144", "#277da1", "#90be6d", "#f8961e", "#7b2cbf", "#577590"};
74
75static const char *font_palette[] = {"#ffffff", "#ffffff", "#111111", "#111111", "#ffffff", "#ffffff"};
76
77static const char *palette_names[] = {"coral", "ocean", "sage", "amber", "violet", "slate"};
78
79static const char *left_positions[Crown_Size] = {"0,8!", "0,6!", "0,4!", "0,2!", "0,0!"};
80
81static const char *right_positions[Crown_Size] = {"5,8!", "5,6!", "5,4!", "5,2!", "5,0!"};
82
83static constexpr size_t palette_size()
84{
85 return sizeof(fill_palette) / sizeof(fill_palette[0]);
86}
87
88static string color_name(size_t c)
89{
90 return palette_names[c % palette_size()];
91}
92
93static string color_legend(size_t num_colors)
94{
95 string legend;
96
97 for (size_t c = 0; c < num_colors; ++c)
98 {
99 if (not legend.empty())
100 legend += ", ";
101
102 legend += "c" + to_string(c) + "=" + color_name(c);
103 }
104
105 return legend;
106}
107
108static void build_crown_graph(Graph &g, Node *left[Crown_Size], Node *right[Crown_Size])
109{
110 for (size_t i = 0; i < Crown_Size; ++i)
111 {
112 left[i] = g.insert_node("u" + to_string(i));
113 right[i] = g.insert_node("v" + to_string(i));
114 }
115
116 for (size_t i = 0; i < Crown_Size; ++i)
117 for (size_t j = 0; j < Crown_Size; ++j)
118 if (i != j)
119 g.insert_arc(left[i], right[j]);
120}
121
122static void locate_node(Node *node, Node *left[Crown_Size], Node *right[Crown_Size], bool &is_left, size_t &index)
123{
124 for (size_t i = 0; i < Crown_Size; ++i)
125 {
126 if (left[i] == node)
127 {
128 is_left = true;
129 index = i;
130 return;
131 }
132
133 if (right[i] == node)
134 {
135 is_left = false;
136 index = i;
137 return;
138 }
139 }
140
141 ah_runtime_error() << "node not found in crown graph export";
142}
143
144static void write_colored_node(ostream &out, const string &dot_id, const string &label, const char *pos, size_t color)
145{
146 const size_t palette_index = color % palette_size();
147
148 out << " " << dot_id << " [label=\"" << label << "\\nc" << color << "\""
149 << ", fillcolor=\"" << fill_palette[palette_index] << "\""
150 << ", fontcolor=\"" << font_palette[palette_index] << "\""
151 << ", pos=\"" << pos << "\"];\n";
152}
153
154static void write_coloring_dot(const string &filename, const string &title, const Graph &g, Node *left[Crown_Size],
155 Node *right[Crown_Size], const ColorMap &colors, size_t num_colors)
156{
157 ofstream out(filename);
158 ah_runtime_error_if(not out) << "cannot open output file " << filename;
159
160 out << "graph CrownColoring {\n"
161 << " layout=neato;\n"
162 << " overlap=false;\n"
163 << " splines=true;\n"
164 << " outputorder=edgesfirst;\n"
165 << " graph [label=\"" << title << "\\n"
166 << "Crown graph H_" << Crown_Size << " (K_" << Crown_Size << "," << Crown_Size << " minus a perfect matching)\\n"
167 << num_colors << " color(s): " << color_legend(num_colors)
168 << "\", labelloc=t, fontsize=20, fontname=\"Helvetica\"];\n"
169 << " node [shape=circle, style=filled, fixedsize=true,\n"
170 << " width=0.95, height=0.95, penwidth=1.8,\n"
171 << " color=\"#1f2937\", fontname=\"Helvetica\"];\n"
172 << " edge [color=\"#94a3b8\", penwidth=1.5];\n"
173 << " left_partition [shape=plaintext, fixedsize=false,"
174 << " label=\"Left partition U\", pos=\"0,9.5!\"];\n"
175 << " right_partition [shape=plaintext, fixedsize=false,"
176 << " label=\"Right partition V\", pos=\"5,9.5!\"];\n";
177
178 for (size_t i = 0; i < Crown_Size; ++i)
179 {
180 write_colored_node(out, "u" + to_string(i), left[i]->get_info(), left_positions[i], colors.find(left[i]));
181 write_colored_node(out, "v" + to_string(i), right[i]->get_info(), right_positions[i], colors.find(right[i]));
182 }
183
184 out << "\n";
185
186 for (Graph::Arc_Iterator it(g); it.has_curr(); it.next_ne())
187 {
188 Node *src = it.get_src_node();
189 Node *tgt = it.get_tgt_node();
190
191 bool src_is_left = false;
192 bool tgt_is_left = false;
193 size_t src_index = 0;
194 size_t tgt_index = 0;
195
196 locate_node(src, left, right, src_is_left, src_index);
197 locate_node(tgt, left, right, tgt_is_left, tgt_index);
198
199 out << " " << (src_is_left ? "u" : "v") << src_index << " -- " << (tgt_is_left ? "u" : "v") << tgt_index
200 << ";\n";
201 }
202
203 out << "}\n";
204}
205
206template <class Coloring>
207static void export_variant(const string &prefix, const string &suffix, const string &title, const Graph &g,
209{
211 const size_t num_colors = coloring(g, colors);
212 const string filename = prefix + "_" + suffix + ".dot";
213
214 write_coloring_dot(filename, title, g, left, right, colors, num_colors);
215
216 cout << " " << suffix << ": " << num_colors << " color(s) -> " << filename << '\n';
217}
218
219int main(int argc, char **argv)
220try
221 {
222 const string prefix = argc > 1 ? argv[1] : "graph_coloring_crown";
223
224 Graph g;
225 Node *left[Crown_Size];
226 Node *right[Crown_Size];
227 build_crown_graph(g, left, right);
228
229 cout << "Graph coloring Graphviz example\n";
230 cout << "==============================\n";
231 cout << "Graph: crown H_" << Crown_Size << " with " << g.get_num_nodes() << " nodes and " << g.get_num_arcs()
232 << " edges\n";
233 cout << "Node order is adversarial for greedy coloring: "
234 << "u0, v0, u1, v1, ...\n\n";
235
236 export_variant(prefix, "greedy", "Greedy coloring", g, left, right,
237 [](const Graph &graph, ColorMap &colors) { return greedy_coloring(graph, colors); });
238
239 export_variant(prefix, "welsh_powell", "Welsh-Powell coloring", g, left, right,
240 [](const Graph &graph, ColorMap &colors) { return welsh_powell_coloring(graph, colors); });
241
242 export_variant(prefix, "dsatur", "DSatur coloring", g, left, right,
243 [](const Graph &graph, ColorMap &colors) { return dsatur_coloring(graph, colors); });
244
245 export_variant(prefix, "exact", "Exact chromatic number", g, left, right,
246 [](const Graph &graph, ColorMap &colors) { return chromatic_number(graph, colors); });
247
248 cout << "\nRender any DOT file with Graphviz, for example:\n";
249 cout << " neato -n -Tsvg " << prefix << "_dsatur.dot -o " << prefix << "_dsatur.svg\n";
250 cout << " neato -n -Tpng " << prefix << "_exact.dot -o " << prefix << "_exact.png\n";
251
252 return 0;
253 }
254catch (const exception &e)
255 {
256 cerr << "Error: " << e.what() << '\n';
257 return 1;
258 }
Graph coloring algorithms and heuristics.
Exception handling system with formatted messages for Aleph-w.
#define ah_runtime_error()
Throws std::runtime_error unconditionally.
Definition ah-errors.H:282
#define ah_runtime_error_if(C)
Throws std::runtime_error if condition holds.
Definition ah-errors.H:266
WeightedDigraph::Node Node
virtual Node * insert_node(Node *node) noexcept
Insertion of a node already allocated.
Definition tpl_graph.H:524
_Graph_Node Node
The graph type.
Definition tpl_graph.H:432
Arc * insert_arc(Node *src_node, Node *tgt_node, void *a)
Definition tpl_graph.H:604
constexpr size_t get_num_nodes() const noexcept
Return the total of nodes of graph.
Definition graph-dry.H:695
constexpr size_t get_num_arcs() const noexcept
Definition graph-dry.H:784
static const char * font_palette[]
static void write_coloring_dot(const string &filename, const string &title, const Graph &g, Node *left[Crown_Size], Node *right[Crown_Size], const ColorMap &colors, size_t num_colors)
static const char * right_positions[Crown_Size]
static void export_variant(const string &prefix, const string &suffix, const string &title, const Graph &g, Node *left[Crown_Size], Node *right[Crown_Size], Coloring coloring)
static const char * palette_names[]
static string color_legend(size_t num_colors)
static const char * fill_palette[]
static constexpr size_t Crown_Size
static string color_name(size_t c)
static const char * left_positions[Crown_Size]
static void locate_node(Node *node, Node *left[Crown_Size], Node *right[Crown_Size], bool &is_left, size_t &index)
static constexpr size_t palette_size()
static void build_crown_graph(Graph &g, Node *left[Crown_Size], Node *right[Crown_Size])
static void write_colored_node(ostream &out, const string &dot_id, const string &label, const char *pos, size_t color)
size_t dsatur_coloring(const GT &g, DynMapTree< typename GT::Node *, size_t > &colors)
DSatur graph coloring (saturation-degree heuristic).
size_t chromatic_number(const GT &g, DynMapTree< typename GT::Node *, size_t > &colors)
Computes the exact chromatic number of a small graph.
size_t greedy_coloring(const GT &g, DynMapTree< typename GT::Node *, size_t > &colors)
Greedy graph coloring in iteration order.
size_t welsh_powell_coloring(const GT &g, DynMapTree< typename GT::Node *, size_t > &colors)
Welsh-Powell graph coloring.
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
static void suffix(Node *root, DynList< Node * > &acc)
Divide_Conquer_DP_Result< Cost > divide_and_conquer_partition_dp(const size_t groups, const size_t n, Transition_Cost_Fn transition_cost, const Cost inf=dp_optimization_detail::default_inf< Cost >())
Optimize partition DP using divide-and-conquer optimization.
static void prefix(Node *root, DynList< Node * > &acc)
std::string to_string(const time_t t, const std::string &format)
Format a time_t value into a string using format.
Definition ah-date.H:140
static long & color(typename GT::Node *p)
STL namespace.
Arc of graph implemented with double-linked adjacency lists.
Definition tpl_graph.H:222
Generic graph and digraph implementations.