C++ Reference

C++ Reference: Graph

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