Google OR-Tools v9.15
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
integer_resolution.h
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
14#ifndef ORTOOLS_SAT_INTEGER_RESOLUTION_H_
15#define ORTOOLS_SAT_INTEGER_RESOLUTION_H_
16
17#include <cstdint>
18#include <limits>
19#include <string>
20#include <vector>
21
22#include "absl/types/span.h"
24#include "ortools/sat/clause.h"
25#include "ortools/sat/integer.h"
27#include "ortools/sat/model.h"
31#include "ortools/util/bitset.h"
32
34
35// Conflict resolution at the "integer level" a bit like if all our integer
36// literals where already instantiated as boolean.
37//
38// In addition we can minimize the conflict by exploiting the relationship
39// between integer literal on the same variable, like x >= 5 => x >= 3.
40//
41// Depending on the options, this code might generate new Boolean during
42// conflict resolution, or keep expanding the integer literals until we only
43// have Booleans left.
45 public:
46 explicit IntegerConflictResolution(Model* model);
48
49 // Same interface as the SAT based one.
50 //
51 // TODO(user): Support LRAT proof, at least for pure Boolean problems.
53 std::vector<Literal>* conflict,
54 std::vector<Literal>* reason_used_to_infer_the_conflict,
55 std::vector<SatClause*>* subsumed_clauses);
56
57 private:
58 // Returns the list of integer_literals associated with an index.
59 absl::Span<const IntegerLiteral> IndexToIntegerLiterals(
60 GlobalTrailIndex index);
61
62 // Remove from subsumed_clauses the one that are not subsumed.
63 // It is a bit hard to track down cardinality during our various optim, so
64 // this is easier to make sure we are correct. I rescan the subsumed_clauses
65 // candidates a second time, which isn't too bad.
66 void FilterSubsumedClauses(std::vector<Literal>* conflict,
67 std::vector<SatClause*>* subsumed_clauses);
68
69 // Adds to our processing queue the reason for source_index.
70 // This is also called for the initial conflict, with a dummy source_index.
71 void AddToQueue(GlobalTrailIndex source_index, const IntegerReason& reason,
72 std::vector<SatClause*>* subsumed_clauses);
73
74 // Updates int_data_[i_lit.var] and add an entry to the queue if needed.
75 void ProcessIntegerLiteral(GlobalTrailIndex source_index,
76 IntegerLiteral i_lit);
77
78 // If a variable has holes and one need to explain var >= value, if the value
79 // fall into a hole of the domain, we actually only need var >= smaller_value.
80 // This returns that smaller value.
81 IntegerValue RelaxBoundIfHoles(IntegerVariable var, IntegerValue value);
82
83 // Debugging function to print info about a GlobalTrailIndex.
84 std::string DebugGlobalIndex(GlobalTrailIndex index);
85 std::string DebugGlobalIndex(absl::Span<const GlobalTrailIndex> indices);
86
87 Trail* trail_;
88 IntegerTrail* integer_trail_;
89 IntegerEncoder* integer_encoder_;
90 SatSolver* sat_solver_;
91 SharedStatistics* shared_stats_;
92 ClauseManager* clauses_propagator_;
93 BinaryImplicationGraph* implications_;
94 const SatParameters& params_;
95
96 // A heap. We manage it manually.
97 mutable std::vector<GlobalTrailIndex> tmp_queue_;
98
99 // Information about the current content of our tmp_queue_ and our conflict
100 // resolution.
101 SparseBitset<int> tmp_bool_index_seen_;
102 SparseBitset<BooleanVariable> tmp_bool_seen_;
103 std::vector<IntegerLiteral> tmp_integer_literals_;
105 tmp_var_to_settled_lb_;
106
107 // The current occurrence of this integer variable in the reason.
108 struct IntegerVariableData {
109 // Whether this variable was added in the queue.
110 // If false, index_in_queue will be the index to re-add it with.
111 bool in_queue = false;
112 int int_index_in_queue = std::numeric_limits<int>::max();
113
114 // We only need var >= bound in the current conflict resolution.
115 // Note that we have: integer_trail_[int_index_in_queue] >= bound.
116 IntegerValue bound = kMinIntegerValue;
117 };
119
120 // Stats.
121 int64_t num_conflicts_at_wrong_level_ = 0;
122 int64_t num_expansions_ = 0;
123 int64_t num_subsumed_ = 0;
124 int64_t num_conflict_literals_ = 0;
125 int64_t num_associated_integer_for_literals_in_conflict_ = 0;
126 int64_t num_associated_literal_use_ = 0;
127 int64_t num_associated_literal_fail_ = 0;
128 int64_t num_possibly_non_optimal_reason_ = 0;
129 int64_t num_slack_usage_ = 0;
130 int64_t num_slack_relax_ = 0;
131 int64_t num_holes_relax_ = 0;
132 int64_t num_created_1uip_bool_ = 0;
133 int64_t num_binary_minimization_ = 0;
134
135 // Stats to compare with old conflict resolution.
136 int64_t comparison_num_win_ = 0;
137 int64_t comparison_num_same_ = 0;
138 int64_t comparison_num_loose_ = 0;
139 int64_t comparison_old_sum_of_literals_ = 0;
140 int64_t comparison_old_num_subsumed_ = 0;
141};
142
143} // namespace operations_research::sat
144
145#endif // ORTOOLS_SAT_INTEGER_RESOLUTION_H_
void ComputeFirstUIPConflict(std::vector< Literal > *conflict, std::vector< Literal > *reason_used_to_infer_the_conflict, std::vector< SatClause * > *subsumed_clauses)
constexpr IntegerValue kMinIntegerValue(-kMaxIntegerValue.value())