Google OR-Tools: ortools/graph/graph_io.h Source File

1

2

3

4

5

6

7

8

9

10

11

12

13

14

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

43

45

46

47

49

50

52

53

55};

56template <class Graph>

58

59

60

61

62

63

64

65

66

67

68

69

70

71template <class Graph>

73 bool directed,

74 absl::Span<const int> num_nodes_with_color);

75

76

77

78template <class Graph>

80 std::string out;

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;

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 {

99 adj.clear();

101 adj.push_back(static_cast<uint64_t>(graph.Head(arc)));

102 }

104 std::sort(adj.begin(), adj.end());

105 }

107 absl::StrAppend(&out, static_cast<uint64_t>(node), ": ",

108 absl::StrJoin(adj, " "));

109 }

110 }

111 return out;

112}

113

114template <class Graph>

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

124

125 int num_self_arcs = 0;

126 if (!directed) {

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

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}

178

179#endif

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

Definition graph_io.h:42

@ PRINT_GRAPH_ADJACENCY_LISTS_SORTED

Definition graph_io.h:51

@ PRINT_GRAPH_ADJACENCY_LISTS

Definition graph_io.h:48

@ PRINT_GRAPH_ARCS

Definition graph_io.h:44

@ PRINT_GRAPH_DOT

Definition graph_io.h:54

std::string GraphToString(const Graph &graph, GraphToStringFormat format)

Definition graph_io.h:79