backport graph from main
This commit is contained in:
@@ -37,6 +37,16 @@ code_sample_cc(name = "dag_shortest_path_sequential")
|
||||
|
||||
code_sample_cc(name = "dag_simple_shortest_path")
|
||||
|
||||
code_sample_cc(name = "dag_multiple_shortest_paths_one_to_all")
|
||||
|
||||
code_sample_cc(name = "dag_multiple_shortest_paths_sequential")
|
||||
|
||||
code_sample_cc(name = "dag_simple_multiple_shortest_paths")
|
||||
|
||||
code_sample_cc(name = "dag_constrained_shortest_path_sequential")
|
||||
|
||||
code_sample_cc(name = "dag_simple_constrained_shortest_path")
|
||||
|
||||
code_sample_cc(name = "dijkstra_all_pairs_shortest_paths")
|
||||
|
||||
code_sample_cc(name = "dijkstra_directed")
|
||||
@@ -47,6 +57,10 @@ code_sample_cc(name = "dijkstra_sequential")
|
||||
|
||||
code_sample_cc(name = "dijkstra_undirected")
|
||||
|
||||
code_sample_cc(name = "root_a_tree")
|
||||
|
||||
code_sample_cc(name = "rooted_tree_paths")
|
||||
|
||||
code_sample_java(name = "SimpleMaxFlowProgram")
|
||||
|
||||
code_sample_cc_py(name = "simple_max_flow_program")
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
"""Helper macro to compile and test code samples."""
|
||||
|
||||
load("@pip_deps//:requirements.bzl", "requirement")
|
||||
load("@rules_python//python:defs.bzl", "py_binary", "py_test")
|
||||
|
||||
def code_sample_cc(name):
|
||||
native.cc_binary(
|
||||
@@ -26,11 +27,13 @@ def code_sample_cc(name):
|
||||
"//ortools/graph:assignment",
|
||||
"//ortools/graph:bounded_dijkstra",
|
||||
"//ortools/graph:bfs",
|
||||
"//ortools/graph:dag_constrained_shortest_path",
|
||||
"//ortools/graph:dag_shortest_path",
|
||||
"//ortools/graph:ebert_graph",
|
||||
"//ortools/graph:linear_assignment",
|
||||
"//ortools/graph:max_flow",
|
||||
"//ortools/graph:min_cost_flow",
|
||||
"//ortools/graph:rooted_tree",
|
||||
"@com_google_absl//absl/random",
|
||||
],
|
||||
)
|
||||
@@ -47,17 +50,19 @@ def code_sample_cc(name):
|
||||
"//ortools/graph:assignment",
|
||||
"//ortools/graph:bounded_dijkstra",
|
||||
"//ortools/graph:bfs",
|
||||
"//ortools/graph:dag_constrained_shortest_path",
|
||||
"//ortools/graph:dag_shortest_path",
|
||||
"//ortools/graph:ebert_graph",
|
||||
"//ortools/graph:linear_assignment",
|
||||
"//ortools/graph:max_flow",
|
||||
"//ortools/graph:min_cost_flow",
|
||||
"//ortools/graph:rooted_tree",
|
||||
"@com_google_absl//absl/random",
|
||||
],
|
||||
)
|
||||
|
||||
def code_sample_py(name):
|
||||
native.py_binary(
|
||||
py_binary(
|
||||
name = name + "_py3",
|
||||
srcs = [name + ".py"],
|
||||
main = name + ".py",
|
||||
@@ -72,7 +77,7 @@ def code_sample_py(name):
|
||||
srcs_version = "PY3",
|
||||
)
|
||||
|
||||
native.py_test(
|
||||
py_test(
|
||||
name = name + "_py_test",
|
||||
size = "small",
|
||||
srcs = [name + ".py"],
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
// Copyright 2010-2024 Google LLC
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// [START imports]
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "absl/strings/str_join.h"
|
||||
#include "ortools/base/init_google.h"
|
||||
#include "ortools/graph/dag_constrained_shortest_path.h"
|
||||
#include "ortools/graph/dag_shortest_path.h"
|
||||
#include "ortools/graph/graph.h"
|
||||
// [END imports]
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
InitGoogle(argv[0], &argc, &argv, true);
|
||||
|
||||
// [START graph]
|
||||
// Create a graph with n + 2 nodes, indexed from 0:
|
||||
// * Node n is `source`
|
||||
// * Node n+1 is `dest`
|
||||
// * Nodes M = [0, 1, ..., n-1] are in the middle.
|
||||
//
|
||||
// There is a single resource constraints with limit 1.
|
||||
//
|
||||
// The graph has 3 * n - 1 arcs (with weights and both resources):
|
||||
// * (source -> i) with weight 100 and no resource use for i in M
|
||||
// * (i -> dest) with weight 100 and no resource use for i in M
|
||||
// * (i -> (i+1)) with weight 1 and resource use of 1 for i = 0, ..., n-2
|
||||
//
|
||||
// Every path [source, i, dest] for i in M is a constrained shortest path from
|
||||
// source to dest with weight 200.
|
||||
const int n = 5;
|
||||
const int source = n;
|
||||
const int dest = n + 1;
|
||||
const int num_arcs = 3 * n - 1;
|
||||
util::StaticGraph<> graph;
|
||||
// There are 3 types of arcs: (1) source to M, (2) M to dest, and (3) within
|
||||
// M. This vector stores all of them, first of type (1), then type (2),
|
||||
// then type (3). The arcs are ordered by i in M within each type.
|
||||
std::vector<double> weights(num_arcs);
|
||||
// Resources are first indexed by resource, then by arc.
|
||||
std::vector<std::vector<double>> resources(1, std::vector<double>(num_arcs));
|
||||
|
||||
for (int i = 0; i < n; ++i) {
|
||||
graph.AddArc(source, i);
|
||||
weights[i] = 100.0;
|
||||
resources[0][i] = 0.0;
|
||||
}
|
||||
for (int i = 0; i < n; ++i) {
|
||||
graph.AddArc(i, dest);
|
||||
weights[n + i] = 100.0;
|
||||
resources[0][n + i] = 0.0;
|
||||
}
|
||||
for (int i = 0; i + 1 < n; ++i) {
|
||||
graph.AddArc(i, i + 1);
|
||||
weights[2 * n + i] = 1.0;
|
||||
resources[0][2 * n + i] = 1.0;
|
||||
}
|
||||
|
||||
// Static graph reorders the arcs at Build() time, use permutation to get from
|
||||
// the old ordering to the new one.
|
||||
std::vector<int32_t> permutation;
|
||||
graph.Build(&permutation);
|
||||
util::Permute(permutation, &weights);
|
||||
util::Permute(permutation, &resources[0]);
|
||||
// [END graph]
|
||||
|
||||
// [START first-path]
|
||||
// A reusable shortest path calculator.
|
||||
// We need a topological order. For this structured graph, we find it by hand
|
||||
// instead of using util::graph::FastTopologicalSort().
|
||||
std::vector<int32_t> topological_order = {source};
|
||||
for (int32_t i = 0; i < n; ++i) {
|
||||
topological_order.push_back(i);
|
||||
}
|
||||
topological_order.push_back(dest);
|
||||
|
||||
const std::vector<int> sources = {source};
|
||||
const std::vector<int> destinations = {dest};
|
||||
const std::vector<double> max_resources = {1.0};
|
||||
|
||||
operations_research::ConstrainedShortestPathsOnDagWrapper<util::StaticGraph<>>
|
||||
constrained_shortest_path_on_dag(&graph, &weights, &resources,
|
||||
topological_order, sources, destinations,
|
||||
&max_resources);
|
||||
operations_research::PathWithLength initial_constrained_shortest_path =
|
||||
constrained_shortest_path_on_dag.RunConstrainedShortestPathOnDag();
|
||||
|
||||
std::cout << "Initial distance: " << initial_constrained_shortest_path.length
|
||||
<< std::endl;
|
||||
std::cout << "Initial path: "
|
||||
<< absl::StrJoin(initial_constrained_shortest_path.node_path, ", ")
|
||||
<< std::endl;
|
||||
// [END first-path]
|
||||
|
||||
// [START more-paths]
|
||||
// Now, we make a single arc from source to M free, and a single arc from M
|
||||
// to dest free, and resolve. If the free edge from the source hits before
|
||||
// the free edge to the dest in M, we use both, walking through M. Otherwise,
|
||||
// we use only one free arc.
|
||||
std::vector<std::pair<int, int>> fast_paths = {{2, 3}, {8, 1}, {3, 7}};
|
||||
for (const auto [free_from_source, free_to_dest] : fast_paths) {
|
||||
weights[permutation[free_from_source]] = 0;
|
||||
weights[permutation[n + free_to_dest]] = 0;
|
||||
|
||||
operations_research::PathWithLength constrained_shortest_path =
|
||||
constrained_shortest_path_on_dag.RunConstrainedShortestPathOnDag();
|
||||
std::cout << "source -> " << free_from_source << " and " << free_to_dest
|
||||
<< " -> dest are now free" << std::endl;
|
||||
std::string label = absl::StrCat("_", free_from_source, "_", free_to_dest);
|
||||
std::cout << "Distance" << label << ": " << constrained_shortest_path.length
|
||||
<< std::endl;
|
||||
std::cout << "Path" << label << ": "
|
||||
<< absl::StrJoin(constrained_shortest_path.node_path, ", ")
|
||||
<< std::endl;
|
||||
|
||||
// Restore the old weights
|
||||
weights[permutation[free_from_source]] = 100;
|
||||
weights[permutation[n + free_to_dest]] = 100;
|
||||
}
|
||||
// [END more-paths]
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
// Copyright 2010-2024 Google LLC
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/log/check.h"
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/strings/str_join.h"
|
||||
#include "ortools/base/init_google.h"
|
||||
#include "ortools/base/status_macros.h"
|
||||
#include "ortools/graph/dag_shortest_path.h"
|
||||
#include "ortools/graph/graph.h"
|
||||
#include "ortools/graph/topologicalsorter.h"
|
||||
|
||||
namespace {
|
||||
|
||||
absl::Status Main() {
|
||||
util::StaticGraph<> graph;
|
||||
std::vector<double> weights;
|
||||
graph.AddArc(0, 1);
|
||||
weights.push_back(2.0);
|
||||
graph.AddArc(0, 2);
|
||||
weights.push_back(5.0);
|
||||
graph.AddArc(1, 4);
|
||||
weights.push_back(1.0);
|
||||
graph.AddArc(2, 4);
|
||||
weights.push_back(-3.0);
|
||||
graph.AddArc(3, 4);
|
||||
weights.push_back(0.0);
|
||||
|
||||
// Static graph reorders the arcs at Build() time, use permutation to get
|
||||
// from the old ordering to the new one.
|
||||
std::vector<int32_t> permutation;
|
||||
graph.Build(&permutation);
|
||||
util::Permute(permutation, &weights);
|
||||
|
||||
// We need a topological order. We can find it by hand on this small graph,
|
||||
// e.g., {0, 1, 2, 3, 4}, but we demonstrate how to compute one instead.
|
||||
ASSIGN_OR_RETURN(const std::vector<int32_t> topological_order,
|
||||
util::graph::FastTopologicalSort(graph));
|
||||
|
||||
operations_research::KShortestPathsOnDagWrapper<util::StaticGraph<>>
|
||||
shortest_paths_on_dag(&graph, &weights, topological_order,
|
||||
/*path_count=*/2);
|
||||
const int source = 0;
|
||||
shortest_paths_on_dag.RunKShortestPathOnDag({source});
|
||||
|
||||
// For each node other than 0, print its distance and the shortest path.
|
||||
for (int node = 1; node < 5; ++node) {
|
||||
std::cout << "Node " << node << ":\n";
|
||||
if (!shortest_paths_on_dag.IsReachable(node)) {
|
||||
std::cout << "\tNo path to node " << node << std::endl;
|
||||
continue;
|
||||
}
|
||||
const std::vector<double> lengths = shortest_paths_on_dag.LengthsTo(node);
|
||||
const std::vector<std::vector<int32_t>> paths =
|
||||
shortest_paths_on_dag.NodePathsTo(node);
|
||||
for (int path_index = 0; path_index < lengths.size(); ++path_index) {
|
||||
std::cout << "\t#" << (path_index + 1) << " shortest path to node "
|
||||
<< node << " has length: " << lengths[path_index] << std::endl;
|
||||
std::cout << "\t#" << (path_index + 1) << " shortest path to node "
|
||||
<< node << " is: " << absl::StrJoin(paths[path_index], ", ")
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
InitGoogle(argv[0], &argc, &argv, true);
|
||||
QCHECK_OK(Main());
|
||||
return 0;
|
||||
}
|
||||
135
ortools/graph/samples/dag_multiple_shortest_paths_sequential.cc
Normal file
135
ortools/graph/samples/dag_multiple_shortest_paths_sequential.cc
Normal file
@@ -0,0 +1,135 @@
|
||||
// Copyright 2010-2024 Google LLC
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// [START imports]
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "absl/strings/str_join.h"
|
||||
#include "ortools/base/init_google.h"
|
||||
#include "ortools/graph/dag_shortest_path.h"
|
||||
#include "ortools/graph/graph.h"
|
||||
// [END imports]
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
InitGoogle(argv[0], &argc, &argv, true);
|
||||
|
||||
// [START graph]
|
||||
// Create a graph with n + 2 nodes, indexed from 0:
|
||||
// * Node n is `source`
|
||||
// * Node n+1 is `dest`
|
||||
// * Nodes M = [0, 1, ..., n-1] are in the middle.
|
||||
//
|
||||
// The graph has 3 * n - 1 arcs (with weights):
|
||||
// * (source -> i) with weight 100 + i for i in M
|
||||
// * (i -> dest) with weight 100 + i for i in M
|
||||
// * (i -> (i+1)) with weight 10 for i = 0, ..., n-2
|
||||
const int n = 10;
|
||||
const int source = n;
|
||||
const int dest = n + 1;
|
||||
util::StaticGraph<> graph;
|
||||
// There are 3 types of arcs: (1) source to M, (2) M to dest, and (3) within
|
||||
// M. This vector stores all of them, first of type (1), then type (2),
|
||||
// then type (3). The arcs are ordered by i in M within each type.
|
||||
std::vector<double> weights(3 * n - 1);
|
||||
|
||||
for (int i = 0; i < n; ++i) {
|
||||
graph.AddArc(source, i);
|
||||
weights[i] = 100.0 + i;
|
||||
}
|
||||
for (int i = 0; i < n; ++i) {
|
||||
graph.AddArc(i, dest);
|
||||
weights[n + i] = 100.0 + i;
|
||||
}
|
||||
for (int i = 0; i + 1 < n; ++i) {
|
||||
graph.AddArc(i, i + 1);
|
||||
weights[2 * n + i] = 10.0;
|
||||
}
|
||||
|
||||
// Static graph reorders the arcs at Build() time, use permutation to get from
|
||||
// the old ordering to the new one.
|
||||
std::vector<int32_t> permutation;
|
||||
graph.Build(&permutation);
|
||||
util::Permute(permutation, &weights);
|
||||
// [END graph]
|
||||
|
||||
// [START first-path]
|
||||
// A reusable shortest path calculator.
|
||||
// We need a topological order. For this structured graph, we find it by hand
|
||||
// instead of using util::graph::FastTopologicalSort().
|
||||
std::vector<int32_t> topological_order = {source};
|
||||
for (int32_t i = 0; i < n; ++i) {
|
||||
topological_order.push_back(i);
|
||||
}
|
||||
topological_order.push_back(dest);
|
||||
|
||||
operations_research::KShortestPathsOnDagWrapper<util::StaticGraph<>>
|
||||
shortest_paths_on_dag(&graph, &weights, topological_order,
|
||||
/*path_count=*/2);
|
||||
shortest_paths_on_dag.RunKShortestPathOnDag({source});
|
||||
|
||||
const std::vector<double> initial_lengths =
|
||||
shortest_paths_on_dag.LengthsTo(dest);
|
||||
const std::vector<std::vector<int32_t>> initial_paths =
|
||||
shortest_paths_on_dag.NodePathsTo(dest);
|
||||
|
||||
std::cout << "No free arcs" << std::endl;
|
||||
for (int path_index = 0; path_index < initial_lengths.size(); ++path_index) {
|
||||
std::cout << "\t#" << (path_index + 1)
|
||||
<< " shortest path has length: " << initial_lengths[path_index]
|
||||
<< std::endl;
|
||||
std::cout << "\t#" << (path_index + 1) << " shortest path is: "
|
||||
<< absl::StrJoin(initial_paths[path_index], ", ") << std::endl;
|
||||
}
|
||||
// [END first-path]
|
||||
|
||||
// [START more-paths]
|
||||
// Now, we make a single arc from source to M free, and a single arc from M
|
||||
// to dest free, and resolve. If the free edge from the source hits before
|
||||
// the free edge to the dest in M, we use both, walking through M. Otherwise,
|
||||
// we use only one free arc.
|
||||
std::vector<std::pair<int, int>> fast_paths = {
|
||||
{2, 4}, {8, 1}, {3, 3}, {0, 0}};
|
||||
for (const auto [free_from_source, free_to_dest] : fast_paths) {
|
||||
weights[permutation[free_from_source]] = 0;
|
||||
weights[permutation[n + free_to_dest]] = 0;
|
||||
|
||||
shortest_paths_on_dag.RunKShortestPathOnDag({source});
|
||||
std::cout << "source -> " << free_from_source << " and " << free_to_dest
|
||||
<< " -> dest are now free" << std::endl;
|
||||
std::string label =
|
||||
absl::StrCat(" (", free_from_source, ", ", free_to_dest, ")");
|
||||
|
||||
const std::vector<double> lengths = shortest_paths_on_dag.LengthsTo(dest);
|
||||
const std::vector<std::vector<int32_t>> paths =
|
||||
shortest_paths_on_dag.NodePathsTo(dest);
|
||||
|
||||
for (int path_index = 0; path_index < lengths.size(); ++path_index) {
|
||||
std::cout << "\t#" << (path_index + 1) << " shortest path" << label
|
||||
<< " has length: " << lengths[path_index] << std::endl;
|
||||
std::cout << "\t#" << (path_index + 1) << " shortest path" << label
|
||||
<< " is: " << absl::StrJoin(paths[path_index], ", ")
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
// Restore the old weights
|
||||
weights[permutation[free_from_source]] = 100 + free_from_source;
|
||||
weights[permutation[n + free_to_dest]] = 100 + free_to_dest;
|
||||
}
|
||||
// [END more-paths]
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
// Copyright 2010-2024 Google LLC
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/strings/str_join.h"
|
||||
#include "ortools/base/init_google.h"
|
||||
#include "ortools/graph/dag_constrained_shortest_path.h"
|
||||
#include "ortools/graph/dag_shortest_path.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
InitGoogle(argv[0], &argc, &argv, true);
|
||||
|
||||
// The input graph, encoded as a list of arcs with distances.
|
||||
std::vector<operations_research::ArcWithLengthAndResources> arcs = {
|
||||
{.from = 0, .to = 1, .length = 5, .resources = {1, 2}},
|
||||
{.from = 0, .to = 2, .length = 4, .resources = {3, 2}},
|
||||
{.from = 0, .to = 2, .length = 1, .resources = {2, 3}},
|
||||
{.from = 1, .to = 3, .length = -3, .resources = {8, 0}},
|
||||
{.from = 2, .to = 3, .length = 0, .resources = {3, 1}}};
|
||||
const int num_nodes = 4;
|
||||
const std::vector<double> max_resources = {6, 3};
|
||||
|
||||
const int source = 0;
|
||||
const int destination = 3;
|
||||
const operations_research::PathWithLength path_with_length =
|
||||
operations_research::ConstrainedShortestPathsOnDag(
|
||||
num_nodes, arcs, source, destination, max_resources);
|
||||
|
||||
// Print to length of the path and then the nodes in the path.
|
||||
std::cout << "Constrained shortest path length: " << path_with_length.length
|
||||
<< std::endl;
|
||||
std::cout << "Constrained shortest path nodes: "
|
||||
<< absl::StrJoin(path_with_length.node_path, ", ") << std::endl;
|
||||
return 0;
|
||||
}
|
||||
47
ortools/graph/samples/dag_simple_multiple_shortest_paths.cc
Normal file
47
ortools/graph/samples/dag_simple_multiple_shortest_paths.cc
Normal file
@@ -0,0 +1,47 @@
|
||||
// Copyright 2010-2024 Google LLC
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/strings/str_join.h"
|
||||
#include "ortools/base/init_google.h"
|
||||
#include "ortools/graph/dag_shortest_path.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
InitGoogle(argv[0], &argc, &argv, true);
|
||||
|
||||
// The input graph, encoded as a list of arcs with distances.
|
||||
std::vector<operations_research::ArcWithLength> arcs = {
|
||||
{.from = 0, .to = 1, .length = 2}, {.from = 0, .to = 2, .length = 5},
|
||||
{.from = 0, .to = 3, .length = 4}, {.from = 1, .to = 4, .length = 1},
|
||||
{.from = 2, .to = 4, .length = -3}, {.from = 3, .to = 4, .length = 0}};
|
||||
const int num_nodes = 5;
|
||||
|
||||
const int source = 0;
|
||||
const int destination = 4;
|
||||
const int path_count = 2;
|
||||
const std::vector<operations_research::PathWithLength> paths_with_length =
|
||||
operations_research::KShortestPathsOnDag(num_nodes, arcs, source,
|
||||
destination, path_count);
|
||||
|
||||
for (int path_index = 0; path_index < paths_with_length.size();
|
||||
++path_index) {
|
||||
std::cout << "#" << (path_index + 1) << " shortest path has length: "
|
||||
<< paths_with_length[path_index].length << std::endl;
|
||||
std::cout << "#" << (path_index + 1) << " shortest path is: "
|
||||
<< absl::StrJoin(paths_with_length[path_index].node_path, ", ")
|
||||
<< std::endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -23,11 +23,11 @@ int main(int argc, char** argv) {
|
||||
|
||||
// The input graph, encoded as a list of arcs with distances.
|
||||
std::vector<operations_research::ArcWithLength> arcs = {
|
||||
{.tail = 0, .head = 2, .length = 5},
|
||||
{.tail = 0, .head = 3, .length = 4},
|
||||
{.tail = 1, .head = 3, .length = 1},
|
||||
{.tail = 2, .head = 4, .length = -3},
|
||||
{.tail = 3, .head = 4, .length = 0}};
|
||||
{.from = 0, .to = 2, .length = 5},
|
||||
{.from = 0, .to = 3, .length = 4},
|
||||
{.from = 1, .to = 3, .length = 1},
|
||||
{.from = 2, .to = 4, .length = -3},
|
||||
{.from = 3, .to = 4, .length = 0}};
|
||||
const int num_nodes = 5;
|
||||
|
||||
const int source = 0;
|
||||
|
||||
86
ortools/graph/samples/root_a_tree.cc
Normal file
86
ortools/graph/samples/root_a_tree.cc
Normal file
@@ -0,0 +1,86 @@
|
||||
// Copyright 2010-2024 Google LLC
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/log/check.h"
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/strings/str_join.h"
|
||||
#include "ortools/base/init_google.h"
|
||||
#include "ortools/base/status_macros.h"
|
||||
#include "ortools/graph/graph.h"
|
||||
#include "ortools/graph/rooted_tree.h"
|
||||
|
||||
namespace {
|
||||
|
||||
absl::Status Main() {
|
||||
// Make an undirected tree as a graph using ListGraph (add the arcs in each
|
||||
// direction).
|
||||
const int32_t num_nodes = 5;
|
||||
std::vector<std::pair<int32_t, int32_t>> arcs = {
|
||||
{0, 1}, {1, 2}, {2, 3}, {1, 4}};
|
||||
util::ListGraph<> graph(num_nodes, 2 * static_cast<int32_t>(arcs.size()));
|
||||
for (const auto [s, t] : arcs) {
|
||||
graph.AddArc(s, t);
|
||||
graph.AddArc(t, s);
|
||||
}
|
||||
|
||||
// Root the tree from 2. Save the depth of each node and topological ordering
|
||||
int root = 2;
|
||||
std::vector<int32_t> topological_order;
|
||||
std::vector<int32_t> depth;
|
||||
ASSIGN_OR_RETURN(const operations_research::RootedTree<int32_t> tree,
|
||||
operations_research::RootedTreeFromGraph(
|
||||
root, graph, &topological_order, &depth));
|
||||
|
||||
// Parents are:
|
||||
// 0 -> 1
|
||||
// 1 -> 2
|
||||
// 2 is root (returns -1)
|
||||
// 3 -> 2
|
||||
// 4 -> 1
|
||||
std::cout << "Parents:" << std::endl;
|
||||
for (int i = 0; i < num_nodes; ++i) {
|
||||
std::cout << " " << i << " -> " << tree.parents()[i] << std::endl;
|
||||
}
|
||||
|
||||
// Depths are:
|
||||
// 0: 2
|
||||
// 1: 1
|
||||
// 2: 0
|
||||
// 3: 1
|
||||
// 4: 2
|
||||
std::cout << "Depths:" << std::endl;
|
||||
for (int i = 0; i < num_nodes; ++i) {
|
||||
std::cout << " " << i << " -> " << depth[i] << std::endl;
|
||||
}
|
||||
|
||||
// Many possible topological orders, including:
|
||||
// [2, 1, 0, 4, 3]
|
||||
// all starting with 2.
|
||||
std::cout << "Topological order: " << absl::StrJoin(topological_order, ", ")
|
||||
<< std::endl;
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
InitGoogle(argv[0], &argc, &argv, true);
|
||||
QCHECK_OK(Main());
|
||||
return 0;
|
||||
}
|
||||
58
ortools/graph/samples/rooted_tree_paths.cc
Normal file
58
ortools/graph/samples/rooted_tree_paths.cc
Normal file
@@ -0,0 +1,58 @@
|
||||
// Copyright 2010-2024 Google LLC
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/log/check.h"
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/strings/str_join.h"
|
||||
#include "ortools/base/init_google.h"
|
||||
#include "ortools/base/status_macros.h"
|
||||
#include "ortools/graph/rooted_tree.h"
|
||||
|
||||
namespace {
|
||||
|
||||
absl::Status Main() {
|
||||
// Make an rooted tree on 5 nodes with root 2 and the parental args:
|
||||
// 0 -> 1
|
||||
// 1 -> 2
|
||||
// 2 is root
|
||||
// 3 -> 2
|
||||
// 4 -> 1
|
||||
ASSIGN_OR_RETURN(
|
||||
const operations_research::RootedTree<int> tree,
|
||||
operations_research::RootedTree<int>::Create(2, {1, 2, -1, 2, 1}));
|
||||
|
||||
// Precompute this for LCA computations below.
|
||||
const std::vector<int> depths = tree.AllDepths();
|
||||
|
||||
// Find the path between every pair of nodes in the tree.
|
||||
for (int s = 0; s < 5; ++s) {
|
||||
for (int t = 0; t < 5; ++t) {
|
||||
int lca = tree.LowestCommonAncestorByDepth(s, t, depths);
|
||||
const std::vector<int> path = tree.Path(s, t, lca);
|
||||
std::cout << s << " -> " << t << " [" << absl::StrJoin(path, ", ") << "]"
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
InitGoogle(argv[0], &argc, &argv, true);
|
||||
QCHECK_OK(Main());
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user