Google OR-Tools v9.14
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
graph_io.h
Go to the documentation of this file.
1// Copyright 2010-2025 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14// A collections of i/o utilities for the Graph classes in ./graph.h.
15
16#ifndef UTIL_GRAPH_IO_H_
17#define UTIL_GRAPH_IO_H_
18
19#include <algorithm>
20#include <cstddef>
21#include <cstdint>
22#include <cstdio>
23#include <memory>
24#include <numeric>
25#include <string>
26#include <vector>
27
28#include "absl/status/status.h"
29#include "absl/status/statusor.h"
30#include "absl/strings/numbers.h"
31#include "absl/strings/str_cat.h"
32#include "absl/strings/str_format.h"
33#include "absl/strings/str_join.h"
34#include "absl/strings/string_view.h"
35#include "absl/types/span.h"
38
39namespace util {
40
41// Returns a string representation of a graph.
43 // One arc per line, eg. "3->1".
45
46 // One space-separated adjacency list per line, eg. "3: 5 1 3 1".
47 // Nodes with no outgoing arc get an empty list.
49
50 // Ditto, but the adjacency lists are sorted.
52
53 // Dot format, can be visualized with Graphviz.
55};
56template <class Graph>
57std::string GraphToString(const Graph& graph, GraphToStringFormat format);
58
59// Writes a graph to the ".g" file format described above. If "directed" is
60// true, all arcs are written to the file. If it is false, the graph is expected
61// to be undirected (i.e. the number of arcs a->b is equal to the number of arcs
62// b->a for all nodes a,b); and only the arcs a->b where a<=b are written. Note
63// however that in this case, the symmetry of the graph is not fully checked
64// (only the parity of the number of non-self arcs is).
65//
66// "num_nodes_with_color" is optional. If it is not empty, then the color
67// information will be written to the header of the .g file. See ReadGraphFile.
68//
69// This method is the reverse of ReadGraphFile (with the same value for
70// "directed").
71template <class Graph>
72absl::Status WriteGraphToFile(const Graph& graph, const std::string& filename,
73 bool directed,
74 absl::Span<const int> num_nodes_with_color);
75
76// Implementations of the templated methods.
77
78template <class Graph>
79std::string GraphToString(const Graph& graph, GraphToStringFormat format) {
80 std::string out;
81 if (format == PRINT_GRAPH_DOT) {
82 absl::StrAppend(&out, "digraph {\n");
83 for (const auto arc : graph.AllForwardArcs()) {
84 absl::StrAppend(&out, " ", static_cast<int64_t>(graph.Tail(arc)), "->",
85 static_cast<int64_t>(graph.Head(arc)), ";\n");
86 }
87 absl::StrAppend(&out, "}\n");
88 return out;
89 }
90 std::vector<uint64_t> adj;
91 for (const typename Graph::NodeIndex node : graph.AllNodes()) {
92 if (format == PRINT_GRAPH_ARCS) {
93 for (const typename Graph::ArcIndex arc : graph.OutgoingArcs(node)) {
94 if (!out.empty()) out += '\n';
95 absl::StrAppend(&out, static_cast<uint64_t>(node), "->",
96 static_cast<uint64_t>(graph.Head(arc)));
97 }
98 } else { // PRINT_GRAPH_ADJACENCY_LISTS[_SORTED]
99 adj.clear();
100 for (const typename Graph::ArcIndex arc : graph.OutgoingArcs(node)) {
101 adj.push_back(static_cast<uint64_t>(graph.Head(arc)));
102 }
104 std::sort(adj.begin(), adj.end());
105 }
106 if (node != typename Graph::NodeIndex(0)) out += '\n';
107 absl::StrAppend(&out, static_cast<uint64_t>(node), ": ",
108 absl::StrJoin(adj, " "));
109 }
110 }
111 return out;
112}
113
114template <class Graph>
115absl::Status WriteGraphToFile(const Graph& graph, const std::string& filename,
116 bool directed,
117 absl::Span<const int> num_nodes_with_color) {
118 FILE* f = fopen(filename.c_str(), "w");
119 if (f == nullptr) {
120 return absl::Status(absl::StatusCode::kInvalidArgument,
121 "Could not open file: '" + filename + "'");
122 }
123 // In undirected mode, we must count the self-arcs separately. All other arcs
124 // should be duplicated.
125 int num_self_arcs = 0;
126 if (!directed) {
127 for (const typename Graph::NodeIndex node : graph.AllNodes()) {
128 for (const typename Graph::ArcIndex arc : graph.OutgoingArcs(node)) {
129 if (graph.Head(arc) == node) ++num_self_arcs;
130 }
131 }
132 if ((graph.num_arcs() - num_self_arcs) % 2 != 0) {
133 fclose(f);
134 return absl::Status(absl::StatusCode::kInvalidArgument,
135 "WriteGraphToFile() called with directed=false"
136 " and with a graph with an odd number of (non-self)"
137 " arcs!");
138 }
139 }
140 absl::FPrintF(
141 f, "%d %d", static_cast<int64_t>(graph.num_nodes()),
142 static_cast<int64_t>(directed ? graph.num_arcs()
143 : (graph.num_arcs() + num_self_arcs) / 2));
144 if (!num_nodes_with_color.empty()) {
145 if (std::accumulate(num_nodes_with_color.begin(),
146 num_nodes_with_color.end(), 0) != graph.num_nodes() ||
147 *std::min_element(num_nodes_with_color.begin(),
148 num_nodes_with_color.end()) <= 0) {
149 return absl::Status(absl::StatusCode::kInvalidArgument,
150 "WriteGraphToFile() called with invalid coloring.");
151 }
152 absl::FPrintF(f, " %d", num_nodes_with_color.size());
153 for (int i = 0; i < num_nodes_with_color.size() - 1; ++i) {
154 absl::FPrintF(f, " %d", static_cast<int64_t>(num_nodes_with_color[i]));
155 }
156 }
157 absl::FPrintF(f, "\n");
158
159 for (const typename Graph::NodeIndex node : graph.AllNodes()) {
160 for (const typename Graph::ArcIndex arc : graph.OutgoingArcs(node)) {
161 const typename Graph::NodeIndex head = graph.Head(arc);
162 if (directed || head >= node) {
163 absl::FPrintF(f, "%d %d\n", static_cast<int64_t>(node),
164 static_cast<uint64_t>(head));
165 }
166 }
167 }
168
169 if (fclose(f) != 0) {
170 return absl::Status(absl::StatusCode::kInternal,
171 "Could not close file '" + filename + "'");
172 }
173
174 return ::absl::OkStatus();
175}
176
177} // namespace util
178
179#endif // UTIL_GRAPH_IO_H_
A collections of i/o utilities for the Graph classes in ./graph.h.
absl::Status WriteGraphToFile(const Graph &graph, const std::string &filename, bool directed, absl::Span< const int > num_nodes_with_color)
Definition graph_io.h:115
GraphToStringFormat
Returns a string representation of a graph.
Definition graph_io.h:42
@ PRINT_GRAPH_ADJACENCY_LISTS_SORTED
Ditto, but the adjacency lists are sorted.
Definition graph_io.h:51
@ PRINT_GRAPH_ADJACENCY_LISTS
Definition graph_io.h:48
@ PRINT_GRAPH_ARCS
One arc per line, eg. "3->1".
Definition graph_io.h:44
@ PRINT_GRAPH_DOT
Dot format, can be visualized with Graphviz.
Definition graph_io.h:54
ListGraph Graph
Defining the simplest Graph interface as Graph for convenience.
Definition graph.h:2053
std::string GraphToString(const Graph &graph, GraphToStringFormat format)
Implementations of the templated methods.
Definition graph_io.h:79