27#include "absl/algorithm/container.h"
28#include "absl/container/btree_map.h"
29#include "absl/container/flat_hash_map.h"
30#include "absl/container/flat_hash_set.h"
31#include "absl/log/check.h"
32#include "absl/log/log.h"
33#include "absl/types/span.h"
47 int num_vars,
const absl::flat_hash_map<int, int64_t>&
solution) {
48 CHECK(!solution_is_loaded_);
49 CHECK(var_has_value_.empty());
50 CHECK(var_values_.empty());
51 solution_is_loaded_ =
true;
52 var_has_value_.resize(num_vars,
false);
53 var_values_.resize(num_vars, 0);
54 for (
const auto [var, value] :
solution) {
55 var_has_value_[var] =
true;
56 var_values_[var] = value;
61 if (!solution_is_loaded_)
return;
62 var_has_value_.resize(new_size,
false);
63 var_values_.resize(new_size, 0);
69 if (!solution_is_loaded_)
return;
70 if (!HasValue(
PositiveRef(literal)) && HasValue(var)) {
71 SetLiteralValue(literal, GetVarValue(var) == value);
76 int64_t value,
bool is_le) {
78 if (!solution_is_loaded_)
return;
79 if (!HasValue(
PositiveRef(literal)) && HasValue(var)) {
81 literal, is_le ? GetVarValue(var) <= value : GetVarValue(var) >= value);
86 int new_var, absl::Span<
const std::pair<int, int64_t>> linear,
88 if (!solution_is_loaded_)
return;
89 int64_t new_value = offset;
90 for (
const auto [var, coeff] : linear) {
91 if (!HasValue(var))
return;
92 new_value += coeff * GetVarValue(var);
94 SetVarValue(new_var, new_value);
98 absl::Span<const int> vars,
99 absl::Span<const int64_t> coeffs,
101 DCHECK_EQ(vars.size(), coeffs.size());
102 if (!solution_is_loaded_)
return;
103 int64_t new_value = offset;
104 for (
int i = 0;
i < vars.size(); ++
i) {
105 const int var = vars[
i];
106 const int64_t coeff = coeffs[
i];
107 if (!HasValue(var))
return;
108 new_value += coeff * GetVarValue(var);
110 SetVarValue(new_var, new_value);
114 if (!solution_is_loaded_)
return;
116 bool all_have_value =
true;
117 for (
const int literal : clause) {
119 if (!HasValue(var)) {
120 all_have_value =
false;
129 if (all_have_value) {
130 SetVarValue(new_var, new_value);
135 absl::Span<const int> conjunction) {
136 if (!solution_is_loaded_)
return;
138 bool all_have_value =
true;
139 for (
const int literal : conjunction) {
141 if (!HasValue(var)) {
142 all_have_value =
false;
151 if (all_have_value) {
152 SetVarValue(new_var, new_value);
157 int new_var, int64_t value,
158 absl::Span<
const std::pair<int, int64_t>> linear,
const Domain& domain) {
159 if (!solution_is_loaded_)
return;
160 int64_t linear_value = 0;
161 bool all_have_value =
true;
162 for (
const auto [var, coeff] : linear) {
163 if (!HasValue(var)) {
164 all_have_value =
false;
167 linear_value += GetVarValue(var) * coeff;
169 if (all_have_value && !domain.
Contains(linear_value)) {
170 SetVarValue(new_var, value);
175 int literal,
bool value, absl::Span<
const std::pair<int, int64_t>> linear,
190 if (!solution_is_loaded_)
return;
192 if (!GetLiteralValue(condition_lit))
return;
193 const std::optional<int64_t> expr_value = GetExpressionValue(expr);
194 if (expr_value.has_value()) {
195 SetVarValue(var, expr_value.value());
207 int var, absl::Span<const int> condition_lits, int64_t value_if_true,
208 int64_t value_if_false) {
209 if (!solution_is_loaded_)
return;
210 bool condition_value =
true;
211 for (
const int condition_lit : condition_lits) {
213 if (!GetLiteralValue(condition_lit)) {
214 condition_value =
false;
218 SetVarValue(var, condition_value ? value_if_true : value_if_false);
222 if (!solution_is_loaded_)
return;
224 SetLiteralValue(lit1, GetLiteralValue(lit2));
226 SetLiteralValue(lit2, GetLiteralValue(lit1));
231 if (!solution_is_loaded_)
return;
233 SetVarValue(var, domain.
ClosestValue(GetVarValue(var)));
240 int var,
const Domain& reduced_var_domain,
241 std::optional<int64_t> unique_escape_value,
242 bool push_down_when_not_in_domain,
243 const absl::btree_map<int64_t, int>& encoding) {
244 if (!solution_is_loaded_)
return;
246 const int64_t old_value = GetVarValue(var);
247 int64_t new_value = old_value;
248 if (reduced_var_domain.
Contains(old_value))
return;
249 if (unique_escape_value.has_value()) {
250 new_value = unique_escape_value.value();
251 }
else if (push_down_when_not_in_domain) {
252 DCHECK_GT(old_value, reduced_var_domain.
Min());
255 DCHECK_LT(old_value, reduced_var_domain.
Max());
259 SetLiteralValue(encoding.at(new_value),
true);
260 CHECK(!encoding.contains(old_value));
261 SetVarValue(var, new_value);
269 const std::vector<std::pair<int, int64_t>> linear = {
271 const Domain domain =
Domain((sign1 == 1 ? 0 : -1) - (sign2 == 1 ? 0 : -1));
277 if (!solution_is_loaded_)
return;
281 if (GetLiteralValue(lit) && !GetLiteralValue(dominating_lit)) {
282 SetLiteralValue(lit,
false);
283 SetLiteralValue(dominating_lit,
true);
289 absl::Span<
const std::unique_ptr<SparsePermutation>> generators) {
290 if (!solution_is_loaded_)
return;
291 if (!HasValue(var))
return;
292 if (GetVarValue(var) ==
static_cast<int64_t
>(value))
return;
294 std::vector<int> schrier_vector;
295 std::vector<int> orbit;
298 bool found_target =
false;
300 for (
int v : orbit) {
301 if (HasValue(v) && GetVarValue(v) ==
static_cast<int64_t
>(value)) {
308 VLOG(1) <<
"Couldn't transform solution properly";
312 const std::vector<int> generator_idx =
313 TracePoint(target_var, schrier_vector, generators);
314 for (
const int i : generator_idx) {
315 PermuteVariables(*generators[
i]);
318 DCHECK(HasValue(var));
319 DCHECK_EQ(GetVarValue(var), value);
323 absl::Span<
const std::vector<int>> orbitope,
int row,
int pivot_col,
325 if (!solution_is_loaded_)
return;
327 for (
int c = 0; c < orbitope[row].size(); ++c) {
328 if (GetLiteralValue(orbitope[row][c]) == value) {
330 VLOG(2) <<
"Multiple literals in row with given value";
336 if (col < pivot_col) {
342 for (
int i = 0;
i < orbitope.size(); ++
i) {
344 if (!HasValue(
PositiveRef(orbitope[
i][pivot_col])))
return;
346 for (
int i = 0;
i < orbitope.size(); ++
i) {
347 const int src_lit = orbitope[
i][col];
348 const int dst_lit = orbitope[
i][pivot_col];
349 const bool src_value = GetLiteralValue(src_lit);
350 const bool dst_value = GetLiteralValue(dst_lit);
351 SetLiteralValue(src_lit, dst_value);
352 SetLiteralValue(dst_lit, src_value);
357 int ref, int64_t min_value, int64_t max_value,
358 absl::Span<
const std::pair<int, Domain>> dominating_refs) {
359 if (!solution_is_loaded_)
return;
360 const std::optional<int64_t> ref_value = GetRefValue(ref);
361 if (!ref_value.has_value())
return;
364 if (*ref_value < min_value)
return;
366 if (*ref_value <= max_value)
return;
368 const int64_t ref_value_delta = *ref_value - max_value;
370 SetRefValue(ref, *ref_value - ref_value_delta);
371 int64_t remaining_delta = ref_value_delta;
372 for (
const auto& [dominating_ref, dominating_ref_domain] : dominating_refs) {
373 const std::optional<int64_t> dominating_ref_value =
374 GetRefValue(dominating_ref);
375 if (!dominating_ref_value.has_value())
continue;
376 const int64_t new_dominating_ref_value =
377 dominating_ref_domain.ValueAtOrBefore(*dominating_ref_value +
380 if (!dominating_ref_domain.Contains(new_dominating_ref_value))
continue;
381 SetRefValue(dominating_ref, new_dominating_ref_value);
382 remaining_delta -= (new_dominating_ref_value - *dominating_ref_value);
383 if (remaining_delta == 0)
break;
388 absl::Span<const int> enforcement_lits, std::optional<int> var_index,
389 absl::Span<const int> vars, absl::Span<const int64_t> default_values,
390 absl::Span<const int64_t> coeffs, int64_t rhs) {
391 DCHECK_EQ(vars.size(), coeffs.size());
392 DCHECK(!var_index.has_value() || var_index.value() < vars.size());
393 if (!solution_is_loaded_)
return;
394 bool constraint_is_enforced =
true;
395 for (
const int lit : enforcement_lits) {
397 constraint_is_enforced = constraint_is_enforced && GetLiteralValue(lit);
399 if (!constraint_is_enforced) {
400 for (
int i = 0;
i < vars.size(); ++
i) {
401 if (!HasValue(vars[
i])) {
402 SetVarValue(vars[
i], default_values[
i]);
407 int64_t term_value = rhs;
408 for (
int i = 0;
i < vars.size(); ++
i) {
409 if (HasValue(vars[
i])) {
410 if (
i != var_index) {
411 term_value -= GetVarValue(vars[
i]) * coeffs[
i];
413 }
else if (!var_index.has_value()) {
415 }
else if (var_index.value() !=
i) {
419 if (!var_index.has_value())
return;
420 SetVarValue(vars[var_index.value()], term_value / coeffs[var_index.value()]);
423 if (term_value % coeffs[var_index.value()] != 0) {
424 std::stringstream lhs;
425 for (
int i = 0;
i < vars.size(); ++
i) {
426 lhs << (
i == var_index ?
"x" : std::to_string(GetVarValue(vars[
i])));
427 lhs <<
" * " << coeffs[
i];
428 if (
i < vars.size() - 1) lhs <<
" + ";
430 LOG(FATAL) <<
"Linear constraint incompatible with solution: " << lhs
438 int64_t max_level, absl::Span<const int> level_vars,
440 if (!solution_is_loaded_)
return;
443 struct ReservoirEventValues {
446 int64_t level_change;
449 std::vector<ReservoirEventValues> active_event_values;
450 for (
int i = 0;
i < num_events; ++
i) {
453 const std::optional<int64_t> time_value =
455 const std::optional<int64_t> change_value =
457 if (!time_value.has_value() || !change_value.has_value())
return;
458 active_event_values.push_back(
459 {
i, time_value.value(), change_value.value()});
464 std::sort(active_event_values.begin(), active_event_values.end(),
465 [](
const ReservoirEventValues& a,
const ReservoirEventValues&
b) {
466 return a.time < b.time;
468 int64_t current_level = 0;
469 for (
int i = 0;
i < active_event_values.size(); ++
i) {
476 while (j < active_event_values.size() &&
477 active_event_values[j].time == active_event_values[
i].time &&
478 (current_level + active_event_values[j].level_change < min_level ||
479 current_level + active_event_values[j].level_change > max_level)) {
482 if (j < active_event_values.size() &&
483 active_event_values[j].time == active_event_values[
i].time) {
484 if (
i != j) std::swap(active_event_values[
i], active_event_values[j]);
485 current_level += active_event_values[
i].level_change;
486 SetVarValue(level_vars[active_event_values[
i].index], current_level);
494 std::vector<int> active_event_value_index(num_events, -1);
495 for (
int i = 0;
i < active_event_values.size(); ++
i) {
496 active_event_value_index[active_event_values[
i].index] =
i;
499 for (
int i = 0;
i < num_events; ++
i) {
500 if (active_event_value_index[
i] == -1) {
501 SetVarValue(level_vars[
i], min_level);
506 const int head = circuit.
heads(
i);
507 const int tail = circuit.
tails(
i);
509 if (tail == num_events) {
510 if (head == num_events) {
512 SetLiteralValue(literal, active_event_values.empty());
515 SetLiteralValue(literal, !active_event_values.empty() &&
516 active_event_values.front().index == head);
518 }
else if (head == num_events) {
520 SetLiteralValue(literal, !active_event_values.empty() &&
521 active_event_values.back().index == tail);
522 }
else if (tail != head) {
524 const int tail_index = active_event_value_index[tail];
525 const int head_index = active_event_value_index[head];
526 SetLiteralValue(literal, tail_index != -1 && tail_index != -1 &&
527 head_index == tail_index + 1);
535 if (!solution_is_loaded_)
return;
536 std::optional<int64_t> time_i_value = GetExpressionValue(time_i);
537 std::optional<int64_t> time_j_value = GetExpressionValue(time_j);
538 std::optional<int64_t> active_i_value = GetRefValue(active_i);
539 std::optional<int64_t> active_j_value = GetRefValue(active_j);
540 if (time_i_value.has_value() && time_j_value.has_value() &&
541 active_i_value.has_value() && active_j_value.has_value()) {
542 const bool reified_value = (active_i_value.value() != 0) &&
543 (active_j_value.value() != 0) &&
544 (time_i_value.value() <= time_j_value.value());
545 SetVarValue(var, reified_value);
550 int div_var,
int prod_var,
551 int64_t default_div_value,
552 int64_t default_prod_value) {
553 if (!solution_is_loaded_)
return;
554 bool constraint_is_enforced =
true;
557 constraint_is_enforced = constraint_is_enforced && GetLiteralValue(lit);
559 if (!constraint_is_enforced) {
560 SetVarValue(div_var, default_div_value);
561 SetVarValue(prod_var, default_prod_value);
565 std::optional<int64_t> v = GetExpressionValue(int_mod.
exprs(0));
566 if (!v.has_value())
return;
567 const int64_t expr_value = v.value();
569 v = GetExpressionValue(int_mod.
exprs(1));
570 if (!v.has_value())
return;
571 const int64_t mod_expr_value = v.value();
573 v = GetExpressionValue(int_mod.
target());
574 if (!v.has_value())
return;
575 const int64_t target_expr_value = v.value();
578 SetVarValue(div_var, expr_value / mod_expr_value);
579 SetVarValue(prod_var, expr_value - target_expr_value);
583 absl::Span<const int> prod_vars) {
584 DCHECK_EQ(int_prod.
exprs_size(), prod_vars.size() + 2);
585 if (!solution_is_loaded_)
return;
586 std::optional<int64_t> v = GetExpressionValue(int_prod.
exprs(0));
587 if (!v.has_value())
return;
588 int64_t last_prod_value = v.value();
590 v = GetExpressionValue(int_prod.
exprs(
i));
591 if (!v.has_value())
return;
592 last_prod_value *= v.value();
593 SetVarValue(prod_vars[
i - 1], last_prod_value);
599 absl::Span<const int> enforcement_lits) {
600 if (!solution_is_loaded_)
return;
601 DCHECK_EQ(enforcement_lits.size(), lin_max.
exprs_size());
602 const std::optional<int64_t> target_value =
603 GetExpressionValue(lin_max.
target());
604 if (!target_value.has_value())
return;
605 int enforcement_value_sum = 0;
606 for (
int i = 0;
i < enforcement_lits.size(); ++
i) {
607 const std::optional<int64_t> expr_value =
608 GetExpressionValue(lin_max.
exprs(
i));
609 if (!expr_value.has_value())
return;
610 if (enforcement_value_sum == 0) {
611 const bool enforcement_value = target_value.value() <= expr_value.value();
612 SetLiteralValue(enforcement_lits[
i], enforcement_value);
613 enforcement_value_sum += enforcement_value;
615 SetLiteralValue(enforcement_lits[
i],
false);
622 absl::Span<const StateVar> state_vars,
623 absl::Span<const TransitionVar> transition_vars) {
624 if (!solution_is_loaded_)
return;
625 absl::flat_hash_map<std::pair<int64_t, int64_t>, int64_t> transitions;
631 std::vector<int64_t> label_values;
632 std::vector<int64_t> state_values;
634 state_values.push_back(current_state);
636 const std::optional<int64_t> label_value =
637 GetExpressionValue(automaton.
exprs(
i));
638 if (!label_value.has_value())
return;
639 label_values.push_back(label_value.value());
641 const auto it = transitions.find({current_state, label_value.value()});
642 if (it == transitions.end())
return;
643 current_state = it->second;
644 state_values.push_back(current_state);
647 for (
const auto& [var, time, state] : state_vars) {
648 SetVarValue(var, state_values[time] == state);
650 for (
const auto& [var, time, transition_tail, transition_label] :
652 SetVarValue(var, state_values[time] == transition_tail &&
653 label_values[time] == transition_label);
658 absl::Span<const int> column_vars, absl::Span<const int> existing_row_lits,
659 absl::Span<const TableRowLiteral> new_row_lits) {
660 if (!solution_is_loaded_)
return;
661 int row_lit_values_sum = 0;
662 for (
const int lit : existing_row_lits) {
664 row_lit_values_sum += GetLiteralValue(lit);
666 const int num_vars = column_vars.size();
667 for (
const auto& [lit, var_values] : new_row_lits) {
668 if (row_lit_values_sum >= 1) {
669 SetLiteralValue(lit,
false);
672 bool row_lit_value =
true;
673 for (
int var_index = 0; var_index < num_vars; ++var_index) {
674 const auto& values = var_values[var_index];
675 if (!values.empty() &&
676 absl::c_find(values, GetVarValue(column_vars[var_index])) ==
678 row_lit_value =
false;
682 SetLiteralValue(lit, row_lit_value);
683 row_lit_values_sum += row_lit_value;
689 if (!solution_is_loaded_)
return;
690 int64_t expr_value = 0;
692 const int var = linear.
vars(
i);
693 if (!HasValue(var))
return;
694 expr_value += linear.
coeffs(
i) * GetVarValue(var);
696 DCHECK_LE(bucket_lits.size(), linear.
domain_size() / 2);
697 for (
int i = 0;
i < bucket_lits.size(); ++
i) {
698 const int64_t lb = linear.
domain(2 *
i);
699 const int64_t ub = linear.
domain(2 *
i + 1);
700 SetLiteralValue(bucket_lits[
i], expr_value >= lb && expr_value <= ub);
705 if (!solution_is_loaded_)
return;
707 for (
int i = 0;
i < var_values_.size(); ++
i) {
708 if (var_has_value_[
i]) {
716 CHECK(solution_is_loaded_);
723 absl::Span<const int> x_intervals, absl::Span<const int> y_intervals,
724 absl::Span<const BoxInAreaLiteral> box_in_area_lits) {
725 if (!solution_is_loaded_)
return;
726 struct RectangleTypeAndIndex {
735 std::vector<Rectangle> rectangles_for_intersections;
736 std::vector<RectangleTypeAndIndex> rectangles_index;
738 for (
int i = 0;
i < x_intervals.size(); ++
i) {
742 const std::optional<int64_t> x_min =
744 const std::optional<int64_t> x_max =
746 const std::optional<int64_t> y_min =
748 const std::optional<int64_t> y_max =
751 if (!x_min.has_value() || !x_max.has_value() || !y_min.has_value() ||
752 !y_max.has_value()) {
755 if (*x_min > *x_max || *y_min > *y_max) {
756 VLOG(2) <<
"Hinted no_overlap_2d coordinate has max lower than min";
759 const Rectangle box = {.x_min = x_min.value(),
760 .x_max = x_max.value(),
761 .y_min = y_min.value(),
762 .y_max = y_max.value()};
763 rectangles_for_intersections.push_back(box);
764 rectangles_index.push_back(
765 {.index =
i, .type = RectangleTypeAndIndex::Type::kHintedBox});
768 for (
int i = 0;
i < areas.
size(); ++
i) {
770 rectangles_for_intersections.push_back(area);
771 rectangles_index.push_back(
772 {.index =
i, .type = RectangleTypeAndIndex::Type::kArea});
776 const std::vector<std::pair<int, int>> intersections =
779 absl::flat_hash_set<std::pair<int, int>> box_to_area_pairs;
781 for (
const auto& [rec1_index, rec2_index] : intersections) {
782 RectangleTypeAndIndex rec1 = rectangles_index[rec1_index];
783 RectangleTypeAndIndex rec2 = rectangles_index[rec2_index];
784 if (rec1.type == rec2.type) {
785 DCHECK(rec1.type == RectangleTypeAndIndex::Type::kHintedBox);
786 VLOG(2) <<
"Hinted position of boxes in no_overlap_2d are overlapping";
789 if (rec1.type != RectangleTypeAndIndex::Type::kHintedBox) {
790 std::swap(rec1, rec2);
793 box_to_area_pairs.insert({rec1.index, rec2.index});
796 for (
const auto& [box_index, area_index, literal] : box_in_area_lits) {
797 SetLiteralValue(literal,
798 box_to_area_pairs.contains({box_index, area_index}));
int64_t ValueAtOrAfter(int64_t input) const
bool Contains(int64_t value) const
int64_t FixedValue() const
int64_t ValueAtOrBefore(int64_t input) const
int64_t ClosestValue(int64_t wanted) const
void ApplyToDenseCollection(Collection &span) const
::int64_t transition_label(int index) const
const ::operations_research::sat::LinearExpressionProto & exprs(int index) const
::int64_t transition_tail(int index) const
::int64_t starting_state() const
int transition_tail_size() const
::int64_t transition_head(int index) const
::int32_t heads(int index) const
::int32_t literals(int index) const
int literals_size() const
::int32_t tails(int index) const
::int32_t enforcement_literal(int index) const
const ::operations_research::sat::IntervalConstraintProto & interval() const
const ::operations_research::sat::LinearArgumentProto & int_mod() const
const ::operations_research::sat::ConstraintProto & constraints(int index) const
void clear_solution_hint()
::operations_research::sat::PartialVariableAssignment *PROTOBUF_NONNULL mutable_solution_hint()
const ::operations_research::sat::LinearExpressionProto & end() const
const ::operations_research::sat::LinearExpressionProto & start() const
const ::operations_research::sat::LinearExpressionProto & exprs(int index) const
const ::operations_research::sat::LinearExpressionProto & target() const
::int32_t vars(int index) const
::int64_t coeffs(int index) const
::int64_t domain(int index) const
void add_values(::int64_t value)
void add_vars(::int32_t value)
::int32_t active_literals(int index) const
int time_exprs_size() const
const ::operations_research::sat::LinearExpressionProto & time_exprs(int index) const
const ::operations_research::sat::LinearExpressionProto & level_changes(int index) const
void LoadSolution(int num_vars, const absl::flat_hash_map< int, int64_t > &solution)
void SetIntModExpandedVars(const ConstraintProto &ct, int div_var, int prod_var, int64_t default_div_value, int64_t default_prod_value)
void MaybeSwapOrbitopeColumns(absl::Span< const std::vector< int > > orbitope, int row, int pivot_col, bool value)
void SetLinearWithComplexDomainExpandedVars(const LinearConstraintProto &linear, absl::Span< const int > bucket_lits)
void StoreSolutionAsHint(CpModelProto &model) const
void SetLinMaxExpandedVars(const LinearArgumentProto &lin_max, absl::Span< const int > enforcement_lits)
void SetVarToConjunction(int var, absl::Span< const int > conjunction)
void SetReservoirCircuitVars(const ReservoirConstraintProto &reservoir, int64_t min_level, int64_t max_level, absl::Span< const int > level_vars, const CircuitConstraintProto &circuit)
void SetVarToValueIf(int var, int64_t value, int condition_lit)
void Resize(int new_size)
void AssignVariableToPackingArea(const CompactVectorVector< int, Rectangle > &areas, const CpModelProto &model, absl::Span< const int > x_intervals, absl::Span< const int > y_intervals, absl::Span< const BoxInAreaLiteral > box_in_area_lits)
void SetAutomatonExpandedVars(const AutomatonConstraintProto &automaton, absl::Span< const StateVar > state_vars, absl::Span< const TransitionVar > transition_vars)
void SetVarToLinearConstraintSolution(absl::Span< const int > enforcement_lits, std::optional< int > var_index, absl::Span< const int > vars, absl::Span< const int64_t > default_values, absl::Span< const int64_t > coeffs, int64_t rhs)
void SetVarToValueIfLinearConstraintViolated(int var, int64_t value, absl::Span< const std::pair< int, int64_t > > linear, const Domain &domain)
void SetVarToReifiedPrecedenceLiteral(int var, const LinearExpressionProto &time_i, const LinearExpressionProto &time_j, int active_i, int active_j)
void MakeLiteralsEqual(int lit1, int lit2)
void UpdateLiteralsWithDominance(int lit, int dominating_lit)
void SetLiteralToValueIfLinearConstraintViolated(int literal, bool value, absl::Span< const std::pair< int, int64_t > > linear, const Domain &domain)
void UpdateRefsWithDominance(int ref, int64_t min_value, int64_t max_value, absl::Span< const std::pair< int, Domain > > dominating_refs)
void SetIntProdExpandedVars(const LinearArgumentProto &int_prod, absl::Span< const int > prod_vars)
void SetVarToLinearExpressionIf(int var, const LinearExpressionProto &expr, int condition_lit)
void MaybeSetLiteralToValueEncoding(int literal, int var, int64_t value)
void MaybeSetLiteralToOrderEncoding(int literal, int var, int64_t value, bool is_le)
void SetOrUpdateVarToDomain(int var, const Domain &domain)
void MaybeUpdateVarWithSymmetriesToValue(int var, bool value, absl::Span< const std::unique_ptr< SparsePermutation > > generators)
void SetVarToLinearExpression(int var, absl::Span< const std::pair< int, int64_t > > linear, int64_t offset=0)
void UpdateLiteralsToFalseIfDifferent(int lit1, int lit2)
void SetLiteralToValueIf(int literal, bool value, int condition_lit)
void SetOrUpdateVarToDomainWithOptionalEscapeValue(int var, const Domain &reduced_var_domain, std::optional< int64_t > unique_escape_value, bool push_down_when_not_in_domain, const absl::btree_map< int64_t, int > &encoding)
void SetTableExpandedVars(absl::Span< const int > column_vars, absl::Span< const int > existing_row_lits, absl::Span< const TableRowLiteral > new_row_lits)
void SetVarToConditionalValue(int var, absl::Span< const int > condition_lits, int64_t value_if_true, int64_t value_if_false)
void SetVarToClause(int var, absl::Span< const int > clause)
void GetSchreierVectorAndOrbit(int point, absl::Span< const std::unique_ptr< SparsePermutation > > generators, std::vector< int > *schrier_vector, std::vector< int > *orbit)
bool RefIsPositive(int ref)
std::vector< int > TracePoint(int point, absl::Span< const int > schrier_vector, absl::Span< const std::unique_ptr< SparsePermutation > > generators)
std::vector< std::pair< int, int > > FindPartialRectangleIntersections(absl::Span< const Rectangle > rectangles)
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