121#ifndef OR_TOOLS_GRAPH_ONE_TREE_LOWER_BOUND_H_
122#define OR_TOOLS_GRAPH_ONE_TREE_LOWER_BOUND_H_
153template <
typename CostType>
157 : step1_initialized_(false),
160 max_iterations_(max_iterations > 0 ? max_iterations
161 : MaxIterations(number_of_nodes)),
162 number_of_nodes_(number_of_nodes) {}
164 bool Next() {
return iteration_++ < max_iterations_; }
167 return (1.0 * (iteration_ - 1) * (2 * max_iterations_ - 5) /
168 (2 * (max_iterations_ - 1))) *
170 (iteration_ - 2) * step1_ +
171 (0.5 * (iteration_ - 1) * (iteration_ - 2) /
172 ((max_iterations_ - 1) * (max_iterations_ - 2))) *
177 const std::vector<int>& degrees) {
178 if (!step1_initialized_) {
179 step1_initialized_ =
true;
180 UpdateStep(one_tree_cost);
184 void OnNewWMax(CostType one_tree_cost) { UpdateStep(one_tree_cost); }
189 static int MaxIterations(
int number_of_nodes) {
190 return static_cast<int>(28 * std::pow(number_of_nodes, 0.62));
193 void UpdateStep(CostType one_tree_cost) {
194 step1_ = one_tree_cost / (2 * number_of_nodes_);
197 bool step1_initialized_;
200 const int max_iterations_;
201 const int number_of_nodes_;
206template <
typename CostType,
typename CostFunction>
211 number_of_iterations_(2 * number_of_nodes),
218 number_of_nodes,
cost);
223 const int min_iterations = 2;
224 if (iteration_ >= number_of_iterations_) {
225 number_of_iterations_ /= 2;
226 if (number_of_iterations_ < min_iterations)
return false;
238 const std::vector<int>& degrees) {
240 for (
int degree : degrees) {
241 const double delta = degree - 2;
244 step_ = lambda_ * (upper_bound_ - w) / norm;
251 int number_of_iterations_;
252 CostType upper_bound_;
262template <
typename CostFunction>
264 int number_of_neighbors,
265 const CostFunction&
cost) {
266 using CostType =
decltype(
cost(0, 0));
267 std::set<std::pair<int, int>> nearest;
268 for (
int i = 0; i < number_of_nodes; ++i) {
269 std::vector<std::pair<CostType, int>> neighbors;
270 neighbors.reserve(number_of_nodes - 1);
271 for (
int j = 0; j < number_of_nodes; ++j) {
273 neighbors.emplace_back(
cost(i, j), j);
276 int size = neighbors.size();
277 if (number_of_neighbors < size) {
278 std::nth_element(neighbors.begin(),
279 neighbors.begin() + number_of_neighbors - 1,
281 size = number_of_neighbors;
283 for (
int j = 0; j < size; ++j) {
284 nearest.insert({i, neighbors[j].second});
285 nearest.insert({neighbors[j].second, i});
293template <
typename CostFunction>
295 const CostFunction&
cost,
296 std::set<std::pair<int, int>>* arcs) {
298 const std::vector<int> mst =
302 for (
int arc : mst) {
310template <
typename CostFunction,
typename GraphType,
typename AcceptFunction>
312 const CostFunction&
cost,
313 AcceptFunction accept) {
315 double best_edge_cost = 0;
316 for (
const auto node : graph.AllNodes()) {
318 const double edge_cost =
cost(node, source);
319 if (best_node == -1 || edge_cost < best_edge_cost) {
321 best_edge_cost = edge_cost;
331template <
typename CostFunction,
typename GraphType,
typename CostType>
333 const CostFunction&
cost,
334 const std::vector<double>& weights,
335 const std::vector<int>& sorted_arcs,
336 CostType* one_tree_cost) {
337 const auto weighed_cost = [&
cost, &weights](
int from,
int to) {
338 return cost(from, to) + weights[from] + weights[to];
341 std::vector<int> mst;
342 if (!sorted_arcs.empty()) {
343 mst = BuildKruskalMinimumSpanningTreeFromSortedArcs<GraphType>(graph,
346 mst = BuildPrimMinimumSpanningTree<GraphType>(
347 graph, [&weighed_cost, &graph](
int arc) {
348 return weighed_cost(graph.Tail(
arc), graph.Head(
arc));
351 std::vector<int> degrees(graph.num_nodes() + 1, 0);
353 for (
int arc : mst) {
354 degrees[graph.Head(
arc)]++;
355 degrees[graph.Tail(
arc)]++;
356 *one_tree_cost +=
cost(graph.Tail(
arc), graph.Head(
arc));
360 const int extra_node = graph.num_nodes();
361 const auto update_one_tree = [extra_node, one_tree_cost, °rees,
363 *one_tree_cost +=
cost(node, extra_node);
368 graph, extra_node, weighed_cost,
369 [extra_node](
int n) {
return n != extra_node; });
370 update_one_tree(node);
372 graph, extra_node, weighed_cost,
373 [extra_node, node](
int n) {
return n != extra_node && n != node; }));
378template <
typename CostFunction,
typename Algorithm>
380 int nearest_neighbors,
381 const CostFunction&
cost,
382 Algorithm* algorithm) {
383 if (number_of_nodes < 2)
return 0;
384 if (number_of_nodes == 2)
return cost(0, 1) +
cost(1, 0);
385 using CostType =
decltype(
cost(0, 0));
392 for (
const auto&
arc : nearest) {
395 std::vector<double> weights(number_of_nodes, 0);
396 std::vector<double> best_weights(number_of_nodes, 0);
397 double max_w = -std::numeric_limits<double>::infinity();
400 while (algorithm->Next()) {
401 CostType one_tree_cost = 0;
402 const std::vector<int> degrees =
404 algorithm->OnOneTree(one_tree_cost, w, degrees);
406 for (
int j = 0; j < number_of_nodes; ++j) {
407 w += weights[j] * (degrees[j] - 2);
411 best_weights = weights;
412 algorithm->OnNewWMax(one_tree_cost);
414 const double step = algorithm->GetStep();
415 for (
int j = 0; j < number_of_nodes; ++j) {
416 weights[j] += step * (degrees[j] - 2);
423 CostType one_tree_cost = 0;
427 const std::vector<int> degrees =
430 for (
int j = 0; j < number_of_nodes; ++j) {
431 w += best_weights[j] * (degrees[j] - 2);
452template <
typename CostFunction>
454 int number_of_nodes,
const CostFunction&
cost,
456 using CostType =
decltype(
cost(0, 0));
460 number_of_nodes,
parameters.volgenant_jonker_iterations);
467 number_of_nodes,
cost);
480template <
typename CostFunction>
CostType TravelingSalesmanCost()
void OnNewWMax(CostType one_tree_cost)
void OnOneTree(CostType one_tree_cost, double w, const std::vector< int > °rees)
HeldWolfeCrowderEvaluator(int number_of_nodes, const CostFunction &cost)
VolgenantJonkerEvaluator(int number_of_nodes, int max_iterations)
void OnNewWMax(CostType one_tree_cost)
void OnOneTree(CostType one_tree_cost, double w, const std::vector< int > °rees)
NodeIndexType Tail(ArcIndexType arc) const
NodeIndexType Head(ArcIndexType arc) const
ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head)
Collection of objects used to extend the Constraint Solver library.
double ComputeOneTreeLowerBoundWithAlgorithm(int number_of_nodes, int nearest_neighbors, const CostFunction &cost, Algorithm *algorithm)
double ComputeOneTreeLowerBoundWithParameters(int number_of_nodes, const CostFunction &cost, const TravelingSalesmanLowerBoundParameters ¶meters)
std::vector< int > ComputeOneTree(const GraphType &graph, const CostFunction &cost, const std::vector< double > &weights, const std::vector< int > &sorted_arcs, CostType *one_tree_cost)
std::vector< typename Graph::ArcIndex > BuildPrimMinimumSpanningTree(const Graph &graph, const ArcValue &arc_value)
std::set< std::pair< int, int > > NearestNeighbors(int number_of_nodes, int number_of_neighbors, const CostFunction &cost)
double ComputeOneTreeLowerBound(int number_of_nodes, const CostFunction &cost)
int GetNodeMinimizingEdgeCostToSource(const GraphType &graph, int source, const CostFunction &cost, AcceptFunction accept)
void AddArcsFromMinimumSpanningTree(int number_of_nodes, const CostFunction &cost, std::set< std::pair< int, int > > *arcs)
int volgenant_jonker_iterations