Google OR-Tools v9.12
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
combine_solutions.cc
Go to the documentation of this file.
1// Copyright 2010-2025 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
15
16#include <cstdint>
17#include <memory>
18#include <optional>
19#include <string>
20#include <string_view>
21#include <vector>
22
23#include "absl/log/check.h"
24#include "absl/strings/str_cat.h"
25#include "absl/types/span.h"
27#include "ortools/sat/model.h"
29
30namespace operations_research {
31namespace sat {
32
33bool TrySolution(const CpModelProto& model, absl::Span<const int64_t> solution,
34 absl::Span<const int64_t> new_solution,
35 absl::Span<const int64_t> base_solution,
36 std::vector<int64_t>* new_combined_solution) {
37 new_combined_solution->resize(new_solution.size());
38 for (int i = 0; i < new_solution.size(); ++i) {
39 if (new_solution[i] != base_solution[i]) {
40 // A value that changed that we patch.
41 (*new_combined_solution)[i] = new_solution[i];
42 } else {
43 (*new_combined_solution)[i] = solution[i];
44 }
45 }
46 return SolutionIsFeasible(model, *new_combined_solution);
47}
48
49std::optional<std::vector<int64_t>> FindCombinedSolution(
50 const CpModelProto& model, absl::Span<const int64_t> new_solution,
51 absl::Span<const int64_t> base_solution,
52 const SharedResponseManager* response_manager, std::string* solution_info) {
53 CHECK_EQ(new_solution.size(), base_solution.size());
54 const std::vector<
55 std::shared_ptr<const SharedSolutionRepository<int64_t>::Solution>>
56 solutions = response_manager->SolutionsRepository().GetBestNSolutions(10);
57
58 for (int sol_idx = 0; sol_idx < solutions.size(); ++sol_idx) {
59 std::shared_ptr<const SharedSolutionRepository<int64_t>::Solution> s =
60 solutions[sol_idx];
61 DCHECK_EQ(s->variable_values.size(), new_solution.size());
62
63 if (s->variable_values == new_solution ||
64 s->variable_values == base_solution) {
65 continue;
66 }
67 std::vector<int64_t> new_combined_solution;
68 if (TrySolution(model, s->variable_values, new_solution, base_solution,
69 &new_combined_solution)) {
70 absl::StrAppend(solution_info, " [combined with: ",
71 std::string_view(solutions[sol_idx]->info).substr(0, 20),
72 "...]");
73 return new_combined_solution;
74 }
75 }
76 return std::nullopt;
77}
78
80 SharedResponseManager* response_manager, const CpModelProto& model_proto,
81 absl::Span<const int64_t> new_solution, const std::string& solution_info,
82 absl::Span<const int64_t> base_solution, Model* model) {
83 PushedSolutionPointers result = {nullptr, nullptr};
84 result.pushed_solution =
85 response_manager->NewSolution(new_solution, solution_info, model);
86 if (!base_solution.empty()) {
87 std::string combined_solution_info = solution_info;
88 std::optional<std::vector<int64_t>> combined_solution =
89 FindCombinedSolution(model_proto, new_solution, base_solution,
90 response_manager, &combined_solution_info);
91 if (combined_solution.has_value()) {
92 result.improved_solution = response_manager->NewSolution(
93 combined_solution.value(), combined_solution_info, model);
94 }
95 }
96 return result;
97}
98
99} // namespace sat
100} // namespace operations_research
std::shared_ptr< const SharedSolutionRepository< int64_t >::Solution > NewSolution(absl::Span< const int64_t > solution_values, const std::string &solution_info, Model *model=nullptr)
const SharedSolutionRepository< int64_t > & SolutionsRepository() const
std::vector< std::shared_ptr< const Solution > > GetBestNSolutions(int n) const
bool TrySolution(const CpModelProto &model, absl::Span< const int64_t > solution, absl::Span< const int64_t > new_solution, absl::Span< const int64_t > base_solution, std::vector< int64_t > *new_combined_solution)
bool SolutionIsFeasible(const CpModelProto &model, absl::Span< const int64_t > variable_values, const CpModelProto *mapping_proto, const std::vector< int > *postsolve_mapping)
std::optional< std::vector< int64_t > > FindCombinedSolution(const CpModelProto &model, absl::Span< const int64_t > new_solution, absl::Span< const int64_t > base_solution, const SharedResponseManager *response_manager, std::string *solution_info)
PushedSolutionPointers PushAndMaybeCombineSolution(SharedResponseManager *response_manager, const CpModelProto &model_proto, absl::Span< const int64_t > new_solution, const std::string &solution_info, absl::Span< const int64_t > base_solution, Model *model)
In SWIG mode, we don't want anything besides these top-level includes.
Select next search node to expand Select next item_i to add this new search node to the search Generate a new search node where item_i is not in the knapsack Check validity of this new partial solution(using propagators) - If valid
std::shared_ptr< const SharedSolutionRepository< int64_t >::Solution > improved_solution
nullptr if no improvement was found.
std::shared_ptr< const SharedSolutionRepository< int64_t >::Solution > pushed_solution