22 #include "absl/container/flat_hash_set.h" 23 #include "absl/synchronization/mutex.h" 43 shared_time_limit_(shared_time_limit),
44 shared_bounds_(shared_bounds),
45 shared_response_(shared_response) {
46 CHECK(shared_response_ !=
nullptr);
47 if (shared_bounds_ !=
nullptr) {
50 *model_proto_with_only_variables_.mutable_variables() =
52 InitializeHelperData();
53 RecomputeHelperData();
58 if (shared_bounds_ !=
nullptr) {
59 std::vector<int> model_variables;
60 std::vector<int64_t> new_lower_bounds;
61 std::vector<int64_t> new_upper_bounds;
63 &new_lower_bounds, &new_upper_bounds);
65 bool new_variables_have_been_fixed =
false;
68 absl::MutexLock domain_lock(&domain_mutex_);
70 for (
int i = 0; i < model_variables.size(); ++i) {
71 const int var = model_variables[i];
72 const int64_t new_lb = new_lower_bounds[i];
73 const int64_t new_ub = new_upper_bounds[i];
76 model_proto_with_only_variables_.variables(
var).domain();
77 const int64_t old_lb = domain.Get(0);
78 const int64_t old_ub = domain.Get(domain.size() - 1);
79 VLOG(3) <<
"Variable: " <<
var <<
" old domain: [" << old_lb <<
", " 80 << old_ub <<
"] new domain: [" << new_lb <<
", " << new_ub
84 model_proto_with_only_variables_.variables(
var));
87 if (new_domain.IsEmpty()) {
105 model_proto_with_only_variables_.mutable_variables(
var));
106 new_variables_have_been_fixed |= new_domain.IsFixed();
111 if (new_variables_have_been_fixed) {
112 RecomputeHelperData();
117 void NeighborhoodGeneratorHelper::InitializeHelperData() {
118 type_to_constraints_.clear();
120 for (
int c = 0; c < num_constraints; ++c) {
122 if (type >= type_to_constraints_.size()) {
123 type_to_constraints_.resize(type + 1);
125 type_to_constraints_[type].push_back(c);
129 void NeighborhoodGeneratorHelper::RecomputeHelperData() {
137 absl::ReaderMutexLock domain_lock(&domain_mutex_);
146 if (IsConstant(
var))
continue;
147 var_to_constraint_[
var].push_back(ct_index);
148 constraint_to_var_[ct_index].push_back(
var);
158 if (IsConstant(
var))
continue;
159 var_to_constraint_[
var].push_back(ct_index);
160 constraint_to_var_[ct_index].push_back(
var);
166 active_variables_.clear();
167 active_variables_set_.assign(model_proto_.
variables_size(),
false);
171 for (
const int var : search_strategy.variables()) {
173 if (!active_variables_set_[pos_var] && !IsConstant(pos_var)) {
174 active_variables_set_[pos_var] =
true;
175 active_variables_.push_back(pos_var);
181 if (!active_variables_.empty())
return;
186 if (!IsConstant(i)) {
187 active_variables_.push_back(i);
188 active_variables_set_[i] =
true;
194 return active_variables_set_[
var];
197 bool NeighborhoodGeneratorHelper::IsConstant(
int var)
const {
198 return model_proto_with_only_variables_.variables(
var).domain_size() == 2 &&
199 model_proto_with_only_variables_.variables(
var).domain(0) ==
200 model_proto_with_only_variables_.variables(
var).domain(1);
205 const absl::flat_hash_set<int>& fixed_variables_set,
217 if (fixed_variables_set.contains(i)) {
236 absl::ReaderMutexLock lock(&domain_mutex_);
238 model_proto_with_only_variables_.variables();
245 std::vector<int> active_intervals;
246 absl::ReaderMutexLock lock(&domain_mutex_);
254 const int enforcement_var =
PositiveRef(enforcement_ref);
255 const int value = initial_solution.
solution(enforcement_var);
265 bool is_constant =
true;
267 if (!IsConstant(v)) {
273 if (!IsConstant(v)) {
279 if (!IsConstant(v)) {
284 if (is_constant)
continue;
294 active_intervals.push_back(i);
296 return active_intervals;
301 struct HeadAndArcLiteral {
306 std::vector<std::vector<int>> result;
307 absl::flat_hash_map<int, HeadAndArcLiteral> tail_to_head_and_arc_literal;
314 tail_to_head_and_arc_literal.clear();
315 for (
int i = 0; i <
ct.literals_size(); ++i) {
317 const int head =
ct.heads(i);
318 const int tail =
ct.tails(i);
325 tail_to_head_and_arc_literal[
tail] = {
head, bool_var};
328 if (tail_to_head_and_arc_literal.empty())
continue;
331 int current_node = min_node;
332 std::vector<int> path;
334 auto it = tail_to_head_and_arc_literal.find(current_node);
335 CHECK(it != tail_to_head_and_arc_literal.end());
336 current_node = it->second.head;
337 path.push_back(it->second.literal);
338 }
while (current_node != min_node);
339 result.push_back(std::move(path));
342 std::vector<HeadAndArcLiteral> route_starts;
345 tail_to_head_and_arc_literal.clear();
346 route_starts.clear();
349 for (
int i = 0; i <
ct.literals_size(); ++i) {
351 const int head =
ct.heads(i);
352 const int tail =
ct.tails(i);
360 route_starts.push_back({
head, bool_var});
362 tail_to_head_and_arc_literal[
tail] = {
head, bool_var};
367 for (
const HeadAndArcLiteral& head_var : route_starts) {
368 std::vector<int> path;
369 int current_node = head_var.head;
370 path.push_back(head_var.literal);
372 auto it = tail_to_head_and_arc_literal.find(current_node);
373 CHECK(it != tail_to_head_and_arc_literal.end());
374 current_node = it->second.head;
375 path.push_back(it->second.literal);
376 }
while (current_node != 0);
377 result.push_back(std::move(path));
386 const absl::flat_hash_set<int>& variables_to_fix)
const {
389 bool copy_is_successful =
true;
391 absl::ReaderMutexLock domain_lock(&domain_mutex_);
394 initial_solution, &neighborhood.
delta);
397 if (!copy_is_successful) {
406 neighborhood.
is_reduced = !variables_to_fix.empty();
424 if (is_fixed(
var))
continue;
433 const std::vector<int>& constraints_to_remove)
const {
436 if (constraints_to_remove.empty())
return neighborhood;
444 const std::vector<int>& relaxed_variables)
const {
445 std::vector<bool> relaxed_variables_set(model_proto_.
variables_size(),
false);
446 for (
const int var : relaxed_variables) relaxed_variables_set[
var] =
true;
447 absl::flat_hash_set<int> fixed_variables;
450 for (
const int i : active_variables_) {
451 if (!relaxed_variables_set[i]) {
452 fixed_variables.insert(i);
462 const absl::flat_hash_set<int> fixed_variables(all_variables.begin(),
463 all_variables.end());
474 if (num_calls_ <= 10)
return std::numeric_limits<double>::infinity();
475 return current_average_ + sqrt((2 * log(total_num_calls)) / num_calls_);
483 std::sort(solve_data_.begin(), solve_data_.end());
486 int num_fully_solved_in_batch = 0;
487 int num_not_fully_solved_in_batch = 0;
489 for (
const SolveData& data : solve_data_) {
498 ++num_fully_solved_calls_;
499 ++num_fully_solved_in_batch;
501 ++num_not_fully_solved_in_batch;
510 const IntegerValue best_objective_improvement =
512 ? IntegerValue(
CapSub(data.new_objective_bound.value(),
513 data.initial_best_objective_bound.value()))
514 : IntegerValue(
CapSub(data.initial_best_objective.value(),
515 data.new_objective.value()));
516 if (best_objective_improvement > 0) {
517 num_consecutive_non_improving_calls_ = 0;
519 ++num_consecutive_non_improving_calls_;
524 const double gain_per_time_unit =
525 std::max(0.0, static_cast<double>(best_objective_improvement.value())) /
526 (1.0 + data.deterministic_time);
527 if (num_calls_ <= 100) {
528 current_average_ += (gain_per_time_unit - current_average_) / num_calls_;
530 current_average_ = 0.9 * current_average_ + 0.1 * gain_per_time_unit;
533 deterministic_time_ += data.deterministic_time;
537 difficulty_.
Update(num_not_fully_solved_in_batch,
538 num_fully_solved_in_batch);
546 if (num_consecutive_non_improving_calls_ > 50) {
547 num_consecutive_non_improving_calls_ = 0;
548 deterministic_limit_ *= 1.02;
552 deterministic_limit_ =
std::min(60.0, deterministic_limit_);
560 void GetRandomSubset(
double relative_size, std::vector<int>* base,
561 absl::BitGenRef random) {
562 if (base->empty())
return;
566 std::shuffle(base->begin(), base->end(), random);
567 const int target_size = std::round(relative_size * base->size());
568 base->resize(target_size);
575 absl::BitGenRef random) {
577 GetRandomSubset(1.0 -
difficulty, &fixed_variables, random);
579 initial_solution, {fixed_variables.begin(), fixed_variables.end()});
584 absl::BitGenRef random) {
585 std::vector<int> active_constraints;
591 active_constraints.push_back(
ct);
594 if (active_constraints.empty() ||
599 std::shuffle(active_constraints.begin(), active_constraints.end(), random);
604 std::vector<bool> visited_variables_set(num_model_vars,
false);
605 std::vector<int> relaxed_variables;
609 const int num_active_vars =
611 const int target_size = std::ceil(
difficulty * num_active_vars);
614 for (
const int constraint_index : active_constraints) {
615 CHECK_LT(constraint_index, num_model_constraints);
617 if (visited_variables_set[
var])
continue;
618 visited_variables_set[
var] =
true;
620 relaxed_variables.push_back(
var);
621 if (relaxed_variables.size() == target_size)
break;
624 if (relaxed_variables.size() == target_size)
break;
632 absl::BitGenRef random) {
638 std::vector<bool> visited_variables_set(num_model_vars,
false);
639 std::vector<int> relaxed_variables;
640 std::vector<int> visited_variables;
644 std::vector<bool> scanned_constraints(num_model_constraints,
false);
646 std::vector<int> random_variables;
652 const int num_active_vars =
654 const int target_size = std::ceil(
difficulty * num_active_vars);
657 const int first_var =
659 random, 0, num_active_vars)];
661 visited_variables_set[first_var] =
true;
662 visited_variables.push_back(first_var);
663 relaxed_variables.push_back(first_var);
665 for (
int i = 0; i < visited_variables.size(); ++i) {
666 random_variables.clear();
670 if (scanned_constraints[
ct])
continue;
671 scanned_constraints[
ct] =
true;
673 if (visited_variables_set[
var])
continue;
674 visited_variables_set[
var] =
true;
675 random_variables.push_back(
var);
680 std::shuffle(random_variables.begin(), random_variables.end(), random);
681 for (
const int var : random_variables) {
682 if (relaxed_variables.size() < target_size) {
683 visited_variables.push_back(
var);
685 relaxed_variables.push_back(
var);
691 if (relaxed_variables.size() >= target_size)
break;
699 absl::BitGenRef random) {
701 if (num_model_constraints == 0 ||
707 std::vector<bool> visited_variables_set(num_model_vars,
false);
708 std::vector<int> relaxed_variables;
710 std::vector<bool> added_constraints(num_model_constraints,
false);
711 std::vector<int> next_constraints;
714 next_constraints.push_back(
715 absl::Uniform<int>(random, 0, num_model_constraints));
716 added_constraints[next_constraints.back()] =
true;
718 std::vector<int> random_variables;
721 const int num_active_vars =
723 const int target_size = std::ceil(
difficulty * num_active_vars);
726 while (relaxed_variables.size() < target_size) {
728 if (next_constraints.empty())
break;
731 const int i = absl::Uniform<int>(random, 0, next_constraints.size());
732 const int constraint_index = next_constraints[i];
733 std::swap(next_constraints[i], next_constraints.back());
734 next_constraints.pop_back();
738 CHECK_LT(constraint_index, num_model_constraints);
740 std::shuffle(random_variables.begin(), random_variables.end(), random);
741 for (
const int var : random_variables) {
742 if (visited_variables_set[
var])
continue;
743 visited_variables_set[
var] =
true;
745 relaxed_variables.push_back(
var);
747 if (relaxed_variables.size() == target_size)
break;
750 if (added_constraints[
ct])
continue;
751 added_constraints[
ct] =
true;
752 next_constraints.push_back(
ct);
770 LinearExpressionProto GetSize(
const IntervalConstraintProto&
interval) {
772 LinearExpressionProto result;
774 result.add_coeffs(1);
778 LinearExpressionProto GetEnd(
const IntervalConstraintProto&
interval) {
780 LinearExpressionProto result;
782 result.add_coeffs(1);
786 int64_t GetLinearExpressionValue(
const LinearExpressionProto& expr,
787 const CpSolverResponse& initial_solution) {
788 int64_t result = expr.offset();
789 for (
int i = 0; i < expr.vars_size(); ++i) {
790 result += expr.coeffs(i) * initial_solution.solution(expr.vars(i));
795 void AddLinearExpressionToConstraint(
const int64_t coeff,
796 const LinearExpressionProto& expr,
797 LinearConstraintProto* constraint,
798 int64_t* rhs_offset) {
799 *rhs_offset -= coeff * expr.offset();
800 for (
int i = 0; i < expr.vars_size(); ++i) {
801 constraint->add_vars(expr.vars(i));
802 constraint->add_coeffs(expr.coeffs(i) * coeff);
806 void AddPrecedenceConstraints(
const absl::Span<const int> intervals,
807 const absl::flat_hash_set<int>& ignored_intervals,
808 const CpSolverResponse& initial_solution,
809 const NeighborhoodGeneratorHelper& helper,
810 Neighborhood* neighborhood) {
813 std::vector<std::pair<int64_t, int>> start_interval_pairs;
814 for (
const int i : intervals) {
815 if (ignored_intervals.contains(i))
continue;
816 const ConstraintProto& interval_ct = helper.ModelProto().constraints(i);
819 const LinearExpressionProto size_var = GetSize(interval_ct.interval());
820 if (GetLinearExpressionValue(size_var, initial_solution) == 0)
continue;
822 const LinearExpressionProto start_var = GetStart(interval_ct.interval());
823 const int64_t start_value =
824 GetLinearExpressionValue(start_var, initial_solution);
826 start_interval_pairs.push_back({start_value, i});
828 std::sort(start_interval_pairs.begin(), start_interval_pairs.end());
831 for (
int i = 0; i + 1 < start_interval_pairs.size(); ++i) {
832 const LinearExpressionProto before_start =
833 GetStart(helper.ModelProto()
834 .constraints(start_interval_pairs[i].second)
836 const LinearExpressionProto before_end =
837 GetEnd(helper.ModelProto()
838 .constraints(start_interval_pairs[i].second)
840 const LinearExpressionProto after_start =
841 GetStart(helper.ModelProto()
842 .constraints(start_interval_pairs[i + 1].second)
847 LinearConstraintProto* linear =
848 neighborhood->delta.add_constraints()->mutable_linear();
850 int64_t rhs_offset = 0;
851 if (GetLinearExpressionValue(before_end, initial_solution) <=
852 GetLinearExpressionValue(after_start, initial_solution)) {
854 AddLinearExpressionToConstraint(1, before_end, linear, &rhs_offset);
858 rhs_offset = GetLinearExpressionValue(before_start, initial_solution) -
859 GetLinearExpressionValue(after_start, initial_solution);
860 AddLinearExpressionToConstraint(1, before_start, linear, &rhs_offset);
863 AddLinearExpressionToConstraint(-1, after_start, linear, &rhs_offset);
864 linear->add_domain(rhs_offset);
868 int64_t activity = 0;
869 for (
int i = 0; i < linear->vars().size(); ++i) {
871 linear->coeffs(i) * initial_solution.solution(linear->vars(i));
873 CHECK_GE(activity, linear->domain(0));
874 CHECK_LE(activity, linear->domain(1));
881 const absl::Span<const int> intervals_to_relax,
886 (intervals_to_relax.size() <
890 absl::flat_hash_set<int> ignored_intervals(intervals_to_relax.begin(),
891 intervals_to_relax.end());
896 if (ignored_intervals.contains(i))
continue;
903 const int enforcement_var =
PositiveRef(enforcement_ref);
904 const int value = initial_solution.
solution(enforcement_var);
912 ignored_intervals.insert(i);
923 AddPrecedenceConstraints(
925 ignored_intervals, initial_solution, helper, &neighborhood);
928 AddPrecedenceConstraints(
930 ignored_intervals, initial_solution, helper, &neighborhood);
933 AddPrecedenceConstraints(
935 ignored_intervals, initial_solution, helper, &neighborhood);
936 AddPrecedenceConstraints(
937 helper.ModelProto().constraints(c).no_overlap_2d().y_intervals(),
938 ignored_intervals, initial_solution, helper, &neighborhood);
950 absl::BitGenRef random) {
951 std::vector<int> intervals_to_relax =
953 GetRandomSubset(
difficulty, &intervals_to_relax, random);
961 absl::BitGenRef random) {
962 std::vector<std::pair<int64_t, int>> start_interval_pairs;
963 const std::vector<int> active_intervals =
965 std::vector<int> intervals_to_relax;
969 for (
const int i : active_intervals) {
972 const int64_t start_value =
973 GetLinearExpressionValue(start_var, initial_solution);
974 start_interval_pairs.push_back({start_value, i});
976 std::sort(start_interval_pairs.begin(), start_interval_pairs.end());
977 const int relaxed_size = std::floor(
difficulty * start_interval_pairs.size());
979 std::uniform_int_distribution<int> random_var(
980 0, start_interval_pairs.size() - relaxed_size - 1);
981 const int random_start_index = random_var(random);
985 for (
int i = random_start_index; i < relaxed_size; ++i) {
986 intervals_to_relax.push_back(start_interval_pairs[i].second);
995 absl::BitGenRef random) {
996 const std::vector<std::vector<int>> all_paths =
1000 absl::flat_hash_set<int> all_path_variables;
1001 for (
auto& path : all_paths) {
1002 all_path_variables.insert(path.begin(), path.end());
1004 std::vector<int> fixed_variables(all_path_variables.begin(),
1005 all_path_variables.end());
1006 std::sort(fixed_variables.begin(), fixed_variables.end());
1007 GetRandomSubset(1.0 -
difficulty, &fixed_variables, random);
1009 initial_solution, {fixed_variables.begin(), fixed_variables.end()});
1014 absl::BitGenRef random) {
1015 std::vector<std::vector<int>> all_paths =
1019 absl::flat_hash_set<int> all_path_variables;
1020 for (
const auto& path : all_paths) {
1021 all_path_variables.insert(path.begin(), path.end());
1025 const int num_variables_to_relax =
1026 static_cast<int>(all_path_variables.size() *
difficulty);
1027 absl::flat_hash_set<int> relaxed_variables;
1028 while (relaxed_variables.size() < num_variables_to_relax) {
1029 DCHECK(!all_paths.empty());
1030 const int path_index = absl::Uniform<int>(random, 0, all_paths.size());
1031 std::vector<int>& path = all_paths[path_index];
1032 const int path_size = path.size();
1033 const int segment_length =
1034 std::min(path_size, absl::Uniform<int>(random, 4, 8));
1035 const int segment_start =
1036 absl::Uniform<int>(random, 0, path_size - segment_length);
1037 for (
int i = segment_start; i < segment_start + segment_length; ++i) {
1038 relaxed_variables.insert(path[i]);
1042 path.erase(path.begin() + segment_start,
1043 path.begin() + segment_start + segment_length);
1045 std::swap(all_paths[path_index], all_paths.back());
1046 all_paths.pop_back();
1051 absl::flat_hash_set<int> fixed_variables;
1052 for (
const int var : all_path_variables) {
1053 if (!relaxed_variables.contains(
var)) fixed_variables.insert(
var);
1060 absl::BitGenRef random) {
1061 std::vector<std::vector<int>> all_paths =
1065 absl::flat_hash_set<int> all_path_variables;
1066 for (
const auto& path : all_paths) {
1067 all_path_variables.insert(path.begin(), path.end());
1071 const int num_variables_to_relax =
1072 static_cast<int>(all_path_variables.size() *
difficulty);
1073 absl::flat_hash_set<int> relaxed_variables;
1076 for (
const auto& path : all_paths) {
1077 relaxed_variables.insert(path.front());
1078 relaxed_variables.insert(path.back());
1082 for (
auto& path : all_paths) {
1083 std::shuffle(path.begin(), path.end(), random);
1087 const int path_to_clean = absl::Uniform<int>(random, 0, all_paths.size());
1088 while (relaxed_variables.size() < num_variables_to_relax) {
1089 DCHECK(!all_paths[path_to_clean].empty());
1090 relaxed_variables.insert(all_paths[path_to_clean].back());
1091 all_paths[path_to_clean].pop_back();
1093 if (all_paths[path_to_clean].empty()) {
1094 std::swap(all_paths[path_to_clean], all_paths.back());
1095 all_paths.pop_back();
1099 while (relaxed_variables.size() < num_variables_to_relax) {
1100 DCHECK(!all_paths.empty());
1101 const int path_index = absl::Uniform<int>(random, 0, all_paths.size());
1102 relaxed_variables.insert(all_paths[path_index].back());
1105 all_paths[path_index].pop_back();
1106 if (all_paths[path_index].empty()) {
1107 std::swap(all_paths[path_index], all_paths.back());
1108 all_paths.pop_back();
1113 absl::flat_hash_set<int> fixed_variables;
1114 for (
const int var : all_path_variables) {
1115 if (!relaxed_variables.contains(
var)) fixed_variables.insert(
var);
1121 if (incomplete_solutions_ !=
nullptr) {
1125 if (response_manager_ !=
nullptr) {
1133 if (lp_solutions_ !=
nullptr && lp_solutions_->
NumSolutions() > 0) {
1137 if (relaxation_solutions_ !=
nullptr &&
1146 absl::BitGenRef random) {
1150 const bool lp_solution_available =
1151 (lp_solutions_ !=
nullptr && lp_solutions_->
NumSolutions() > 0);
1153 const bool relaxation_solution_available =
1154 (relaxation_solutions_ !=
nullptr &&
1157 const bool incomplete_solution_available =
1158 (incomplete_solutions_ !=
nullptr &&
1161 if (!lp_solution_available && !relaxation_solution_available &&
1162 !incomplete_solution_available) {
1163 return neighborhood;
1170 std::bernoulli_distribution random_bool(0.5);
1171 const bool use_lp_relaxation =
1172 (lp_solution_available && relaxation_solution_available)
1173 ? random_bool(random)
1174 : lp_solution_available;
1175 if (use_lp_relaxation) {
1178 nullptr, lp_solutions_,
1179 incomplete_solutions_, random);
1181 incomplete_solution_available ?
"incomplete" :
"lp";
1183 CHECK(relaxation_solution_available || incomplete_solution_available);
1185 response_manager_, relaxation_solutions_,
1186 nullptr, incomplete_solutions_, random);
1188 incomplete_solution_available ?
"incomplete" :
"relaxation";
1193 return neighborhood;
1198 for (
const std::pair</*model_var*/ int, /*value*/ int64_t> fixed_var :
1200 const int var = fixed_var.first;
1201 const int64_t
value = fixed_var.second;
1207 return neighborhood;
1216 for (
const std::pair<
int,
1217 std::pair<int64_t, int64_t>>
1219 const int var = reduced_var.first;
1220 const int64_t lb = reduced_var.second.first;
1221 const int64_t ub = reduced_var.second.second;
1226 if (domain.IsEmpty()) {
1228 return neighborhood;
1234 return neighborhood;
1239 absl::BitGenRef random) {
1240 std::vector<int> removable_constraints;
1242 removable_constraints.reserve(num_constraints);
1243 for (
int c = 0; c < num_constraints; ++c) {
1250 removable_constraints.push_back(c);
1253 const int target_size =
1254 std::round((1.0 -
difficulty) * removable_constraints.size());
1256 const int random_start_index =
1257 absl::Uniform<int>(random, 0, removable_constraints.size());
1258 std::vector<int> removed_constraints;
1259 removed_constraints.reserve(target_size);
1260 int c = random_start_index;
1261 while (removed_constraints.size() < target_size) {
1262 removed_constraints.push_back(removable_constraints[c]);
1264 if (c == removable_constraints.size()) {
1276 std::vector<int> removable_constraints;
1278 constraint_weights_.reserve(num_constraints);
1280 for (
int c = 0; c < num_constraints; ++c) {
1287 constraint_weights_.push_back(3.0);
1288 num_removable_constraints_++;
1302 constraint_weights_.push_back(2.0);
1303 num_removable_constraints_++;
1312 constraint_weights_.push_back(1.0);
1313 num_removable_constraints_++;
1320 constraint_weights_.push_back(0.0);
1326 void WeightedRandomRelaxationNeighborhoodGenerator::
1327 AdditionalProcessingOnSynchronize(
const SolveData& solve_data) {
1328 const IntegerValue best_objective_improvement =
1329 solve_data.new_objective_bound - solve_data.initial_best_objective_bound;
1331 const std::vector<int>& removed_constraints =
1332 removed_constraints_[solve_data.neighborhood_id];
1346 if (best_objective_improvement > 0) {
1348 for (
int c : removed_constraints) {
1349 if (constraint_weights_[c] <= 90.0) {
1350 constraint_weights_[c] += 10.0;
1352 constraint_weights_[c] = 100.0;
1356 best_objective_improvement < 0) {
1358 for (
int c : removed_constraints) {
1359 if (constraint_weights_[c] > 0.5) {
1360 constraint_weights_[c] -= 0.5;
1364 removed_constraints_.erase(solve_data.neighborhood_id);
1369 absl::BitGenRef random) {
1370 const int target_size =
1371 std::round((1.0 -
difficulty) * num_removable_constraints_);
1373 std::vector<int> removed_constraints;
1378 std::vector<std::pair<double, int>> constraint_removal_scores;
1379 std::uniform_real_distribution<double> random_var(0.0, 1.0);
1380 for (
int c = 0; c < constraint_weights_.size(); ++c) {
1381 if (constraint_weights_[c] <= 0)
continue;
1382 const double u = random_var(random);
1383 const double score = std::pow(u, (1 / constraint_weights_[c]));
1384 constraint_removal_scores.push_back({score, c});
1386 std::sort(constraint_removal_scores.rbegin(),
1387 constraint_removal_scores.rend());
1388 for (
int i = 0; i < target_size; ++i) {
1389 removed_constraints.push_back(constraint_removal_scores[i].second);
1395 result.
id = next_available_id_;
1396 next_available_id_++;
1397 removed_constraints_.insert({result.
id, removed_constraints});
std::vector< int > UsedVariables(const ConstraintProto &ct)
const std::string & name() const
std::vector< int > ActiveVariables() const
int64_t CapSub(int64_t x, int64_t y)
void Update(int num_decreases, int num_increases)
RINSNeighborhood GetRINSNeighborhood(const SharedResponseManager *response_manager, const SharedRelaxationSolutionRepository *relaxation_solutions, const SharedLPSolutionRepository *lp_solutions, SharedIncompleteSolutionManager *incomplete_solutions, absl::BitGenRef random)
ConstraintCase constraint_case() const
#define CHECK_GE(val1, val2)
Neighborhood Generate(const CpSolverResponse &initial_solution, double difficulty, absl::BitGenRef random) final
Neighborhood GenerateSchedulingNeighborhoodForRelaxation(const absl::Span< const int > intervals_to_relax, const CpSolverResponse &initial_solution, const NeighborhoodGeneratorHelper &helper)
Neighborhood RemoveMarkedConstraints(const std::vector< int > &constraints_to_remove) const
NeighborhoodGeneratorHelper(CpModelProto const *model_proto, SatParameters const *parameters, SharedResponseManager *shared_response, SharedTimeLimit *shared_time_limit=nullptr, SharedBoundsManager *shared_bounds=nullptr)
#define CHECK_GT(val1, val2)
Neighborhood Generate(const CpSolverResponse &initial_solution, double difficulty, absl::BitGenRef random) final
bool IsActive(int var) const ABSL_SHARED_LOCKS_REQUIRED(graph_mutex_)
#define VLOG(verboselevel)
::PROTOBUF_NAMESPACE_ID::int32 size() const
bool lns_expand_intervals_in_constraint_graph() const
void swap(IdMap< K, V > &a, IdMap< K, V > &b)
Neighborhood FixAllVariables(const CpSolverResponse &initial_solution) const
const absl::Span< const int > TypeToConstraints(ConstraintProto::ConstraintCase type) const
bool ReadyToGenerate() const override
void add_vars(::PROTOBUF_NAMESPACE_ID::int32 value)
double GetUCBScore(int64_t total_num_calls) const
const ::operations_research::sat::RoutesConstraintProto & routes() const
std::vector< int > constraints_to_ignore
int variables_size() const
::operations_research::sat::IntegerVariableProto * add_variables()
Neighborhood Generate(const CpSolverResponse &initial_solution, double difficulty, absl::BitGenRef random) final
bool DifficultyMeansFullNeighborhood(double difficulty) const
bool has_start_view() const
const ::operations_research::sat::LinearExpressionProto & end_view() const
#define CHECK_LT(val1, val2)
bool lns_focus_on_decision_variables() const
double difficulty() const
const std::vector< int > & ActiveVariablesWhileHoldingLock() const ABSL_SHARED_LOCKS_REQUIRED(graph_mutex_)
::PROTOBUF_NAMESPACE_ID::int32 enforcement_literal(int index) const
void AddSolutionHinting(const CpSolverResponse &initial_solution, CpModelProto *model_proto) const
Neighborhood Generate(const CpSolverResponse &initial_solution, double difficulty, absl::BitGenRef random) final
const ::operations_research::sat::NoOverlapConstraintProto & no_overlap() const
const ::operations_research::sat::IntegerVariableProto & variables(int index) const
void set_name(ArgT0 &&arg0, ArgT... args)
const CpModelProto & ModelProto() const
std::vector< std::pair< int, int64_t > > fixed_vars
const ::operations_research::sat::CumulativeConstraintProto & cumulative() const
bool CopyAndFixVariables(const CpModelProto &source_model, const absl::flat_hash_set< int > &fixed_variables_set, const CpSolverResponse &initial_solution, CpModelProto *output_model) const
#define CHECK_LE(val1, val2)
const ::operations_research::sat::ConstraintProto & constraints(int index) const
absl::Mutex generator_mutex_
Neighborhood Generate(const CpSolverResponse &initial_solution, double difficulty, absl::BitGenRef random) final
const ::operations_research::sat::LinearExpressionProto & size_view() const
const ::operations_research::sat::LinearExpressionProto & start_view() const
void add_domain(::PROTOBUF_NAMESPACE_ID::int64 value)
Neighborhood Generate(const CpSolverResponse &initial_solution, double difficulty, absl::BitGenRef random) final
Neighborhood Generate(const CpSolverResponse &initial_solution, double difficulty, absl::BitGenRef random) final
const SharedResponseManager & shared_response() const
::PROTOBUF_NAMESPACE_ID::int32 end() const
PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final
void Synchronize() override
virtual void AdditionalProcessingOnSynchronize(const SolveData &solve_data)
Domain IntersectionWith(const Domain &domain) const
Returns the intersection of D and domain.
#define DCHECK_GE(val1, val2)
const std::vector< std::vector< int > > & VarToConstraint() const ABSL_SHARED_LOCKS_REQUIRED(graph_mutex_)
int constraints_size() const
#define CHECK_EQ(val1, val2)
WeightedRandomRelaxationNeighborhoodGenerator(NeighborhoodGeneratorHelper const *helper, const std::string &name)
std::vector< int > UsedIntervals(const ConstraintProto &ct)
Neighborhood FullNeighborhood() const
CpModelProto const * model_proto
::PROTOBUF_NAMESPACE_ID::int32 start() const
const ::operations_research::sat::NoOverlap2DConstraintProto & no_overlap_2d() const
::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int64 > * mutable_domain()
const ::operations_research::sat::CircuitConstraintProto & circuit() const
#define DCHECK(condition)
::PROTOBUF_NAMESPACE_ID::int32 intervals(int index) const
We call domain any subset of Int64 = [kint64min, kint64max].
void FillDomainInProto(const Domain &domain, ProtoWithDomain *proto)
::PROTOBUF_NAMESPACE_ID::int64 solution(int index) const
virtual bool IsRelaxationGenerator() const
const std::vector< std::vector< int > > & ConstraintToVar() const ABSL_SHARED_LOCKS_REQUIRED(graph_mutex_)
const ::operations_research::sat::DecisionStrategyProto & search_strategy(int index) const
bool HasNewSolution() const
std::vector< std::vector< int > > GetRoutingPaths(const CpSolverResponse &initial_solution) const
Neighborhood Generate(const CpSolverResponse &initial_solution, double difficulty, absl::BitGenRef random) final
void GetChangedBounds(int id, std::vector< int > *variables, std::vector< int64_t > *new_lower_bounds, std::vector< int64_t > *new_upper_bounds)
Neighborhood RelaxGivenVariables(const CpSolverResponse &initial_solution, const std::vector< int > &relaxed_variables) const
Collection of objects used to extend the Constraint Solver library.
Neighborhood Generate(const CpSolverResponse &initial_solution, double difficulty, absl::BitGenRef random) final
Neighborhood FixGivenVariables(const CpSolverResponse &initial_solution, const absl::flat_hash_set< int > &variables_to_fix) const
const ::operations_research::sat::IntervalConstraintProto & interval() const
Neighborhood Generate(const CpSolverResponse &initial_solution, double difficulty, absl::BitGenRef random) final
::PROTOBUF_NAMESPACE_ID::int32 vars(int index) const
bool RefIsPositive(int ref)
void add_coeffs(::PROTOBUF_NAMESPACE_ID::int64 value)
virtual bool ReadyToGenerate() const
::PROTOBUF_NAMESPACE_ID::int64 domain(int index) const
Neighborhood Generate(const CpSolverResponse &initial_solution, double difficulty, absl::BitGenRef random) final
::PROTOBUF_NAMESPACE_ID::int32 intervals(int index) const
#define VLOG_IS_ON(verboselevel)
Neighborhood Generate(const CpSolverResponse &initial_solution, double difficulty, absl::BitGenRef random) final
std::vector< std::pair< int, std::pair< int64_t, int64_t > > > reduced_domain_vars
const SharedSolutionRepository< int64_t > & SolutionsRepository() const
Domain ReadDomainFromProto(const ProtoWithDomain &proto)
bool DomainInProtoContains(const ProtoWithDomain &proto, int64_t value)
std::vector< int > GetActiveIntervals(const CpSolverResponse &initial_solution) const
::operations_research::sat::IntegerVariableProto * mutable_variables(int index)
::PROTOBUF_NAMESPACE_ID::int32 x_intervals(int index) const
const NeighborhoodGeneratorHelper & helper_