C++ Reference

C++ Reference: Graph

io.h
Go to the documentation of this file.
1// Copyright 2010-2021 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 <cstdint>
21#include <memory>
22#include <numeric>
23#include <string>
24#include <vector>
25
26#include "absl/status/status.h"
27#include "absl/status/statusor.h"
28#include "absl/strings/numbers.h"
29#include "absl/strings/str_format.h"
30#include "absl/strings/str_join.h"
31#include "absl/strings/str_split.h"
32#include "ortools/base/filelineiter.h"
33#include "ortools/graph/graph.h"
34
35namespace util {
36
37// Returns a string representation of a graph.
39 // One arc per line, eg. "3->1".
41
42 // One space-separated adjacency list per line, eg. "3: 5 1 3 1".
43 // Nodes with no outgoing arc get an empty list.
45
46 // Ditto, but the adjacency lists are sorted.
48};
49template <class Graph>
50std::string GraphToString(const Graph& graph, GraphToStringFormat format);
51
52// Writes a graph to the ".g" file format described above. If "directed" is
53// true, all arcs are written to the file. If it is false, the graph is expected
54// to be undirected (i.e. the number of arcs a->b is equal to the number of arcs
55// b->a for all nodes a,b); and only the arcs a->b where a<=b are written. Note
56// however that in this case, the symmetry of the graph is not fully checked
57// (only the parity of the number of non-self arcs is).
58//
59// "num_nodes_with_color" is optional. If it is not empty, then the color
60// information will be written to the header of the .g file. See ReadGraphFile.
61//
62// This method is the reverse of ReadGraphFile (with the same value for
63// "directed").
64template <class Graph>
65absl::Status WriteGraphToFile(const Graph& graph, const std::string& filename,
66 bool directed,
67 const std::vector<int>& num_nodes_with_color);
68
69// Implementations of the templated methods.
70
71template <class Graph>
72std::string GraphToString(const Graph& graph, GraphToStringFormat format) {
73 std::string out;
74 std::vector<typename Graph::NodeIndex> adj;
75 for (const typename Graph::NodeIndex node : graph.AllNodes()) {
76 if (format == PRINT_GRAPH_ARCS) {
77 for (const typename Graph::ArcIndex arc : graph.OutgoingArcs(node)) {
78 if (!out.empty()) out += '\n';
79 absl::StrAppend(&out, node, "->", graph.Head(arc));
80 }
81 } else { // PRINT_GRAPH_ADJACENCY_LISTS[_SORTED]
82 adj.clear();
83 for (const typename Graph::ArcIndex arc : graph.OutgoingArcs(node)) {
84 adj.push_back(graph.Head(arc));
85 }
87 std::sort(adj.begin(), adj.end());
88 }
89 if (node != 0) out += '\n';
90 absl::StrAppend(&out, node, ": ", absl::StrJoin(adj, " "));
91 }
92 }
93 return out;
94}
95
96template <class Graph>
97absl::Status WriteGraphToFile(const Graph& graph, const std::string& filename,
98 bool directed,
99 const std::vector<int>& num_nodes_with_color) {
100 FILE* f = fopen(filename.c_str(), "w");
101 if (f == nullptr) {
102 return absl::Status(absl::StatusCode::kInvalidArgument,
103 "Could not open file: '" + filename + "'");
104 }
105 // In undirected mode, we must count the self-arcs separately. All other arcs
106 // should be duplicated.
107 int num_self_arcs = 0;
108 if (!directed) {
109 for (const typename Graph::NodeIndex node : graph.AllNodes()) {
110 for (const typename Graph::ArcIndex arc : graph.OutgoingArcs(node)) {
111 if (graph.Head(arc) == node) ++num_self_arcs;
112 }
113 }
114 if ((graph.num_arcs() - num_self_arcs) % 2 != 0) {
115 fclose(f);
116 return absl::Status(absl::StatusCode::kInvalidArgument,
117 "WriteGraphToFile() called with directed=false"
118 " and with a graph with an odd number of (non-self)"
119 " arcs!");
120 }
121 }
122 absl::FPrintF(
123 f, "%d %d", static_cast<int64_t>(graph.num_nodes()),
124 static_cast<int64_t>(directed ? graph.num_arcs()
125 : (graph.num_arcs() + num_self_arcs) / 2));
126 if (!num_nodes_with_color.empty()) {
127 if (std::accumulate(num_nodes_with_color.begin(),
128 num_nodes_with_color.end(), 0) != graph.num_nodes() ||
129 *std::min_element(num_nodes_with_color.begin(),
130 num_nodes_with_color.end()) <= 0) {
131 return absl::Status(absl::StatusCode::kInvalidArgument,
132 "WriteGraphToFile() called with invalid coloring.");
133 }
134 absl::FPrintF(f, " %d", num_nodes_with_color.size());
135 for (int i = 0; i < num_nodes_with_color.size() - 1; ++i) {
136 absl::FPrintF(f, " %d", static_cast<int64_t>(num_nodes_with_color[i]));
137 }
138 }
139 absl::FPrintF(f, "\n");
140
141 for (const typename Graph::NodeIndex node : graph.AllNodes()) {
142 for (const typename Graph::ArcIndex arc : graph.OutgoingArcs(node)) {
143 const typename Graph::NodeIndex head = graph.Head(arc);
144 if (directed || head >= node) {
145 absl::FPrintF(f, "%d %d\n", static_cast<int64_t>(node),
146 static_cast<uint64_t>(head));
147 }
148 }
149 }
150 if (fclose(f) != 0) {
151 return absl::Status(absl::StatusCode::kInternal,
152 "Could not close file '" + filename + "'");
153 }
154 return ::absl::OkStatus();
155}
156
157} // namespace util
158
159#endif // UTIL_GRAPH_IO_H_
ArcIndexType num_arcs() const
Definition: graph.h:207
NodeIndexType num_nodes() const
Definition: graph.h:204
IntegerRange< NodeIndex > AllNodes() const
Definition: graph.h:937
NodeIndexType Head(ArcIndexType arc) const
Definition: graph.h:1119
BeginEndWrapper< OutgoingArcIterator > OutgoingArcs(NodeIndexType node) const
GraphToStringFormat
Definition: io.h:38
@ PRINT_GRAPH_ARCS
Definition: io.h:40
@ PRINT_GRAPH_ADJACENCY_LISTS
Definition: io.h:44
@ PRINT_GRAPH_ADJACENCY_LISTS_SORTED
Definition: io.h:47
ListGraph Graph
Definition: graph.h:2362
std::string GraphToString(const Graph &graph, GraphToStringFormat format)
Definition: io.h:72
absl::Status WriteGraphToFile(const Graph &graph, const std::string &filename, bool directed, const std::vector< int > &num_nodes_with_color)
Definition: io.h:97