Skip to content

Commit a5adf42

Browse files
committed
graph: remove ebert_graph usage
1 parent 847e205 commit a5adf42

14 files changed

+97
-104
lines changed

ortools/graph/BUILD.bazel

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,6 @@ cc_library(
101101
srcs = ["minimum_vertex_cover.cc"],
102102
hdrs = ["minimum_vertex_cover.h"],
103103
deps = [
104-
":ebert_graph",
105104
":max_flow",
106105
"@com_google_absl//absl/log:check",
107106
],
@@ -398,7 +397,6 @@ cc_test(
398397
srcs = ["shortest_paths_test.cc"],
399398
tags = ["noasan"], # Times out occasionally in ASAN mode.
400399
deps = [
401-
":ebert_graph",
402400
":graph",
403401
":shortest_paths",
404402
":strongly_connected_components",
@@ -471,7 +469,6 @@ cc_test(
471469
srcs = ["max_flow_test.cc"],
472470
data = ["//ortools/graph/testdata:max_flow_test1.pb.txt"],
473471
deps = [
474-
":ebert_graph",
475472
":flow_problem_cc_proto",
476473
":max_flow",
477474
"//ortools/base:gmock_main",
@@ -681,7 +678,6 @@ cc_library(
681678
srcs = ["dag_shortest_path.cc"],
682679
hdrs = ["dag_shortest_path.h"],
683680
deps = [
684-
":ebert_graph",
685681
":graph",
686682
":topologicalsorter",
687683
"@com_google_absl//absl/algorithm:container",

ortools/graph/csharp/graph.i

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@
2727

2828
%include "ortools/base/base.i"
2929

30-
%import "ortools/graph/ebert_graph.h"
31-
3230
%{
3331
#include "ortools/graph/assignment.h"
3432
#include "ortools/graph/max_flow.h"

ortools/graph/dag_shortest_path.cc

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919

2020
#include "absl/log/check.h"
2121
#include "absl/types/span.h"
22-
#include "ortools/graph/ebert_graph.h"
2322
#include "ortools/graph/graph.h"
2423
#include "ortools/graph/topologicalsorter.h"
2524

@@ -109,7 +108,7 @@ std::vector<PathWithLength> KShortestPathsOnDag(
109108
const ShortestPathOnDagProblem problem =
110109
ReadProblem(num_nodes, arcs_with_length);
111110

112-
KShortestPathsOnDagWrapper<util::StaticGraph<>> shortest_paths_on_dag(
111+
KShortestPathsOnDagWrapper<GraphType> shortest_paths_on_dag(
113112
&problem.graph, &problem.arc_lengths, problem.topological_order,
114113
path_count);
115114
shortest_paths_on_dag.RunKShortestPathOnDag({source});
@@ -119,9 +118,9 @@ std::vector<PathWithLength> KShortestPathsOnDag(
119118
}
120119

121120
std::vector<double> lengths = shortest_paths_on_dag.LengthsTo(destination);
122-
std::vector<std::vector<ArcIndex>> arc_paths =
121+
std::vector<std::vector<GraphType::ArcIndex>> arc_paths =
123122
shortest_paths_on_dag.ArcPathsTo(destination);
124-
std::vector<std::vector<NodeIndex>> node_paths =
123+
std::vector<std::vector<GraphType::NodeIndex>> node_paths =
125124
shortest_paths_on_dag.NodePathsTo(destination);
126125
std::vector<PathWithLength> paths;
127126
paths.reserve(lengths.size());

ortools/graph/java/graph.i

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,6 @@
3434

3535
%include "ortools/base/base.i"
3636

37-
%import "ortools/graph/ebert_graph.h"
38-
3937
%{
4038
#include "ortools/graph/assignment.h"
4139
#include "ortools/graph/max_flow.h"

ortools/graph/k_shortest_paths.h

Lines changed: 52 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@
7070
#include "absl/types/span.h"
7171
#include "ortools/base/logging.h"
7272
#include "ortools/graph/bounded_dijkstra.h"
73-
#include "ortools/graph/ebert_graph.h"
7473
#include "ortools/graph/shortest_paths.h"
7574

7675
namespace operations_research {
@@ -82,14 +81,15 @@ namespace operations_research {
8281
// The paths in `paths` start with `origin` and end at `destination`.
8382
//
8483
// If the computations are unsuccessful for any reason, the vectors are empty.
84+
template <class GraphType>
8585
struct KShortestPaths {
8686
// The paths are stored as vectors of nodes, like the other graph algorithms.
8787
// TODO(user): what about vectors of arcs? That might be faster
8888
// (potentially, add a function to transform it into a vector of nodes if the
8989
// user really needs it). It would also have the nice benefit of removing the
9090
// need for `distances` (compute it on the fly), with a reference to the graph
9191
// and the costs.
92-
std::vector<std::vector<NodeIndex>> paths;
92+
std::vector<std::vector<typename GraphType::NodeIndex>> paths;
9393
std::vector<PathDistance> distances;
9494
};
9595

@@ -113,10 +113,10 @@ struct KShortestPaths {
113113
// Science. 17 (11): 712–716, 1971.
114114
// https://doi.org/10.1287%2Fmnsc.17.11.712
115115
template <class GraphType>
116-
KShortestPaths YenKShortestPaths(const GraphType& graph,
117-
const std::vector<PathDistance>& arc_lengths,
118-
NodeIndex source, NodeIndex destination,
119-
unsigned k);
116+
KShortestPaths<GraphType> YenKShortestPaths(
117+
const GraphType& graph, const std::vector<PathDistance>& arc_lengths,
118+
typename GraphType::NodeIndex source,
119+
typename GraphType::NodeIndex destination, unsigned k);
120120

121121
// End of the interface. Below is the implementation.
122122

@@ -137,23 +137,26 @@ const PathDistance kDisconnectedDistance =
137137
// In a multigraph, this function returns an index for one of the edges between
138138
// the source and the destination.
139139
template <class GraphType>
140-
ArcIndex FindArcIndex(const GraphType& graph, const NodeIndex source,
141-
const NodeIndex destination) {
140+
typename GraphType::ArcIndex FindArcIndex(
141+
const GraphType& graph, const typename GraphType::NodeIndex source,
142+
const typename GraphType::NodeIndex destination) {
142143
const auto outgoing_arcs_iter = graph.OutgoingArcs(source);
143-
const auto arc =
144-
std::find_if(outgoing_arcs_iter.begin(), outgoing_arcs_iter.end(),
145-
[&graph, destination](const ArcIndex arc) {
146-
return graph.Head(arc) == destination;
147-
});
144+
const auto arc = std::find_if(
145+
outgoing_arcs_iter.begin(), outgoing_arcs_iter.end(),
146+
[&graph, destination](const typename GraphType::ArcIndex arc) {
147+
return graph.Head(arc) == destination;
148+
});
148149
return (arc != outgoing_arcs_iter.end()) ? *arc : GraphType::kNilArc;
149150
}
150151

151152
// Determines the shortest path from the given source and destination, returns a
152153
// tuple with the path (as a vector of node indices) and its cost.
153154
template <class GraphType>
154-
std::tuple<std::vector<NodeIndex>, PathDistance> ComputeShortestPath(
155-
const GraphType& graph, const std::vector<PathDistance>& arc_lengths,
156-
const NodeIndex source, const NodeIndex destination) {
155+
std::tuple<std::vector<typename GraphType::NodeIndex>, PathDistance>
156+
ComputeShortestPath(const GraphType& graph,
157+
const std::vector<PathDistance>& arc_lengths,
158+
const typename GraphType::NodeIndex source,
159+
const typename GraphType::NodeIndex destination) {
157160
BoundedDijkstraWrapper<GraphType, PathDistance> dijkstra(&graph,
158161
&arc_lengths);
159162
dijkstra.RunBoundedDijkstra(source, kMaxDistance);
@@ -165,25 +168,29 @@ std::tuple<std::vector<NodeIndex>, PathDistance> ComputeShortestPath(
165168
// This case only happens when some arcs have an infinite length (i.e.
166169
// larger than `kMaxDistance`): `BoundedDijkstraWrapper::NodePathTo` fails
167170
// to return a path, even empty.
168-
return {std::vector<NodeIndex>{}, kDisconnectedDistance};
171+
return {std::vector<typename GraphType::NodeIndex>{},
172+
kDisconnectedDistance};
169173
}
170174

171-
if (std::vector<NodeIndex> path = std::move(dijkstra.NodePathTo(destination));
175+
if (std::vector<typename GraphType::NodeIndex> path =
176+
std::move(dijkstra.NodePathTo(destination));
172177
!path.empty()) {
173178
return {std::move(path), path_length};
174179
} else {
175-
return {std::vector<NodeIndex>{}, kDisconnectedDistance};
180+
return {std::vector<typename GraphType::NodeIndex>{},
181+
kDisconnectedDistance};
176182
}
177183
}
178184

179185
// Computes the total length of a path.
180186
template <class GraphType>
181-
PathDistance ComputePathLength(const GraphType& graph,
182-
const absl::Span<const PathDistance> arc_lengths,
183-
const absl::Span<const NodeIndex> path) {
187+
PathDistance ComputePathLength(
188+
const GraphType& graph, const absl::Span<const PathDistance> arc_lengths,
189+
const absl::Span<const typename GraphType::NodeIndex> path) {
184190
PathDistance distance = 0;
185-
for (NodeIndex i = 0; i < path.size() - 1; ++i) {
186-
const ArcIndex arc = internal::FindArcIndex(graph, path[i], path[i + 1]);
191+
for (typename GraphType::NodeIndex i = 0; i < path.size() - 1; ++i) {
192+
const typename GraphType::ArcIndex arc =
193+
internal::FindArcIndex(graph, path[i], path[i + 1]);
187194
DCHECK_NE(arc, GraphType::kNilArc);
188195
distance += arc_lengths[arc];
189196
}
@@ -192,8 +199,11 @@ PathDistance ComputePathLength(const GraphType& graph,
192199

193200
// Stores a path with a priority (typically, the distance), with a comparison
194201
// operator that operates on the priority.
202+
template <class GraphType>
195203
class PathWithPriority {
196204
public:
205+
using NodeIndex = typename GraphType::NodeIndex;
206+
197207
PathWithPriority(PathDistance priority, std::vector<NodeIndex> path)
198208
: path_(std::move(path)), priority_(priority) {}
199209
bool operator<(const PathWithPriority& other) const {
@@ -265,10 +275,12 @@ class UnderlyingContainerAdapter : public Container {
265275
// spur paths, the cheapest being:
266276
// S_1^2 = B - E - F - G - H
267277
template <class GraphType>
268-
KShortestPaths YenKShortestPaths(const GraphType& graph,
269-
const std::vector<PathDistance>& arc_lengths,
270-
NodeIndex source, NodeIndex destination,
271-
unsigned k) {
278+
KShortestPaths<GraphType> YenKShortestPaths(
279+
const GraphType& graph, const std::vector<PathDistance>& arc_lengths,
280+
typename GraphType::NodeIndex source,
281+
typename GraphType::NodeIndex destination, unsigned k) {
282+
using NodeIndex = typename GraphType::NodeIndex;
283+
272284
CHECK_GT(internal::kDisconnectedDistance, internal::kMaxDistance);
273285

274286
CHECK_GE(k, 0) << "k must be nonnegative. Input value: " << k;
@@ -289,7 +301,7 @@ KShortestPaths YenKShortestPaths(const GraphType& graph,
289301
<< destination
290302
<< ". Number of nodes in the input graph: " << graph.num_nodes();
291303

292-
KShortestPaths paths;
304+
KShortestPaths<GraphType> paths;
293305

294306
// First step: compute the shortest path.
295307
{
@@ -306,7 +318,7 @@ KShortestPaths YenKShortestPaths(const GraphType& graph,
306318

307319
// Generate variant paths.
308320
internal::UnderlyingContainerAdapter<
309-
std::priority_queue<internal::PathWithPriority>>
321+
std::priority_queue<internal::PathWithPriority<GraphType>>>
310322
variant_path_queue;
311323

312324
// One path has already been generated (the shortest one). Only k-1 more
@@ -364,7 +376,7 @@ KShortestPaths YenKShortestPaths(const GraphType& graph,
364376
previous_path.begin() + root_path.length());
365377
if (!has_same_prefix_as_root_path) continue;
366378

367-
const ArcIndex after_spur_node_arc =
379+
const typename GraphType::ArcIndex after_spur_node_arc =
368380
internal::FindArcIndex(graph, previous_path[spur_node_position],
369381
previous_path[spur_node_position + 1]);
370382
VLOG(4) << " after_spur_node_arc: " << graph.Tail(after_spur_node_arc)
@@ -417,8 +429,8 @@ KShortestPaths YenKShortestPaths(const GraphType& graph,
417429
// coincide at the spur node).
418430
const bool root_path_leads_to_spur_path = absl::c_any_of(
419431
graph.OutgoingArcs(root_path.back()),
420-
[&graph, node_after_spur_in_spur_path =
421-
*(spur_path.begin() + 1)](const ArcIndex arc_index) {
432+
[&graph, node_after_spur_in_spur_path = *(spur_path.begin() + 1)](
433+
const typename GraphType::ArcIndex arc_index) {
422434
return graph.Head(arc_index) == node_after_spur_in_spur_path;
423435
});
424436
CHECK(root_path_leads_to_spur_path);
@@ -471,12 +483,12 @@ KShortestPaths YenKShortestPaths(const GraphType& graph,
471483
// filter by fingerprints? Due to the probability of error with
472484
// fingerprints, still use this slow-but-exact code, but after
473485
// filtering.
474-
const bool is_new_path_already_known =
475-
std::any_of(variant_path_queue.container().cbegin(),
476-
variant_path_queue.container().cend(),
477-
[&new_path](const internal::PathWithPriority& element) {
478-
return element.path() == new_path;
479-
});
486+
const bool is_new_path_already_known = std::any_of(
487+
variant_path_queue.container().cbegin(),
488+
variant_path_queue.container().cend(),
489+
[&new_path](const internal::PathWithPriority<GraphType>& element) {
490+
return element.path() == new_path;
491+
});
480492
if (is_new_path_already_known) continue;
481493

482494
const PathDistance path_length =
@@ -498,7 +510,7 @@ KShortestPaths YenKShortestPaths(const GraphType& graph,
498510
// this iteration found no shorter one.
499511
if (variant_path_queue.empty()) break;
500512

501-
const internal::PathWithPriority& next_shortest_path =
513+
const internal::PathWithPriority<GraphType>& next_shortest_path =
502514
variant_path_queue.top();
503515
VLOG(5) << "> New path generated: "
504516
<< absl::StrJoin(next_shortest_path.path(), " - ") << " ("

ortools/graph/k_shortest_paths_test.cc

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,9 @@ TEST(KShortestPathsYenTest, ReducesToShortestPath) {
128128
(void)graph.Build();
129129
std::vector<PathDistance> lengths{1, 1};
130130

131-
const KShortestPaths paths = YenKShortestPaths(graph, lengths, /*source=*/0,
132-
/*destination=*/2, /*k=*/1);
131+
const KShortestPaths<StaticGraph<>> paths =
132+
YenKShortestPaths(graph, lengths, /*source=*/0,
133+
/*destination=*/2, /*k=*/1);
133134
EXPECT_THAT(paths.paths, ElementsAre(std::vector<int>{0, 1, 2}));
134135
EXPECT_THAT(paths.distances, ElementsAre(2));
135136
}
@@ -141,8 +142,9 @@ TEST(KShortestPathsYenTest, OnlyHasOnePath) {
141142
(void)graph.Build();
142143
std::vector<PathDistance> lengths{1, 1};
143144

144-
const KShortestPaths paths = YenKShortestPaths(graph, lengths, /*source=*/0,
145-
/*destination=*/2, /*k=*/10);
145+
const KShortestPaths<StaticGraph<>> paths =
146+
YenKShortestPaths(graph, lengths, /*source=*/0,
147+
/*destination=*/2, /*k=*/10);
146148
EXPECT_THAT(paths.paths, ElementsAre(std::vector<int>{0, 1, 2}));
147149
EXPECT_THAT(paths.distances, ElementsAre(2));
148150
}
@@ -155,8 +157,9 @@ TEST(KShortestPathsYenTest, HasTwoPaths) {
155157
(void)graph.Build();
156158
std::vector<PathDistance> lengths{1, 30, 1};
157159

158-
const KShortestPaths paths = YenKShortestPaths(graph, lengths, /*source=*/0,
159-
/*destination=*/2, /*k=*/10);
160+
const KShortestPaths<StaticGraph<>> paths =
161+
YenKShortestPaths(graph, lengths, /*source=*/0,
162+
/*destination=*/2, /*k=*/10);
160163
EXPECT_THAT(paths.paths,
161164
ElementsAre(std::vector<int>{0, 1, 2}, std::vector<int>{0, 2}));
162165
EXPECT_THAT(paths.distances, ElementsAre(2, 30));
@@ -172,8 +175,9 @@ TEST(KShortestPathsYenTest, HasTwoPathsWithLongerPath) {
172175
(void)graph.Build();
173176
std::vector<PathDistance> lengths{1, 30, 1, 1, 1};
174177

175-
const KShortestPaths paths = YenKShortestPaths(graph, lengths, /*source=*/0,
176-
/*destination=*/4, /*k=*/10);
178+
const KShortestPaths<StaticGraph<>> paths =
179+
YenKShortestPaths(graph, lengths, /*source=*/0,
180+
/*destination=*/4, /*k=*/10);
177181
EXPECT_THAT(paths.paths, ElementsAre(std::vector<int>{0, 1, 2, 3, 4},
178182
std::vector<int>{0, 4}));
179183
EXPECT_THAT(paths.distances, ElementsAre(4, 30));
@@ -190,8 +194,9 @@ TEST(KShortestPathsYenTest, ReturnsTheRightNumberOfPaths) {
190194
(void)graph.Build();
191195
std::vector<PathDistance> lengths{1, 1, 1, 1, 1};
192196

193-
const KShortestPaths paths = YenKShortestPaths(graph, lengths, /*source=*/0,
194-
/*destination=*/2, /*k=*/2);
197+
const KShortestPaths<StaticGraph<>> paths =
198+
YenKShortestPaths(graph, lengths, /*source=*/0,
199+
/*destination=*/2, /*k=*/2);
195200
EXPECT_THAT(paths.paths,
196201
ElementsAre(std::vector<int>{0, 2}, std::vector<int>{0, 1, 2}));
197202
EXPECT_THAT(paths.distances, ElementsAre(1, 2));

ortools/graph/max_flow_test.cc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
#include "gtest/gtest.h"
2020
#include "ortools/base/gmock.h"
2121
#include "ortools/base/path.h"
22-
#include "ortools/graph/ebert_graph.h"
2322
#include "ortools/graph/flow_problem.pb.h"
2423
#include "ortools/util/file_util.h"
2524

ortools/graph/minimum_vertex_cover.cc

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
#include <vector>
1717

1818
#include "absl/log/check.h"
19-
#include "ortools/graph/ebert_graph.h"
2019
#include "ortools/graph/max_flow.h"
2120

2221
namespace operations_research {
@@ -31,7 +30,7 @@ std::vector<bool> BipartiteMinimumVertexCover(
3130
// alternating matched/unmatched edges to find a minimum vertex cover.
3231
SimpleMaxFlow max_flow;
3332
const int num_left = left_to_right_arcs.size();
34-
std::vector<ArcIndex> arcs;
33+
std::vector<SimpleMaxFlow::ArcIndex> arcs;
3534
for (int i = 0; i < num_left; ++i) {
3635
for (const int right_node : left_to_right_arcs[i]) {
3736
DCHECK_GE(right_node, num_left);
@@ -56,7 +55,7 @@ std::vector<bool> BipartiteMinimumVertexCover(
5655
}
5756
CHECK(max_flow.Solve(source, sink) == SimpleMaxFlow::OPTIMAL);
5857
std::vector<int> maximum_matching(num_left + num_right, -1);
59-
for (const ArcIndex arc : arcs) {
58+
for (const SimpleMaxFlow::ArcIndex arc : arcs) {
6059
if (max_flow.Flow(arc) > 0) {
6160
maximum_matching[max_flow.Tail(arc)] = max_flow.Head(arc);
6261
maximum_matching[max_flow.Head(arc)] = max_flow.Tail(arc);

ortools/graph/samples/assignment_min_flow.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ void AssignmentMinFlow() {
6969
// [END solve]
7070

7171
// [START print_solution]
72-
if (status == MinCostFlow::OPTIMAL) {
72+
if (status == SimpleMinCostFlow::OPTIMAL) {
7373
LOG(INFO) << "Total cost: " << min_cost_flow.OptimalCost();
7474
LOG(INFO) << "";
7575
for (std::size_t i = 0; i < min_cost_flow.NumArcs(); ++i) {

0 commit comments

Comments
 (0)