diff --git a/ortools/algorithms/samples/knapsack.cc b/ortools/algorithms/samples/knapsack.cc index a60d2a708e..f3df98f154 100644 --- a/ortools/algorithms/samples/knapsack.cc +++ b/ortools/algorithms/samples/knapsack.cc @@ -13,6 +13,7 @@ // [START program] // [START import] +#include #include #include #include @@ -30,23 +31,23 @@ void RunKnapsackExample() { // [END solver] // [START data] - std::vector values = { + std::vector values = { 360, 83, 59, 130, 431, 67, 230, 52, 93, 125, 670, 892, 600, 38, 48, 147, 78, 256, 63, 17, 120, 164, 432, 35, 92, 110, 22, 42, 50, 323, 514, 28, 87, 73, 78, 15, 26, 78, 210, 36, 85, 189, 274, 43, 33, 10, 19, 389, 276, 312}; - std::vector> weights = { + std::vector> weights = { {7, 0, 30, 22, 80, 94, 11, 81, 70, 64, 59, 18, 0, 36, 3, 8, 15, 42, 9, 0, 42, 47, 52, 32, 26, 48, 55, 6, 29, 84, 2, 4, 18, 56, 7, 29, 93, 44, 71, 3, 86, 66, 31, 65, 0, 79, 20, 65, 52, 13}}; - std::vector capacities = {850}; + std::vector capacities = {850}; // [END data] // [START solve] solver.Init(values, weights, capacities); - int64 computed_value = solver.Solve(); + int64_t computed_value = solver.Solve(); // [END solve] // Print solution @@ -60,7 +61,7 @@ void RunKnapsackExample() { std::ostream_iterator(packed_items_ss, ", ")); packed_items_ss << packed_items.back(); - std::vector packed_weights; + std::vector packed_weights; packed_weights.reserve(packed_items.size()); for (const auto& it : packed_items) { packed_weights.push_back(weights[0][it]); @@ -70,8 +71,8 @@ void RunKnapsackExample() { std::ostream_iterator(packed_weights_ss, ", ")); packed_weights_ss << packed_weights.back(); - int64 total_weights = - std::accumulate(packed_weights.begin(), packed_weights.end(), int64{0}); + int64_t total_weights = + std::accumulate(packed_weights.begin(), packed_weights.end(), int64_t{0}); LOG(INFO) << "Total value: " << computed_value; LOG(INFO) << "Packed items: {" << packed_items_ss.str() << "}"; diff --git a/ortools/algorithms/samples/simple_knapsack_program.cc b/ortools/algorithms/samples/simple_knapsack_program.cc index 142f26461c..db75532b9e 100644 --- a/ortools/algorithms/samples/simple_knapsack_program.cc +++ b/ortools/algorithms/samples/simple_knapsack_program.cc @@ -13,6 +13,7 @@ // [START program] // [START import] +#include #include #include #include @@ -30,16 +31,16 @@ void SimpleKnapsackProgram() { // [END solver] // [START data] - std::vector> weights = {{565, 406, 194, 130, 435, 367, 230, - 315, 393, 125, 670, 892, 600, 293, - 712, 147, 421, 255}}; - std::vector capacities = {850}; - std::vector values = weights[0]; + std::vector> weights = {{565, 406, 194, 130, 435, 367, + 230, 315, 393, 125, 670, 892, + 600, 293, 712, 147, 421, 255}}; + std::vector capacities = {850}; + std::vector values = weights[0]; // [END data] // [START solve] solver.Init(values, weights, capacities); - int64 computed_value = solver.Solve(); + int64_t computed_value = solver.Solve(); // [END solve] // [START print_solution] @@ -52,7 +53,7 @@ void SimpleKnapsackProgram() { std::ostream_iterator(packed_items_ss, ", ")); packed_items_ss << packed_items.back(); - std::vector packed_weights; + std::vector packed_weights; packed_weights.reserve(packed_items.size()); for (const auto& it : packed_items) { packed_weights.push_back(weights[0][it]); @@ -62,8 +63,8 @@ void SimpleKnapsackProgram() { std::ostream_iterator(packed_weights_ss, ", ")); packed_weights_ss << packed_weights.back(); - int64 total_weights = - std::accumulate(packed_weights.begin(), packed_weights.end(), int64{0}); + int64_t total_weights = + std::accumulate(packed_weights.begin(), packed_weights.end(), int64_t{0}); LOG(INFO) << "Total value: " << computed_value; LOG(INFO) << "Packed items: {" << packed_items_ss.str() << "}"; diff --git a/ortools/flatzinc/checker.cc b/ortools/flatzinc/checker.cc index 9d0d21e5f1..e2758fdcb3 100644 --- a/ortools/flatzinc/checker.cc +++ b/ortools/flatzinc/checker.cc @@ -14,6 +14,8 @@ #include "ortools/flatzinc/checker.h" #include +#include +#include #include "absl/container/flat_hash_map.h" #include "absl/container/flat_hash_set.h" @@ -27,8 +29,8 @@ namespace { // Helpers -int64 Eval(const Argument& arg, - const std::function& evaluator) { +int64_t Eval(const Argument& arg, + const std::function& evaluator) { switch (arg.type) { case Argument::INT_VALUE: { return arg.Value(); @@ -47,8 +49,8 @@ int Size(const Argument& arg) { return std::max(arg.values.size(), arg.variables.size()); } -int64 EvalAt(const Argument& arg, int pos, - const std::function& evaluator) { +int64_t EvalAt(const Argument& arg, int pos, + const std::function& evaluator) { switch (arg.type) { case Argument::INT_LIST: { return arg.ValueAt(pos); @@ -67,10 +69,10 @@ int64 EvalAt(const Argument& arg, int pos, bool CheckAllDifferentInt( const Constraint& ct, - const std::function& evaluator) { - absl::flat_hash_set visited; + const std::function& evaluator) { + absl::flat_hash_set visited; for (int i = 0; i < Size(ct.arguments[0]); ++i) { - const int64 value = EvalAt(ct.arguments[0], i, evaluator); + const int64_t value = EvalAt(ct.arguments[0], i, evaluator); if (gtl::ContainsKey(visited, value)) { return false; } @@ -82,10 +84,10 @@ bool CheckAllDifferentInt( bool CheckAlldifferentExcept0( const Constraint& ct, - const std::function& evaluator) { - absl::flat_hash_set visited; + const std::function& evaluator) { + absl::flat_hash_set visited; for (int i = 0; i < Size(ct.arguments[0]); ++i) { - const int64 value = EvalAt(ct.arguments[0], i, evaluator); + const int64_t value = EvalAt(ct.arguments[0], i, evaluator); if (value != 0 && gtl::ContainsKey(visited, value)) { return false; } @@ -96,11 +98,11 @@ bool CheckAlldifferentExcept0( } bool CheckAmong(const Constraint& ct, - const std::function& evaluator) { - const int64 expected = Eval(ct.arguments[0], evaluator); - int64 count = 0; + const std::function& evaluator) { + const int64_t expected = Eval(ct.arguments[0], evaluator); + int64_t count = 0; for (int i = 0; i < Size(ct.arguments[1]); ++i) { - const int64 value = EvalAt(ct.arguments[0], i, evaluator); + const int64_t value = EvalAt(ct.arguments[0], i, evaluator); count += ct.arguments[2].Contains(value); } @@ -109,23 +111,24 @@ bool CheckAmong(const Constraint& ct, bool CheckArrayBoolAnd( const Constraint& ct, - const std::function& evaluator) { - int64 result = 1; + const std::function& evaluator) { + int64_t result = 1; for (int i = 0; i < Size(ct.arguments[0]); ++i) { - const int64 value = EvalAt(ct.arguments[0], i, evaluator); + const int64_t value = EvalAt(ct.arguments[0], i, evaluator); result = std::min(result, value); } return result == Eval(ct.arguments[1], evaluator); } -bool CheckArrayBoolOr(const Constraint& ct, - const std::function& evaluator) { - int64 result = 0; +bool CheckArrayBoolOr( + const Constraint& ct, + const std::function& evaluator) { + int64_t result = 0; for (int i = 0; i < Size(ct.arguments[0]); ++i) { - const int64 value = EvalAt(ct.arguments[0], i, evaluator); + const int64_t value = EvalAt(ct.arguments[0], i, evaluator); result = std::max(result, value); } @@ -134,8 +137,8 @@ bool CheckArrayBoolOr(const Constraint& ct, bool CheckArrayBoolXor( const Constraint& ct, - const std::function& evaluator) { - int64 result = 0; + const std::function& evaluator) { + int64_t result = 0; for (int i = 0; i < Size(ct.arguments[0]); ++i) { result += EvalAt(ct.arguments[0], i, evaluator); @@ -146,48 +149,48 @@ bool CheckArrayBoolXor( bool CheckArrayIntElement( const Constraint& ct, - const std::function& evaluator) { + const std::function& evaluator) { if (ct.arguments[0].variables.size() == 2) { // TODO(user): Check 2D element. return true; } // Flatzinc arrays are 1 based. - const int64 shifted_index = Eval(ct.arguments[0], evaluator) - 1; - const int64 element = EvalAt(ct.arguments[1], shifted_index, evaluator); - const int64 target = Eval(ct.arguments[2], evaluator); + const int64_t shifted_index = Eval(ct.arguments[0], evaluator) - 1; + const int64_t element = EvalAt(ct.arguments[1], shifted_index, evaluator); + const int64_t target = Eval(ct.arguments[2], evaluator); return element == target; } bool CheckArrayIntElementNonShifted( const Constraint& ct, - const std::function& evaluator) { + const std::function& evaluator) { CHECK_EQ(ct.arguments[0].variables.size(), 1); - const int64 index = Eval(ct.arguments[0], evaluator); - const int64 element = EvalAt(ct.arguments[1], index, evaluator); - const int64 target = Eval(ct.arguments[2], evaluator); + const int64_t index = Eval(ct.arguments[0], evaluator); + const int64_t element = EvalAt(ct.arguments[1], index, evaluator); + const int64_t target = Eval(ct.arguments[2], evaluator); return element == target; } bool CheckArrayVarIntElement( const Constraint& ct, - const std::function& evaluator) { + const std::function& evaluator) { if (ct.arguments[0].variables.size() == 2) { // TODO(user): Check 2D element. return true; } // Flatzinc arrays are 1 based. - const int64 shifted_index = Eval(ct.arguments[0], evaluator) - 1; - const int64 element = EvalAt(ct.arguments[1], shifted_index, evaluator); - const int64 target = Eval(ct.arguments[2], evaluator); + const int64_t shifted_index = Eval(ct.arguments[0], evaluator) - 1; + const int64_t element = EvalAt(ct.arguments[1], shifted_index, evaluator); + const int64_t target = Eval(ct.arguments[2], evaluator); return element == target; } bool CheckAtMostInt(const Constraint& ct, - const std::function& evaluator) { - const int64 expected = Eval(ct.arguments[0], evaluator); - const int64 value = Eval(ct.arguments[2], evaluator); + const std::function& evaluator) { + const int64_t expected = Eval(ct.arguments[0], evaluator); + const int64_t value = Eval(ct.arguments[2], evaluator); - int64 count = 0; + int64_t count = 0; for (int i = 0; i < Size(ct.arguments[1]); ++i) { count += EvalAt(ct.arguments[1], i, evaluator) == value; } @@ -195,25 +198,26 @@ bool CheckAtMostInt(const Constraint& ct, } bool CheckBoolAnd(const Constraint& ct, - const std::function& evaluator) { - const int64 left = Eval(ct.arguments[0], evaluator); - const int64 right = Eval(ct.arguments[1], evaluator); - const int64 status = Eval(ct.arguments[2], evaluator); + const std::function& evaluator) { + const int64_t left = Eval(ct.arguments[0], evaluator); + const int64_t right = Eval(ct.arguments[1], evaluator); + const int64_t status = Eval(ct.arguments[2], evaluator); return status == std::min(left, right); } -bool CheckBoolClause(const Constraint& ct, - const std::function& evaluator) { - int64 result = 0; +bool CheckBoolClause( + const Constraint& ct, + const std::function& evaluator) { + int64_t result = 0; // Positive variables. for (int i = 0; i < Size(ct.arguments[0]); ++i) { - const int64 value = EvalAt(ct.arguments[0], i, evaluator); + const int64_t value = EvalAt(ct.arguments[0], i, evaluator); result = std::max(result, value); } // Negative variables. for (int i = 0; i < Size(ct.arguments[1]); ++i) { - const int64 value = EvalAt(ct.arguments[1], i, evaluator); + const int64_t value = EvalAt(ct.arguments[1], i, evaluator); result = std::max(result, 1 - value); } @@ -221,36 +225,36 @@ bool CheckBoolClause(const Constraint& ct, } bool CheckBoolNot(const Constraint& ct, - const std::function& evaluator) { - const int64 left = Eval(ct.arguments[0], evaluator); - const int64 right = Eval(ct.arguments[1], evaluator); + const std::function& evaluator) { + const int64_t left = Eval(ct.arguments[0], evaluator); + const int64_t right = Eval(ct.arguments[1], evaluator); return left == 1 - right; } bool CheckBoolOr(const Constraint& ct, - const std::function& evaluator) { - const int64 left = Eval(ct.arguments[0], evaluator); - const int64 right = Eval(ct.arguments[1], evaluator); - const int64 status = Eval(ct.arguments[2], evaluator); + const std::function& evaluator) { + const int64_t left = Eval(ct.arguments[0], evaluator); + const int64_t right = Eval(ct.arguments[1], evaluator); + const int64_t status = Eval(ct.arguments[2], evaluator); return status == std::max(left, right); } bool CheckBoolXor(const Constraint& ct, - const std::function& evaluator) { - const int64 left = Eval(ct.arguments[0], evaluator); - const int64 right = Eval(ct.arguments[1], evaluator); - const int64 target = Eval(ct.arguments[2], evaluator); + const std::function& evaluator) { + const int64_t left = Eval(ct.arguments[0], evaluator); + const int64_t right = Eval(ct.arguments[1], evaluator); + const int64_t target = Eval(ct.arguments[2], evaluator); return target == (left + right == 1); } bool CheckCircuit(const Constraint& ct, - const std::function& evaluator) { + const std::function& evaluator) { // There are two versions of the constraint. 0 based and 1 based. // Let's try to detect which one we have. const int size = Size(ct.arguments[0]); int shift = 0; for (int i = 0; i < size; ++i) { - const int64 next = EvalAt(ct.arguments[0], i, evaluator); + const int64_t next = EvalAt(ct.arguments[0], i, evaluator); if (next == 0) { // 0 based. shift = 0; break; @@ -260,20 +264,21 @@ bool CheckCircuit(const Constraint& ct, } } - absl::flat_hash_set visited; - int64 current = 0; + absl::flat_hash_set visited; + int64_t current = 0; for (int i = 0; i < Size(ct.arguments[0]); ++i) { - const int64 next = EvalAt(ct.arguments[0], current, evaluator) + shift; + const int64_t next = EvalAt(ct.arguments[0], current, evaluator) + shift; visited.insert(next); current = next; } return visited.size() == Size(ct.arguments[0]); } -int64 ComputeCount(const Constraint& ct, - const std::function& evaluator) { - int64 result = 0; - const int64 value = Eval(ct.arguments[1], evaluator); +int64_t ComputeCount( + const Constraint& ct, + const std::function& evaluator) { + int64_t result = 0; + const int64_t value = Eval(ct.arguments[1], evaluator); for (int i = 0; i < Size(ct.arguments[0]); ++i) { result += EvalAt(ct.arguments[0], i, evaluator) == value; } @@ -281,68 +286,69 @@ int64 ComputeCount(const Constraint& ct, } bool CheckCountEq(const Constraint& ct, - const std::function& evaluator) { - const int64 count = ComputeCount(ct, evaluator); - const int64 expected = Eval(ct.arguments[2], evaluator); + const std::function& evaluator) { + const int64_t count = ComputeCount(ct, evaluator); + const int64_t expected = Eval(ct.arguments[2], evaluator); return count == expected; } bool CheckCountGeq(const Constraint& ct, - const std::function& evaluator) { - const int64 count = ComputeCount(ct, evaluator); - const int64 expected = Eval(ct.arguments[2], evaluator); + const std::function& evaluator) { + const int64_t count = ComputeCount(ct, evaluator); + const int64_t expected = Eval(ct.arguments[2], evaluator); return count >= expected; } bool CheckCountGt(const Constraint& ct, - const std::function& evaluator) { - const int64 count = ComputeCount(ct, evaluator); - const int64 expected = Eval(ct.arguments[2], evaluator); + const std::function& evaluator) { + const int64_t count = ComputeCount(ct, evaluator); + const int64_t expected = Eval(ct.arguments[2], evaluator); return count > expected; } bool CheckCountLeq(const Constraint& ct, - const std::function& evaluator) { - const int64 count = ComputeCount(ct, evaluator); - const int64 expected = Eval(ct.arguments[2], evaluator); + const std::function& evaluator) { + const int64_t count = ComputeCount(ct, evaluator); + const int64_t expected = Eval(ct.arguments[2], evaluator); return count <= expected; } bool CheckCountLt(const Constraint& ct, - const std::function& evaluator) { - const int64 count = ComputeCount(ct, evaluator); - const int64 expected = Eval(ct.arguments[2], evaluator); + const std::function& evaluator) { + const int64_t count = ComputeCount(ct, evaluator); + const int64_t expected = Eval(ct.arguments[2], evaluator); return count < expected; } bool CheckCountNeq(const Constraint& ct, - const std::function& evaluator) { - const int64 count = ComputeCount(ct, evaluator); - const int64 expected = Eval(ct.arguments[2], evaluator); + const std::function& evaluator) { + const int64_t count = ComputeCount(ct, evaluator); + const int64_t expected = Eval(ct.arguments[2], evaluator); return count != expected; } bool CheckCountReif(const Constraint& ct, - const std::function& evaluator) { - const int64 count = ComputeCount(ct, evaluator); - const int64 expected = Eval(ct.arguments[2], evaluator); - const int64 status = Eval(ct.arguments[3], evaluator); + const std::function& evaluator) { + const int64_t count = ComputeCount(ct, evaluator); + const int64_t expected = Eval(ct.arguments[2], evaluator); + const int64_t status = Eval(ct.arguments[3], evaluator); return status == (expected == count); } -bool CheckCumulative(const Constraint& ct, - const std::function& evaluator) { +bool CheckCumulative( + const Constraint& ct, + const std::function& evaluator) { // TODO(user): Improve complexity for large durations. - const int64 capacity = Eval(ct.arguments[3], evaluator); + const int64_t capacity = Eval(ct.arguments[3], evaluator); const int size = Size(ct.arguments[0]); CHECK_EQ(size, Size(ct.arguments[1])); CHECK_EQ(size, Size(ct.arguments[2])); - absl::flat_hash_map usage; + absl::flat_hash_map usage; for (int i = 0; i < size; ++i) { - const int64 start = EvalAt(ct.arguments[0], i, evaluator); - const int64 duration = EvalAt(ct.arguments[1], i, evaluator); - const int64 requirement = EvalAt(ct.arguments[2], i, evaluator); - for (int64 t = start; t < start + duration; ++t) { + const int64_t start = EvalAt(ct.arguments[0], i, evaluator); + const int64_t duration = EvalAt(ct.arguments[1], i, evaluator); + const int64_t requirement = EvalAt(ct.arguments[2], i, evaluator); + for (int64_t t = start; t < start + duration; ++t) { usage[t] += requirement; if (usage[t] > capacity) { return false; @@ -353,51 +359,52 @@ bool CheckCumulative(const Constraint& ct, } bool CheckDiffn(const Constraint& ct, - const std::function& evaluator) { + const std::function& evaluator) { return true; } bool CheckDiffnK(const Constraint& ct, - const std::function& evaluator) { + const std::function& evaluator) { return true; } bool CheckDiffnNonStrict( const Constraint& ct, - const std::function& evaluator) { + const std::function& evaluator) { return true; } bool CheckDiffnNonStrictK( const Constraint& ct, - const std::function& evaluator) { + const std::function& evaluator) { return true; } -bool CheckDisjunctive(const Constraint& ct, - const std::function& evaluator) { +bool CheckDisjunctive( + const Constraint& ct, + const std::function& evaluator) { return true; } bool CheckDisjunctiveStrict( const Constraint& ct, - const std::function& evaluator) { + const std::function& evaluator) { return true; } bool CheckFalseConstraint( const Constraint& ct, - const std::function& evaluator) { + const std::function& evaluator) { return false; } -std::vector ComputeGlobalCardinalityCards( +std::vector ComputeGlobalCardinalityCards( const Constraint& ct, - const std::function& evaluator) { - std::vector cards(Size(ct.arguments[1]), 0); - absl::flat_hash_map positions; + const std::function& evaluator) { + std::vector cards(Size(ct.arguments[1]), 0); + absl::flat_hash_map positions; for (int i = 0; i < ct.arguments[1].values.size(); ++i) { - const int64 value = ct.arguments[1].values[i]; + const int64_t value = ct.arguments[1].values[i]; CHECK(!gtl::ContainsKey(positions, value)); positions[value] = i; } @@ -412,11 +419,12 @@ std::vector ComputeGlobalCardinalityCards( bool CheckGlobalCardinality( const Constraint& ct, - const std::function& evaluator) { - const std::vector cards = ComputeGlobalCardinalityCards(ct, evaluator); + const std::function& evaluator) { + const std::vector cards = + ComputeGlobalCardinalityCards(ct, evaluator); CHECK_EQ(cards.size(), Size(ct.arguments[2])); for (int i = 0; i < Size(ct.arguments[2]); ++i) { - const int64 card = EvalAt(ct.arguments[2], i, evaluator); + const int64_t card = EvalAt(ct.arguments[2], i, evaluator); if (card != cards[i]) { return false; } @@ -426,17 +434,18 @@ bool CheckGlobalCardinality( bool CheckGlobalCardinalityClosed( const Constraint& ct, - const std::function& evaluator) { - const std::vector cards = ComputeGlobalCardinalityCards(ct, evaluator); + const std::function& evaluator) { + const std::vector cards = + ComputeGlobalCardinalityCards(ct, evaluator); CHECK_EQ(cards.size(), Size(ct.arguments[2])); for (int i = 0; i < Size(ct.arguments[2]); ++i) { - const int64 card = EvalAt(ct.arguments[2], i, evaluator); + const int64_t card = EvalAt(ct.arguments[2], i, evaluator); if (card != cards[i]) { return false; } } - int64 sum_of_cards = 0; - for (int64 card : cards) { + int64_t sum_of_cards = 0; + for (int64_t card : cards) { sum_of_cards += card; } return sum_of_cards == Size(ct.arguments[0]); @@ -444,12 +453,13 @@ bool CheckGlobalCardinalityClosed( bool CheckGlobalCardinalityLowUp( const Constraint& ct, - const std::function& evaluator) { - const std::vector cards = ComputeGlobalCardinalityCards(ct, evaluator); + const std::function& evaluator) { + const std::vector cards = + ComputeGlobalCardinalityCards(ct, evaluator); CHECK_EQ(cards.size(), ct.arguments[2].values.size()); CHECK_EQ(cards.size(), ct.arguments[3].values.size()); for (int i = 0; i < cards.size(); ++i) { - const int64 card = cards[i]; + const int64_t card = cards[i]; if (card < ct.arguments[2].values[i] || card > ct.arguments[3].values[i]) { return false; } @@ -459,18 +469,19 @@ bool CheckGlobalCardinalityLowUp( bool CheckGlobalCardinalityLowUpClosed( const Constraint& ct, - const std::function& evaluator) { - const std::vector cards = ComputeGlobalCardinalityCards(ct, evaluator); + const std::function& evaluator) { + const std::vector cards = + ComputeGlobalCardinalityCards(ct, evaluator); CHECK_EQ(cards.size(), ct.arguments[2].values.size()); CHECK_EQ(cards.size(), ct.arguments[3].values.size()); for (int i = 0; i < cards.size(); ++i) { - const int64 card = cards[i]; + const int64_t card = cards[i]; if (card < ct.arguments[2].values[i] || card > ct.arguments[3].values[i]) { return false; } } - int64 sum_of_cards = 0; - for (int64 card : cards) { + int64_t sum_of_cards = 0; + for (int64_t card : cards) { sum_of_cards += card; } return sum_of_cards == Size(ct.arguments[0]); @@ -478,17 +489,17 @@ bool CheckGlobalCardinalityLowUpClosed( bool CheckGlobalCardinalityOld( const Constraint& ct, - const std::function& evaluator) { + const std::function& evaluator) { const int size = Size(ct.arguments[1]); - std::vector cards(size, 0); + std::vector cards(size, 0); for (int i = 0; i < Size(ct.arguments[0]); ++i) { - const int64 value = EvalAt(ct.arguments[0], i, evaluator); + const int64_t value = EvalAt(ct.arguments[0], i, evaluator); if (value >= 0 && value < size) { cards[value]++; } } for (int i = 0; i < size; ++i) { - const int64 card = EvalAt(ct.arguments[1], i, evaluator); + const int64_t card = EvalAt(ct.arguments[1], i, evaluator); if (card != cards[i]) { return false; } @@ -497,138 +508,139 @@ bool CheckGlobalCardinalityOld( } bool CheckIntAbs(const Constraint& ct, - const std::function& evaluator) { - const int64 left = Eval(ct.arguments[0], evaluator); - const int64 right = Eval(ct.arguments[1], evaluator); + const std::function& evaluator) { + const int64_t left = Eval(ct.arguments[0], evaluator); + const int64_t right = Eval(ct.arguments[1], evaluator); return std::abs(left) == right; } bool CheckIntDiv(const Constraint& ct, - const std::function& evaluator) { - const int64 left = Eval(ct.arguments[0], evaluator); - const int64 right = Eval(ct.arguments[1], evaluator); - const int64 target = Eval(ct.arguments[2], evaluator); + const std::function& evaluator) { + const int64_t left = Eval(ct.arguments[0], evaluator); + const int64_t right = Eval(ct.arguments[1], evaluator); + const int64_t target = Eval(ct.arguments[2], evaluator); return target == left / right; } bool CheckIntEq(const Constraint& ct, - const std::function& evaluator) { - const int64 left = Eval(ct.arguments[0], evaluator); - const int64 right = Eval(ct.arguments[1], evaluator); + const std::function& evaluator) { + const int64_t left = Eval(ct.arguments[0], evaluator); + const int64_t right = Eval(ct.arguments[1], evaluator); return left == right; } bool CheckIntEqImp(const Constraint& ct, - const std::function& evaluator) { - const int64 left = Eval(ct.arguments[0], evaluator); - const int64 right = Eval(ct.arguments[1], evaluator); + const std::function& evaluator) { + const int64_t left = Eval(ct.arguments[0], evaluator); + const int64_t right = Eval(ct.arguments[1], evaluator); const bool status = Eval(ct.arguments[2], evaluator) != 0; return (status && (left == right)) || !status; } bool CheckIntEqReif(const Constraint& ct, - const std::function& evaluator) { - const int64 left = Eval(ct.arguments[0], evaluator); - const int64 right = Eval(ct.arguments[1], evaluator); + const std::function& evaluator) { + const int64_t left = Eval(ct.arguments[0], evaluator); + const int64_t right = Eval(ct.arguments[1], evaluator); const bool status = Eval(ct.arguments[2], evaluator) != 0; return status == (left == right); } bool CheckIntGe(const Constraint& ct, - const std::function& evaluator) { - const int64 left = Eval(ct.arguments[0], evaluator); - const int64 right = Eval(ct.arguments[1], evaluator); + const std::function& evaluator) { + const int64_t left = Eval(ct.arguments[0], evaluator); + const int64_t right = Eval(ct.arguments[1], evaluator); return left >= right; } bool CheckIntGeImp(const Constraint& ct, - const std::function& evaluator) { - const int64 left = Eval(ct.arguments[0], evaluator); - const int64 right = Eval(ct.arguments[1], evaluator); + const std::function& evaluator) { + const int64_t left = Eval(ct.arguments[0], evaluator); + const int64_t right = Eval(ct.arguments[1], evaluator); const bool status = Eval(ct.arguments[2], evaluator) != 0; return (status && (left >= right)) || !status; } bool CheckIntGeReif(const Constraint& ct, - const std::function& evaluator) { - const int64 left = Eval(ct.arguments[0], evaluator); - const int64 right = Eval(ct.arguments[1], evaluator); + const std::function& evaluator) { + const int64_t left = Eval(ct.arguments[0], evaluator); + const int64_t right = Eval(ct.arguments[1], evaluator); const bool status = Eval(ct.arguments[2], evaluator) != 0; return status == (left >= right); } bool CheckIntGt(const Constraint& ct, - const std::function& evaluator) { - const int64 left = Eval(ct.arguments[0], evaluator); - const int64 right = Eval(ct.arguments[1], evaluator); + const std::function& evaluator) { + const int64_t left = Eval(ct.arguments[0], evaluator); + const int64_t right = Eval(ct.arguments[1], evaluator); return left > right; } bool CheckIntGtImp(const Constraint& ct, - const std::function& evaluator) { - const int64 left = Eval(ct.arguments[0], evaluator); - const int64 right = Eval(ct.arguments[1], evaluator); + const std::function& evaluator) { + const int64_t left = Eval(ct.arguments[0], evaluator); + const int64_t right = Eval(ct.arguments[1], evaluator); const bool status = Eval(ct.arguments[2], evaluator) != 0; return (status && (left > right)) || !status; } bool CheckIntGtReif(const Constraint& ct, - const std::function& evaluator) { - const int64 left = Eval(ct.arguments[0], evaluator); - const int64 right = Eval(ct.arguments[1], evaluator); + const std::function& evaluator) { + const int64_t left = Eval(ct.arguments[0], evaluator); + const int64_t right = Eval(ct.arguments[1], evaluator); const bool status = Eval(ct.arguments[2], evaluator) != 0; return status == (left > right); } bool CheckIntLe(const Constraint& ct, - const std::function& evaluator) { - const int64 left = Eval(ct.arguments[0], evaluator); - const int64 right = Eval(ct.arguments[1], evaluator); + const std::function& evaluator) { + const int64_t left = Eval(ct.arguments[0], evaluator); + const int64_t right = Eval(ct.arguments[1], evaluator); return left <= right; } bool CheckIntLeImp(const Constraint& ct, - const std::function& evaluator) { - const int64 left = Eval(ct.arguments[0], evaluator); - const int64 right = Eval(ct.arguments[1], evaluator); + const std::function& evaluator) { + const int64_t left = Eval(ct.arguments[0], evaluator); + const int64_t right = Eval(ct.arguments[1], evaluator); const bool status = Eval(ct.arguments[2], evaluator) != 0; return (status && (left <= right)) || !status; } bool CheckIntLeReif(const Constraint& ct, - const std::function& evaluator) { - const int64 left = Eval(ct.arguments[0], evaluator); - const int64 right = Eval(ct.arguments[1], evaluator); + const std::function& evaluator) { + const int64_t left = Eval(ct.arguments[0], evaluator); + const int64_t right = Eval(ct.arguments[1], evaluator); const bool status = Eval(ct.arguments[2], evaluator) != 0; return status == (left <= right); } bool CheckIntLt(const Constraint& ct, - const std::function& evaluator) { - const int64 left = Eval(ct.arguments[0], evaluator); - const int64 right = Eval(ct.arguments[1], evaluator); + const std::function& evaluator) { + const int64_t left = Eval(ct.arguments[0], evaluator); + const int64_t right = Eval(ct.arguments[1], evaluator); return left < right; } bool CheckIntLtImp(const Constraint& ct, - const std::function& evaluator) { - const int64 left = Eval(ct.arguments[0], evaluator); - const int64 right = Eval(ct.arguments[1], evaluator); + const std::function& evaluator) { + const int64_t left = Eval(ct.arguments[0], evaluator); + const int64_t right = Eval(ct.arguments[1], evaluator); const bool status = Eval(ct.arguments[2], evaluator) != 0; return (status && (left < right)) || !status; } bool CheckIntLtReif(const Constraint& ct, - const std::function& evaluator) { - const int64 left = Eval(ct.arguments[0], evaluator); - const int64 right = Eval(ct.arguments[1], evaluator); + const std::function& evaluator) { + const int64_t left = Eval(ct.arguments[0], evaluator); + const int64_t right = Eval(ct.arguments[1], evaluator); const bool status = Eval(ct.arguments[2], evaluator) != 0; return status == (left < right); } -int64 ComputeIntLin(const Constraint& ct, - const std::function& evaluator) { - int64 result = 0; +int64_t ComputeIntLin( + const Constraint& ct, + const std::function& evaluator) { + int64_t result = 0; for (int i = 0; i < Size(ct.arguments[0]); ++i) { result += EvalAt(ct.arguments[0], i, evaluator) * EvalAt(ct.arguments[1], i, evaluator); @@ -637,195 +649,199 @@ int64 ComputeIntLin(const Constraint& ct, } bool CheckIntLinEq(const Constraint& ct, - const std::function& evaluator) { - const int64 left = ComputeIntLin(ct, evaluator); - const int64 right = Eval(ct.arguments[2], evaluator); + const std::function& evaluator) { + const int64_t left = ComputeIntLin(ct, evaluator); + const int64_t right = Eval(ct.arguments[2], evaluator); return left == right; } -bool CheckIntLinEqImp(const Constraint& ct, - const std::function& evaluator) { - const int64 left = ComputeIntLin(ct, evaluator); - const int64 right = Eval(ct.arguments[2], evaluator); +bool CheckIntLinEqImp( + const Constraint& ct, + const std::function& evaluator) { + const int64_t left = ComputeIntLin(ct, evaluator); + const int64_t right = Eval(ct.arguments[2], evaluator); const bool status = Eval(ct.arguments[3], evaluator) != 0; return (status && (left == right)) || !status; } bool CheckIntLinEqReif( const Constraint& ct, - const std::function& evaluator) { - const int64 left = ComputeIntLin(ct, evaluator); - const int64 right = Eval(ct.arguments[2], evaluator); + const std::function& evaluator) { + const int64_t left = ComputeIntLin(ct, evaluator); + const int64_t right = Eval(ct.arguments[2], evaluator); const bool status = Eval(ct.arguments[3], evaluator) != 0; return status == (left == right); } bool CheckIntLinGe(const Constraint& ct, - const std::function& evaluator) { - const int64 left = ComputeIntLin(ct, evaluator); - const int64 right = Eval(ct.arguments[2], evaluator); + const std::function& evaluator) { + const int64_t left = ComputeIntLin(ct, evaluator); + const int64_t right = Eval(ct.arguments[2], evaluator); return left >= right; } -bool CheckIntLinGeImp(const Constraint& ct, - const std::function& evaluator) { - const int64 left = ComputeIntLin(ct, evaluator); - const int64 right = Eval(ct.arguments[2], evaluator); +bool CheckIntLinGeImp( + const Constraint& ct, + const std::function& evaluator) { + const int64_t left = ComputeIntLin(ct, evaluator); + const int64_t right = Eval(ct.arguments[2], evaluator); const bool status = Eval(ct.arguments[3], evaluator) != 0; return (status && (left >= right)) || !status; } bool CheckIntLinGeReif( const Constraint& ct, - const std::function& evaluator) { - const int64 left = ComputeIntLin(ct, evaluator); - const int64 right = Eval(ct.arguments[2], evaluator); + const std::function& evaluator) { + const int64_t left = ComputeIntLin(ct, evaluator); + const int64_t right = Eval(ct.arguments[2], evaluator); const bool status = Eval(ct.arguments[3], evaluator) != 0; return status == (left >= right); } bool CheckIntLinLe(const Constraint& ct, - const std::function& evaluator) { - const int64 left = ComputeIntLin(ct, evaluator); - const int64 right = Eval(ct.arguments[2], evaluator); + const std::function& evaluator) { + const int64_t left = ComputeIntLin(ct, evaluator); + const int64_t right = Eval(ct.arguments[2], evaluator); return left <= right; } -bool CheckIntLinLeImp(const Constraint& ct, - const std::function& evaluator) { - const int64 left = ComputeIntLin(ct, evaluator); - const int64 right = Eval(ct.arguments[2], evaluator); +bool CheckIntLinLeImp( + const Constraint& ct, + const std::function& evaluator) { + const int64_t left = ComputeIntLin(ct, evaluator); + const int64_t right = Eval(ct.arguments[2], evaluator); const bool status = Eval(ct.arguments[3], evaluator) != 0; return (status && (left <= right)) || !status; } bool CheckIntLinLeReif( const Constraint& ct, - const std::function& evaluator) { - const int64 left = ComputeIntLin(ct, evaluator); - const int64 right = Eval(ct.arguments[2], evaluator); + const std::function& evaluator) { + const int64_t left = ComputeIntLin(ct, evaluator); + const int64_t right = Eval(ct.arguments[2], evaluator); const bool status = Eval(ct.arguments[3], evaluator) != 0; return status == (left <= right); } bool CheckIntLinNe(const Constraint& ct, - const std::function& evaluator) { - const int64 left = ComputeIntLin(ct, evaluator); - const int64 right = Eval(ct.arguments[2], evaluator); + const std::function& evaluator) { + const int64_t left = ComputeIntLin(ct, evaluator); + const int64_t right = Eval(ct.arguments[2], evaluator); return left != right; } -bool CheckIntLinNeImp(const Constraint& ct, - const std::function& evaluator) { - const int64 left = ComputeIntLin(ct, evaluator); - const int64 right = Eval(ct.arguments[2], evaluator); +bool CheckIntLinNeImp( + const Constraint& ct, + const std::function& evaluator) { + const int64_t left = ComputeIntLin(ct, evaluator); + const int64_t right = Eval(ct.arguments[2], evaluator); const bool status = Eval(ct.arguments[3], evaluator) != 0; return (status && (left != right)) || !status; } bool CheckIntLinNeReif( const Constraint& ct, - const std::function& evaluator) { - const int64 left = ComputeIntLin(ct, evaluator); - const int64 right = Eval(ct.arguments[2], evaluator); + const std::function& evaluator) { + const int64_t left = ComputeIntLin(ct, evaluator); + const int64_t right = Eval(ct.arguments[2], evaluator); const bool status = Eval(ct.arguments[3], evaluator) != 0; return status == (left != right); } bool CheckIntMax(const Constraint& ct, - const std::function& evaluator) { - const int64 left = Eval(ct.arguments[0], evaluator); - const int64 right = Eval(ct.arguments[1], evaluator); - const int64 status = Eval(ct.arguments[2], evaluator); + const std::function& evaluator) { + const int64_t left = Eval(ct.arguments[0], evaluator); + const int64_t right = Eval(ct.arguments[1], evaluator); + const int64_t status = Eval(ct.arguments[2], evaluator); return status == std::max(left, right); } bool CheckIntMin(const Constraint& ct, - const std::function& evaluator) { - const int64 left = Eval(ct.arguments[0], evaluator); - const int64 right = Eval(ct.arguments[1], evaluator); - const int64 status = Eval(ct.arguments[2], evaluator); + const std::function& evaluator) { + const int64_t left = Eval(ct.arguments[0], evaluator); + const int64_t right = Eval(ct.arguments[1], evaluator); + const int64_t status = Eval(ct.arguments[2], evaluator); return status == std::min(left, right); } bool CheckIntMinus(const Constraint& ct, - const std::function& evaluator) { - const int64 left = Eval(ct.arguments[0], evaluator); - const int64 right = Eval(ct.arguments[1], evaluator); - const int64 target = Eval(ct.arguments[2], evaluator); + const std::function& evaluator) { + const int64_t left = Eval(ct.arguments[0], evaluator); + const int64_t right = Eval(ct.arguments[1], evaluator); + const int64_t target = Eval(ct.arguments[2], evaluator); return target == left - right; } bool CheckIntMod(const Constraint& ct, - const std::function& evaluator) { - const int64 left = Eval(ct.arguments[0], evaluator); - const int64 right = Eval(ct.arguments[1], evaluator); - const int64 target = Eval(ct.arguments[2], evaluator); + const std::function& evaluator) { + const int64_t left = Eval(ct.arguments[0], evaluator); + const int64_t right = Eval(ct.arguments[1], evaluator); + const int64_t target = Eval(ct.arguments[2], evaluator); return target == left % right; } bool CheckIntNe(const Constraint& ct, - const std::function& evaluator) { - const int64 left = Eval(ct.arguments[0], evaluator); - const int64 right = Eval(ct.arguments[1], evaluator); + const std::function& evaluator) { + const int64_t left = Eval(ct.arguments[0], evaluator); + const int64_t right = Eval(ct.arguments[1], evaluator); return left != right; } bool CheckIntNeImp(const Constraint& ct, - const std::function& evaluator) { - const int64 left = Eval(ct.arguments[0], evaluator); - const int64 right = Eval(ct.arguments[1], evaluator); + const std::function& evaluator) { + const int64_t left = Eval(ct.arguments[0], evaluator); + const int64_t right = Eval(ct.arguments[1], evaluator); const bool status = Eval(ct.arguments[2], evaluator) != 0; return (status && (left != right)) || !status; } bool CheckIntNeReif(const Constraint& ct, - const std::function& evaluator) { - const int64 left = Eval(ct.arguments[0], evaluator); - const int64 right = Eval(ct.arguments[1], evaluator); + const std::function& evaluator) { + const int64_t left = Eval(ct.arguments[0], evaluator); + const int64_t right = Eval(ct.arguments[1], evaluator); const bool status = Eval(ct.arguments[2], evaluator) != 0; return status == (left != right); } bool CheckIntNegate(const Constraint& ct, - const std::function& evaluator) { - const int64 left = Eval(ct.arguments[0], evaluator); - const int64 right = Eval(ct.arguments[1], evaluator); + const std::function& evaluator) { + const int64_t left = Eval(ct.arguments[0], evaluator); + const int64_t right = Eval(ct.arguments[1], evaluator); return left == -right; } bool CheckIntPlus(const Constraint& ct, - const std::function& evaluator) { - const int64 left = Eval(ct.arguments[0], evaluator); - const int64 right = Eval(ct.arguments[1], evaluator); - const int64 target = Eval(ct.arguments[2], evaluator); + const std::function& evaluator) { + const int64_t left = Eval(ct.arguments[0], evaluator); + const int64_t right = Eval(ct.arguments[1], evaluator); + const int64_t target = Eval(ct.arguments[2], evaluator); return target == left + right; } bool CheckIntTimes(const Constraint& ct, - const std::function& evaluator) { - const int64 left = Eval(ct.arguments[0], evaluator); - const int64 right = Eval(ct.arguments[1], evaluator); - const int64 target = Eval(ct.arguments[2], evaluator); + const std::function& evaluator) { + const int64_t left = Eval(ct.arguments[0], evaluator); + const int64_t right = Eval(ct.arguments[1], evaluator); + const int64_t target = Eval(ct.arguments[2], evaluator); return target == left * right; } bool CheckInverse(const Constraint& ct, - const std::function& evaluator) { + const std::function& evaluator) { CHECK_EQ(Size(ct.arguments[0]), Size(ct.arguments[1])); const int size = Size(ct.arguments[0]); // Check all bounds. for (int i = 0; i < size; ++i) { - const int64 x = EvalAt(ct.arguments[0], i, evaluator) - 1; - const int64 y = EvalAt(ct.arguments[1], i, evaluator) - 1; + const int64_t x = EvalAt(ct.arguments[0], i, evaluator) - 1; + const int64_t y = EvalAt(ct.arguments[1], i, evaluator) - 1; if (x < 0 || x >= size || y < 0 || y >= size) { return false; } } // Check f-1(f(i)) = i. for (int i = 0; i < size; ++i) { - const int64 fi = EvalAt(ct.arguments[0], i, evaluator) - 1; - const int64 invf_fi = EvalAt(ct.arguments[1], fi, evaluator) - 1; + const int64_t fi = EvalAt(ct.arguments[0], i, evaluator) - 1; + const int64_t invf_fi = EvalAt(ct.arguments[1], fi, evaluator) - 1; if (invf_fi != i) { return false; } @@ -834,12 +850,13 @@ bool CheckInverse(const Constraint& ct, return true; } -bool CheckLexLessInt(const Constraint& ct, - const std::function& evaluator) { +bool CheckLexLessInt( + const Constraint& ct, + const std::function& evaluator) { CHECK_EQ(Size(ct.arguments[0]), Size(ct.arguments[1])); for (int i = 0; i < Size(ct.arguments[0]); ++i) { - const int64 x = EvalAt(ct.arguments[0], i, evaluator); - const int64 y = EvalAt(ct.arguments[1], i, evaluator); + const int64_t x = EvalAt(ct.arguments[0], i, evaluator); + const int64_t y = EvalAt(ct.arguments[1], i, evaluator); if (x < y) { return true; } @@ -853,11 +870,11 @@ bool CheckLexLessInt(const Constraint& ct, bool CheckLexLesseqInt( const Constraint& ct, - const std::function& evaluator) { + const std::function& evaluator) { CHECK_EQ(Size(ct.arguments[0]), Size(ct.arguments[1])); for (int i = 0; i < Size(ct.arguments[0]); ++i) { - const int64 x = EvalAt(ct.arguments[0], i, evaluator); - const int64 y = EvalAt(ct.arguments[1], i, evaluator); + const int64_t x = EvalAt(ct.arguments[0], i, evaluator); + const int64_t y = EvalAt(ct.arguments[1], i, evaluator); if (x < y) { return true; } @@ -871,9 +888,9 @@ bool CheckLexLesseqInt( bool CheckMaximumArgInt( const Constraint& ct, - const std::function& evaluator) { - const int64 max_index = Eval(ct.arguments[1], evaluator) - 1; - const int64 max_value = EvalAt(ct.arguments[0], max_index, evaluator); + const std::function& evaluator) { + const int64_t max_index = Eval(ct.arguments[1], evaluator) - 1; + const int64_t max_value = EvalAt(ct.arguments[0], max_index, evaluator); // Checks that all value before max_index are < max_value. for (int i = 0; i < max_index; ++i) { if (EvalAt(ct.arguments[0], i, evaluator) >= max_value) { @@ -890,9 +907,10 @@ bool CheckMaximumArgInt( return true; } -bool CheckMaximumInt(const Constraint& ct, - const std::function& evaluator) { - int64 max_value = kint64min; +bool CheckMaximumInt( + const Constraint& ct, + const std::function& evaluator) { + int64_t max_value = std::numeric_limits::min(); for (int i = 0; i < Size(ct.arguments[1]); ++i) { max_value = std::max(max_value, EvalAt(ct.arguments[1], i, evaluator)); } @@ -901,9 +919,9 @@ bool CheckMaximumInt(const Constraint& ct, bool CheckMinimumArgInt( const Constraint& ct, - const std::function& evaluator) { - const int64 min_index = Eval(ct.arguments[1], evaluator) - 1; - const int64 min_value = EvalAt(ct.arguments[0], min_index, evaluator); + const std::function& evaluator) { + const int64_t min_index = Eval(ct.arguments[1], evaluator) - 1; + const int64_t min_value = EvalAt(ct.arguments[0], min_index, evaluator); // Checks that all value before min_index are > min_value. for (int i = 0; i < min_index; ++i) { if (EvalAt(ct.arguments[0], i, evaluator) <= min_value) { @@ -920,9 +938,10 @@ bool CheckMinimumArgInt( return true; } -bool CheckMinimumInt(const Constraint& ct, - const std::function& evaluator) { - int64 min_value = kint64max; +bool CheckMinimumInt( + const Constraint& ct, + const std::function& evaluator) { + int64_t min_value = std::numeric_limits::max(); for (int i = 0; i < Size(ct.arguments[1]); ++i) { min_value = std::min(min_value, EvalAt(ct.arguments[1], i, evaluator)); } @@ -932,44 +951,45 @@ bool CheckMinimumInt(const Constraint& ct, bool CheckNetworkFlowConservation( const Argument& arcs, const Argument& balance_input, const Argument& flow_vars, - const std::function& evaluator) { - std::vector balance(balance_input.values); + const std::function& evaluator) { + std::vector balance(balance_input.values); const int num_arcs = Size(arcs) / 2; for (int arc = 0; arc < num_arcs; arc++) { const int tail = arcs.values[arc * 2] - 1; const int head = arcs.values[arc * 2 + 1] - 1; - const int64 flow = EvalAt(flow_vars, arc, evaluator); + const int64_t flow = EvalAt(flow_vars, arc, evaluator); balance[tail] -= flow; balance[head] += flow; } - for (const int64 value : balance) { + for (const int64_t value : balance) { if (value != 0) return false; } return true; } -bool CheckNetworkFlow(const Constraint& ct, - const std::function& evaluator) { +bool CheckNetworkFlow( + const Constraint& ct, + const std::function& evaluator) { return CheckNetworkFlowConservation(ct.arguments[0], ct.arguments[1], ct.arguments[2], evaluator); } bool CheckNetworkFlowCost( const Constraint& ct, - const std::function& evaluator) { + const std::function& evaluator) { if (!CheckNetworkFlowConservation(ct.arguments[0], ct.arguments[1], ct.arguments[3], evaluator)) { return false; } - int64 total_cost = 0; + int64_t total_cost = 0; const int num_arcs = Size(ct.arguments[3]); for (int arc = 0; arc < num_arcs; arc++) { - const int64 flow = EvalAt(ct.arguments[3], arc, evaluator); - const int64 cost = EvalAt(ct.arguments[2], arc, evaluator); + const int64_t flow = EvalAt(ct.arguments[3], arc, evaluator); + const int64_t cost = EvalAt(ct.arguments[2], arc, evaluator); total_cost += flow * cost; } @@ -977,9 +997,9 @@ bool CheckNetworkFlowCost( } bool CheckNvalue(const Constraint& ct, - const std::function& evaluator) { - const int64 count = Eval(ct.arguments[0], evaluator); - absl::flat_hash_set all_values; + const std::function& evaluator) { + const int64_t count = Eval(ct.arguments[0], evaluator); + absl::flat_hash_set all_values; for (int i = 0; i < Size(ct.arguments[1]); ++i) { all_values.insert(EvalAt(ct.arguments[1], i, evaluator)); } @@ -988,42 +1008,44 @@ bool CheckNvalue(const Constraint& ct, } bool CheckRegular(const Constraint& ct, - const std::function& evaluator) { + const std::function& evaluator) { return true; } -bool CheckRegularNfa(const Constraint& ct, - const std::function& evaluator) { +bool CheckRegularNfa( + const Constraint& ct, + const std::function& evaluator) { return true; } bool CheckSetIn(const Constraint& ct, - const std::function& evaluator) { - const int64 value = Eval(ct.arguments[0], evaluator); + const std::function& evaluator) { + const int64_t value = Eval(ct.arguments[0], evaluator); return ct.arguments[1].Contains(value); } bool CheckSetNotIn(const Constraint& ct, - const std::function& evaluator) { - const int64 value = Eval(ct.arguments[0], evaluator); + const std::function& evaluator) { + const int64_t value = Eval(ct.arguments[0], evaluator); return !ct.arguments[1].Contains(value); } bool CheckSetInReif(const Constraint& ct, - const std::function& evaluator) { - const int64 value = Eval(ct.arguments[0], evaluator); - const int64 status = Eval(ct.arguments[2], evaluator); + const std::function& evaluator) { + const int64_t value = Eval(ct.arguments[0], evaluator); + const int64_t status = Eval(ct.arguments[2], evaluator); return status == ct.arguments[1].Contains(value); } -bool CheckSlidingSum(const Constraint& ct, - const std::function& evaluator) { - const int64 low = Eval(ct.arguments[0], evaluator); - const int64 up = Eval(ct.arguments[1], evaluator); - const int64 length = Eval(ct.arguments[2], evaluator); +bool CheckSlidingSum( + const Constraint& ct, + const std::function& evaluator) { + const int64_t low = Eval(ct.arguments[0], evaluator); + const int64_t up = Eval(ct.arguments[1], evaluator); + const int64_t length = Eval(ct.arguments[2], evaluator); // Compute initial sum. - int64 sliding_sum = 0; - for (int i = 0; i < std::min(length, Size(ct.arguments[3])); ++i) { + int64_t sliding_sum = 0; + for (int i = 0; i < std::min(length, Size(ct.arguments[3])); ++i) { sliding_sum += EvalAt(ct.arguments[3], i, evaluator); } if (sliding_sum < low || sliding_sum > up) { @@ -1040,10 +1062,10 @@ bool CheckSlidingSum(const Constraint& ct, } bool CheckSort(const Constraint& ct, - const std::function& evaluator) { + const std::function& evaluator) { CHECK_EQ(Size(ct.arguments[0]), Size(ct.arguments[1])); - absl::flat_hash_map init_count; - absl::flat_hash_map sorted_count; + absl::flat_hash_map init_count; + absl::flat_hash_map sorted_count; for (int i = 0; i < Size(ct.arguments[0]); ++i) { init_count[EvalAt(ct.arguments[0], i, evaluator)]++; sorted_count[EvalAt(ct.arguments[1], i, evaluator)]++; @@ -1060,13 +1082,14 @@ bool CheckSort(const Constraint& ct, return true; } -bool CheckSubCircuit(const Constraint& ct, - const std::function& evaluator) { - absl::flat_hash_set visited; +bool CheckSubCircuit( + const Constraint& ct, + const std::function& evaluator) { + absl::flat_hash_set visited; // Find inactive nodes (pointing to themselves). - int64 current = -1; + int64_t current = -1; for (int i = 0; i < Size(ct.arguments[0]); ++i) { - const int64 next = EvalAt(ct.arguments[0], i, evaluator) - 1; + const int64_t next = EvalAt(ct.arguments[0], i, evaluator) - 1; if (next != i && current == -1) { current = next; } else if (next == i) { @@ -1077,7 +1100,7 @@ bool CheckSubCircuit(const Constraint& ct, // Try to find a path of length 'residual_size'. const int residual_size = Size(ct.arguments[0]) - visited.size(); for (int i = 0; i < residual_size; ++i) { - const int64 next = EvalAt(ct.arguments[0], current, evaluator) - 1; + const int64_t next = EvalAt(ct.arguments[0], current, evaluator) - 1; visited.insert(next); if (next == current) { return false; @@ -1090,20 +1113,20 @@ bool CheckSubCircuit(const Constraint& ct, } bool CheckTableInt(const Constraint& ct, - const std::function& evaluator) { + const std::function& evaluator) { return true; } bool CheckSymmetricAllDifferent( const Constraint& ct, - const std::function& evaluator) { + const std::function& evaluator) { const int size = Size(ct.arguments[0]); for (int i = 0; i < size; ++i) { - const int64 value = EvalAt(ct.arguments[0], i, evaluator) - 1; + const int64_t value = EvalAt(ct.arguments[0], i, evaluator) - 1; if (value < 0 || value >= size) { return false; } - const int64 reverse_value = EvalAt(ct.arguments[0], value, evaluator) - 1; + const int64_t reverse_value = EvalAt(ct.arguments[0], value, evaluator) - 1; if (reverse_value != i) { return false; } @@ -1113,7 +1136,7 @@ bool CheckSymmetricAllDifferent( using CallMap = absl::flat_hash_map< std::string, std::function)>>; + std::function)>>; // Creates a map between flatzinc predicates and CP-SAT builders. // @@ -1261,7 +1284,7 @@ CallMap CreateCallMap() { } // namespace bool CheckSolution(const Model& model, - const std::function& evaluator) { + const std::function& evaluator) { bool ok = true; const CallMap call_map = CreateCallMap(); for (Constraint* ct : model.constraints()) { diff --git a/ortools/flatzinc/checker.h b/ortools/flatzinc/checker.h index 3a1dee4518..25da3b0f14 100644 --- a/ortools/flatzinc/checker.h +++ b/ortools/flatzinc/checker.h @@ -14,6 +14,7 @@ #ifndef OR_TOOLS_FLATZINC_CHECKER_H_ #define OR_TOOLS_FLATZINC_CHECKER_H_ +#include #include #include "ortools/flatzinc/model.h" @@ -25,7 +26,7 @@ namespace fz { // feasible solution of the given model. Returns true iff this is the // case. bool CheckSolution(const Model& model, - const std::function& evaluator); + const std::function& evaluator); } // namespace fz } // namespace operations_research diff --git a/ortools/flatzinc/cp_model_fz_solver.cc b/ortools/flatzinc/cp_model_fz_solver.cc index 21cc439c6d..21259bff78 100644 --- a/ortools/flatzinc/cp_model_fz_solver.cc +++ b/ortools/flatzinc/cp_model_fz_solver.cc @@ -15,6 +15,7 @@ #include #include +#include #include #include @@ -48,7 +49,7 @@ #include "ortools/sat/table.h" ABSL_FLAG(bool, use_flatzinc_format, true, "Output uses the flatzinc format"); -ABSL_FLAG(int64, fz_int_max, int64{1} << 50, +ABSL_FLAG(int64_t, fz_int_max, int64_t{1} << 50, "Default max value for unbounded integer variables."); namespace operations_research { @@ -64,7 +65,7 @@ int NegatedCpModelVariable(int var) { return -var - 1; } // Helper class to convert a flatzinc model to a CpModelProto. struct CpModelProtoWithMapping { // Returns a constant CpModelProto variable created on-demand. - int LookupConstant(int64 value); + int LookupConstant(int64_t value); // Convert a flatzinc argument to a variable or a list of variable. // Note that we always encode a constant argument with a constant variable. @@ -89,9 +90,9 @@ struct CpModelProtoWithMapping { int GetOrCreateOptionalInterval(int start_var, int size_var, int opt_var); // Helpers to fill a ConstraintProto. - void FillAMinusBInDomain(const std::vector& domain, + void FillAMinusBInDomain(const std::vector& domain, const fz::Constraint& fz_ct, ConstraintProto* ct); - void FillLinearConstraintWithGivenDomain(const std::vector& domain, + void FillLinearConstraintWithGivenDomain(const std::vector& domain, const fz::Constraint& fz_ct, ConstraintProto* ct); void FillConstraint(const fz::Constraint& fz_ct, ConstraintProto* ct); @@ -109,12 +110,12 @@ struct CpModelProtoWithMapping { // Mapping from flatzinc variables to CpModelProto variables. absl::flat_hash_map fz_var_to_index; - absl::flat_hash_map constant_value_to_index; + absl::flat_hash_map constant_value_to_index; absl::flat_hash_map, int> start_size_opt_tuple_to_interval; }; -int CpModelProtoWithMapping::LookupConstant(int64 value) { +int CpModelProtoWithMapping::LookupConstant(int64_t value) { if (gtl::ContainsKey(constant_value_to_index, value)) { return constant_value_to_index[value]; } @@ -139,7 +140,7 @@ std::vector CpModelProtoWithMapping::LookupVars( std::vector result; if (argument.type == fz::Argument::VOID_ARGUMENT) return result; if (argument.type == fz::Argument::INT_LIST) { - for (int64 value : argument.values) { + for (int64_t value : argument.values) { result.push_back(LookupConstant(value)); } } else if (argument.type == fz::Argument::INT_VALUE) { @@ -155,7 +156,8 @@ std::vector CpModelProtoWithMapping::LookupVars( } int CpModelProtoWithMapping::GetOrCreateInterval(int start_var, int size_var) { - return GetOrCreateOptionalInterval(start_var, size_var, kint32max); + return GetOrCreateOptionalInterval(start_var, size_var, + std::numeric_limits::max()); } int CpModelProtoWithMapping::GetOrCreateOptionalInterval(int start_var, @@ -169,7 +171,7 @@ int CpModelProtoWithMapping::GetOrCreateOptionalInterval(int start_var, const int interval_index = proto.constraints_size(); auto* ct = proto.add_constraints(); - if (opt_var != kint32max) { + if (opt_var != std::numeric_limits::max()) { ct->add_enforcement_literal(opt_var); } auto* interval = ct->mutable_interval(); @@ -197,14 +199,15 @@ std::vector CpModelProtoWithMapping::CreateIntervals( } void CpModelProtoWithMapping::FillAMinusBInDomain( - const std::vector& domain, const fz::Constraint& fz_ct, + const std::vector& domain, const fz::Constraint& fz_ct, ConstraintProto* ct) { auto* arg = ct->mutable_linear(); if (fz_ct.arguments[1].type == fz::Argument::INT_VALUE) { - const int64 value = fz_ct.arguments[1].Value(); + const int64_t value = fz_ct.arguments[1].Value(); const int var_a = LookupVar(fz_ct.arguments[0]); - for (const int64 domain_bound : domain) { - if (domain_bound == kint64min || domain_bound == kint64max) { + for (const int64_t domain_bound : domain) { + if (domain_bound == std::numeric_limits::min() || + domain_bound == std::numeric_limits::max()) { arg->add_domain(domain_bound); } else { arg->add_domain(domain_bound + value); @@ -213,13 +216,13 @@ void CpModelProtoWithMapping::FillAMinusBInDomain( arg->add_vars(var_a); arg->add_coeffs(1); } else if (fz_ct.arguments[0].type == fz::Argument::INT_VALUE) { - const int64 value = fz_ct.arguments[0].Value(); + const int64_t value = fz_ct.arguments[0].Value(); const int var_b = LookupVar(fz_ct.arguments[1]); - for (int64 domain_bound : gtl::reversed_view(domain)) { - if (domain_bound == kint64min) { - arg->add_domain(kint64max); - } else if (domain_bound == kint64max) { - arg->add_domain(kint64min); + for (int64_t domain_bound : gtl::reversed_view(domain)) { + if (domain_bound == std::numeric_limits::min()) { + arg->add_domain(std::numeric_limits::max()); + } else if (domain_bound == std::numeric_limits::max()) { + arg->add_domain(std::numeric_limits::min()); } else { arg->add_domain(value - domain_bound); } @@ -227,7 +230,7 @@ void CpModelProtoWithMapping::FillAMinusBInDomain( arg->add_vars(var_b); arg->add_coeffs(1); } else { - for (const int64 domain_bound : domain) arg->add_domain(domain_bound); + for (const int64_t domain_bound : domain) arg->add_domain(domain_bound); arg->add_vars(LookupVar(fz_ct.arguments[0])); arg->add_coeffs(1); arg->add_vars(LookupVar(fz_ct.arguments[1])); @@ -236,10 +239,10 @@ void CpModelProtoWithMapping::FillAMinusBInDomain( } void CpModelProtoWithMapping::FillLinearConstraintWithGivenDomain( - const std::vector& domain, const fz::Constraint& fz_ct, + const std::vector& domain, const fz::Constraint& fz_ct, ConstraintProto* ct) { auto* arg = ct->mutable_linear(); - for (const int64 domain_bound : domain) arg->add_domain(domain_bound); + for (const int64_t domain_bound : domain) arg->add_domain(domain_bound); std::vector vars = LookupVars(fz_ct.arguments[1]); for (int i = 0; i < vars.size(); ++i) { arg->add_vars(vars[i]); @@ -313,13 +316,13 @@ void CpModelProtoWithMapping::FillConstraint(const fz::Constraint& fz_ct, arg->add_literals(TrueLiteral(var)); } } else if (fz_ct.type == "bool_le" || fz_ct.type == "int_le") { - FillAMinusBInDomain({kint64min, 0}, fz_ct, ct); + FillAMinusBInDomain({std::numeric_limits::min(), 0}, fz_ct, ct); } else if (fz_ct.type == "bool_ge" || fz_ct.type == "int_ge") { - FillAMinusBInDomain({0, kint64max}, fz_ct, ct); + FillAMinusBInDomain({0, std::numeric_limits::max()}, fz_ct, ct); } else if (fz_ct.type == "bool_lt" || fz_ct.type == "int_lt") { - FillAMinusBInDomain({kint64min, -1}, fz_ct, ct); + FillAMinusBInDomain({std::numeric_limits::min(), -1}, fz_ct, ct); } else if (fz_ct.type == "bool_gt" || fz_ct.type == "int_gt") { - FillAMinusBInDomain({1, kint64max}, fz_ct, ct); + FillAMinusBInDomain({1, std::numeric_limits::max()}, fz_ct, ct); } else if (fz_ct.type == "bool_eq" || fz_ct.type == "int_eq" || fz_ct.type == "bool2int") { FillAMinusBInDomain({0, 0}, fz_ct, ct); @@ -332,9 +335,11 @@ void CpModelProtoWithMapping::FillConstraint(const fz::Constraint& fz_ct, arg->add_domain(1); arg->add_domain(1); } else if (fz_ct.type == "int_ne") { - FillAMinusBInDomain({kint64min, -1, 1, kint64max}, fz_ct, ct); + FillAMinusBInDomain({std::numeric_limits::min(), -1, 1, + std::numeric_limits::max()}, + fz_ct, ct); } else if (fz_ct.type == "int_lin_eq") { - const int64 rhs = fz_ct.arguments[2].values[0]; + const int64_t rhs = fz_ct.arguments[2].values[0]; FillLinearConstraintWithGivenDomain({rhs, rhs}, fz_ct, ct); } else if (fz_ct.type == "bool_lin_eq") { auto* arg = ct->mutable_linear(); @@ -349,32 +354,38 @@ void CpModelProtoWithMapping::FillConstraint(const fz::Constraint& fz_ct, arg->add_domain(0); arg->add_domain(0); } else { - const int64 v = fz_ct.arguments[2].Value(); + const int64_t v = fz_ct.arguments[2].Value(); arg->add_domain(v); arg->add_domain(v); } } else if (fz_ct.type == "int_lin_le" || fz_ct.type == "bool_lin_le") { - const int64 rhs = fz_ct.arguments[2].values[0]; - FillLinearConstraintWithGivenDomain({kint64min, rhs}, fz_ct, ct); - } else if (fz_ct.type == "int_lin_lt") { - const int64 rhs = fz_ct.arguments[2].values[0]; - FillLinearConstraintWithGivenDomain({kint64min, rhs - 1}, fz_ct, ct); - } else if (fz_ct.type == "int_lin_ge") { - const int64 rhs = fz_ct.arguments[2].values[0]; - FillLinearConstraintWithGivenDomain({rhs, kint64max}, fz_ct, ct); - } else if (fz_ct.type == "int_lin_gt") { - const int64 rhs = fz_ct.arguments[2].values[0]; - FillLinearConstraintWithGivenDomain({rhs + 1, kint64max}, fz_ct, ct); - } else if (fz_ct.type == "int_lin_ne") { - const int64 rhs = fz_ct.arguments[2].values[0]; + const int64_t rhs = fz_ct.arguments[2].values[0]; FillLinearConstraintWithGivenDomain( - {kint64min, rhs - 1, rhs + 1, kint64max}, fz_ct, ct); + {std::numeric_limits::min(), rhs}, fz_ct, ct); + } else if (fz_ct.type == "int_lin_lt") { + const int64_t rhs = fz_ct.arguments[2].values[0]; + FillLinearConstraintWithGivenDomain( + {std::numeric_limits::min(), rhs - 1}, fz_ct, ct); + } else if (fz_ct.type == "int_lin_ge") { + const int64_t rhs = fz_ct.arguments[2].values[0]; + FillLinearConstraintWithGivenDomain( + {rhs, std::numeric_limits::max()}, fz_ct, ct); + } else if (fz_ct.type == "int_lin_gt") { + const int64_t rhs = fz_ct.arguments[2].values[0]; + FillLinearConstraintWithGivenDomain( + {rhs + 1, std::numeric_limits::max()}, fz_ct, ct); + } else if (fz_ct.type == "int_lin_ne") { + const int64_t rhs = fz_ct.arguments[2].values[0]; + FillLinearConstraintWithGivenDomain( + {std::numeric_limits::min(), rhs - 1, rhs + 1, + std::numeric_limits::max()}, + fz_ct, ct); } else if (fz_ct.type == "set_in") { auto* arg = ct->mutable_linear(); arg->add_vars(LookupVar(fz_ct.arguments[0])); arg->add_coeffs(1); if (fz_ct.arguments[1].type == fz::Argument::INT_LIST) { - FillDomainInProto(Domain::FromValues(std::vector{ + FillDomainInProto(Domain::FromValues(std::vector{ fz_ct.arguments[1].values.begin(), fz_ct.arguments[1].values.end()}), arg); @@ -392,8 +403,8 @@ void CpModelProtoWithMapping::FillConstraint(const fz::Constraint& fz_ct, if (fz_ct.arguments[1].type == fz::Argument::INT_LIST) { FillDomainInProto( Domain::FromValues( - std::vector{fz_ct.arguments[1].values.begin(), - fz_ct.arguments[1].values.end()}) + std::vector{fz_ct.arguments[1].values.begin(), + fz_ct.arguments[1].values.end()}) .Complement(), arg); } else if (fz_ct.arguments[1].type == fz::Argument::INT_INTERVAL) { @@ -480,13 +491,14 @@ void CpModelProtoWithMapping::FillConstraint(const fz::Constraint& fz_ct, for (const int var : LookupVars(fz_ct.arguments[0])) arg->add_vars(var); arg->add_vars(LookupVar(fz_ct.arguments[2])); // the target - const std::vector& values = fz_ct.arguments[1].values; - const int64 coeff1 = fz_ct.arguments[3].values[0]; - const int64 coeff2 = fz_ct.arguments[3].values[1]; - const int64 offset = fz_ct.arguments[4].values[0] - 1; + const std::vector& values = fz_ct.arguments[1].values; + const int64_t coeff1 = fz_ct.arguments[3].values[0]; + const int64_t coeff2 = fz_ct.arguments[3].values[1]; + const int64_t offset = fz_ct.arguments[4].values[0] - 1; - for (const int64 a : AllValuesInDomain(proto.variables(arg->vars(0)))) { - for (const int64 b : AllValuesInDomain(proto.variables(arg->vars(1)))) { + for (const int64_t a : AllValuesInDomain(proto.variables(arg->vars(0)))) { + for (const int64_t b : + AllValuesInDomain(proto.variables(arg->vars(1)))) { const int index = coeff1 * a + coeff2 * b + offset; CHECK_GE(index, 0); CHECK_LT(index, values.size()); @@ -499,7 +511,8 @@ void CpModelProtoWithMapping::FillConstraint(const fz::Constraint& fz_ct, } else if (fz_ct.type == "ortools_table_int") { auto* arg = ct->mutable_table(); for (const int var : LookupVars(fz_ct.arguments[0])) arg->add_vars(var); - for (const int64 value : fz_ct.arguments[1].values) arg->add_values(value); + for (const int64_t value : fz_ct.arguments[1].values) + arg->add_values(value); } else if (fz_ct.type == "ortools_regular") { auto* arg = ct->mutable_automaton(); for (const int var : LookupVars(fz_ct.arguments[0])) arg->add_vars(var); @@ -548,12 +561,12 @@ void CpModelProtoWithMapping::FillConstraint(const fz::Constraint& fz_ct, // Try to auto-detect if it is zero or one based. bool found_zero = false; bool found_size = false; - int64 size = 0; + int64_t size = 0; if (fz_ct.arguments[0].variables.empty() && !fz_ct.arguments[0].values.empty()) { // Fully instantiated (sub)circuit constraints. size = fz_ct.arguments[0].values.size(); - for (const int64 value : fz_ct.arguments[0].values) { + for (const int64_t value : fz_ct.arguments[0].values) { if (value == 0) found_zero = true; if (value == size) found_size = true; } @@ -566,14 +579,14 @@ void CpModelProtoWithMapping::FillConstraint(const fz::Constraint& fz_ct, } const bool is_one_based = !found_zero || found_size; - const int64 min_index = is_one_based ? 1 : 0; - const int64 max_index = min_index + size - 1; + const int64_t min_index = is_one_based ? 1 : 0; + const int64_t max_index = min_index + size - 1; // The arc-based mutable circuit. auto* circuit_arg = ct->mutable_circuit(); // We fully encode all variables so we can use the literal based circuit. // TODO(user): avoid fully encoding more than once? - int64 index = min_index; + int64_t index = min_index; const bool is_circuit = (fz_ct.type == "fzn_circuit"); for (const int var : LookupVars(fz_ct.arguments[0])) { Domain domain = ReadDomainFromProto(proto.variables(var)); @@ -583,12 +596,13 @@ void CpModelProtoWithMapping::FillConstraint(const fz::Constraint& fz_ct, if (is_circuit) { // We simply make sure that the variable cannot take the value index. domain = domain.IntersectionWith(Domain::FromIntervals( - {{kint64min, index - 1}, {index + 1, kint64max}})); + {{std::numeric_limits::min(), index - 1}, + {index + 1, std::numeric_limits::max()}})); } FillDomainInProto(domain, proto.mutable_variables(var)); for (const ClosedInterval interval : domain.intervals()) { - for (int64 value = interval.start; value <= interval.end; ++value) { + for (int64_t value = interval.start; value <= interval.end; ++value) { // Create one Boolean variable for this arc. const int literal = proto.variables_size(); { @@ -618,10 +632,12 @@ void CpModelProtoWithMapping::FillConstraint(const fz::Constraint& fz_ct, ct->add_enforcement_literal(NegatedRef(literal)); ct->mutable_linear()->add_coeffs(1); ct->mutable_linear()->add_vars(var); - ct->mutable_linear()->add_domain(kint64min); + ct->mutable_linear()->add_domain( + std::numeric_limits::min()); ct->mutable_linear()->add_domain(value - 1); ct->mutable_linear()->add_domain(value + 1); - ct->mutable_linear()->add_domain(kint64max); + ct->mutable_linear()->add_domain( + std::numeric_limits::max()); } } } @@ -746,7 +762,7 @@ void CpModelProtoWithMapping::FillConstraint(const fz::Constraint& fz_ct, arg->add_domain(0); arg->add_domain(0); for (int arc = 0; arc < num_arcs; arc++) { - const int64 weight = fz_ct.arguments[2].values[arc]; + const int64_t weight = fz_ct.arguments[2].values[arc]; if (weight != 0) { arg->add_vars(flow[arc]); arg->add_coeffs(weight); @@ -913,9 +929,9 @@ void CpModelProtoWithMapping::TranslateSearchAnnotations( // The format is fixed in the flatzinc specification. std::string SolutionString( const fz::SolutionOutputSpecs& output, - const std::function& value_func) { + const std::function& value_func) { if (output.variable != nullptr) { - const int64 value = value_func(output.variable); + const int64_t value = value_func(output.variable); if (output.display_as_boolean) { return absl::StrCat(output.name, " = ", value == 1 ? "true" : "false", ";"); @@ -936,7 +952,7 @@ std::string SolutionString( } result.append("["); for (int i = 0; i < output.flat_variables.size(); ++i) { - const int64 value = value_func(output.flat_variables[i]); + const int64_t value = value_func(output.flat_variables[i]); if (output.display_as_boolean) { result.append(value ? "true" : "false"); } else { @@ -954,7 +970,7 @@ std::string SolutionString( std::string SolutionString( const fz::Model& model, - const std::function& value_func) { + const std::function& value_func) { std::string solution_string; for (const auto& output_spec : model.output()) { solution_string.append(SolutionString(output_spec, value_func)); diff --git a/ortools/flatzinc/fz.cc b/ortools/flatzinc/fz.cc index f5f6523fb1..337fba7a78 100644 --- a/ortools/flatzinc/fz.cc +++ b/ortools/flatzinc/fz.cc @@ -15,6 +15,8 @@ // of the funcionalities are fixed (name of parameters, format of the // input): see http://www.minizinc.org/downloads/doc-1.6/flatzinc-spec.pdf +#include + #if defined(__GNUC__) // Linux or Mac OS X. #include #endif // __GNUC__ @@ -194,7 +196,9 @@ int main(int argc, char** argv) { parameters.verbose_logging = absl::GetFlag(FLAGS_fz_logging); if (absl::GetFlag(FLAGS_num_solutions) == 0) { absl::SetFlag(&FLAGS_num_solutions, - absl::GetFlag(FLAGS_all_solutions) ? kint32max : 1); + absl::GetFlag(FLAGS_all_solutions) + ? std::numeric_limits::max() + : 1); } parameters.max_number_of_solutions = absl::GetFlag(FLAGS_num_solutions); parameters.random_seed = absl::GetFlag(FLAGS_fz_seed); diff --git a/ortools/flatzinc/model.cc b/ortools/flatzinc/model.cc index d6512337d6..ffff0c7846 100644 --- a/ortools/flatzinc/model.cc +++ b/ortools/flatzinc/model.cc @@ -13,6 +13,8 @@ #include "ortools/flatzinc/model.h" +#include +#include #include #include @@ -28,7 +30,7 @@ namespace operations_research { namespace fz { // ----- Domain ----- -Domain Domain::IntegerList(std::vector values) { +Domain Domain::IntegerList(std::vector values) { Domain result; result.is_interval = false; result.values = std::move(values); @@ -46,7 +48,7 @@ Domain Domain::AllInt64() { return result; } -Domain Domain::IntegerValue(int64 value) { +Domain Domain::IntegerValue(int64_t value) { Domain result; result.is_interval = false; result.values.push_back(value); @@ -55,7 +57,7 @@ Domain Domain::IntegerValue(int64 value) { return result; } -Domain Domain::Interval(int64 included_min, int64 included_max) { +Domain Domain::Interval(int64_t included_min, int64_t included_max) { Domain result; result.is_interval = true; result.display_as_boolean = false; @@ -75,7 +77,7 @@ Domain Domain::Boolean() { return result; } -Domain Domain::SetOfIntegerList(std::vector values) { +Domain Domain::SetOfIntegerList(std::vector values) { Domain result = IntegerList(std::move(values)); result.is_a_set = true; return result; @@ -87,13 +89,13 @@ Domain Domain::SetOfAllInt64() { return result; } -Domain Domain::SetOfIntegerValue(int64 value) { +Domain Domain::SetOfIntegerValue(int64_t value) { Domain result = IntegerValue(value); result.is_a_set = true; return result; } -Domain Domain::SetOfInterval(int64 included_min, int64 included_max) { +Domain Domain::SetOfInterval(int64_t included_min, int64_t included_max) { Domain result = Interval(included_min, included_max); result.is_a_set = true; return result; @@ -125,8 +127,8 @@ bool Domain::IntersectWithDomain(const Domain& domain) { if (values.empty()) { values = domain.values; } else { - const int64 imin = values[0]; - const int64 imax = values[1]; + const int64_t imin = values[0]; + const int64_t imax = values[1]; values = domain.values; IntersectWithInterval(imin, imax); } @@ -136,11 +138,11 @@ bool Domain::IntersectWithDomain(const Domain& domain) { return IntersectWithListOfIntegers(domain.values); } -bool Domain::IntersectWithSingleton(int64 value) { +bool Domain::IntersectWithSingleton(int64_t value) { return IntersectWithInterval(value, value); } -bool Domain::IntersectWithInterval(int64 interval_min, int64 interval_max) { +bool Domain::IntersectWithInterval(int64_t interval_min, int64_t interval_max) { if (interval_min > interval_max) { // Empty interval -> empty domain. is_interval = false; values.clear(); @@ -166,10 +168,10 @@ bool Domain::IntersectWithInterval(int64 interval_min, int64 interval_max) { } else { if (!values.empty()) { std::sort(values.begin(), values.end()); - std::vector new_values; + std::vector new_values; new_values.reserve(values.size()); bool changed = false; - for (const int64 val : values) { + for (const int64_t val : values) { if (val > interval_max) { changed = true; break; @@ -188,12 +190,14 @@ bool Domain::IntersectWithInterval(int64 interval_min, int64 interval_max) { return false; } -bool Domain::IntersectWithListOfIntegers(const std::vector& integers) { +bool Domain::IntersectWithListOfIntegers(const std::vector& integers) { if (is_interval) { - const int64 dmin = values.empty() ? kint64min : values[0]; - const int64 dmax = values.empty() ? kint64max : values[1]; + const int64_t dmin = + values.empty() ? std::numeric_limits::min() : values[0]; + const int64_t dmax = + values.empty() ? std::numeric_limits::max() : values[1]; values.clear(); - for (const int64 v : integers) { + for (const int64_t v : integers) { if (v >= dmin && v <= dmax) values.push_back(v); } gtl::STLSortAndRemoveDuplicates(&values); @@ -202,7 +206,7 @@ bool Domain::IntersectWithListOfIntegers(const std::vector& integers) { values.size() >= 2) { if (values.size() > 2) { // Contiguous case. - const int64 last = values.back(); + const int64_t last = values.back(); values.resize(2); values[1] = last; } @@ -215,11 +219,11 @@ bool Domain::IntersectWithListOfIntegers(const std::vector& integers) { } else { // TODO(user): Investigate faster code for small arrays. std::sort(values.begin(), values.end()); - absl::flat_hash_set other_values(integers.begin(), integers.end()); - std::vector new_values; + absl::flat_hash_set other_values(integers.begin(), integers.end()); + std::vector new_values; new_values.reserve(std::min(values.size(), integers.size())); bool changed = false; - for (const int64 val : values) { + for (const int64_t val : values) { if (gtl::ContainsKey(other_values, val)) { if (new_values.empty() || val != new_values.back()) { new_values.push_back(val); @@ -242,27 +246,30 @@ bool Domain::empty() const { : values.empty(); } -int64 Domain::Min() const { +int64_t Domain::Min() const { CHECK(!empty()); - return is_interval && values.empty() ? kint64min : values.front(); + return is_interval && values.empty() ? std::numeric_limits::min() + : values.front(); } -int64 Domain::Max() const { +int64_t Domain::Max() const { CHECK(!empty()); - return is_interval && values.empty() ? kint64max : values.back(); + return is_interval && values.empty() ? std::numeric_limits::max() + : values.back(); } -int64 Domain::Value() const { +int64_t Domain::Value() const { CHECK(HasOneValue()); return values.front(); } bool Domain::IsAllInt64() const { return is_interval && - (values.empty() || (values[0] == kint64min && values[1] == kint64max)); + (values.empty() || (values[0] == std::numeric_limits::min() && + values[1] == std::numeric_limits::max())); } -bool Domain::Contains(int64 value) const { +bool Domain::Contains(int64_t value) const { if (is_interval) { if (values.empty()) { return true; @@ -275,9 +282,9 @@ bool Domain::Contains(int64 value) const { } namespace { -bool IntervalOverlapValues(int64 lb, int64 ub, - const std::vector& values) { - for (int64 value : values) { +bool IntervalOverlapValues(int64_t lb, int64_t ub, + const std::vector& values) { + for (int64_t value : values) { if (lb <= value && value <= ub) { return true; } @@ -286,7 +293,7 @@ bool IntervalOverlapValues(int64 lb, int64 ub, } } // namespace -bool Domain::OverlapsIntList(const std::vector& vec) const { +bool Domain::OverlapsIntList(const std::vector& vec) const { if (IsAllInt64()) { return true; } @@ -295,13 +302,13 @@ bool Domain::OverlapsIntList(const std::vector& vec) const { return IntervalOverlapValues(values[0], values[1], vec); } else { // TODO(user): Better algorithm, sort and compare increasingly. - const std::vector& to_scan = + const std::vector& to_scan = values.size() <= vec.size() ? values : vec; - const absl::flat_hash_set container = + const absl::flat_hash_set container = values.size() <= vec.size() - ? absl::flat_hash_set(vec.begin(), vec.end()) - : absl::flat_hash_set(values.begin(), values.end()); - for (int64 value : to_scan) { + ? absl::flat_hash_set(vec.begin(), vec.end()) + : absl::flat_hash_set(values.begin(), values.end()); + for (int64_t value : to_scan) { if (gtl::ContainsKey(container, value)) { return true; } @@ -310,14 +317,14 @@ bool Domain::OverlapsIntList(const std::vector& vec) const { } } -bool Domain::OverlapsIntInterval(int64 lb, int64 ub) const { +bool Domain::OverlapsIntInterval(int64_t lb, int64_t ub) const { if (IsAllInt64()) { return true; } if (is_interval) { CHECK(!values.empty()); - const int64 dlb = values[0]; - const int64 dub = values[1]; + const int64_t dlb = values[0]; + const int64_t dub = values[1]; return !(dub < lb || dlb > ub); } else { return IntervalOverlapValues(lb, ub, values); @@ -336,7 +343,7 @@ bool Domain::OverlapsDomain(const Domain& other) const { } } -bool Domain::RemoveValue(int64 value) { +bool Domain::RemoveValue(int64_t value) { if (is_interval) { if (values.empty()) { return false; @@ -348,10 +355,10 @@ bool Domain::RemoveValue(int64 value) { return true; } else if (values[1] - values[0] < 1024 && value > values[0] && value < values[1]) { // small - const int64 vmax = values[1]; + const int64_t vmax = values[1]; values.pop_back(); values.reserve(vmax - values[0]); - for (int64 v = values[0] + 1; v <= vmax; ++v) { + for (int64_t v = values[0] + 1; v <= vmax; ++v) { if (v != value) { values.push_back(v); } @@ -383,14 +390,14 @@ std::string Domain::DebugString() const { // ----- Argument ----- -Argument Argument::IntegerValue(int64 value) { +Argument Argument::IntegerValue(int64_t value) { Argument result; result.type = INT_VALUE; result.values.push_back(value); return result; } -Argument Argument::Interval(int64 imin, int64 imax) { +Argument Argument::Interval(int64_t imin, int64_t imax) { Argument result; result.type = INT_INTERVAL; result.values.push_back(imin); @@ -398,7 +405,7 @@ Argument Argument::Interval(int64 imin, int64 imax) { return result; } -Argument Argument::IntegerList(std::vector values) { +Argument Argument::IntegerList(std::vector values) { Argument result; result.type = INT_LIST; result.values = std::move(values); @@ -435,7 +442,8 @@ Argument Argument::VoidArgument() { Argument Argument::FromDomain(const Domain& domain) { if (domain.is_interval) { if (domain.values.empty()) { - return Argument::Interval(kint64min, kint64max); + return Argument::Interval(std::numeric_limits::min(), + std::numeric_limits::max()); } else { return Argument::Interval(domain.values[0], domain.values[1]); } @@ -479,7 +487,7 @@ bool Argument::HasOneValue() const { (type == INT_VAR_REF && variables[0]->domain.HasOneValue())); } -int64 Argument::Value() const { +int64_t Argument::Value() const { DCHECK(HasOneValue()) << "Value() called on unbound Argument: " << DebugString(); switch (type) { @@ -528,7 +536,7 @@ bool Argument::IsArrayOfValues() const { } } -bool Argument::Contains(int64 value) const { +bool Argument::Contains(int64_t value) const { switch (type) { case Argument::INT_LIST: { return std::find(values.begin(), values.end(), value) != values.end(); @@ -546,7 +554,7 @@ bool Argument::Contains(int64 value) const { } } -int64 Argument::ValueAt(int pos) const { +int64_t Argument::ValueAt(int pos) const { switch (type) { case INT_LIST: CHECK_GE(pos, 0); @@ -683,7 +691,7 @@ Annotation Annotation::FunctionCall(const std::string& id) { return result; } -Annotation Annotation::Interval(int64 interval_min, int64 interval_max) { +Annotation Annotation::Interval(int64_t interval_min, int64_t interval_max) { Annotation result; result.type = INTERVAL; result.interval_min = interval_min; @@ -691,7 +699,7 @@ Annotation Annotation::Interval(int64 interval_min, int64 interval_max) { return result; } -Annotation Annotation::IntegerValue(int64 value) { +Annotation Annotation::IntegerValue(int64_t value) { Annotation result; result.type = INT_VALUE; result.interval_min = value; @@ -831,7 +839,7 @@ IntegerVariable* Model::AddVariable(const std::string& name, } // TODO(user): Create only once constant per value. -IntegerVariable* Model::AddConstant(int64 value) { +IntegerVariable* Model::AddConstant(int64_t value) { IntegerVariable* const var = new IntegerVariable( absl::StrCat(value), Domain::IntegerValue(value), true); variables_.push_back(var); diff --git a/ortools/flatzinc/model.h b/ortools/flatzinc/model.h index 2f0c2d3381..6264872d23 100644 --- a/ortools/flatzinc/model.h +++ b/ortools/flatzinc/model.h @@ -14,6 +14,7 @@ #ifndef OR_TOOLS_FLATZINC_MODEL_H_ #define OR_TOOLS_FLATZINC_MODEL_H_ +#include #include #include @@ -47,15 +48,15 @@ class Model; // instead of exactly one value. struct Domain { // The values will be sorted and duplicate values will be removed. - static Domain IntegerList(std::vector values); + static Domain IntegerList(std::vector values); static Domain AllInt64(); - static Domain IntegerValue(int64 value); - static Domain Interval(int64 included_min, int64 included_max); + static Domain IntegerValue(int64_t value); + static Domain Interval(int64_t included_min, int64_t included_max); static Domain Boolean(); - static Domain SetOfIntegerList(std::vector values); + static Domain SetOfIntegerList(std::vector values); static Domain SetOfAllInt64(); - static Domain SetOfIntegerValue(int64 value); - static Domain SetOfInterval(int64 included_min, int64 included_max); + static Domain SetOfIntegerValue(int64_t value); + static Domain SetOfInterval(int64_t included_min, int64_t included_max); static Domain SetOfBoolean(); static Domain EmptyDomain(); @@ -63,38 +64,38 @@ struct Domain { bool empty() const; // Returns the min of the domain. - int64 Min() const; + int64_t Min() const; // Returns the max of the domain. - int64 Max() const; + int64_t Max() const; // Returns the value of the domain. HasOneValue() must return true. - int64 Value() const; + int64_t Value() const; // Returns true if the domain is [kint64min..kint64max] bool IsAllInt64() const; // Various inclusion tests on a domain. - bool Contains(int64 value) const; - bool OverlapsIntList(const std::vector& vec) const; - bool OverlapsIntInterval(int64 lb, int64 ub) const; + bool Contains(int64_t value) const; + bool OverlapsIntList(const std::vector& vec) const; + bool OverlapsIntInterval(int64_t lb, int64_t ub) const; bool OverlapsDomain(const Domain& other) const; // All the following modifiers change the internal representation // list to interval or interval to list. - bool IntersectWithSingleton(int64 value); + bool IntersectWithSingleton(int64_t value); bool IntersectWithDomain(const Domain& domain); - bool IntersectWithInterval(int64 interval_min, int64 interval_max); - bool IntersectWithListOfIntegers(const std::vector& integers); + bool IntersectWithInterval(int64_t interval_min, int64_t interval_max); + bool IntersectWithListOfIntegers(const std::vector& integers); // Returns true iff the value did belong to the domain, and was removed. // Try to remove the value. It returns true if it was actually removed. // If the value is inside a large interval, then it will not be removed. - bool RemoveValue(int64 value); + bool RemoveValue(int64_t value); std::string DebugString() const; // These should never be modified from outside the class. - std::vector values; + std::vector values; bool is_interval; bool display_as_boolean; // Indicates if the domain was created as a set domain. @@ -151,9 +152,9 @@ struct Argument { VOID_ARGUMENT, }; - static Argument IntegerValue(int64 value); - static Argument Interval(int64 imin, int64 imax); - static Argument IntegerList(std::vector values); + static Argument IntegerValue(int64_t value); + static Argument Interval(int64_t imin, int64_t imax); + static Argument IntegerList(std::vector values); static Argument DomainList(std::vector domains); static Argument IntVarRef(IntegerVariable* const var); static Argument IntVarRefArray(std::vector vars); @@ -168,16 +169,16 @@ struct Argument { // list of size 1, interval of size 1, or variable with a singleton domain). bool HasOneValue() const; // Returns the value of the argument. Does DCHECK(HasOneValue()). - int64 Value() const; + int64_t Value() const; // Returns true if it an integer list, or an array of integer // variables (or domain) each having only one value. bool IsArrayOfValues() const; // Returns true if the argument is an integer value, an integer // list, or an interval, and it contains the given value. // It will check that the type is actually one of the above. - bool Contains(int64 value) const; + bool Contains(int64_t value) const; // Returns the value of the pos-th element. - int64 ValueAt(int pos) const; + int64_t ValueAt(int pos) const; // Returns the variable inside the argument if the type is INT_VAR_REF, // or nullptr otherwise. IntegerVariable* Var() const; @@ -186,7 +187,7 @@ struct Argument { IntegerVariable* VarAt(int pos) const; Type type; - std::vector values; + std::vector values; std::vector variables; std::vector domains; }; @@ -253,8 +254,8 @@ struct Annotation { static Annotation FunctionCallWithArguments(const std::string& id, std::vector args); static Annotation FunctionCall(const std::string& id); - static Annotation Interval(int64 interval_min, int64 interval_max); - static Annotation IntegerValue(int64 value); + static Annotation Interval(int64_t interval_min, int64_t interval_max); + static Annotation IntegerValue(int64_t value); static Annotation Variable(IntegerVariable* const var); static Annotation VariableList(std::vector variables); static Annotation String(const std::string& str); @@ -269,8 +270,8 @@ struct Annotation { void AppendAllIntegerVariables(std::vector* vars) const; Type type; - int64 interval_min; - int64 interval_max; + int64_t interval_min; + int64_t interval_max; std::string id; std::vector annotations; std::vector variables; @@ -281,11 +282,11 @@ struct Annotation { // It follows the flatzinc specification (www.minizinc.org). struct SolutionOutputSpecs { struct Bounds { - Bounds(int64 min_value_, int64 max_value_) + Bounds(int64_t min_value_, int64_t max_value_) : min_value(min_value_), max_value(max_value_) {} std::string DebugString() const; - int64 min_value; - int64 max_value; + int64_t min_value; + int64_t max_value; }; // Will output: name = . @@ -324,7 +325,7 @@ class Model { // are owned by the model and will remain live for its lifetime. IntegerVariable* AddVariable(const std::string& name, const Domain& domain, bool defined); - IntegerVariable* AddConstant(int64 value); + IntegerVariable* AddConstant(int64_t value); // Creates and add a constraint to the model. void AddConstraint(const std::string& id, std::vector arguments, bool is_domain); diff --git a/ortools/flatzinc/parser_util.h b/ortools/flatzinc/parser_util.h index baf29e23fa..3346c2bfbb 100644 --- a/ortools/flatzinc/parser_util.h +++ b/ortools/flatzinc/parser_util.h @@ -18,6 +18,7 @@ #define OR_TOOLS_FLATZINC_PARSER_UTIL_H_ #include +#include #include "absl/container/flat_hash_map.h" #include "ortools/base/map_util.h" @@ -27,8 +28,8 @@ namespace operations_research { namespace fz { // This is the context used during parsing. struct ParserContext { - absl::flat_hash_map integer_map; - absl::flat_hash_map> integer_array_map; + absl::flat_hash_map integer_map; + absl::flat_hash_map> integer_array_map; absl::flat_hash_map float_map; absl::flat_hash_map> float_array_map; absl::flat_hash_map variable_map; @@ -56,7 +57,7 @@ struct VariableRefOrValue { result.defined = true; return result; } - static VariableRefOrValue Value(int64 value) { + static VariableRefOrValue Value(int64_t value) { VariableRefOrValue result; result.variable = nullptr; result.value = value; @@ -65,13 +66,13 @@ struct VariableRefOrValue { } IntegerVariable* variable; - int64 value; + int64_t value; bool defined; }; struct VariableRefOrValueArray { std::vector variables; - std::vector values; + std::vector values; void PushBack(const VariableRefOrValue& v) { CHECK(v.defined); @@ -85,12 +86,12 @@ struct VariableRefOrValueArray { // Class needed to pass information from the lexer to the parser. // TODO(user): Use std::unique_ptr> to ease memory management. struct LexerInfo { - int64 integer_value; + int64_t integer_value; double double_value; std::string string_value; Domain domain; std::vector* domains; - std::vector* integers; + std::vector* integers; std::vector* doubles; Argument arg; std::vector* args; @@ -101,7 +102,7 @@ struct LexerInfo { }; // If the argument is an integer, return it as int64. Otherwise, die. -int64 ConvertAsIntegerOrDie(double d); +int64_t ConvertAsIntegerOrDie(double d); } // namespace fz } // namespace operations_research #endif // OR_TOOLS_FLATZINC_PARSER_UTIL_H_ diff --git a/ortools/flatzinc/presolve.cc b/ortools/flatzinc/presolve.cc index 8cbc6a0afe..a2be1291ac 100644 --- a/ortools/flatzinc/presolve.cc +++ b/ortools/flatzinc/presolve.cc @@ -13,6 +13,7 @@ #include "ortools/flatzinc/presolve.h" +#include #include #include @@ -40,7 +41,7 @@ bool Has01Values(IntegerVariable* var) { return var->domain.Min() == 0 && var->domain.Max() == 1; } -bool Is0Or1(int64 value) { return !(value & ~1LL); } +bool Is0Or1(int64_t value) { return !(value & ~1LL); } template bool IsArrayBoolean(const std::vector& values) { @@ -70,14 +71,14 @@ bool AtMostOne0OrAtMostOne1(const std::vector& values) { return true; } -absl::flat_hash_set GetValueSet(const Argument& arg) { - absl::flat_hash_set result; +absl::flat_hash_set GetValueSet(const Argument& arg) { + absl::flat_hash_set result; if (arg.HasOneValue()) { result.insert(arg.Value()); } else { const Domain& domain = arg.Var()->domain; if (domain.is_interval && !domain.values.empty()) { - for (int64 v = domain.values[0]; v <= domain.values[1]; ++v) { + for (int64_t v = domain.values[0]; v <= domain.values[1]; ++v) { result.insert(v); } } else { @@ -87,7 +88,7 @@ absl::flat_hash_set GetValueSet(const Argument& arg) { return result; } -void SetConstraintAsIntEq(Constraint* ct, IntegerVariable* var, int64 value) { +void SetConstraintAsIntEq(Constraint* ct, IntegerVariable* var, int64_t value) { CHECK(var != nullptr); ct->type = "int_eq"; ct->arguments.clear(); @@ -120,7 +121,7 @@ bool OverlapsAt(const Argument& array, int pos, const Argument& other) { } } } else if (array.type == Argument::INT_LIST) { - const int64 value = array.values[pos]; + const int64_t value = array.values[pos]; switch (other.type) { case Argument::INT_VALUE: { return value == other.values[0]; @@ -200,9 +201,9 @@ void Presolver::PresolveStoreAffineMapping(Constraint* ct) { CHECK_EQ(2, ct->arguments[1].variables.size()); IntegerVariable* const var0 = ct->arguments[1].variables[0]; IntegerVariable* const var1 = ct->arguments[1].variables[1]; - const int64 coeff0 = ct->arguments[0].values[0]; - const int64 coeff1 = ct->arguments[0].values[1]; - const int64 rhs = ct->arguments[2].Value(); + const int64_t coeff0 = ct->arguments[0].values[0]; + const int64_t coeff1 = ct->arguments[0].values[1]; + const int64_t rhs = ct->arguments[2].Value(); if (coeff0 == -1 && !gtl::ContainsKey(affine_map_, var0)) { affine_map_[var0] = AffineMapping(var1, coeff0, -rhs, ct); UpdateRuleStats("int_lin_eq: store affine mapping"); @@ -217,10 +218,10 @@ void Presolver::PresolveStoreFlatteningMapping(Constraint* ct) { IntegerVariable* const var0 = ct->arguments[1].variables[0]; IntegerVariable* const var1 = ct->arguments[1].variables[1]; IntegerVariable* const var2 = ct->arguments[1].variables[2]; - const int64 coeff0 = ct->arguments[0].values[0]; - const int64 coeff1 = ct->arguments[0].values[1]; - const int64 coeff2 = ct->arguments[0].values[2]; - const int64 rhs = ct->arguments[2].Value(); + const int64_t coeff0 = ct->arguments[0].values[0]; + const int64_t coeff1 = ct->arguments[0].values[1]; + const int64_t coeff2 = ct->arguments[0].values[2]; + const int64_t rhs = ct->arguments[2].Value(); if (coeff0 == -1 && coeff2 == 1 && !gtl::ContainsKey(array2d_index_map_, var0)) { array2d_index_map_[var0] = @@ -245,7 +246,7 @@ void Presolver::PresolveStoreFlatteningMapping(Constraint* ct) { } namespace { -bool IsIncreasingAndContiguous(const std::vector& values) { +bool IsIncreasingAndContiguous(const std::vector& values) { for (int i = 0; i < values.size() - 1; ++i) { if (values[i + 1] != values[i] + 1) { return false; @@ -254,7 +255,7 @@ bool IsIncreasingAndContiguous(const std::vector& values) { return true; } -bool AreOnesFollowedByMinusOne(const std::vector& coeffs) { +bool AreOnesFollowedByMinusOne(const std::vector& coeffs) { CHECK(!coeffs.empty()); for (int i = 0; i < coeffs.size() - 1; ++i) { if (coeffs[i] != 1) { @@ -325,10 +326,10 @@ void Presolver::PresolveSimplifyElement(Constraint* ct) { return; } else if (mapping.offset + mapping.coefficient > 0 && domain.values[0] > 0) { - const std::vector& values = ct->arguments[1].values; - std::vector new_values; - for (int64 i = 1; i <= domain.values.back(); ++i) { - const int64 index = i * mapping.coefficient + mapping.offset - 1; + const std::vector& values = ct->arguments[1].values; + std::vector new_values; + for (int64_t i = 1; i <= domain.values.back(); ++i) { + const int64_t index = i * mapping.coefficient + mapping.offset - 1; if (index < 0) { return; } @@ -363,7 +364,7 @@ void Presolver::PresolveSimplifyElement(Constraint* ct) { // Rewrite constraint. ct->arguments[0] = Argument::IntVarRefArray({mapping.variable1, mapping.variable2}); - std::vector coefs; + std::vector coefs; coefs.push_back(mapping.coefficient); coefs.push_back(1); ct->arguments.push_back(Argument::IntegerList(coefs)); @@ -385,7 +386,7 @@ void Presolver::PresolveSimplifyElement(Constraint* ct) { // Rule 4. if (IsIncreasingAndContiguous(ct->arguments[1].values) && ct->arguments[2].type == Argument::INT_VAR_REF) { - const int64 start = ct->arguments[1].values.front(); + const int64_t start = ct->arguments[1].values.front(); IntegerVariable* const index = ct->arguments[0].Var(); IntegerVariable* const target = ct->arguments[2].Var(); UpdateRuleStats("array_int_element: rewrite as a linear constraint"); @@ -421,8 +422,8 @@ void Presolver::PresolveSimplifyExprElement(Constraint* ct) { } const std::vector& vars = ct->arguments[1].variables; std::vector new_vars; - for (int64 i = domain.values.front(); i <= domain.values.back(); ++i) { - const int64 index = i * mapping.coefficient + mapping.offset - 1; + for (int64_t i = domain.values.front(); i <= domain.values.back(); ++i) { + const int64_t index = i * mapping.coefficient + mapping.offset - 1; if (index < 0) { return; } diff --git a/ortools/flatzinc/presolve.h b/ortools/flatzinc/presolve.h index 1ddde810a7..ddc89a1c66 100644 --- a/ortools/flatzinc/presolve.h +++ b/ortools/flatzinc/presolve.h @@ -14,6 +14,7 @@ #ifndef OR_TOOLS_FLATZINC_PRESOLVE_H_ #define OR_TOOLS_FLATZINC_PRESOLVE_H_ +#include #include #include @@ -47,13 +48,13 @@ class Presolver { // constraint that defines this mapping. struct AffineMapping { IntegerVariable* variable; - int64 coefficient; - int64 offset; + int64_t coefficient; + int64_t offset; Constraint* constraint; AffineMapping() : variable(nullptr), coefficient(0), offset(0), constraint(nullptr) {} - AffineMapping(IntegerVariable* v, int64 c, int64 o, Constraint* ct) + AffineMapping(IntegerVariable* v, int64_t c, int64_t o, Constraint* ct) : variable(v), coefficient(c), offset(o), constraint(ct) {} }; @@ -64,9 +65,9 @@ class Presolver { // Eg. new_index_var = index_var1 * int_coeff + index_var2 + int_offset struct Array2DIndexMapping { IntegerVariable* variable1; - int64 coefficient; + int64_t coefficient; IntegerVariable* variable2; - int64 offset; + int64_t offset; Constraint* constraint; Array2DIndexMapping() @@ -75,8 +76,8 @@ class Presolver { variable2(nullptr), offset(0), constraint(nullptr) {} - Array2DIndexMapping(IntegerVariable* v1, int64 c, IntegerVariable* v2, - int64 o, Constraint* ct) + Array2DIndexMapping(IntegerVariable* v1, int64_t c, IntegerVariable* v2, + int64_t o, Constraint* ct) : variable1(v1), coefficient(c), variable2(v2), diff --git a/ortools/glop/basis_representation.cc b/ortools/glop/basis_representation.cc index 49bdd36de5..1b63d9addf 100644 --- a/ortools/glop/basis_representation.cc +++ b/ortools/glop/basis_representation.cc @@ -207,8 +207,7 @@ Status BasisFactorization::Initialize() { SCOPED_TIME_STAT(&stats_); Clear(); if (IsIdentityBasis()) return Status::OK(); - CompactSparseMatrixView basis_matrix(&compact_matrix_, &basis_); - return lu_factorization_.ComputeFactorization(basis_matrix); + return ComputeFactorization(); } bool BasisFactorization::IsRefactorized() const { return num_updates_ == 0; } @@ -222,9 +221,12 @@ Status BasisFactorization::ForceRefactorization() { SCOPED_TIME_STAT(&stats_); stats_.refactorization_interval.Add(num_updates_); Clear(); + return ComputeFactorization(); +} + +Status BasisFactorization::ComputeFactorization() { CompactSparseMatrixView basis_matrix(&compact_matrix_, &basis_); const Status status = lu_factorization_.ComputeFactorization(basis_matrix); - const double kLuComplexityFactor = 10; deterministic_time_ += kLuComplexityFactor * DeterministicTimeForFpOperations( @@ -306,7 +308,6 @@ Status BasisFactorization::Update(ColIndex entering_col, void BasisFactorization::LeftSolve(ScatteredRow* y) const { SCOPED_TIME_STAT(&stats_); RETURN_IF_NULL(y); - BumpDeterministicTimeForSolve(compact_matrix_.num_rows().value()); if (use_middle_product_form_update_) { lu_factorization_.LeftSolveUWithNonZeros(y); rank_one_factorization_.LeftSolveWithNonZeros(y); @@ -317,12 +318,12 @@ void BasisFactorization::LeftSolve(ScatteredRow* y) const { eta_factorization_.LeftSolve(&y->values); lu_factorization_.LeftSolve(&y->values); } + BumpDeterministicTimeForSolve(y->NumNonZerosEstimate()); } void BasisFactorization::RightSolve(ScatteredColumn* d) const { SCOPED_TIME_STAT(&stats_); RETURN_IF_NULL(d); - BumpDeterministicTimeForSolve(d->non_zeros.size()); if (use_middle_product_form_update_) { lu_factorization_.RightSolveLWithNonZeros(d); rank_one_factorization_.RightSolveWithNonZeros(d); @@ -333,12 +334,12 @@ void BasisFactorization::RightSolve(ScatteredColumn* d) const { lu_factorization_.RightSolve(&d->values); eta_factorization_.RightSolve(&d->values); } + BumpDeterministicTimeForSolve(d->NumNonZerosEstimate()); } const DenseColumn& BasisFactorization::RightSolveForTau( const ScatteredColumn& a) const { SCOPED_TIME_STAT(&stats_); - BumpDeterministicTimeForSolve(compact_matrix_.num_rows().value()); if (use_middle_product_form_update_) { if (tau_computation_can_be_optimized_) { // Once used, the intermediate result is overwritten, so @@ -358,6 +359,7 @@ const DenseColumn& BasisFactorization::RightSolveForTau( eta_factorization_.RightSolve(&tau_.values); } tau_is_computed_ = true; + BumpDeterministicTimeForSolve(tau_.NumNonZerosEstimate()); return tau_.values; } @@ -365,7 +367,6 @@ void BasisFactorization::LeftSolveForUnitRow(ColIndex j, ScatteredRow* y) const { SCOPED_TIME_STAT(&stats_); RETURN_IF_NULL(y); - BumpDeterministicTimeForSolve(1); ClearAndResizeVectorWithNonZeros(RowToColIndex(compact_matrix_.num_rows()), y); if (!use_middle_product_form_update_) { @@ -373,6 +374,7 @@ void BasisFactorization::LeftSolveForUnitRow(ColIndex j, y->non_zeros.push_back(j); eta_factorization_.SparseLeftSolve(&y->values, &y->non_zeros); lu_factorization_.LeftSolve(&y->values); + BumpDeterministicTimeForSolve(y->NumNonZerosEstimate()); return; } @@ -410,6 +412,7 @@ void BasisFactorization::LeftSolveForUnitRow(ColIndex j, } tau_is_computed_ = false; y->SortNonZerosIfNeeded(); + BumpDeterministicTimeForSolve(y->NumNonZerosEstimate()); } void BasisFactorization::TemporaryLeftSolveForUnitRow(ColIndex j, @@ -417,26 +420,25 @@ void BasisFactorization::TemporaryLeftSolveForUnitRow(ColIndex j, CHECK(IsRefactorized()); SCOPED_TIME_STAT(&stats_); RETURN_IF_NULL(y); - BumpDeterministicTimeForSolve(1); ClearAndResizeVectorWithNonZeros(RowToColIndex(compact_matrix_.num_rows()), y); lu_factorization_.LeftSolveUForUnitRow(j, y); lu_factorization_.LeftSolveLWithNonZeros(y); y->SortNonZerosIfNeeded(); + BumpDeterministicTimeForSolve(y->NumNonZerosEstimate()); } void BasisFactorization::RightSolveForProblemColumn(ColIndex col, ScatteredColumn* d) const { SCOPED_TIME_STAT(&stats_); RETURN_IF_NULL(d); - BumpDeterministicTimeForSolve( - compact_matrix_.column(col).num_entries().value()); ClearAndResizeVectorWithNonZeros(compact_matrix_.num_rows(), d); if (!use_middle_product_form_update_) { compact_matrix_.ColumnCopyToClearedDenseColumn(col, &d->values); lu_factorization_.RightSolve(&d->values); eta_factorization_.RightSolve(&d->values); + BumpDeterministicTimeForSolve(d->NumNonZerosEstimate()); return; } @@ -461,6 +463,7 @@ void BasisFactorization::RightSolveForProblemColumn(ColIndex col, } lu_factorization_.RightSolveUWithNonZeros(d); d->SortNonZerosIfNeeded(); + BumpDeterministicTimeForSolve(d->NumNonZerosEstimate()); } Fractional BasisFactorization::RightSolveSquaredNorm( @@ -580,8 +583,8 @@ void BasisFactorization::BumpDeterministicTimeForSolve(int num_entries) const { static_cast(num_entries) / static_cast(compact_matrix_.num_rows().value()); deterministic_time_ += - (1.0 + density) * DeterministicTimeForFpOperations( - lu_factorization_.NumberOfEntries().value()) + + density * DeterministicTimeForFpOperations( + lu_factorization_.NumberOfEntries().value()) + DeterministicTimeForFpOperations( rank_one_factorization_.num_entries().value()); } diff --git a/ortools/glop/basis_representation.h b/ortools/glop/basis_representation.h index a3dfe9fa25..c25def16ed 100644 --- a/ortools/glop/basis_representation.h +++ b/ortools/glop/basis_representation.h @@ -282,6 +282,9 @@ class BasisFactorization { double DeterministicTime() const; private: + // Called by ForceRefactorization() or Refactorize() or Initialize(). + Status ComputeFactorization(); + // Return true if the submatrix of matrix_ given by basis_ is exactly the // identity (without permutation). bool IsIdentityBasis() const; diff --git a/ortools/glop/markowitz.cc b/ortools/glop/markowitz.cc index 1263fba04e..1956677619 100644 --- a/ortools/glop/markowitz.cc +++ b/ortools/glop/markowitz.cc @@ -13,6 +13,7 @@ #include "ortools/glop/markowitz.h" +#include #include #include "absl/strings/str_format.h" @@ -72,8 +73,8 @@ Status Markowitz::ComputeRowAndColumnPermutation( // matrix becomes dense (i.e. when its density factor is above a certain // threshold). The residual size is 'end_index - index' and the // density can either be computed exactly or estimated from min_markowitz. - const int64 min_markowitz = FindPivot(*row_perm, *col_perm, &pivot_row, - &pivot_col, &pivot_coefficient); + const int64_t min_markowitz = FindPivot(*row_perm, *col_perm, &pivot_row, + &pivot_col, &pivot_coefficient); // Singular matrix? No pivot will be selected if a column has no entries. If // a column has some entries, then we are sure that a pivot will be selected @@ -295,10 +296,10 @@ const SparseColumn& Markowitz::ComputeColumn(const RowPermutation& row_perm, return *lower_column; } -int64 Markowitz::FindPivot(const RowPermutation& row_perm, - const ColumnPermutation& col_perm, - RowIndex* pivot_row, ColIndex* pivot_col, - Fractional* pivot_coefficient) { +int64_t Markowitz::FindPivot(const RowPermutation& row_perm, + const ColumnPermutation& col_perm, + RowIndex* pivot_row, ColIndex* pivot_col, + Fractional* pivot_coefficient) { SCOPED_TIME_STAT(&stats_); // Fast track for singleton columns. @@ -380,7 +381,7 @@ int64 Markowitz::FindPivot(const RowPermutation& row_perm, // Note(user): we use int64 since this is a product of two ints, moreover // the ints should be relatively small, so that should be fine for a while. - int64 min_markowitz_number = std::numeric_limits::max(); + int64_t min_markowitz_number = std::numeric_limits::max(); examined_col_.clear(); const int num_columns_to_examine = parameters_.markowitz_zlatev_parameter(); const Fractional threshold = parameters_.lu_factorization_pivot_threshold(); @@ -400,7 +401,7 @@ int64 Markowitz::FindPivot(const RowPermutation& row_perm, // to eventually have a better pivot. // // Todo(user): keep the minimum row degree to have a better bound? - const int64 markowitz_lower_bound = col_degree - 1; + const int64_t markowitz_lower_bound = col_degree - 1; if (min_markowitz_number < markowitz_lower_bound) break; // TODO(user): col_degree (which is the same as column.num_entries()) is @@ -427,7 +428,7 @@ int64 Markowitz::FindPivot(const RowPermutation& row_perm, if (magnitude < skip_threshold) continue; const int row_degree = residual_matrix_non_zero_.RowDegree(e.row()); - const int64 markowitz_number = (col_degree - 1) * (row_degree - 1); + const int64_t markowitz_number = (col_degree - 1) * (row_degree - 1); DCHECK_NE(markowitz_number, 0); if (markowitz_number < min_markowitz_number || ((markowitz_number == min_markowitz_number) && @@ -596,7 +597,7 @@ void MatrixNonZeroPattern::InitializeFromMatrixSubset( // Initialize row_non_zero_. for (ColIndex col(0); col < num_cols; ++col) { if (col_perm[col] != kInvalidCol) continue; - int32 col_degree = 0; + int32_t col_degree = 0; for (const SparseColumn::Entry e : basis_matrix.column(col)) { const RowIndex row = e.row(); if (row_perm[row] == kInvalidRow) { @@ -615,11 +616,11 @@ void MatrixNonZeroPattern::AddEntry(RowIndex row, ColIndex col) { row_non_zero_[row].push_back(col); } -int32 MatrixNonZeroPattern::DecreaseColDegree(ColIndex col) { +int32_t MatrixNonZeroPattern::DecreaseColDegree(ColIndex col) { return --col_degree_[col]; } -int32 MatrixNonZeroPattern::DecreaseRowDegree(RowIndex row) { +int32_t MatrixNonZeroPattern::DecreaseRowDegree(RowIndex row) { return --row_degree_[row]; } @@ -804,12 +805,12 @@ void ColumnPriorityQueue::Reset(int max_degree, ColIndex num_cols) { min_degree_ = num_cols.value(); } -void ColumnPriorityQueue::PushOrAdjust(ColIndex col, int32 degree) { +void ColumnPriorityQueue::PushOrAdjust(ColIndex col, int32_t degree) { DCHECK_GE(degree, 0); DCHECK_LT(degree, col_by_degree_.size()); - const int32 old_degree = col_degree_[col]; + const int32_t old_degree = col_degree_[col]; if (degree != old_degree) { - const int32 old_index = col_index_[col]; + const int32_t old_index = col_index_[col]; if (old_index != -1) { col_by_degree_[old_degree][old_index] = col_by_degree_[old_degree].back(); col_index_[col_by_degree_[old_degree].back()] = old_index; diff --git a/ortools/glop/markowitz.h b/ortools/glop/markowitz.h index 08fa51ddcc..e8eb643f39 100644 --- a/ortools/glop/markowitz.h +++ b/ortools/glop/markowitz.h @@ -73,6 +73,7 @@ #ifndef OR_TOOLS_GLOP_MARKOWITZ_H_ #define OR_TOOLS_GLOP_MARKOWITZ_H_ +#include #include #include "absl/container/inlined_vector.h" @@ -125,8 +126,8 @@ class MatrixNonZeroPattern { // Decreases the degree of a row/column. This is the basic operation used to // keep the correct degree after a call to DeleteRowAndColumn(). This is // because row_non_zero_[row] is only lazily cleaned. - int32 DecreaseRowDegree(RowIndex row); - int32 DecreaseColDegree(ColIndex col); + int32_t DecreaseRowDegree(RowIndex row); + int32_t DecreaseColDegree(ColIndex col); // Returns true if the column has been deleted by DeleteRowAndColumn(). bool IsColumnDeleted(ColIndex col) const; @@ -152,14 +153,14 @@ class MatrixNonZeroPattern { // Returns the degree (i.e. the number of non-zeros) of the given column. // This is only valid for the column indices still in the residual matrix. - int32 ColDegree(ColIndex col) const { + int32_t ColDegree(ColIndex col) const { DCHECK(!deleted_columns_[col]); return col_degree_[col]; } // Returns the degree (i.e. the number of non-zeros) of the given row. // This is only valid for the row indices still in the residual matrix. - int32 RowDegree(RowIndex row) const { return row_degree_[row]; } + int32_t RowDegree(RowIndex row) const { return row_degree_[row]; } // Returns the set of non-zeros of the given row (unsorted). // Call RemoveDeletedColumnsFromRow(row) to clean the row first. @@ -188,8 +189,8 @@ class MatrixNonZeroPattern { // TODO(user): We could be even more efficient since a size of int32 is enough // for us and we could store in common the inlined/not-inlined size. absl::StrongVector> row_non_zero_; - StrictITIVector row_degree_; - StrictITIVector col_degree_; + StrictITIVector row_degree_; + StrictITIVector col_degree_; DenseBooleanRow deleted_columns_; DenseBooleanRow bool_scratchpad_; std::vector col_scratchpad_; @@ -210,22 +211,22 @@ class ColumnPriorityQueue { // Clears the queue and prepares it to store up to num_cols column indices // with a degree from 1 to max_degree included. - void Reset(int32 max_degree, ColIndex num_cols); + void Reset(int32_t max_degree, ColIndex num_cols); // Changes the degree of a column and make sure it is in the queue. The degree // must be non-negative (>= 0) and at most equal to the value of num_cols used // in Reset(). A degree of zero will remove the column from the queue. - void PushOrAdjust(ColIndex col, int32 degree); + void PushOrAdjust(ColIndex col, int32_t degree); // Removes the column index with higher priority from the queue and returns // it. Returns kInvalidCol if the queue is empty. ColIndex Pop(); private: - StrictITIVector col_index_; - StrictITIVector col_degree_; + StrictITIVector col_index_; + StrictITIVector col_degree_; std::vector> col_by_degree_; - int32 min_degree_; + int32_t min_degree_; DISALLOW_COPY_AND_ASSIGN(ColumnPriorityQueue); }; @@ -373,9 +374,9 @@ class Markowitz { // Amongst the pivots with a minimum Markowitz number, we choose the one // with highest magnitude. This doesn't apply to pivots with a 0 Markowitz // number because all such pivots will have to be taken at some point anyway. - int64 FindPivot(const RowPermutation& row_perm, - const ColumnPermutation& col_perm, RowIndex* pivot_row, - ColIndex* pivot_col, Fractional* pivot_coefficient); + int64_t FindPivot(const RowPermutation& row_perm, + const ColumnPermutation& col_perm, RowIndex* pivot_row, + ColIndex* pivot_col, Fractional* pivot_coefficient); // Updates the degree of a given column in the internal structure of the // class. diff --git a/ortools/glop/preprocessor.cc b/ortools/glop/preprocessor.cc index e06f6f51f9..7941a939e4 100644 --- a/ortools/glop/preprocessor.cc +++ b/ortools/glop/preprocessor.cc @@ -13,6 +13,7 @@ #include "ortools/glop/preprocessor.h" +#include #include #include "absl/strings/str_format.h" @@ -158,9 +159,9 @@ void MainLpPreprocessor::RunAndPushIfRelevant( lp->num_variables().value(), (lp->num_variables() - initial_num_cols_).value(), // static_cast is needed because the Android port uses int32. - static_cast(new_num_entries.value()), - static_cast(new_num_entries.value() - - initial_num_entries_.value())); + static_cast(new_num_entries.value()), + static_cast(new_num_entries.value() - + initial_num_entries_.value())); } status_ = preprocessor->status(); preprocessors_.push_back(std::move(preprocessor)); diff --git a/ortools/glop/primal_edge_norms.h b/ortools/glop/primal_edge_norms.h index 51e4cc4f8f..c0374d7511 100644 --- a/ortools/glop/primal_edge_norms.h +++ b/ortools/glop/primal_edge_norms.h @@ -14,6 +14,8 @@ #ifndef OR_TOOLS_GLOP_PRIMAL_EDGE_NORMS_H_ #define OR_TOOLS_GLOP_PRIMAL_EDGE_NORMS_H_ +#include + #include "ortools/glop/basis_representation.h" #include "ortools/glop/parameters.pb.h" #include "ortools/glop/update_row.h" @@ -197,7 +199,7 @@ class PrimalEdgeNorms { ScatteredRow direction_left_inverse_; // Used by DeterministicTime(). - int64 num_operations_; + int64_t num_operations_; DISALLOW_COPY_AND_ASSIGN(PrimalEdgeNorms); }; diff --git a/ortools/glop/reduced_costs.cc b/ortools/glop/reduced_costs.cc index e163d3673c..d69a177a67 100644 --- a/ortools/glop/reduced_costs.cc +++ b/ortools/glop/reduced_costs.cc @@ -408,6 +408,8 @@ void ReducedCosts::ComputeReducedCosts() { #endif // OMP } + deterministic_time_ += + DeterministicTimeForFpOperations(matrix_.num_entries().value()); recompute_reduced_costs_ = false; are_reduced_costs_recomputed_ = true; are_reduced_costs_precise_ = basis_factorization_.IsRefactorized(); diff --git a/ortools/glop/reduced_costs.h b/ortools/glop/reduced_costs.h index 1abfbadd93..0033335a13 100644 --- a/ortools/glop/reduced_costs.h +++ b/ortools/glop/reduced_costs.h @@ -183,6 +183,9 @@ class ReducedCosts { // Visible for testing. const DenseRow& GetCostPerturbations() const { return cost_perturbations_; } + // The deterministic time used by this class. + double DeterministicTime() const { return deterministic_time_; } + private: // Statistics about this class. struct Stats : public StatsGroup { @@ -284,6 +287,8 @@ class ReducedCosts { // Indicates if the dual-infeasible positions are maintained or not. bool are_dual_infeasible_positions_maintained_; + double deterministic_time_ = 0.0; + DISALLOW_COPY_AND_ASSIGN(ReducedCosts); }; diff --git a/ortools/glop/revised_simplex.cc b/ortools/glop/revised_simplex.cc index f544a451a2..fdfe1a6d75 100644 --- a/ortools/glop/revised_simplex.cc +++ b/ortools/glop/revised_simplex.cc @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -73,7 +74,7 @@ class Cleanup { DCHECK_GT(num_rows_, row); \ } -constexpr const uint64 kDeterministicSeed = 42; +constexpr const uint64_t kDeterministicSeed = 42; RevisedSimplex::RevisedSimplex() : problem_status_(ProblemStatus::INIT), @@ -81,14 +82,12 @@ RevisedSimplex::RevisedSimplex() num_cols_(0), first_slack_col_(0), objective_(), - lower_bound_(), - upper_bound_(), basis_(), variable_name_(), direction_(), error_(), basis_factorization_(&compact_matrix_, &basis_), - variables_info_(compact_matrix_, lower_bound_, upper_bound_), + variables_info_(compact_matrix_), variable_values_(parameters_, compact_matrix_, basis_, variables_info_, basis_factorization_), dual_edge_norms_(basis_factorization_), @@ -402,10 +401,11 @@ Status RevisedSimplex::Solve(const LinearProgram& lp, TimeLimit* time_limit) { } // Store the result for the solution getters. - SaveState(); solution_objective_value_ = ComputeInitialProblemObjectiveValue(); solution_dual_values_ = reduced_costs_.GetDualValues(); solution_reduced_costs_ = reduced_costs_.GetReducedCosts(); + SaveState(); + if (lp.IsMaximizationProblem()) { ChangeSign(&solution_dual_values_); ChangeSign(&solution_reduced_costs_); @@ -438,7 +438,9 @@ Fractional RevisedSimplex::GetObjectiveValue() const { return solution_objective_value_; } -int64 RevisedSimplex::GetNumberOfIterations() const { return num_iterations_; } +int64_t RevisedSimplex::GetNumberOfIterations() const { + return num_iterations_; +} RowIndex RevisedSimplex::GetProblemNumRows() const { return num_rows_; } @@ -523,10 +525,10 @@ std::string RevisedSimplex::GetPrettySolverStats() const { } double RevisedSimplex::DeterministicTime() const { - // TODO(user): Also take into account the dual edge norms and the reduced cost - // updates. - return basis_factorization_.DeterministicTime() + - update_row_.DeterministicTime() + + // TODO(user): Count what is missing. + return DeterministicTimeForFpOperations(num_update_price_operations_) + + basis_factorization_.DeterministicTime() + + update_row_.DeterministicTime() + reduced_costs_.DeterministicTime() + primal_edge_norms_.DeterministicTime(); } @@ -542,24 +544,6 @@ void RevisedSimplex::SetVariableNames() { } } -VariableStatus RevisedSimplex::ComputeDefaultVariableStatus( - ColIndex col) const { - DCHECK_COL_BOUNDS(col); - if (lower_bound_[col] == upper_bound_[col]) { - return VariableStatus::FIXED_VALUE; - } - if (lower_bound_[col] == -kInfinity && upper_bound_[col] == kInfinity) { - return VariableStatus::FREE; - } - - // Returns the bound with the lowest magnitude. Note that it must be finite - // because the VariableStatus::FREE case was tested earlier. - DCHECK(IsFinite(lower_bound_[col]) || IsFinite(upper_bound_[col])); - return std::abs(lower_bound_[col]) <= std::abs(upper_bound_[col]) - ? VariableStatus::AT_LOWER_BOUND - : VariableStatus::AT_UPPER_BOUND; -} - void RevisedSimplex::SetNonBasicVariableStatusAndDeriveValue( ColIndex col, VariableStatus status) { variables_info_.UpdateToNonBasicStatus(col, status); @@ -609,13 +593,13 @@ void RevisedSimplex::UpdateBasis(ColIndex entering_col, RowIndex basis_row, // Make leaving_col leave the basis and update relevant data. // Note thate the leaving variable value is not necessarily at its exact // bound, which is like a bound shift. - variables_info_.Update(leaving_col, leaving_variable_status); + variables_info_.UpdateToNonBasicStatus(leaving_col, leaving_variable_status); DCHECK(leaving_variable_status == VariableStatus::AT_UPPER_BOUND || leaving_variable_status == VariableStatus::AT_LOWER_BOUND || leaving_variable_status == VariableStatus::FIXED_VALUE); basis_[basis_row] = entering_col; - variables_info_.Update(entering_col, VariableStatus::BASIC); + variables_info_.UpdateToBasicStatus(entering_col); update_row_.Invalidate(); } @@ -638,7 +622,7 @@ class ColumnComparator { // To understand better what is going on in this function, let us say that this // algorithm will produce the optimal solution to a problem containing only // singleton columns (provided that the variables start at the minimum possible -// cost, see ComputeDefaultVariableStatus()). This is unit tested. +// cost, see DefaultVariableStatus()). This is unit tested. // // The error_ must be equal to the constraint activity for the current variable // values before this function is called. If error_[row] is 0.0, that mean this @@ -652,11 +636,13 @@ void RevisedSimplex::UseSingletonColumnInInitialBasis(RowToColMapping* basis) { // Note that the slack columns will be treated as normal singleton columns. std::vector singleton_column; DenseRow cost_variation(num_cols_, 0.0); + const DenseRow& lower_bounds = variables_info_.GetVariableLowerBounds(); + const DenseRow& upper_bounds = variables_info_.GetVariableUpperBounds(); for (ColIndex col(0); col < num_cols_; ++col) { if (compact_matrix_.column(col).num_entries() != 1) continue; - if (lower_bound_[col] == upper_bound_[col]) continue; + if (lower_bounds[col] == upper_bounds[col]) continue; const Fractional slope = compact_matrix_.column(col).GetFirstCoefficient(); - if (variable_values_.Get(col) == lower_bound_[col]) { + if (variable_values_.Get(col) == lower_bounds[col]) { cost_variation[col] = objective_[col] / std::abs(slope); } else { cost_variation[col] = -objective_[col] / std::abs(slope); @@ -701,7 +687,7 @@ void RevisedSimplex::UseSingletonColumnInInitialBasis(RowToColMapping* basis) { const Fractional coeff = compact_matrix_.column(col).EntryCoefficient(EntryIndex(0)); const Fractional new_value = variable_values[col] + error_[row] / coeff; - if (new_value >= lower_bound_[col] && new_value <= upper_bound_[col]) { + if (new_value >= lower_bounds[col] && new_value <= upper_bounds[col]) { error_[row] = 0.0; // Use this variable in the initial basis. @@ -716,14 +702,14 @@ void RevisedSimplex::UseSingletonColumnInInitialBasis(RowToColMapping* basis) { DCHECK_NE(box_width, 0.0); DCHECK_NE(error_[row], 0.0); const Fractional error_sign = error_[row] / coeff; - if (variable_values[col] == lower_bound_[col] && error_sign > 0.0) { + if (variable_values[col] == lower_bounds[col] && error_sign > 0.0) { DCHECK(IsFinite(box_width)); error_[row] -= coeff * box_width; SetNonBasicVariableStatusAndDeriveValue(col, VariableStatus::AT_UPPER_BOUND); continue; } - if (variable_values[col] == upper_bound_[col] && error_sign < 0.0) { + if (variable_values[col] == upper_bounds[col] && error_sign < 0.0) { DCHECK(IsFinite(box_width)); error_[row] += coeff * box_width; SetNonBasicVariableStatusAndDeriveValue(col, @@ -799,9 +785,11 @@ bool RevisedSimplex::OldBoundsAreUnchangedAndNewVariablesHaveOneBoundAtZero( const ColIndex first_new_col(first_slack_col_ - num_new_cols); // Check the original variable bounds. + const DenseRow& lower_bounds = variables_info_.GetVariableLowerBounds(); + const DenseRow& upper_bounds = variables_info_.GetVariableUpperBounds(); for (ColIndex col(0); col < first_new_col; ++col) { - if (lower_bound_[col] != lp.variable_lower_bounds()[col] || - upper_bound_[col] != lp.variable_upper_bounds()[col]) { + if (lower_bounds[col] != lp.variable_lower_bounds()[col] || + upper_bounds[col] != lp.variable_upper_bounds()[col]) { return false; } } @@ -814,37 +802,14 @@ bool RevisedSimplex::OldBoundsAreUnchangedAndNewVariablesHaveOneBoundAtZero( } // Check that the slack bounds are unchanged. for (ColIndex col(first_slack_col_); col < num_cols_; ++col) { - if (lower_bound_[col - num_new_cols] != lp.variable_lower_bounds()[col] || - upper_bound_[col - num_new_cols] != lp.variable_upper_bounds()[col]) { + if (lower_bounds[col - num_new_cols] != lp.variable_lower_bounds()[col] || + upper_bounds[col - num_new_cols] != lp.variable_upper_bounds()[col]) { return false; } } return true; } -bool RevisedSimplex::InitializeBoundsAndTestIfUnchanged( - const LinearProgram& lp) { - SCOPED_TIME_STAT(&function_stats_); - lower_bound_.resize(num_cols_, 0.0); - upper_bound_.resize(num_cols_, 0.0); - - // Variable bounds, for both non-slack and slack variables. - bool bounds_are_unchanged = true; - DCHECK_EQ(lp.num_variables(), num_cols_); - for (ColIndex col(0); col < lp.num_variables(); ++col) { - if (lower_bound_[col] != lp.variable_lower_bounds()[col] || - upper_bound_[col] != lp.variable_upper_bounds()[col]) { - bounds_are_unchanged = false; - break; - } - } - if (!bounds_are_unchanged) { - lower_bound_ = lp.variable_lower_bounds(); - upper_bound_ = lp.variable_upper_bounds(); - } - return bounds_are_unchanged; -} - bool RevisedSimplex::InitializeObjectiveAndTestIfUnchanged( const LinearProgram& lp) { SCOPED_TIME_STAT(&function_stats_); @@ -911,58 +876,6 @@ void RevisedSimplex::InitializeObjectiveLimit(const LinearProgram& lp) { } } -void RevisedSimplex::InitializeVariableStatusesForWarmStart( - const BasisState& state, ColIndex num_new_cols) { - variables_info_.InitializeAndComputeType(); - RowIndex num_basic_variables(0); - DCHECK_LE(num_new_cols, first_slack_col_); - const ColIndex first_new_col(first_slack_col_ - num_new_cols); - // Compute the status for all the columns (note that the slack variables are - // already added at the end of the matrix at this stage). - for (ColIndex col(0); col < num_cols_; ++col) { - const VariableStatus default_status = ComputeDefaultVariableStatus(col); - - // Start with the given "warm" status from the BasisState if it exists. - VariableStatus status = default_status; - if (col < first_new_col && col < state.statuses.size()) { - status = state.statuses[col]; - } else if (col >= first_slack_col_ && - col - num_new_cols < state.statuses.size()) { - status = state.statuses[col - num_new_cols]; - } - - if (status == VariableStatus::BASIC) { - // Do not allow more than num_rows_ VariableStatus::BASIC variables. - if (num_basic_variables == num_rows_) { - VLOG(1) << "Too many basic variables in the warm-start basis." - << "Only keeping the first ones as VariableStatus::BASIC."; - variables_info_.UpdateToNonBasicStatus(col, default_status); - } else { - ++num_basic_variables; - variables_info_.UpdateToBasicStatus(col); - } - } else { - // Remove incompatibilities between the warm status and the variable - // bounds. We use the default status as an indication of the bounds - // type. - if ((status != default_status) && - ((default_status == VariableStatus::FIXED_VALUE) || - (status == VariableStatus::FREE) || - (status == VariableStatus::FIXED_VALUE) || - (status == VariableStatus::AT_LOWER_BOUND && - lower_bound_[col] == -kInfinity) || - (status == VariableStatus::AT_UPPER_BOUND && - upper_bound_[col] == kInfinity))) { - status = default_status; - } - variables_info_.UpdateToNonBasicStatus(col, status); - } - } - - // Initialize the values. - variable_values_.ResetAllNonBasicVariableValues(); -} - // This implementation starts with an initial matrix B equal to the identity // matrix (modulo a column permutation). For that it uses either the slack // variables or the singleton columns present in the problem. Afterwards, the @@ -975,14 +888,17 @@ Status RevisedSimplex::CreateInitialBasis() { // Note that for the dual algorithm, boxed variables will be made // dual-feasible later by MakeBoxedVariableDualFeasible(), so it doesn't // really matter at which of their two finite bounds they start. - int num_free_variables = 0; - variables_info_.InitializeAndComputeType(); - for (ColIndex col(0); col < num_cols_; ++col) { - const VariableStatus status = ComputeDefaultVariableStatus(col); - SetNonBasicVariableStatusAndDeriveValue(col, status); - if (status == VariableStatus::FREE) ++num_free_variables; + variables_info_.InitializeToDefaultStatus(); + variable_values_.ResetAllNonBasicVariableValues(); + + if (VLOG_IS_ON(1)) { + int num_free_variables = 0; + for (const VariableStatus status : variables_info_.GetStatusRow()) { + if (status == VariableStatus::FREE) ++num_free_variables; + } + VLOG(1) << "Number of free variables in the problem: " + << num_free_variables; } - VLOG(1) << "Number of free variables in the problem: " << num_free_variables; // Start by using an all-slack basis. RowToColMapping basis(num_rows_, kInvalidCol); @@ -992,6 +908,8 @@ Status RevisedSimplex::CreateInitialBasis() { // If possible, for the primal simplex we replace some slack variables with // some singleton columns present in the problem. + const DenseRow& lower_bounds = variables_info_.GetVariableLowerBounds(); + const DenseRow& upper_bounds = variables_info_.GetVariableUpperBounds(); if (!parameters_.use_dual_simplex() && parameters_.initial_basis() != GlopParameters::MAROS && parameters_.exploit_singleton_column_in_initial_basis()) { @@ -1002,11 +920,11 @@ Status RevisedSimplex::CreateInitialBasis() { if (compact_matrix_.column(col).num_entries() != 1) continue; const VariableStatus status = variables_info_.GetStatusRow()[col]; const Fractional objective = objective_[col]; - if (objective > 0 && IsFinite(lower_bound_[col]) && + if (objective > 0 && IsFinite(lower_bounds[col]) && status == VariableStatus::AT_UPPER_BOUND) { SetNonBasicVariableStatusAndDeriveValue(col, VariableStatus::AT_LOWER_BOUND); - } else if (objective < 0 && IsFinite(upper_bound_[col]) && + } else if (objective < 0 && IsFinite(upper_bounds[col]) && status == VariableStatus::AT_LOWER_BOUND) { SetNonBasicVariableStatusAndDeriveValue(col, VariableStatus::AT_UPPER_BOUND); @@ -1039,8 +957,8 @@ Status RevisedSimplex::CreateInitialBasis() { return InitializeFirstBasis(basis); } if (parameters_.initial_basis() == GlopParameters::MAROS) { - InitialBasis initial_basis(compact_matrix_, objective_, lower_bound_, - upper_bound_, variables_info_.GetTypeRow()); + InitialBasis initial_basis(compact_matrix_, objective_, lower_bounds, + upper_bounds, variables_info_.GetTypeRow()); if (parameters_.use_dual_simplex()) { // This dual version only uses zero-cost columns to complete the // basis. @@ -1061,7 +979,7 @@ Status RevisedSimplex::CreateInitialBasis() { int num_fixed_variables = 0; for (RowIndex row(0); row < basis.size(); ++row) { const ColIndex col = basis[row]; - if (lower_bound_[col] == upper_bound_[col]) { + if (lower_bounds[col] == upper_bounds[col]) { basis[row] = kInvalidCol; ++num_fixed_variables; } @@ -1075,8 +993,8 @@ Status RevisedSimplex::CreateInitialBasis() { // Then complete the basis with an advanced initial basis algorithm. VLOG(1) << "Trying to remove " << num_fixed_variables << " fixed variables from the initial basis."; - InitialBasis initial_basis(compact_matrix_, objective_, lower_bound_, - upper_bound_, variables_info_.GetTypeRow()); + InitialBasis initial_basis(compact_matrix_, objective_, lower_bounds, + upper_bounds, variables_info_.GetTypeRow()); if (parameters_.initial_basis() == GlopParameters::BIXBY) { if (parameters_.use_scaling()) { @@ -1148,13 +1066,14 @@ Status RevisedSimplex::InitializeFirstBasis(const RowToColMapping& basis) { // Everything is okay, finish the initialization. for (RowIndex row(0); row < num_rows_; ++row) { - variables_info_.Update(basis_[row], VariableStatus::BASIC); + variables_info_.UpdateToBasicStatus(basis_[row]); } DCHECK(BasisIsConsistent()); // TODO(user): Maybe return an error status if this is too high. Note however // that if we want to do that, we need to reset variables_info_ to a // consistent state. + variable_values_.ResetAllNonBasicVariableValues(); variable_values_.RecomputeBasicVariableValues(); if (VLOG_IS_ON(1)) { const Fractional tolerance = parameters_.primal_feasibility_tolerance(); @@ -1192,8 +1111,13 @@ Status RevisedSimplex::Initialize(const LinearProgram& lp) { lp, &only_change_is_new_rows, &only_change_is_new_cols, &num_new_cols)); } notify_that_matrix_is_unchanged_ = false; + + // TODO(user): move objective with ReducedCosts class. const bool objective_is_unchanged = InitializeObjectiveAndTestIfUnchanged(lp); - const bool bounds_are_unchanged = InitializeBoundsAndTestIfUnchanged(lp); + + const bool bounds_are_unchanged = + variables_info_.LoadBoundsAndReturnTrueIfUnchanged( + lp.variable_lower_bounds(), lp.variable_upper_bounds()); // If parameters_.allow_simplex_algorithm_change() is true and we already have // a primal (resp. dual) feasible solution, then we use the primal (resp. @@ -1242,7 +1166,10 @@ Status RevisedSimplex::Initialize(const LinearProgram& lp) { reduced_costs_.ClearAndRemoveCostShifts(); solve_from_scratch = false; } else if (only_change_is_new_cols && only_new_bounds) { - InitializeVariableStatusesForWarmStart(solution_state_, num_new_cols); + variables_info_.InitializeFromBasisState(first_slack_col_, num_new_cols, + solution_state_); + variable_values_.ResetAllNonBasicVariableValues(); + const ColIndex first_new_col(first_slack_col_ - num_new_cols); for (ColIndex& col_ref : basis_) { if (col_ref >= first_new_col) { @@ -1265,15 +1192,17 @@ Status RevisedSimplex::Initialize(const LinearProgram& lp) { if (objective_is_unchanged) { if (matrix_is_unchanged) { if (!bounds_are_unchanged) { - InitializeVariableStatusesForWarmStart(solution_state_, - ColIndex(0)); + variables_info_.InitializeFromBasisState( + first_slack_col_, ColIndex(0), solution_state_); + variable_values_.ResetAllNonBasicVariableValues(); variable_values_.RecomputeBasicVariableValues(); } solve_from_scratch = false; } else if (only_change_is_new_rows) { // For the dual-simplex, we also perform a warm start if a couple of // new rows where added. - InitializeVariableStatusesForWarmStart(solution_state_, ColIndex(0)); + variables_info_.InitializeFromBasisState( + first_slack_col_, ColIndex(0), solution_state_); dual_edge_norms_.ResizeOnNewRows(num_rows_); // TODO(user): The reduced costs do not really need to be recomputed. @@ -1297,7 +1226,8 @@ Status RevisedSimplex::Initialize(const LinearProgram& lp) { if (solve_from_scratch && !solution_state_.IsEmpty()) { // If an external basis has been provided or if the matrix changed, we need // to perform more work, e.g., factorize the proposed basis and validate it. - InitializeVariableStatusesForWarmStart(solution_state_, ColIndex(0)); + variables_info_.InitializeFromBasisState(first_slack_col_, ColIndex(0), + solution_state_); basis_.assign(num_rows_, kInvalidCol); RowIndex row(0); for (ColIndex col : variables_info_.GetIsBasicBitRow()) { @@ -1350,6 +1280,8 @@ void RevisedSimplex::DisplayBasicVariableStatistics() { const DenseRow& variable_values = variable_values_.GetDenseRow(); const VariableTypeRow& variable_types = variables_info_.GetTypeRow(); + const DenseRow& lower_bounds = variables_info_.GetVariableLowerBounds(); + const DenseRow& upper_bounds = variables_info_.GetVariableUpperBounds(); const Fractional tolerance = parameters_.primal_feasibility_tolerance(); for (RowIndex row(0); row < num_rows_; ++row) { const ColIndex col = basis_[row]; @@ -1357,17 +1289,17 @@ void RevisedSimplex::DisplayBasicVariableStatistics() { if (variable_types[col] == VariableType::UNCONSTRAINED) { ++num_free_variables; } - if (value > upper_bound_[col] + tolerance || - value < lower_bound_[col] - tolerance) { + if (value > upper_bounds[col] + tolerance || + value < lower_bounds[col] - tolerance) { ++num_infeasible_variables; } if (col >= first_slack_col_) { ++num_slack_variables; } - if (lower_bound_[col] == upper_bound_[col]) { + if (lower_bounds[col] == upper_bounds[col]) { ++num_fixed_variables; - } else if (variable_values[col] == lower_bound_[col] || - variable_values[col] == upper_bound_[col]) { + } else if (variable_values[col] == lower_bounds[col] || + variable_values[col] == upper_bounds[col]) { ++num_variables_at_bound; } } @@ -1485,7 +1417,9 @@ Fractional RevisedSimplex::ComputeDirectionError(ColIndex col) { } template -Fractional RevisedSimplex::GetRatio(RowIndex row) const { +Fractional RevisedSimplex::GetRatio(const DenseRow& lower_bounds, + const DenseRow& upper_bounds, + RowIndex row) const { const ColIndex col = basis_[row]; const Fractional direction = direction_[row]; const Fractional value = variable_values_.Get(col); @@ -1493,15 +1427,15 @@ Fractional RevisedSimplex::GetRatio(RowIndex row) const { DCHECK_NE(direction, 0.0); if (is_entering_reduced_cost_positive) { if (direction > 0.0) { - return (upper_bound_[col] - value) / direction; + return (upper_bounds[col] - value) / direction; } else { - return (lower_bound_[col] - value) / direction; + return (lower_bounds[col] - value) / direction; } } else { if (direction > 0.0) { - return (value - lower_bound_[col]) / direction; + return (value - lower_bounds[col]) / direction; } else { - return (value - upper_bound_[col]) / direction; + return (value - upper_bounds[col]) / direction; } } } @@ -1530,11 +1464,13 @@ Fractional RevisedSimplex::ComputeHarrisRatioAndLeavingCandidates( ? parameters_.minimum_acceptable_pivot() : parameters_.ratio_test_zero_threshold(); + const DenseRow& lower_bounds = variables_info_.GetVariableLowerBounds(); + const DenseRow& upper_bounds = variables_info_.GetVariableUpperBounds(); for (const auto e : direction_) { const Fractional magnitude = std::abs(e.coefficient()); if (magnitude <= threshold) continue; - const Fractional ratio = - GetRatio(e.row()); + const Fractional ratio = GetRatio( + lower_bounds, upper_bounds, e.row()); if (ratio <= harris_ratio) { leaving_candidates->SetCoefficient(e.row(), ratio); @@ -1590,6 +1526,8 @@ Status RevisedSimplex::ChooseLeavingVariableRow( // A few cases will cause the test to be recomputed from the beginning. int stats_num_leaving_choices = 0; equivalent_leaving_choices_.clear(); + const DenseRow& lower_bounds = variables_info_.GetVariableLowerBounds(); + const DenseRow& upper_bounds = variables_info_.GetVariableUpperBounds(); while (true) { stats_num_leaving_choices = 0; @@ -1597,8 +1535,8 @@ Status RevisedSimplex::ChooseLeavingVariableRow( // can take (bound-flip). Note that we do not use tolerance here. const Fractional entering_value = variable_values_.Get(entering_col); Fractional current_ratio = - (reduced_cost > 0.0) ? entering_value - lower_bound_[entering_col] - : upper_bound_[entering_col] - entering_value; + (reduced_cost > 0.0) ? entering_value - lower_bounds[entering_col] + : upper_bounds[entering_col] - entering_value; DCHECK_GT(current_ratio, 0.0); // First pass of the Harris ratio test. If 'harris_tolerance' is zero, this @@ -1733,8 +1671,8 @@ Status RevisedSimplex::ChooseLeavingVariableRow( const bool is_reduced_cost_positive = (reduced_cost > 0.0); const bool is_leaving_coeff_positive = (direction_[*leaving_row] > 0.0); *target_bound = (is_reduced_cost_positive == is_leaving_coeff_positive) - ? upper_bound_[basis_[*leaving_row]] - : lower_bound_[basis_[*leaving_row]]; + ? upper_bounds[basis_[*leaving_row]] + : lower_bounds[basis_[*leaving_row]]; } // Stats. @@ -1795,13 +1733,15 @@ void RevisedSimplex::PrimalPhaseIChooseLeavingVariableRow( RETURN_IF_NULL(step_length); DCHECK_COL_BOUNDS(entering_col); DCHECK_NE(0.0, reduced_cost); + const DenseRow& lower_bounds = variables_info_.GetVariableLowerBounds(); + const DenseRow& upper_bounds = variables_info_.GetVariableUpperBounds(); // We initialize current_ratio with the maximum step the entering variable // can take (bound-flip). Note that we do not use tolerance here. const Fractional entering_value = variable_values_.Get(entering_col); Fractional current_ratio = (reduced_cost > 0.0) - ? entering_value - lower_bound_[entering_col] - : upper_bound_[entering_col] - entering_value; + ? entering_value - lower_bounds[entering_col] + : upper_bounds[entering_col] - entering_value; DCHECK_GT(current_ratio, 0.0); std::vector breakpoints; @@ -1829,8 +1769,8 @@ void RevisedSimplex::PrimalPhaseIChooseLeavingVariableRow( DCHECK(variables_info_.GetIsBasicBitRow().IsSet(col)); const Fractional value = variable_values_.Get(col); - const Fractional lower_bound = lower_bound_[col]; - const Fractional upper_bound = upper_bound_[col]; + const Fractional lower_bound = lower_bounds[col]; + const Fractional upper_bound = upper_bounds[col]; const Fractional to_lower = (lower_bound - tolerance - value) / direction; const Fractional to_upper = (upper_bound + tolerance - value) / direction; @@ -1897,6 +1837,8 @@ Status RevisedSimplex::DualChooseLeavingVariableRow(RowIndex* leaving_row, Fractional* target_bound) { GLOP_RETURN_ERROR_IF_NULL(leaving_row); GLOP_RETURN_ERROR_IF_NULL(cost_variation); + const DenseRow& lower_bounds = variables_info_.GetVariableLowerBounds(); + const DenseRow& upper_bounds = variables_info_.GetVariableUpperBounds(); // TODO(user): Reuse parameters_.optimization_rule() to decide if we use // steepest edge or the normal Dantzig pricing. @@ -1935,13 +1877,13 @@ Status RevisedSimplex::DualChooseLeavingVariableRow(RowIndex* leaving_row, if (*leaving_row == kInvalidRow) return Status::OK(); const ColIndex leaving_col = basis_[*leaving_row]; const Fractional value = variable_values_.Get(leaving_col); - if (value < lower_bound_[leaving_col]) { - *cost_variation = lower_bound_[leaving_col] - value; - *target_bound = lower_bound_[leaving_col]; + if (value < lower_bounds[leaving_col]) { + *cost_variation = lower_bounds[leaving_col] - value; + *target_bound = lower_bounds[leaving_col]; DCHECK_GT(*cost_variation, 0.0); } else { - *cost_variation = upper_bound_[leaving_col] - value; - *target_bound = upper_bound_[leaving_col]; + *cost_variation = upper_bounds[leaving_col] - value; + *target_bound = upper_bounds[leaving_col]; DCHECK_LT(*cost_variation, 0.0); } return Status::OK(); @@ -2029,6 +1971,10 @@ void RevisedSimplex::DualPhaseIUpdatePriceOnReducedCostChange( initially_all_zero_scratchpad_.non_zeros.clear(); something_to_do = true; } + + // We add a factor 10 because of the scattered access. + num_update_price_operations_ += + 10 * compact_matrix_.column(col).num_entries().value(); compact_matrix_.ColumnAddMultipleToSparseScatteredColumn( col, sign - dual_infeasibility_improvement_direction_[col], &initially_all_zero_scratchpad_); @@ -2072,6 +2018,8 @@ Status RevisedSimplex::DualPhaseIChooseLeavingVariableRow( SCOPED_TIME_STAT(&function_stats_); GLOP_RETURN_ERROR_IF_NULL(leaving_row); GLOP_RETURN_ERROR_IF_NULL(cost_variation); + const DenseRow& lower_bounds = variables_info_.GetVariableLowerBounds(); + const DenseRow& upper_bounds = variables_info_.GetVariableUpperBounds(); // dual_infeasibility_improvement_direction_ is zero for dual-feasible // positions and contains the sign in which the reduced cost of this column @@ -2139,9 +2087,9 @@ Status RevisedSimplex::DualPhaseIChooseLeavingVariableRow( *cost_variation = dual_pricing_vector_[*leaving_row]; const ColIndex leaving_col = basis_[*leaving_row]; if (*cost_variation < 0.0) { - *target_bound = upper_bound_[leaving_col]; + *target_bound = upper_bounds[leaving_col]; } else { - *target_bound = lower_bound_[leaving_col]; + *target_bound = lower_bounds[leaving_col]; } DCHECK(IsFinite(*target_bound)); return Status::OK(); @@ -2159,6 +2107,8 @@ void RevisedSimplex::MakeBoxedVariableDualFeasible( // test). const DenseRow& variable_values = variable_values_.GetDenseRow(); const DenseRow& reduced_costs = reduced_costs_.GetReducedCosts(); + const DenseRow& lower_bounds = variables_info_.GetVariableLowerBounds(); + const DenseRow& upper_bounds = variables_info_.GetVariableUpperBounds(); const Fractional dual_feasibility_tolerance = reduced_costs_.GetDualFeasibilityTolerance(); const VariableStatusRow& variable_status = variables_info_.GetStatusRow(); @@ -2168,16 +2118,18 @@ void RevisedSimplex::MakeBoxedVariableDualFeasible( DCHECK(variables_info_.GetTypeRow()[col] == VariableType::UPPER_AND_LOWER_BOUNDED); // TODO(user): refactor this as DCHECK(IsVariableBasicOrExactlyAtBound())? - DCHECK(variable_values[col] == lower_bound_[col] || - variable_values[col] == upper_bound_[col] || + DCHECK(variable_values[col] == lower_bounds[col] || + variable_values[col] == upper_bounds[col] || status == VariableStatus::BASIC); if (reduced_cost > dual_feasibility_tolerance && status == VariableStatus::AT_UPPER_BOUND) { - variables_info_.Update(col, VariableStatus::AT_LOWER_BOUND); + variables_info_.UpdateToNonBasicStatus(col, + VariableStatus::AT_LOWER_BOUND); changed_cols.push_back(col); } else if (reduced_cost < -dual_feasibility_tolerance && status == VariableStatus::AT_LOWER_BOUND) { - variables_info_.Update(col, VariableStatus::AT_UPPER_BOUND); + variables_info_.UpdateToNonBasicStatus(col, + VariableStatus::AT_UPPER_BOUND); changed_cols.push_back(col); } } @@ -2258,11 +2210,13 @@ Status RevisedSimplex::UpdateAndPivot(ColIndex entering_col, RowIndex leaving_row, Fractional target_bound) { SCOPED_TIME_STAT(&function_stats_); + const DenseRow& lower_bounds = variables_info_.GetVariableLowerBounds(); + const DenseRow& upper_bounds = variables_info_.GetVariableUpperBounds(); const ColIndex leaving_col = basis_[leaving_row]; const VariableStatus leaving_variable_status = - lower_bound_[leaving_col] == upper_bound_[leaving_col] + lower_bounds[leaving_col] == upper_bounds[leaving_col] ? VariableStatus::FIXED_VALUE - : target_bound == lower_bound_[leaving_col] + : target_bound == lower_bounds[leaving_col] ? VariableStatus::AT_LOWER_BOUND : VariableStatus::AT_UPPER_BOUND; if (variable_values_.Get(leaving_col) != target_bound) { @@ -3107,13 +3061,15 @@ std::string RevisedSimplex::SimpleVariableInfo(ColIndex col) const { std::string output; VariableType variable_type = variables_info_.GetTypeRow()[col]; VariableStatus variable_status = variables_info_.GetStatusRow()[col]; + const DenseRow& lower_bounds = variables_info_.GetVariableLowerBounds(); + const DenseRow& upper_bounds = variables_info_.GetVariableUpperBounds(); absl::StrAppendFormat(&output, "%d (%s) = %s, %s, %s, [%s,%s]", col.value(), variable_name_[col], StringifyWithFlags(variable_values_.Get(col)), GetVariableStatusString(variable_status), GetVariableTypeString(variable_type), - StringifyWithFlags(lower_bound_[col]), - StringifyWithFlags(upper_bound_[col])); + StringifyWithFlags(lower_bounds[col]), + StringifyWithFlags(upper_bounds[col])); return output; } @@ -3136,26 +3092,28 @@ void RevisedSimplex::DisplayInfoOnVariables() const { void RevisedSimplex::DisplayVariableBounds() { if (VLOG_IS_ON(3)) { const VariableTypeRow& variable_type = variables_info_.GetTypeRow(); + const DenseRow& lower_bounds = variables_info_.GetVariableLowerBounds(); + const DenseRow& upper_bounds = variables_info_.GetVariableUpperBounds(); for (ColIndex col(0); col < num_cols_; ++col) { switch (variable_type[col]) { case VariableType::UNCONSTRAINED: break; case VariableType::LOWER_BOUNDED: VLOG(3) << variable_name_[col] - << " >= " << StringifyWithFlags(lower_bound_[col]) << ";"; + << " >= " << StringifyWithFlags(lower_bounds[col]) << ";"; break; case VariableType::UPPER_BOUNDED: VLOG(3) << variable_name_[col] - << " <= " << StringifyWithFlags(upper_bound_[col]) << ";"; + << " <= " << StringifyWithFlags(upper_bounds[col]) << ";"; break; case VariableType::UPPER_AND_LOWER_BOUNDED: - VLOG(3) << StringifyWithFlags(lower_bound_[col]) + VLOG(3) << StringifyWithFlags(lower_bounds[col]) << " <= " << variable_name_[col] - << " <= " << StringifyWithFlags(upper_bound_[col]) << ";"; + << " <= " << StringifyWithFlags(upper_bounds[col]) << ";"; break; case VariableType::FIXED_VARIABLE: VLOG(3) << variable_name_[col] << " = " - << StringifyWithFlags(lower_bound_[col]) << ";"; + << StringifyWithFlags(lower_bounds[col]) << ";"; break; default: // This should never happen. LOG(DFATAL) << "Column " << col << " has no meaningful status."; diff --git a/ortools/glop/revised_simplex.h b/ortools/glop/revised_simplex.h index be100e9755..d28bd4e95c 100644 --- a/ortools/glop/revised_simplex.h +++ b/ortools/glop/revised_simplex.h @@ -91,6 +91,7 @@ #ifndef OR_TOOLS_GLOP_REVISED_SIMPLEX_H_ #define OR_TOOLS_GLOP_REVISED_SIMPLEX_H_ +#include #include #include @@ -117,32 +118,6 @@ namespace operations_research { namespace glop { -// Holds the statuses of all the variables, including slack variables. There -// is no point storing constraint statuses since internally all constraints are -// always fixed to zero. -// -// Note that this is the minimal amount of information needed to perform a "warm -// start". Using this information and the original linear program, the basis can -// be refactorized and all the needed quantities derived. -// -// TODO(user): Introduce another state class to store a complete state of the -// solver. Using this state and the original linear program, the solver can be -// restarted with as little time overhead as possible. This is especially useful -// for strong branching in a MIP context. -struct BasisState { - // TODO(user): A MIP solver will potentially store a lot of BasicStates so - // memory usage is important. It is possible to use only 2 bits for one - // VariableStatus enum. To achieve this, the FIXED_VALUE status can be - // converted to either AT_LOWER_BOUND or AT_UPPER_BOUND and decoded properly - // later since this will be used with a given linear program. This way we can - // even encode more information by using the reduced cost sign to choose to - // which bound the fixed status correspond. - VariableStatusRow statuses; - - // Returns true if this state is empty. - bool IsEmpty() const { return statuses.empty(); } -}; - // Entry point of the revised simplex algorithm implementation. class RevisedSimplex { public: @@ -187,7 +162,7 @@ class RevisedSimplex { ColIndex GetProblemNumCols() const; ProblemStatus GetProblemStatus() const; Fractional GetObjectiveValue() const; - int64 GetNumberOfIterations() const; + int64_t GetNumberOfIterations() const; Fractional GetVariableValue(ColIndex col) const; Fractional GetReducedCost(ColIndex col) const; const DenseRow& GetReducedCosts() const; @@ -320,10 +295,6 @@ class RevisedSimplex { // x1..., slack variables will be s1... . void SetVariableNames(); - // Computes the initial variable status from its type. A constrained variable - // is set to the lowest of its 2 bounds in absolute value. - VariableStatus ComputeDefaultVariableStatus(ColIndex col) const; - // Sets the variable status and derives the variable value according to the // exact status definition. This can only be called for non-basic variables // because the value of a basic variable is computed from the values of the @@ -354,9 +325,6 @@ class RevisedSimplex { bool* only_change_is_new_cols, ColIndex* num_new_cols); - // Initializes bound-related internal data. Returns true if unchanged. - bool InitializeBoundsAndTestIfUnchanged(const LinearProgram& lp); - // Checks if the only change to the bounds is the addition of new columns, // and that the new columns have at least one bound equal to zero. bool OldBoundsAreUnchangedAndNewVariablesHaveOneBoundAtZero( @@ -368,10 +336,6 @@ class RevisedSimplex { // Computes the stopping criterion on the problem objective value. void InitializeObjectiveLimit(const LinearProgram& lp); - // Initializes the variable statuses using a warm-start basis. - void InitializeVariableStatusesForWarmStart(const BasisState& state, - ColIndex num_new_cols); - // Initializes the starting basis. In most cases it starts by the all slack // basis and tries to apply some heuristics to replace fixed variables. ABSL_MUST_USE_RESULT Status CreateInitialBasis(); @@ -432,7 +396,8 @@ class RevisedSimplex { // that adding 'ratio * d_[row]' to the variable value changes it to its // target bound. template - Fractional GetRatio(RowIndex row) const; + Fractional GetRatio(const DenseRow& lower_bounds, + const DenseRow& upper_bounds, RowIndex row) const; // First pass of the Harris ratio test. Returns the harris ratio value which // is an upper bound on the ratio value that the leaving variable can take. @@ -623,10 +588,6 @@ class RevisedSimplex { Fractional objective_offset_; Fractional objective_scaling_factor_; - // Array of values representing variable bounds. Indexed by column number. - DenseRow lower_bound_; - DenseRow upper_bound_; - // Used in dual phase I to keep track of the non-basic dual infeasible // columns and their sign of infeasibility (+1 or -1). DenseRow dual_infeasibility_improvement_direction_; @@ -692,13 +653,16 @@ class RevisedSimplex { std::vector> pair_to_ignore_; // Total number of iterations performed. - uint64 num_iterations_; + uint64_t num_iterations_; // Number of iterations performed during the first (feasibility) phase. - uint64 num_feasibility_iterations_; + uint64_t num_feasibility_iterations_; // Number of iterations performed during the second (optimization) phase. - uint64 num_optimization_iterations_; + uint64_t num_optimization_iterations_; + + // Deterministic time for DualPhaseIUpdatePriceOnReducedCostChange(). + int64 num_update_price_operations_ = 0; // Total time spent in Solve(). double total_time_; diff --git a/ortools/glop/update_row.h b/ortools/glop/update_row.h index 6a09d6409e..b4849c44b6 100644 --- a/ortools/glop/update_row.h +++ b/ortools/glop/update_row.h @@ -14,6 +14,8 @@ #ifndef OR_TOOLS_GLOP_UPDATE_ROW_H_ #define OR_TOOLS_GLOP_UPDATE_ROW_H_ +#include + #include "ortools/glop/basis_representation.h" #include "ortools/glop/parameters.pb.h" #include "ortools/glop/variables_info.h" @@ -147,7 +149,7 @@ class UpdateRow { // Track the number of basic floating point multiplication. // Used by DeterministicTime(). - int64 num_operations_; + int64_t num_operations_; // Glop standard classes. GlopParameters parameters_; diff --git a/ortools/glop/variables_info.cc b/ortools/glop/variables_info.cc index bbe725804b..076d7bafbb 100644 --- a/ortools/glop/variables_info.cc +++ b/ortools/glop/variables_info.cc @@ -16,33 +16,140 @@ namespace operations_research { namespace glop { -VariablesInfo::VariablesInfo(const CompactSparseMatrix& matrix, - const DenseRow& lower_bound, - const DenseRow& upper_bound) - : matrix_(matrix), - lower_bound_(lower_bound), - upper_bound_(upper_bound), - boxed_variables_are_relevant_(true) {} +VariablesInfo::VariablesInfo(const CompactSparseMatrix& matrix) + : matrix_(matrix) {} -void VariablesInfo::InitializeAndComputeType() { +bool VariablesInfo::LoadBoundsAndReturnTrueIfUnchanged( + const DenseRow& new_lower_bounds, const DenseRow& new_upper_bounds) { const ColIndex num_cols = matrix_.num_cols(); + DCHECK_EQ(num_cols, new_lower_bounds.size()); + DCHECK_EQ(num_cols, new_upper_bounds.size()); + + // Optim if nothing changed. + if (lower_bounds_ == new_lower_bounds && upper_bounds_ == new_upper_bounds) { + return true; + } + + lower_bounds_ = new_lower_bounds; + upper_bounds_ = new_upper_bounds; + variable_type_.resize(num_cols, VariableType::UNCONSTRAINED); + for (ColIndex col(0); col < num_cols; ++col) { + variable_type_[col] = ComputeVariableType(col); + } + return false; +} + +void VariablesInfo::ResetStatusInfo() { + const ColIndex num_cols = matrix_.num_cols(); + DCHECK_EQ(num_cols, lower_bounds_.size()); + DCHECK_EQ(num_cols, upper_bounds_.size()); + + // TODO(user): These could just be Resized() but there is a bug with the + // iteration and resize it seems. Investigate. I suspect the last bucket + // is not cleared so you can still iterate on the ones there even if it all + // positions before num_cols are set to zero. + variable_status_.resize(num_cols, VariableStatus::FREE); can_increase_.ClearAndResize(num_cols); can_decrease_.ClearAndResize(num_cols); is_basic_.ClearAndResize(num_cols); not_basic_.ClearAndResize(num_cols); non_basic_boxed_variables_.ClearAndResize(num_cols); - num_entries_in_relevant_columns_ = 0; + // This one cannot just be resized. boxed_variables_are_relevant_ = true; + num_entries_in_relevant_columns_ = 0; relevance_.ClearAndResize(num_cols); +} - variable_status_.resize(num_cols, VariableStatus::FREE); - variable_type_.resize(num_cols, VariableType::UNCONSTRAINED); +void VariablesInfo::InitializeFromBasisState(ColIndex first_slack_col, + ColIndex num_new_cols, + const BasisState& state) { + ResetStatusInfo(); + + RowIndex num_basic_variables(0); + const ColIndex num_cols = lower_bounds_.size(); + const RowIndex num_rows = ColToRowIndex(num_cols - first_slack_col); + DCHECK_LE(num_new_cols, first_slack_col); + const ColIndex first_new_col(first_slack_col - num_new_cols); + + // Compute the status for all the columns (note that the slack variables are + // already added at the end of the matrix at this stage). for (ColIndex col(0); col < num_cols; ++col) { - variable_type_[col] = ComputeVariableType(col); + // Start with the given "warm" status from the BasisState if it exists. + VariableStatus status; + if (col < first_new_col && col < state.statuses.size()) { + status = state.statuses[col]; + } else if (col >= first_slack_col && + col - num_new_cols < state.statuses.size()) { + status = state.statuses[col - num_new_cols]; + } else { + UpdateToNonBasicStatus(col, DefaultVariableStatus(col)); + continue; + } + + // Remove incompatibilities between the warm status and the current state. + switch (status) { + case VariableStatus::BASIC: + // Do not allow more than num_rows VariableStatus::BASIC variables. + if (num_basic_variables == num_rows) { + VLOG(1) << "Too many basic variables in the warm-start basis." + << "Only keeping the first ones as VariableStatus::BASIC."; + UpdateToNonBasicStatus(col, DefaultVariableStatus(col)); + } else { + ++num_basic_variables; + UpdateToBasicStatus(col); + } + break; + case VariableStatus::AT_LOWER_BOUND: + if (lower_bounds_[col] == upper_bounds_[col]) { + UpdateToNonBasicStatus(col, VariableStatus::FIXED_VALUE); + } else { + UpdateToNonBasicStatus(col, lower_bounds_[col] == -kInfinity + ? DefaultVariableStatus(col) + : status); + } + break; + case VariableStatus::AT_UPPER_BOUND: + if (lower_bounds_[col] == upper_bounds_[col]) { + UpdateToNonBasicStatus(col, VariableStatus::FIXED_VALUE); + } else { + UpdateToNonBasicStatus(col, upper_bounds_[col] == kInfinity + ? DefaultVariableStatus(col) + : status); + } + break; + default: + UpdateToNonBasicStatus(col, DefaultVariableStatus(col)); + } } } +void VariablesInfo::InitializeToDefaultStatus() { + ResetStatusInfo(); + const ColIndex num_cols = lower_bounds_.size(); + for (ColIndex col(0); col < num_cols; ++col) { + UpdateToNonBasicStatus(col, DefaultVariableStatus(col)); + } +} + +VariableStatus VariablesInfo::DefaultVariableStatus(ColIndex col) const { + DCHECK_GE(col, 0); + DCHECK_LT(col, lower_bounds_.size()); + if (lower_bounds_[col] == upper_bounds_[col]) { + return VariableStatus::FIXED_VALUE; + } + if (lower_bounds_[col] == -kInfinity && upper_bounds_[col] == kInfinity) { + return VariableStatus::FREE; + } + + // Returns the bound with the lowest magnitude. Note that it must be finite + // because the VariableStatus::FREE case was tested earlier. + DCHECK(IsFinite(lower_bounds_[col]) || IsFinite(upper_bounds_[col])); + return std::abs(lower_bounds_[col]) <= std::abs(upper_bounds_[col]) + ? VariableStatus::AT_LOWER_BOUND + : VariableStatus::AT_UPPER_BOUND; +} + void VariablesInfo::MakeBoxedVariableRelevant(bool value) { if (value == boxed_variables_are_relevant_) return; boxed_variables_are_relevant_ = value; @@ -57,14 +164,6 @@ void VariablesInfo::MakeBoxedVariableRelevant(bool value) { } } -void VariablesInfo::Update(ColIndex col, VariableStatus status) { - if (status == VariableStatus::BASIC) { - UpdateToBasicStatus(col); - } else { - UpdateToNonBasicStatus(col, status); - } -} - void VariablesInfo::UpdateToBasicStatus(ColIndex col) { variable_status_[col] = VariableStatus::BASIC; is_basic_.Set(col, true); @@ -129,15 +228,15 @@ EntryIndex VariablesInfo::GetNumEntriesInRelevantColumns() const { } VariableType VariablesInfo::ComputeVariableType(ColIndex col) const { - DCHECK_LE(lower_bound_[col], upper_bound_[col]); - if (lower_bound_[col] == -kInfinity) { - if (upper_bound_[col] == kInfinity) { + DCHECK_LE(lower_bounds_[col], upper_bounds_[col]); + if (lower_bounds_[col] == -kInfinity) { + if (upper_bounds_[col] == kInfinity) { return VariableType::UNCONSTRAINED; } return VariableType::UPPER_BOUNDED; - } else if (upper_bound_[col] == kInfinity) { + } else if (upper_bounds_[col] == kInfinity) { return VariableType::LOWER_BOUNDED; - } else if (lower_bound_[col] == upper_bound_[col]) { + } else if (lower_bounds_[col] == upper_bounds_[col]) { return VariableType::FIXED_VARIABLE; } else { return VariableType::UPPER_AND_LOWER_BOUNDED; diff --git a/ortools/glop/variables_info.h b/ortools/glop/variables_info.h index 4cc138acea..b8807146e7 100644 --- a/ortools/glop/variables_info.h +++ b/ortools/glop/variables_info.h @@ -20,6 +20,32 @@ namespace operations_research { namespace glop { +// Holds the statuses of all the variables, including slack variables. There +// is no point storing constraint statuses since internally all constraints are +// always fixed to zero. +// +// Note that this is the minimal amount of information needed to perform a "warm +// start". Using this information and the original linear program, the basis can +// be refactorized and all the needed quantities derived. +// +// TODO(user): Introduce another state class to store a complete state of the +// solver. Using this state and the original linear program, the solver can be +// restarted with as little time overhead as possible. This is especially useful +// for strong branching in a MIP context. +struct BasisState { + // TODO(user): A MIP solver will potentially store a lot of BasisStates so + // memory usage is important. It is possible to use only 2 bits for one + // VariableStatus enum. To achieve this, the FIXED_VALUE status can be + // converted to either AT_LOWER_BOUND or AT_UPPER_BOUND and decoded properly + // later since this will be used with a given linear program. This way we can + // even encode more information by using the reduced cost sign to choose to + // which bound the fixed status correspond. + VariableStatusRow statuses; + + // Returns true if this state is empty. + bool IsEmpty() const { return statuses.empty(); } +}; + // Class responsible for maintaining diverse information for each variable that // depend on its bounds and status. // @@ -29,21 +55,30 @@ namespace glop { class VariablesInfo { public: // Takes references to the linear program data we need. - VariablesInfo(const CompactSparseMatrix& matrix, const DenseRow& lower_bound, - const DenseRow& upper_bound); + explicit VariablesInfo(const CompactSparseMatrix& matrix); - // Recomputes the variable types from the bounds (this is the only function - // that changes them). This also resets all the non-type quantities to a - // default value. Note however that nothing should be assumed on the return - // values of the getters until Update() has been called at least once on all - // the columns. - void InitializeAndComputeType(); + // Updates the internal bounds and recomputes the variable types from the + // bounds (this is the only function that changes them). + // + // Returns true iff the existing bounds didn't change. Except if the bounds + // AND underlying matrix didn't change, one will need to call one of the two + // Initialize*() methods below before using this class. + bool LoadBoundsAndReturnTrueIfUnchanged(const DenseRow& new_lower_bounds, + const DenseRow& new_upper_bounds); + + // Initializes the status according to the given BasisState. Incompatible + // statuses will be corrected, and we transfrom the state correctly if new + // columns / rows were added. Note however that one will need to update the + // BasisState with deletions to preserve the status of unchanged columns. + void InitializeFromBasisState(ColIndex first_slack, ColIndex num_new_cols, + const BasisState& state); + + // Sets all variables status to their lowest magnitude bounds. Note that there + // will be no basic variable after this is called. + void InitializeToDefaultStatus(); // Updates the information of the given variable. Note that it is not needed // to call this if the status or the bound of a variable didn't change. - void Update(ColIndex col, VariableStatus status); - - // Slightly optimized version of Update() above for the two separate cases. void UpdateToBasicStatus(ColIndex col); void UpdateToNonBasicStatus(ColIndex col, VariableStatus status); @@ -59,8 +94,8 @@ class VariablesInfo { const DenseBitRow& GetNonBasicBoxedVariables() const; // Returns the variable bounds. - const DenseRow& GetVariableLowerBounds() const { return lower_bound_; } - const DenseRow& GetVariableUpperBounds() const { return upper_bound_; } + const DenseRow& GetVariableLowerBounds() const { return lower_bounds_; } + const DenseRow& GetVariableUpperBounds() const { return upper_bounds_; } const ColIndex GetNumberOfColumns() const { return matrix_.num_cols(); } @@ -74,10 +109,17 @@ class VariablesInfo { // Returns the distance between the upper and lower bound of the given column. Fractional GetBoundDifference(ColIndex col) const { - return upper_bound_[col] - lower_bound_[col]; + return upper_bounds_[col] - lower_bounds_[col]; } private: + // Computes the initial/default variable status from its type. A constrained + // variable is set to the lowest of its 2 bounds in absolute value. + VariableStatus DefaultVariableStatus(ColIndex col) const; + + // Resizes all status related vectors. + void ResetStatusInfo(); + // Computes the variable type from its lower and upper bound. VariableType ComputeVariableType(ColIndex col) const; @@ -86,8 +128,11 @@ class VariablesInfo { // Problem data that should be updated from outside. const CompactSparseMatrix& matrix_; - const DenseRow& lower_bound_; - const DenseRow& upper_bound_; + + // The variables bounds of the current problem. Like everything here, it + // include the slacks. + DenseRow lower_bounds_; + DenseRow upper_bounds_; // Array of variable statuses, indexed by column index. VariableStatusRow variable_status_; @@ -120,7 +165,7 @@ class VariablesInfo { EntryIndex num_entries_in_relevant_columns_; // Whether or not a boxed variable should be considered relevant. - bool boxed_variables_are_relevant_; + bool boxed_variables_are_relevant_ = true; DISALLOW_COPY_AND_ASSIGN(VariablesInfo); }; diff --git a/ortools/lp_data/scattered_vector.h b/ortools/lp_data/scattered_vector.h index 82f344fd12..900df8db27 100644 --- a/ortools/lp_data/scattered_vector.h +++ b/ortools/lp_data/scattered_vector.h @@ -159,6 +159,12 @@ struct ScatteredVector { void ClearNonZerosIfTooDense() { ClearNonZerosIfTooDense(kDefaultRatioForUsingDenseIteration); } + + // Returns an over-estimate of the number of non-zeros. This is actually + // exact for sparse vector, or the full size otherwise. + size_t NumNonZerosEstimate() const { + return non_zeros.empty() ? values.size().value() : non_zeros.size(); + } }; // Specializations used in the code. diff --git a/ortools/sat/all_different.cc b/ortools/sat/all_different.cc index 7196ba4c89..8c31ce1788 100644 --- a/ortools/sat/all_different.cc +++ b/ortools/sat/all_different.cc @@ -14,6 +14,8 @@ #include "ortools/sat/all_different.h" #include +#include +#include #include #include @@ -94,8 +96,8 @@ AllDifferentConstraint::AllDifferentConstraint( trail_(trail), integer_trail_(integer_trail) { // Initialize literals cache. - int64 min_value = kint64max; - int64 max_value = kint64min; + int64_t min_value = std::numeric_limits::max(); + int64_t max_value = std::numeric_limits::min(); variable_min_value_.resize(num_variables_); variable_max_value_.resize(num_variables_); variable_literal_index_.resize(num_variables_); @@ -122,10 +124,10 @@ AllDifferentConstraint::AllDifferentConstraint( } // Fill cache with literals, default value is kFalseLiteralIndex. - int64 size = variable_max_value_[x] - variable_min_value_[x] + 1; + int64_t size = variable_max_value_[x] - variable_min_value_[x] + 1; variable_literal_index_[x].resize(size, kFalseLiteralIndex); for (const auto& entry : encoder->FullDomainEncoding(variables_[x])) { - int64 value = entry.value.value(); + int64_t value = entry.value.value(); // Can happen because of initial propagation! if (value < variable_min_value_[x] || variable_max_value_[x] < value) { continue; @@ -161,14 +163,14 @@ void AllDifferentConstraint::RegisterWith(GenericLiteralWatcher* watcher) { } LiteralIndex AllDifferentConstraint::VariableLiteralIndexOf(int x, - int64 value) { + int64_t value) { return (value < variable_min_value_[x] || variable_max_value_[x] < value) ? kFalseLiteralIndex : variable_literal_index_[x][value - variable_min_value_[x]]; } inline bool AllDifferentConstraint::VariableHasPossibleValue(int x, - int64 value) { + int64_t value) { LiteralIndex li = VariableLiteralIndexOf(x, value); if (li == kFalseLiteralIndex) return false; if (li == kTrueLiteralIndex) return true; @@ -241,9 +243,9 @@ bool AllDifferentConstraint::Propagate() { variable_to_value_.assign(num_variables_, -1); for (int x = 0; x < num_variables_; x++) { successor_[x].clear(); - const int64 min_value = integer_trail_->LowerBound(variables_[x]).value(); - const int64 max_value = integer_trail_->UpperBound(variables_[x]).value(); - for (int64 value = min_value; value <= max_value; value++) { + const int64_t min_value = integer_trail_->LowerBound(variables_[x]).value(); + const int64_t max_value = integer_trail_->UpperBound(variables_[x]).value(); + for (int64_t value = min_value; value <= max_value; value++) { if (VariableHasPossibleValue(x, value)) { const int offset_value = value - min_all_values_; // Forward-checking should propagate x != value. diff --git a/ortools/sat/all_different.h b/ortools/sat/all_different.h index 66286addd4..357eaa67e8 100644 --- a/ortools/sat/all_different.h +++ b/ortools/sat/all_different.h @@ -14,6 +14,7 @@ #ifndef OR_TOOLS_SAT_ALL_DIFFERENT_H_ #define OR_TOOLS_SAT_ALL_DIFFERENT_H_ +#include #include #include #include @@ -80,8 +81,8 @@ class AllDifferentConstraint : PropagatorInterface { bool MakeAugmentingPath(int start); // Accessors to the cache of literals. - inline LiteralIndex VariableLiteralIndexOf(int x, int64 value); - inline bool VariableHasPossibleValue(int x, int64 value); + inline LiteralIndex VariableLiteralIndexOf(int x, int64_t value); + inline bool VariableHasPossibleValue(int x, int64_t value); // This caches all literals of the fully encoded variables. // Values of a given variable are 0-indexed using offsets variable_min_value_, @@ -89,10 +90,10 @@ class AllDifferentConstraint : PropagatorInterface { // TODO(user): compare this encoding to a sparser hash_map encoding. const int num_variables_; const std::vector variables_; - int64 min_all_values_; - int64 num_all_values_; - std::vector variable_min_value_; - std::vector variable_max_value_; + int64_t min_all_values_; + int64_t num_all_values_; + std::vector variable_min_value_; + std::vector variable_max_value_; std::vector> variable_literal_index_; // Internal state of MakeAugmentingPath(). diff --git a/ortools/sat/boolean_problem.cc b/ortools/sat/boolean_problem.cc index 48e6bfe850..30b117c4df 100644 --- a/ortools/sat/boolean_problem.cc +++ b/ortools/sat/boolean_problem.cc @@ -14,6 +14,7 @@ #include "ortools/sat/boolean_problem.h" #include +#include #include #include #include @@ -163,11 +164,11 @@ CpModelProto BooleanProblemToCpModelproto(const LinearBooleanProblem& problem) { ConstraintProto* ct = result.add_constraints(); ct->set_name(constraint.name()); LinearConstraintProto* linear = ct->mutable_linear(); - int64 offset = 0; + int64_t offset = 0; for (int i = 0; i < constraint.literals_size(); ++i) { // Note that the new format is slightly different. const int lit = constraint.literals(i); - const int64 coeff = constraint.coefficients(i); + const int64_t coeff = constraint.coefficients(i); if (lit > 0) { linear->add_vars(lit - 1); linear->add_coeffs(coeff); @@ -180,17 +181,17 @@ CpModelProto BooleanProblemToCpModelproto(const LinearBooleanProblem& problem) { } linear->add_domain(constraint.has_lower_bound() ? constraint.lower_bound() + offset - : kint32min + offset); + : std::numeric_limits::min() + offset); linear->add_domain(constraint.has_upper_bound() ? constraint.upper_bound() + offset - : kint32max + offset); + : std::numeric_limits::max() + offset); } if (problem.has_objective()) { CpObjectiveProto* objective = result.mutable_objective(); - int64 offset = 0; + int64_t offset = 0; for (int i = 0; i < problem.objective().literals_size(); ++i) { const int lit = problem.objective().literals(i); - const int64 coeff = problem.objective().coefficients(i); + const int64_t coeff = problem.objective().coefficients(i); if (lit > 0) { objective->add_vars(lit - 1); objective->add_coeffs(coeff); @@ -235,7 +236,7 @@ bool LoadBooleanProblem(const LinearBooleanProblem& problem, } solver->SetNumVariables(problem.num_variables()); std::vector cst; - int64 num_terms = 0; + int64_t num_terms = 0; int num_constraints = 0; for (const LinearBooleanConstraint& constraint : problem.constraints()) { num_terms += constraint.literals_size(); @@ -273,7 +274,7 @@ bool LoadAndConsumeBooleanProblem(LinearBooleanProblem* problem, } solver->SetNumVariables(problem->num_variables()); std::vector cst; - int64 num_terms = 0; + int64_t num_terms = 0; int num_constraints = 0; // We will process the constraints backward so we can free the memory used by @@ -309,14 +310,14 @@ void UseObjectiveForSatAssignmentPreference(const LinearBooleanProblem& problem, SatSolver* solver) { const LinearObjective& objective = problem.objective(); CHECK_EQ(objective.literals_size(), objective.coefficients_size()); - int64 max_abs_weight = 0; - for (const int64 coefficient : objective.coefficients()) { + int64_t max_abs_weight = 0; + for (const int64_t coefficient : objective.coefficients()) { max_abs_weight = std::max(max_abs_weight, std::abs(coefficient)); } const double max_abs_weight_double = max_abs_weight; for (int i = 0; i < objective.literals_size(); ++i) { const Literal literal(objective.literals(i)); - const int64 coefficient = objective.coefficients(i); + const int64_t coefficient = objective.coefficients(i); const double abs_weight = std::abs(coefficient) / max_abs_weight_double; // Because this is a minimization problem, we prefer to assign a Boolean // variable to its "low" objective value. So if a literal has a positive @@ -401,16 +402,16 @@ std::string LinearBooleanProblemToCnfString( const int first_slack_variable = problem.original_num_variables(); // This will contains the objective. - absl::flat_hash_map literal_to_weight; - std::vector> non_slack_objective; + absl::flat_hash_map literal_to_weight; + std::vector> non_slack_objective; // This will be the weight of the "hard" clauses in the wcnf format. It must // be greater than the sum of the weight of all the soft clauses, so we will // just set it to this sum + 1. - int64 hard_weight = 1; + int64_t hard_weight = 1; if (is_wcnf) { int i = 0; - for (int64 weight : objective.coefficients()) { + for (int64_t weight : objective.coefficients()) { CHECK_NE(weight, 0); int signed_literal = objective.literals(i); @@ -444,7 +445,7 @@ std::string LinearBooleanProblemToCnfString( for (const LinearBooleanConstraint& constraint : problem.constraints()) { if (constraint.literals_size() == 0) return ""; // Assumption. constraint_output.clear(); - int64 weight = hard_weight; + int64_t weight = hard_weight; for (int i = 0; i < constraint.literals_size(); ++i) { if (constraint.coefficients(i) != 1) return ""; // Assumption. if (is_wcnf && abs(constraint.literals(i)) - 1 >= first_slack_variable) { @@ -462,7 +463,7 @@ std::string LinearBooleanProblemToCnfString( // Output the rest of the objective as singleton constraints. if (is_wcnf) { - for (std::pair p : non_slack_objective) { + for (std::pair p : non_slack_objective) { // Since it is falsifying this clause that cost "weigtht", we need to take // its negation. const Literal literal(-p.first); @@ -506,12 +507,12 @@ class IdGenerator { // If the pair (type, coefficient) was never seen before, then generate // a new id, otherwise return the previously generated id. int GetId(int type, Coefficient coefficient) { - const std::pair key(type, coefficient.value()); + const std::pair key(type, coefficient.value()); return gtl::LookupOrInsert(&id_map_, key, id_map_.size()); } private: - absl::flat_hash_map, int> id_map_; + absl::flat_hash_map, int> id_map_; }; } // namespace. @@ -636,11 +637,11 @@ Graph* GenerateGraphForSymmetryDetection( void MakeAllLiteralsPositive(LinearBooleanProblem* problem) { // Objective. LinearObjective* mutable_objective = problem->mutable_objective(); - int64 objective_offset = 0; + int64_t objective_offset = 0; for (int i = 0; i < mutable_objective->literals_size(); ++i) { const int signed_literal = mutable_objective->literals(i); if (signed_literal < 0) { - const int64 coefficient = mutable_objective->coefficients(i); + const int64_t coefficient = mutable_objective->coefficients(i); mutable_objective->set_literals(i, -signed_literal); mutable_objective->set_coefficients(i, -coefficient); objective_offset += coefficient; @@ -651,7 +652,7 @@ void MakeAllLiteralsPositive(LinearBooleanProblem* problem) { // Constraints. for (LinearBooleanConstraint& constraint : *(problem->mutable_constraints())) { - int64 sum = 0; + int64_t sum = 0; for (int i = 0; i < constraint.literals_size(); ++i) { if (constraint.literals(i) < 0) { sum += constraint.coefficients(i); diff --git a/ortools/sat/clause.cc b/ortools/sat/clause.cc index 59c1a3bbc8..48ed6a67f8 100644 --- a/ortools/sat/clause.cc +++ b/ortools/sat/clause.cc @@ -14,6 +14,7 @@ #include "ortools/sat/clause.h" #include +#include #include #include #include @@ -1018,10 +1019,10 @@ class SccGraph { using Implication = absl::StrongVector>; using AtMostOne = - absl::StrongVector>; + absl::StrongVector>; using SccFinder = - StronglyConnectedComponentsFinder>>; + StronglyConnectedComponentsFinder>>; explicit SccGraph(SccFinder* finder, Implication* graph, AtMostOne* at_most_ones, @@ -1031,7 +1032,7 @@ class SccGraph { at_most_ones_(*at_most_ones), at_most_one_buffer_(*at_most_one_buffer) {} - const std::vector& operator[](int32 node) const { + const std::vector& operator[](int32_t node) const { tmp_.clear(); for (const Literal l : implications_[LiteralIndex(node)]) { tmp_.push_back(l.Index().value()); @@ -1106,7 +1107,7 @@ class SccGraph { mutable std::vector to_fix_; // For the deterministic time. - mutable int64 work_done_ = 0; + mutable int64_t work_done_ = 0; private: const SccFinder& finder_; @@ -1114,7 +1115,7 @@ class SccGraph { const AtMostOne& at_most_ones_; const std::vector& at_most_one_buffer_; - mutable std::vector tmp_; + mutable std::vector tmp_; // Used to get a non-quadratic complexity in the presence of at most ones. mutable std::vector at_most_one_already_explored_; @@ -1136,8 +1137,8 @@ bool BinaryImplicationGraph::DetectEquivalences(bool log_info) { // TODO(user): We could just do it directly though. int num_fixed_during_scc = 0; - const int32 size(implications_.size()); - std::vector> scc; + const int32_t size(implications_.size()); + std::vector> scc; double dtime = 0.0; { SccGraph::SccFinder finder; @@ -1160,7 +1161,7 @@ bool BinaryImplicationGraph::DetectEquivalences(bool log_info) { int num_equivalences = 0; reverse_topological_order_.clear(); - for (std::vector& component : scc) { + for (std::vector& component : scc) { // If one is fixed then all must be fixed. Note that the reason why the // propagation didn't already do that and we don't always get fixed // component of size 1 is because of the potential newly fixed literals @@ -1170,7 +1171,7 @@ bool BinaryImplicationGraph::DetectEquivalences(bool log_info) { { bool all_fixed = false; bool all_true = false; - for (const int32 i : component) { + for (const int32_t i : component) { const Literal l = Literal(LiteralIndex(i)); if (trail_->Assignment().LiteralIsAssigned(l)) { all_fixed = true; @@ -1179,7 +1180,7 @@ bool BinaryImplicationGraph::DetectEquivalences(bool log_info) { } } if (all_fixed) { - for (const int32 i : component) { + for (const int32_t i : component) { const Literal l = Literal(LiteralIndex(i)); if (!is_redundant_[l.Index()]) { ++num_redundant_literals_; @@ -1322,8 +1323,8 @@ bool BinaryImplicationGraph::ComputeTransitiveReduction(bool log_info) { WallTimer wall_timer; wall_timer.Start(); - int64 num_fixed = 0; - int64 num_new_redundant_implications = 0; + int64_t num_fixed = 0; + int64_t num_new_redundant_implications = 0; bool aborted = false; work_done_in_mark_descendants_ = 0; int marked_index = 0; @@ -1499,7 +1500,7 @@ struct VectorHash { bool BinaryImplicationGraph::TransformIntoMaxCliques( std::vector>* at_most_ones, - int64 max_num_explored_nodes) { + int64_t max_num_explored_nodes) { // The code below assumes a DAG. if (!DetectEquivalences()) return false; work_done_in_mark_descendants_ = 0; @@ -1582,7 +1583,7 @@ std::vector BinaryImplicationGraph::ExpandAtMostOneWithWeight( std::vector clique(at_most_one.begin(), at_most_one.end()); std::vector intersection; double clique_weight = 0.0; - const int64 old_work = work_done_in_mark_descendants_; + const int64_t old_work = work_done_in_mark_descendants_; for (const Literal l : clique) clique_weight += expanded_lp_values[l.Index()]; for (int i = 0; i < clique.size(); ++i) { // Do not spend too much time here. @@ -1864,13 +1865,13 @@ bool BinaryImplicationGraph::FindFailedLiteralAroundVar(BooleanVariable var, return propagation_trail_index_ > saved_index; } -int64 BinaryImplicationGraph::NumImplicationOnVariableRemoval( +int64_t BinaryImplicationGraph::NumImplicationOnVariableRemoval( BooleanVariable var) { const Literal literal(var, true); - int64 result = 0; + int64_t result = 0; direct_implications_of_negated_literal_ = DirectImplications(literal.Negated()); - const int64 s1 = DirectImplications(literal).size(); + const int64_t s1 = DirectImplications(literal).size(); for (const Literal l : direct_implications_of_negated_literal_) { result += s1; diff --git a/ortools/sat/clause.h b/ortools/sat/clause.h index 8206d68900..0da6ca501b 100644 --- a/ortools/sat/clause.h +++ b/ortools/sat/clause.h @@ -17,6 +17,7 @@ #ifndef OR_TOOLS_SAT_CLAUSE_H_ #define OR_TOOLS_SAT_CLAUSE_H_ +#include #include #include #include @@ -128,7 +129,7 @@ class SatClause { for (const Literal l : new_clause) literals_[size_++] = l; } - int32 size_; + int32_t size_; // This class store the literals inline, and literals_ mark the starts of the // variable length portion. @@ -142,7 +143,7 @@ class SatClause { // the learned one that we wants to keep forever do not have one. struct ClauseInfo { double activity = 0.0; - int32 lbd = 0; + int32_t lbd = 0; bool protected_during_next_cleanup = false; }; @@ -207,7 +208,7 @@ class LiteralWatchers : public SatPropagator { // zero) and remove them from AllClausesInCreationOrder() this work in // O(num_clauses()). void DeleteRemovedClauses(); - int64 num_clauses() const { return clauses_.size(); } + int64_t num_clauses() const { return clauses_.size(); } const std::vector& AllClausesInCreationOrder() const { return clauses_; } @@ -219,22 +220,22 @@ class LiteralWatchers : public SatPropagator { bool IsRemovable(SatClause* const clause) const { return gtl::ContainsKey(clauses_info_, clause); } - int64 num_removable_clauses() const { return clauses_info_.size(); } + int64_t num_removable_clauses() const { return clauses_info_.size(); } absl::flat_hash_map* mutable_clauses_info() { return &clauses_info_; } // Total number of clauses inspected during calls to PropagateOnFalse(). - int64 num_inspected_clauses() const { return num_inspected_clauses_; } - int64 num_inspected_clause_literals() const { + int64_t num_inspected_clauses() const { return num_inspected_clauses_; } + int64_t num_inspected_clause_literals() const { return num_inspected_clause_literals_; } // The number of different literals (always twice the number of variables). - int64 literal_size() const { return needs_cleaning_.size().value(); } + int64_t literal_size() const { return needs_cleaning_.size().value(); } // Number of clauses currently watched. - int64 num_watched_clauses() const { return num_watched_clauses_; } + int64_t num_watched_clauses() const { return num_watched_clauses_; } void SetDratProofHandler(DratProofHandler* drat_proof_handler) { drat_proof_handler_ = drat_proof_handler; @@ -302,7 +303,7 @@ class LiteralWatchers : public SatPropagator { // Note that ideally, this should be part of a SatClause, so it can be // shared across watchers. However, since we have 32 bits for "free" here // because of the struct alignment, we store it here instead. - int32 start_index; + int32_t start_index; SatClause* clause; }; @@ -344,9 +345,9 @@ class LiteralWatchers : public SatPropagator { BinaryImplicationGraph* implication_graph_; Trail* trail_; - int64 num_inspected_clauses_; - int64 num_inspected_clause_literals_; - int64 num_watched_clauses_; + int64_t num_inspected_clauses_; + int64_t num_inspected_clause_literals_; + int64_t num_watched_clauses_; mutable StatsGroup stats_; // For DetachAllClauses()/AttachAllClauses(). @@ -586,7 +587,7 @@ class BinaryImplicationGraph : public SatPropagator { // Returns false if the model is detected to be UNSAT (this needs to call // DetectEquivalences() if not already done). bool TransformIntoMaxCliques(std::vector>* at_most_ones, - int64 max_num_explored_nodes = 1e8); + int64_t max_num_explored_nodes = 1e8); // LP clique cut heuristic. Returns a set of "at most one" constraints on the // given literals or their negation that are violated by the current LP @@ -602,14 +603,14 @@ class BinaryImplicationGraph : public SatPropagator { const std::vector& lp_values); // Number of literal propagated by this class (including conflicts). - int64 num_propagations() const { return num_propagations_; } + int64_t num_propagations() const { return num_propagations_; } // Number of literals inspected by this class during propagation. - int64 num_inspections() const { return num_inspections_; } + int64_t num_inspections() const { return num_inspections_; } // MinimizeClause() stats. - int64 num_minimization() const { return num_minimization_; } - int64 num_literals_removed() const { return num_literals_removed_; } + int64_t num_minimization() const { return num_minimization_; } + int64_t num_literals_removed() const { return num_literals_removed_; } // Returns true if this literal is fixed or is equivalent to another literal. // This means that it can just be ignored in most situation. @@ -618,13 +619,13 @@ class BinaryImplicationGraph : public SatPropagator { // time. This is because we always use the lowest index as representative of // an equivalent class, so a redundant literal will stay that way. bool IsRedundant(Literal l) const { return is_redundant_[l.Index()]; } - int64 num_redundant_literals() const { + int64_t num_redundant_literals() const { CHECK_EQ(num_redundant_literals_ % 2, 0); return num_redundant_literals_; } // Number of implications removed by transitive reduction. - int64 num_redundant_implications() const { + int64_t num_redundant_implications() const { return num_redundant_implications_; } @@ -632,8 +633,8 @@ class BinaryImplicationGraph : public SatPropagator { // not(a) are counted separately since they appear separately in our // propagation lists. The number of size 2 clauses that represent the same // thing is half this number. - int64 num_implications() const { return num_implications_; } - int64 literal_size() const { return implications_.size(); } + int64_t num_implications() const { return num_implications_; } + int64_t literal_size() const { return implications_.size(); } // Extract all the binary clauses managed by this class. The Output type must // support an AddBinaryClause(Literal a, Literal b) function. @@ -702,7 +703,7 @@ class BinaryImplicationGraph : public SatPropagator { // var => not(a) then a must be false and this is detected and dealt with by // FindFailedLiteralAroundVar(). bool FindFailedLiteralAroundVar(BooleanVariable var, bool* is_unsat); - int64 NumImplicationOnVariableRemoval(BooleanVariable var); + int64_t NumImplicationOnVariableRemoval(BooleanVariable var); void RemoveBooleanVariable( BooleanVariable var, std::deque>* postsolve_clauses); bool IsRemoved(Literal l) const { return is_removed_[l.Index()]; } @@ -769,7 +770,7 @@ class BinaryImplicationGraph : public SatPropagator { // for us and we could store in common the inlined/not-inlined size. absl::StrongVector> implications_; - int64 num_implications_ = 0; + int64_t num_implications_ = 0; // Internal representation of at_most_one constraints. Each entry point to the // start of a constraint in the buffer. Contraints are terminated by @@ -778,19 +779,20 @@ class BinaryImplicationGraph : public SatPropagator { // // TODO(user): We could be more cache efficient by combining this with // implications_ in some way. Do some propagation speed benchmark. - absl::StrongVector> at_most_ones_; + absl::StrongVector> + at_most_ones_; std::vector at_most_one_buffer_; // Used by GenerateAtMostOnesWithLargeWeight(). std::vector> tmp_cuts_; // Some stats. - int64 num_propagations_ = 0; - int64 num_inspections_ = 0; - int64 num_minimization_ = 0; - int64 num_literals_removed_ = 0; - int64 num_redundant_implications_ = 0; - int64 num_redundant_literals_ = 0; + int64_t num_propagations_ = 0; + int64_t num_inspections_ = 0; + int64_t num_minimization_ = 0; + int64_t num_literals_removed_ = 0; + int64_t num_redundant_implications_ = 0; + int64_t num_redundant_literals_ = 0; // Bitset used by MinimizeClause(). // TODO(user): use the same one as the one used in the classic minimization @@ -804,7 +806,7 @@ class BinaryImplicationGraph : public SatPropagator { // Used to limit the work done by ComputeTransitiveReduction() and // TransformIntoMaxCliques(). - int64 work_done_in_mark_descendants_ = 0; + int64_t work_done_in_mark_descendants_ = 0; // Filled by DetectEquivalences(). bool is_dag_ = false; diff --git a/ortools/sat/cp_constraints.h b/ortools/sat/cp_constraints.h index 5dabae0cc3..dc981bb233 100644 --- a/ortools/sat/cp_constraints.h +++ b/ortools/sat/cp_constraints.h @@ -14,6 +14,7 @@ #ifndef OR_TOOLS_SAT_CP_CONSTRAINTS_H_ #define OR_TOOLS_SAT_CP_CONSTRAINTS_H_ +#include #include #include #include @@ -99,7 +100,7 @@ class GreaterThanAtLeastOneOfPropagator : public PropagatorInterface { // ============================================================================ inline std::vector ToIntegerValueVector( - const std::vector& input) { + const std::vector& input) { std::vector result(input.size()); for (int i = 0; i < input.size(); ++i) { result[i] = IntegerValue(input[i]); diff --git a/ortools/sat/cp_model.cc b/ortools/sat/cp_model.cc index 554b279d30..5fc9957136 100644 --- a/ortools/sat/cp_model.cc +++ b/ortools/sat/cp_model.cc @@ -13,6 +13,9 @@ #include "ortools/sat/cp_model.h" +#include +#include + #include "absl/strings/str_format.h" #include "ortools/base/map_util.h" #include "ortools/sat/cp_model.pb.h" @@ -94,7 +97,7 @@ BoolVar IntVar::ToBoolVar() const { return var; } -LinearExpr IntVar::AddConstant(int64 value) const { +LinearExpr IntVar::AddConstant(int64_t value) const { return LinearExpr(*this).AddConstant(value); } @@ -138,7 +141,7 @@ LinearExpr::LinearExpr(BoolVar var) { AddVar(var); } LinearExpr::LinearExpr(IntVar var) { AddVar(var); } -LinearExpr::LinearExpr(int64 constant) { constant_ = constant; } +LinearExpr::LinearExpr(int64_t constant) { constant_ = constant; } LinearExpr LinearExpr::Sum(absl::Span vars) { LinearExpr result; @@ -149,7 +152,7 @@ LinearExpr LinearExpr::Sum(absl::Span vars) { } LinearExpr LinearExpr::ScalProd(absl::Span vars, - absl::Span coeffs) { + absl::Span coeffs) { CHECK_EQ(vars.size(), coeffs.size()); LinearExpr result; for (int i = 0; i < vars.size(); ++i) { @@ -158,7 +161,7 @@ LinearExpr LinearExpr::ScalProd(absl::Span vars, return result; } -LinearExpr LinearExpr::Term(IntVar var, int64 coefficient) { +LinearExpr LinearExpr::Term(IntVar var, int64_t coefficient) { LinearExpr result; result.AddTerm(var, coefficient); return result; @@ -173,7 +176,7 @@ LinearExpr LinearExpr::BooleanSum(absl::Span vars) { } LinearExpr LinearExpr::BooleanScalProd(absl::Span vars, - absl::Span coeffs) { + absl::Span coeffs) { CHECK_EQ(vars.size(), coeffs.size()); LinearExpr result; for (int i = 0; i < vars.size(); ++i) { @@ -182,14 +185,14 @@ LinearExpr LinearExpr::BooleanScalProd(absl::Span vars, return result; } -LinearExpr& LinearExpr::AddConstant(int64 value) { +LinearExpr& LinearExpr::AddConstant(int64_t value) { constant_ += value; return *this; } void LinearExpr::AddVar(IntVar var) { AddTerm(var, 1); } -void LinearExpr::AddTerm(IntVar var, int64 coeff) { +void LinearExpr::AddTerm(IntVar var, int64_t coeff) { const int index = var.index_; if (RefIsPositive(index)) { variables_.push_back(var); @@ -234,9 +237,9 @@ void MultipleCircuitConstraint::AddArc(int tail, int head, BoolVar literal) { proto_->mutable_routes()->add_literals(literal.index_); } -void TableConstraint::AddTuple(absl::Span tuple) { +void TableConstraint::AddTuple(absl::Span tuple) { CHECK_EQ(tuple.size(), proto_->table().vars_size()); - for (const int64 t : tuple) { + for (const int64_t t : tuple) { proto_->mutable_table()->add_values(t); } } @@ -245,14 +248,14 @@ ReservoirConstraint::ReservoirConstraint(ConstraintProto* proto, CpModelBuilder* builder) : Constraint(proto), builder_(builder) {} -void ReservoirConstraint::AddEvent(IntVar time, int64 demand) { +void ReservoirConstraint::AddEvent(IntVar time, int64_t demand) { proto_->mutable_reservoir()->add_times( builder_->GetOrCreateIntegerIndex(time.index_)); proto_->mutable_reservoir()->add_demands(demand); proto_->mutable_reservoir()->add_actives(builder_->IndexFromConstant(1)); } -void ReservoirConstraint::AddOptionalEvent(IntVar time, int64 demand, +void ReservoirConstraint::AddOptionalEvent(IntVar time, int64_t demand, BoolVar is_active) { proto_->mutable_reservoir()->add_times( builder_->GetOrCreateIntegerIndex(time.index_)); @@ -261,7 +264,7 @@ void ReservoirConstraint::AddOptionalEvent(IntVar time, int64 demand, } void AutomatonConstraint::AddTransition(int tail, int head, - int64 transition_label) { + int64_t transition_label) { proto_->mutable_automaton()->add_transition_tail(tail); proto_->mutable_automaton()->add_transition_head(head); proto_->mutable_automaton()->add_transition_label(transition_label); @@ -332,7 +335,7 @@ std::ostream& operator<<(std::ostream& os, const IntervalVar& var) { return os; } -int CpModelBuilder::IndexFromConstant(int64 value) { +int CpModelBuilder::IndexFromConstant(int64_t value) { if (!gtl::ContainsKey(constant_to_index_map_, value)) { const int index = cp_model_.variables_size(); IntegerVariableProto* const var_proto = cp_model_.add_variables(); @@ -382,7 +385,7 @@ BoolVar CpModelBuilder::NewBoolVar() { return BoolVar(index, &cp_model_); } -IntVar CpModelBuilder::NewConstant(int64 value) { +IntVar CpModelBuilder::NewConstant(int64_t value) { return IntVar(IndexFromConstant(value), &cp_model_); } @@ -442,13 +445,13 @@ void CpModelBuilder::FillLinearTerms(const LinearExpr& left, for (const IntVar& x : left.variables()) { proto->add_vars(x.index_); } - for (const int64 coeff : left.coefficients()) { + for (const int64_t coeff : left.coefficients()) { proto->add_coeffs(coeff); } for (const IntVar& x : right.variables()) { proto->add_vars(x.index_); } - for (const int64 coeff : right.coefficients()) { + for (const int64_t coeff : right.coefficients()) { proto->add_coeffs(-coeff); } } @@ -457,7 +460,7 @@ Constraint CpModelBuilder::AddEquality(const LinearExpr& left, const LinearExpr& right) { ConstraintProto* const proto = cp_model_.add_constraints(); FillLinearTerms(left, right, proto->mutable_linear()); - const int64 rhs = right.constant() - left.constant(); + const int64_t rhs = right.constant() - left.constant(); proto->mutable_linear()->add_domain(rhs); proto->mutable_linear()->add_domain(rhs); return Constraint(proto); @@ -467,9 +470,9 @@ Constraint CpModelBuilder::AddGreaterOrEqual(const LinearExpr& left, const LinearExpr& right) { ConstraintProto* const proto = cp_model_.add_constraints(); FillLinearTerms(left, right, proto->mutable_linear()); - const int64 rhs = right.constant() - left.constant(); + const int64_t rhs = right.constant() - left.constant(); proto->mutable_linear()->add_domain(rhs); - proto->mutable_linear()->add_domain(kint64max); + proto->mutable_linear()->add_domain(std::numeric_limits::max()); return Constraint(proto); } @@ -477,8 +480,8 @@ Constraint CpModelBuilder::AddLessOrEqual(const LinearExpr& left, const LinearExpr& right) { ConstraintProto* const proto = cp_model_.add_constraints(); FillLinearTerms(left, right, proto->mutable_linear()); - const int64 rhs = right.constant() - left.constant(); - proto->mutable_linear()->add_domain(kint64min); + const int64_t rhs = right.constant() - left.constant(); + proto->mutable_linear()->add_domain(std::numeric_limits::min()); proto->mutable_linear()->add_domain(rhs); return Constraint(proto); } @@ -487,9 +490,9 @@ Constraint CpModelBuilder::AddGreaterThan(const LinearExpr& left, const LinearExpr& right) { ConstraintProto* const proto = cp_model_.add_constraints(); FillLinearTerms(left, right, proto->mutable_linear()); - const int64 rhs = right.constant() - left.constant(); + const int64_t rhs = right.constant() - left.constant(); proto->mutable_linear()->add_domain(rhs + 1); - proto->mutable_linear()->add_domain(kint64max); + proto->mutable_linear()->add_domain(std::numeric_limits::max()); return Constraint(proto); } @@ -497,8 +500,8 @@ Constraint CpModelBuilder::AddLessThan(const LinearExpr& left, const LinearExpr& right) { ConstraintProto* const proto = cp_model_.add_constraints(); FillLinearTerms(left, right, proto->mutable_linear()); - const int64 rhs = right.constant() - left.constant(); - proto->mutable_linear()->add_domain(kint64min); + const int64_t rhs = right.constant() - left.constant(); + proto->mutable_linear()->add_domain(std::numeric_limits::min()); proto->mutable_linear()->add_domain(rhs - 1); return Constraint(proto); } @@ -509,10 +512,10 @@ Constraint CpModelBuilder::AddLinearConstraint(const LinearExpr& expr, for (const IntVar& x : expr.variables()) { proto->mutable_linear()->add_vars(x.index_); } - for (const int64 coeff : expr.coefficients()) { + for (const int64_t coeff : expr.coefficients()) { proto->mutable_linear()->add_coeffs(coeff); } - const int64 cst = expr.constant(); + const int64_t cst = expr.constant(); for (const auto& i : domain) { proto->mutable_linear()->add_domain(i.start - cst); proto->mutable_linear()->add_domain(i.end - cst); @@ -524,11 +527,11 @@ Constraint CpModelBuilder::AddNotEqual(const LinearExpr& left, const LinearExpr& right) { ConstraintProto* const proto = cp_model_.add_constraints(); FillLinearTerms(left, right, proto->mutable_linear()); - const int64 rhs = right.constant() - left.constant(); - proto->mutable_linear()->add_domain(kint64min); + const int64_t rhs = right.constant() - left.constant(); + proto->mutable_linear()->add_domain(std::numeric_limits::min()); proto->mutable_linear()->add_domain(rhs - 1); proto->mutable_linear()->add_domain(rhs + 1); - proto->mutable_linear()->add_domain(kint64max); + proto->mutable_linear()->add_domain(std::numeric_limits::max()); return Constraint(proto); } @@ -552,12 +555,12 @@ Constraint CpModelBuilder::AddVariableElement( } Constraint CpModelBuilder::AddElement(IntVar index, - absl::Span values, + absl::Span values, IntVar target) { ConstraintProto* const proto = cp_model_.add_constraints(); proto->mutable_element()->set_index(GetOrCreateIntegerIndex(index.index_)); proto->mutable_element()->set_target(GetOrCreateIntegerIndex(target.index_)); - for (int64 value : values) { + for (int64_t value : values) { proto->mutable_element()->add_vars(IndexFromConstant(value)); } return Constraint(proto); @@ -604,8 +607,8 @@ Constraint CpModelBuilder::AddInverseConstraint( return Constraint(proto); } -ReservoirConstraint CpModelBuilder::AddReservoirConstraint(int64 min_level, - int64 max_level) { +ReservoirConstraint CpModelBuilder::AddReservoirConstraint(int64_t min_level, + int64_t max_level) { ConstraintProto* const proto = cp_model_.add_constraints(); proto->mutable_reservoir()->set_min_level(min_level); proto->mutable_reservoir()->set_max_level(max_level); @@ -641,7 +644,7 @@ void CpModelBuilder::LinearExprToProto(const LinearExpr& expr, for (const IntVar var : expr.variables()) { expr_proto->add_vars(GetOrCreateIntegerIndex(var.index_)); } - for (const int64 coeff : expr.coefficients()) { + for (const int64_t coeff : expr.coefficients()) { expr_proto->add_coeffs(coeff); } expr_proto->set_offset(expr.constant()); @@ -742,7 +745,7 @@ void CpModelBuilder::Minimize(const LinearExpr& expr) { for (const IntVar& x : expr.variables()) { cp_model_.mutable_objective()->add_vars(x.index_); } - for (const int64 coeff : expr.coefficients()) { + for (const int64_t coeff : expr.coefficients()) { cp_model_.mutable_objective()->add_coeffs(coeff); } cp_model_.mutable_objective()->set_offset(expr.constant()); @@ -753,7 +756,7 @@ void CpModelBuilder::Maximize(const LinearExpr& expr) { for (const IntVar& x : expr.variables()) { cp_model_.mutable_objective()->add_vars(x.index_); } - for (const int64 coeff : expr.coefficients()) { + for (const int64_t coeff : expr.coefficients()) { cp_model_.mutable_objective()->add_coeffs(-coeff); } cp_model_.mutable_objective()->set_offset(-expr.constant()); @@ -790,7 +793,7 @@ void CpModelBuilder::AddDecisionStrategy( proto->set_domain_reduction_strategy(domain_strategy); } -void CpModelBuilder::AddHint(IntVar var, int64 value) { +void CpModelBuilder::AddHint(IntVar var, int64_t value) { cp_model_.mutable_solution_hint()->add_vars( GetOrCreateIntegerIndex(var.index_)); cp_model_.mutable_solution_hint()->add_values(value); @@ -860,15 +863,16 @@ IntervalVar CpModelBuilder::GetIntervalVarFromProtoIndex(int index) { return IntervalVar(index, &cp_model_); } -int64 SolutionIntegerValue(const CpSolverResponse& r, const LinearExpr& expr) { - int64 result = expr.constant(); +int64_t SolutionIntegerValue(const CpSolverResponse& r, + const LinearExpr& expr) { + int64_t result = expr.constant(); for (int i = 0; i < expr.variables().size(); ++i) { result += r.solution(expr.variables()[i].index_) * expr.coefficients()[i]; } return result; } -int64 SolutionIntegerMin(const CpSolverResponse& r, IntVar x) { +int64_t SolutionIntegerMin(const CpSolverResponse& r, IntVar x) { if (r.solution_size() > 0) { return r.solution(x.index_); } else { @@ -876,7 +880,7 @@ int64 SolutionIntegerMin(const CpSolverResponse& r, IntVar x) { } } -int64 SolutionIntegerMax(const CpSolverResponse& r, IntVar x) { +int64_t SolutionIntegerMax(const CpSolverResponse& r, IntVar x) { if (r.solution_size() > 0) { return r.solution(x.index_); } else { diff --git a/ortools/sat/cp_model.h b/ortools/sat/cp_model.h index a1db14b726..ae745f0350 100644 --- a/ortools/sat/cp_model.h +++ b/ortools/sat/cp_model.h @@ -38,6 +38,8 @@ #ifndef OR_TOOLS_SAT_CP_MODEL_H_ #define OR_TOOLS_SAT_CP_MODEL_H_ +#include +#include #include #include "absl/container/flat_hash_map.h" @@ -122,7 +124,7 @@ class BoolVar { BoolVar(int index, CpModelProto* cp_model); CpModelProto* cp_model_ = nullptr; - int index_ = kint32min; + int index_ = std::numeric_limits::min(); }; std::ostream& operator<<(std::ostream& os, const BoolVar& var); @@ -162,7 +164,7 @@ class IntVar { /// Adds a constant value to an integer variable and returns a linear /// expression. - LinearExpr AddConstant(int64 value) const; + LinearExpr AddConstant(int64_t value) const; /// Equality test with another IntVar. bool operator==(const IntVar& other) const { @@ -197,15 +199,15 @@ class IntVar { friend class LinearExpr; friend class IntervalVar; friend class ReservoirConstraint; - friend int64 SolutionIntegerValue(const CpSolverResponse& r, - const LinearExpr& expr); - friend int64 SolutionIntegerMin(const CpSolverResponse& r, IntVar x); - friend int64 SolutionIntegerMax(const CpSolverResponse& r, IntVar x); + friend int64_t SolutionIntegerValue(const CpSolverResponse& r, + const LinearExpr& expr); + friend int64_t SolutionIntegerMin(const CpSolverResponse& r, IntVar x); + friend int64_t SolutionIntegerMax(const CpSolverResponse& r, IntVar x); IntVar(int index, CpModelProto* cp_model); CpModelProto* cp_model_ = nullptr; - int index_ = kint32min; + int index_ = std::numeric_limits::min(); }; std::ostream& operator<<(std::ostream& os, const IntVar& var); @@ -260,48 +262,48 @@ class LinearExpr { LinearExpr(IntVar var); // NOLINT(runtime/explicit) /// Constructs a constant linear expression. - LinearExpr(int64 constant); // NOLINT(runtime/explicit) + LinearExpr(int64_t constant); // NOLINT(runtime/explicit) /// Adds a constant value to the linear expression. - LinearExpr& AddConstant(int64 value); + LinearExpr& AddConstant(int64_t value); /// Adds a single integer variable to the linear expression. void AddVar(IntVar var); /// Adds a term (var * coeff) to the linear expression. - void AddTerm(IntVar var, int64 coeff); + void AddTerm(IntVar var, int64_t coeff); /// Constructs the sum of a list of variables. static LinearExpr Sum(absl::Span vars); /// Constructs the scalar product of variables and coefficients. static LinearExpr ScalProd(absl::Span vars, - absl::Span coeffs); + absl::Span coeffs); /// Constructs the sum of a list of Booleans. static LinearExpr BooleanSum(absl::Span vars); /// Constructs the scalar product of Booleans and coefficients. static LinearExpr BooleanScalProd(absl::Span vars, - absl::Span coeffs); + absl::Span coeffs); /// Construncts var * coefficient. - static LinearExpr Term(IntVar var, int64 coefficient); + static LinearExpr Term(IntVar var, int64_t coefficient); /// Returns the vector of variables. const std::vector& variables() const { return variables_; } /// Returns the vector of coefficients. - const std::vector& coefficients() const { return coefficients_; } + const std::vector& coefficients() const { return coefficients_; } /// Returns the constant term. - int64 constant() const { return constant_; } + int64_t constant() const { return constant_; } // TODO(user): LinearExpr.DebugString() and operator<<. private: std::vector variables_; - std::vector coefficients_; - int64 constant_ = 0; + std::vector coefficients_; + int64_t constant_ = 0; }; /** @@ -385,7 +387,7 @@ class IntervalVar { IntervalVar(int index, CpModelProto* cp_model); CpModelProto* cp_model_ = nullptr; - int index_ = kint32min; + int index_ = std::numeric_limits::min(); }; std::ostream& operator<<(std::ostream& os, const IntervalVar& var); @@ -497,7 +499,7 @@ class MultipleCircuitConstraint : public Constraint { class TableConstraint : public Constraint { public: /// Adds a tuple of possible values to the constraint. - void AddTuple(absl::Span tuple); + void AddTuple(absl::Span tuple); private: friend class CpModelBuilder; @@ -518,7 +520,7 @@ class ReservoirConstraint : public Constraint { * * It will increase the used capacity by `c demand at time `c time. */ - void AddEvent(IntVar time, int64 demand); + void AddEvent(IntVar time, int64_t demand); /** * Adds a optional event @@ -526,7 +528,7 @@ class ReservoirConstraint : public Constraint { * If `c is_active is true, It will increase the used capacity by `c demand at * time `c time. */ - void AddOptionalEvent(IntVar time, int64 demand, BoolVar is_active); + void AddOptionalEvent(IntVar time, int64_t demand, BoolVar is_active); private: friend class CpModelBuilder; @@ -545,7 +547,7 @@ class ReservoirConstraint : public Constraint { class AutomatonConstraint : public Constraint { public: /// Adds a transitions to the automaton. - void AddTransition(int tail, int head, int64 transition_label); + void AddTransition(int tail, int head, int64_t transition_label); private: friend class CpModelBuilder; @@ -605,7 +607,7 @@ class CpModelBuilder { BoolVar NewBoolVar(); /// Creates a constant variable. - IntVar NewConstant(int64 value); + IntVar NewConstant(int64_t value); /// Creates an always true Boolean variable. BoolVar TrueVar(); @@ -664,7 +666,7 @@ class CpModelBuilder { IntVar target); /// Adds the element constraint: values[index] == target - Constraint AddElement(IntVar index, absl::Span values, + Constraint AddElement(IntVar index, absl::Span values, IntVar target); /** @@ -751,7 +753,8 @@ class CpModelBuilder { * It returns a ReservoirConstraint that allows adding optional and non * optional events incrementally after construction. */ - ReservoirConstraint AddReservoirConstraint(int64 min_level, int64 max_level); + ReservoirConstraint AddReservoirConstraint(int64_t min_level, + int64_t max_level); /** * @@ -857,7 +860,7 @@ class CpModelBuilder { DecisionStrategyProto::DomainReductionStrategy domain_strategy); /// Adds hinting to a variable. - void AddHint(IntVar var, int64 value); + void AddHint(IntVar var, int64_t value); /// Remove all hints. void ClearHints(); @@ -899,7 +902,7 @@ class CpModelBuilder { LinearExpressionProto* expr_proto); // Returns a (cached) integer variable index with a constant value. - int IndexFromConstant(int64 value); + int IndexFromConstant(int64_t value); // Returns a valid integer index from a BoolVar index. // If the input index is a positive, it returns this index. @@ -912,18 +915,18 @@ class CpModelBuilder { LinearConstraintProto* proto); CpModelProto cp_model_; - absl::flat_hash_map constant_to_index_map_; + absl::flat_hash_map constant_to_index_map_; absl::flat_hash_map bool_to_integer_index_map_; }; /// Evaluates the value of an linear expression in a solver response. -int64 SolutionIntegerValue(const CpSolverResponse& r, const LinearExpr& expr); +int64_t SolutionIntegerValue(const CpSolverResponse& r, const LinearExpr& expr); /// Returns the min of an integer variable in a solution. -int64 SolutionIntegerMin(const CpSolverResponse& r, IntVar x); +int64_t SolutionIntegerMin(const CpSolverResponse& r, IntVar x); /// Returns the max of an integer variable in a solution. -int64 SolutionIntegerMax(const CpSolverResponse& r, IntVar x); +int64_t SolutionIntegerMax(const CpSolverResponse& r, IntVar x); /// Evaluates the value of a Boolean literal in a solver response. bool SolutionBooleanValue(const CpSolverResponse& r, BoolVar x); diff --git a/ortools/sat/cp_model_checker.cc b/ortools/sat/cp_model_checker.cc index d0125eeea3..20f75df16f 100644 --- a/ortools/sat/cp_model_checker.cc +++ b/ortools/sat/cp_model_checker.cc @@ -14,6 +14,8 @@ #include "ortools/sat/cp_model_checker.h" #include +#include +#include #include #include @@ -64,8 +66,8 @@ bool VariableReferenceIsValid(const CpModelProto& model, int reference) { bool LiteralReferenceIsValid(const CpModelProto& model, int reference) { if (!VariableReferenceIsValid(model, reference)) return false; const auto& var_proto = model.variables(PositiveRef(reference)); - const int64 min_domain = var_proto.domain(0); - const int64 max_domain = var_proto.domain(var_proto.domain_size() - 1); + const int64_t min_domain = var_proto.domain(0); + const int64_t max_domain = var_proto.domain(var_proto.domain_size() - 1); return min_domain >= 0 && max_domain <= 1; } @@ -87,9 +89,10 @@ std::string ValidateIntegerVariable(const CpModelProto& model, int v) { // Internally, we often take the negation of a domain, and we also want to // have sentinel values greater than the min/max of a variable domain, so // the domain must fall in [kint64min + 2, kint64max - 1]. - const int64 lb = proto.domain(0); - const int64 ub = proto.domain(proto.domain_size() - 1); - if (lb < kint64min + 2 || ub > kint64max - 1) { + const int64_t lb = proto.domain(0); + const int64_t ub = proto.domain(proto.domain_size() - 1); + if (lb < std::numeric_limits::min() + 2 || + ub > std::numeric_limits::max() - 1) { return absl::StrCat( "var #", v, " domain do not fall in [kint64min + 2, kint64max - 1]. ", ProtobufShortDebugString(proto)); @@ -97,7 +100,7 @@ std::string ValidateIntegerVariable(const CpModelProto& model, int v) { // We do compute ub - lb in some place in the code and do not want to deal // with overflow everywhere. This seems like a reasonable precondition anyway. - if (lb < 0 && lb + kint64max < ub) { + if (lb < 0 && lb + std::numeric_limits::max() < ub) { return absl::StrCat( "var #", v, " has a domain that is too large, i.e. |UB - LB| overflow an int64: ", @@ -150,31 +153,34 @@ std::string ValidateArgumentReferencesInConstraint(const CpModelProto& model, template bool PossibleIntegerOverflow(const CpModelProto& model, const LinearExpressionProto& proto) { - int64 sum_min = 0; - int64 sum_max = 0; + int64_t sum_min = 0; + int64_t sum_max = 0; for (int i = 0; i < proto.vars_size(); ++i) { const int ref = proto.vars(i); const auto& var_proto = model.variables(PositiveRef(ref)); - const int64 min_domain = var_proto.domain(0); - const int64 max_domain = var_proto.domain(var_proto.domain_size() - 1); - if (proto.coeffs(i) == kint64min) return true; - const int64 coeff = RefIsPositive(ref) ? proto.coeffs(i) : -proto.coeffs(i); - const int64 prod1 = CapProd(min_domain, coeff); - const int64 prod2 = CapProd(max_domain, coeff); + const int64_t min_domain = var_proto.domain(0); + const int64_t max_domain = var_proto.domain(var_proto.domain_size() - 1); + if (proto.coeffs(i) == std::numeric_limits::min()) return true; + const int64_t coeff = + RefIsPositive(ref) ? proto.coeffs(i) : -proto.coeffs(i); + const int64_t prod1 = CapProd(min_domain, coeff); + const int64_t prod2 = CapProd(max_domain, coeff); // Note that we use min/max with zero to disallow "alternative" terms and // be sure that we cannot have an overflow if we do the computation in a // different order. - sum_min = CapAdd(sum_min, std::min(int64{0}, std::min(prod1, prod2))); - sum_max = CapAdd(sum_max, std::max(int64{0}, std::max(prod1, prod2))); - for (const int64 v : {prod1, prod2, sum_min, sum_max}) { - if (v == kint64max || v == kint64min) return true; + sum_min = CapAdd(sum_min, std::min(int64_t{0}, std::min(prod1, prod2))); + sum_max = CapAdd(sum_max, std::max(int64_t{0}, std::max(prod1, prod2))); + for (const int64_t v : {prod1, prod2, sum_min, sum_max}) { + if (v == std::numeric_limits::max() || + v == std::numeric_limits::min()) + return true; } } // In addition to computing the min/max possible sum, we also often compare // it with the constraint bounds, so we do not want max - min to overflow. - if (sum_min < 0 && sum_min + kint64max < sum_max) { + if (sum_min < 0 && sum_min + std::numeric_limits::max() < sum_max) { return true; } return false; @@ -325,10 +331,10 @@ std::string ValidateReservoirConstraint(const CpModelProto& model, ProtobufShortDebugString(ct)); } - int64 sum_abs = 0; - for (const int64 demand : ct.reservoir().demands()) { + int64_t sum_abs = 0; + for (const int64_t demand : ct.reservoir().demands()) { sum_abs = CapAdd(sum_abs, std::abs(demand)); - if (sum_abs == kint64max) { + if (sum_abs == std::numeric_limits::max()) { return "Possible integer overflow in constraint: " + ProtobufDebugString(ct); } @@ -591,7 +597,7 @@ namespace { class ConstraintChecker { public: - explicit ConstraintChecker(const std::vector& variable_values) + explicit ConstraintChecker(const std::vector& variable_values) : variable_values_(variable_values) {} bool LiteralIsTrue(int l) const { @@ -601,7 +607,7 @@ class ConstraintChecker { bool LiteralIsFalse(int l) const { return !LiteralIsTrue(l); } - int64 Value(int var) const { + int64_t Value(int var) const { if (var >= 0) return variable_values_[var]; return -variable_values_[-var - 1]; } @@ -652,7 +658,7 @@ class ConstraintChecker { } bool LinearConstraintIsFeasible(const ConstraintProto& ct) { - int64 sum = 0; + int64_t sum = 0; const int num_variables = ct.linear().coeffs_size(); for (int i = 0; i < num_variables; ++i) { sum += Value(ct.linear().vars(i)) * ct.linear().coeffs(i); @@ -661,16 +667,16 @@ class ConstraintChecker { } bool IntMaxConstraintIsFeasible(const ConstraintProto& ct) { - const int64 max = Value(ct.int_max().target()); - int64 actual_max = kint64min; + const int64_t max = Value(ct.int_max().target()); + int64_t actual_max = std::numeric_limits::min(); for (int i = 0; i < ct.int_max().vars_size(); ++i) { actual_max = std::max(actual_max, Value(ct.int_max().vars(i))); } return max == actual_max; } - int64 LinearExpressionValue(const LinearExpressionProto& expr) const { - int64 sum = expr.offset(); + int64_t LinearExpressionValue(const LinearExpressionProto& expr) const { + int64_t sum = expr.offset(); const int num_variables = expr.vars_size(); for (int i = 0; i < num_variables; ++i) { sum += Value(expr.vars(i)) * expr.coeffs(i); @@ -679,18 +685,18 @@ class ConstraintChecker { } bool LinMaxConstraintIsFeasible(const ConstraintProto& ct) { - const int64 max = LinearExpressionValue(ct.lin_max().target()); - int64 actual_max = kint64min; + const int64_t max = LinearExpressionValue(ct.lin_max().target()); + int64_t actual_max = std::numeric_limits::min(); for (int i = 0; i < ct.lin_max().exprs_size(); ++i) { - const int64 expr_value = LinearExpressionValue(ct.lin_max().exprs(i)); + const int64_t expr_value = LinearExpressionValue(ct.lin_max().exprs(i)); actual_max = std::max(actual_max, expr_value); } return max == actual_max; } bool IntProdConstraintIsFeasible(const ConstraintProto& ct) { - const int64 prod = Value(ct.int_prod().target()); - int64 actual_prod = 1; + const int64_t prod = Value(ct.int_prod().target()); + int64_t actual_prod = 1; for (int i = 0; i < ct.int_prod().vars_size(); ++i) { actual_prod *= Value(ct.int_prod().vars(i)); } @@ -708,8 +714,8 @@ class ConstraintChecker { } bool IntMinConstraintIsFeasible(const ConstraintProto& ct) { - const int64 min = Value(ct.int_min().target()); - int64 actual_min = kint64max; + const int64_t min = Value(ct.int_min().target()); + int64_t actual_min = std::numeric_limits::max(); for (int i = 0; i < ct.int_min().vars_size(); ++i) { actual_min = std::min(actual_min, Value(ct.int_min().vars(i))); } @@ -717,17 +723,17 @@ class ConstraintChecker { } bool LinMinConstraintIsFeasible(const ConstraintProto& ct) { - const int64 min = LinearExpressionValue(ct.lin_min().target()); - int64 actual_min = kint64max; + const int64_t min = LinearExpressionValue(ct.lin_min().target()); + int64_t actual_min = std::numeric_limits::max(); for (int i = 0; i < ct.lin_min().exprs_size(); ++i) { - const int64 expr_value = LinearExpressionValue(ct.lin_min().exprs(i)); + const int64_t expr_value = LinearExpressionValue(ct.lin_min().exprs(i)); actual_min = std::min(actual_min, expr_value); } return min == actual_min; } bool AllDiffConstraintIsFeasible(const ConstraintProto& ct) { - absl::flat_hash_set values; + absl::flat_hash_set values; for (const int v : ct.all_diff().vars()) { if (gtl::ContainsKey(values, Value(v))) return false; values.insert(Value(v)); @@ -735,32 +741,32 @@ class ConstraintChecker { return true; } - int64 IntervalStart(const IntervalConstraintProto& interval) const { + int64_t IntervalStart(const IntervalConstraintProto& interval) const { return interval.has_start_view() ? LinearExpressionValue(interval.start_view()) : Value(interval.start()); } - int64 IntervalSize(const IntervalConstraintProto& interval) const { + int64_t IntervalSize(const IntervalConstraintProto& interval) const { return interval.has_size_view() ? LinearExpressionValue(interval.size_view()) : Value(interval.size()); } - int64 IntervalEnd(const IntervalConstraintProto& interval) const { + int64_t IntervalEnd(const IntervalConstraintProto& interval) const { return interval.has_end_view() ? LinearExpressionValue(interval.end_view()) : Value(interval.end()); } bool IntervalConstraintIsFeasible(const ConstraintProto& ct) { - const int64 size = IntervalSize(ct.interval()); + const int64_t size = IntervalSize(ct.interval()); if (size < 0) return false; return IntervalStart(ct.interval()) + size == IntervalEnd(ct.interval()); } bool NoOverlapConstraintIsFeasible(const CpModelProto& model, const ConstraintProto& ct) { - std::vector> start_durations_pairs; + std::vector> start_durations_pairs; for (const int i : ct.no_overlap().intervals()) { const ConstraintProto& interval_constraint = model.constraints(i); if (ConstraintIsEnforced(interval_constraint)) { @@ -771,7 +777,7 @@ class ConstraintChecker { } } std::sort(start_durations_pairs.begin(), start_durations_pairs.end()); - int64 previous_end = kint64min; + int64_t previous_end = std::numeric_limits::min(); for (const auto pair : start_durations_pairs) { if (pair.first < previous_end) return false; previous_end = pair.first + pair.second; @@ -837,19 +843,19 @@ class ConstraintChecker { bool CumulativeConstraintIsFeasible(const CpModelProto& model, const ConstraintProto& ct) { // TODO(user,user): Improve complexity for large durations. - const int64 capacity = Value(ct.cumulative().capacity()); + const int64_t capacity = Value(ct.cumulative().capacity()); const int num_intervals = ct.cumulative().intervals_size(); - absl::flat_hash_map usage; + absl::flat_hash_map usage; for (int i = 0; i < num_intervals; ++i) { const ConstraintProto& interval_constraint = model.constraints(ct.cumulative().intervals(i)); if (ConstraintIsEnforced(interval_constraint)) { const IntervalConstraintProto& interval = interval_constraint.interval(); - const int64 start = IntervalStart(interval); - const int64 duration = IntervalSize(interval); - const int64 demand = Value(ct.cumulative().demands(i)); - for (int64 t = start; t < start + duration; ++t) { + const int64_t start = IntervalStart(interval); + const int64_t duration = IntervalSize(interval); + const int64_t demand = Value(ct.cumulative().demands(i)); + for (int64_t t = start; t < start + duration; ++t) { usage[t] += demand; if (usage[t] > capacity) return false; } @@ -879,7 +885,7 @@ class ConstraintChecker { bool AutomatonConstraintIsFeasible(const ConstraintProto& ct) { // Build the transition table {tail, label} -> head. - absl::flat_hash_map, int64> transition_map; + absl::flat_hash_map, int64_t> transition_map; const int num_transitions = ct.automaton().transition_tail().size(); for (int i = 0; i < num_transitions; ++i) { transition_map[{ct.automaton().transition_tail(i), @@ -888,11 +894,11 @@ class ConstraintChecker { } // Walk the automaton. - int64 current_state = ct.automaton().starting_state(); + int64_t current_state = ct.automaton().starting_state(); const int num_steps = ct.automaton().vars_size(); for (int i = 0; i < num_steps; ++i) { - const std::pair key = {current_state, - Value(ct.automaton().vars(i))}; + const std::pair key = {current_state, + Value(ct.automaton().vars(i))}; if (!gtl::ContainsKey(transition_map, key)) { return false; } @@ -900,7 +906,7 @@ class ConstraintChecker { } // Check we are now in a final state. - for (const int64 final : ct.automaton().final_states()) { + for (const int64_t final : ct.automaton().final_states()) { if (current_state == final) return true; } return false; @@ -1021,13 +1027,13 @@ class ConstraintChecker { bool ReservoirConstraintIsFeasible(const ConstraintProto& ct) { const int num_variables = ct.reservoir().times_size(); - const int64 min_level = ct.reservoir().min_level(); - const int64 max_level = ct.reservoir().max_level(); - std::map deltas; + const int64_t min_level = ct.reservoir().min_level(); + const int64_t max_level = ct.reservoir().max_level(); + std::map deltas; deltas[0] = 0; const bool has_active_variables = ct.reservoir().actives_size() > 0; for (int i = 0; i < num_variables; i++) { - const int64 time = Value(ct.reservoir().times(i)); + const int64_t time = Value(ct.reservoir().times(i)); if (time < 0) { VLOG(1) << "reservoir times(" << i << ") is negative."; return false; @@ -1036,7 +1042,7 @@ class ConstraintChecker { deltas[time] += ct.reservoir().demands(i); } } - int64 current_level = 0; + int64_t current_level = 0; for (const auto& delta : deltas) { current_level += delta.second; if (current_level < min_level || current_level > max_level) { @@ -1049,13 +1055,13 @@ class ConstraintChecker { } private: - std::vector variable_values_; + std::vector variable_values_; }; } // namespace bool SolutionIsFeasible(const CpModelProto& model, - const std::vector& variable_values, + const std::vector& variable_values, const CpModelProto* mapping_proto, const std::vector* postsolve_mapping) { if (variable_values.size() != model.variables_size()) { diff --git a/ortools/sat/cp_model_checker.h b/ortools/sat/cp_model_checker.h index f002a70e2d..e7885e756f 100644 --- a/ortools/sat/cp_model_checker.h +++ b/ortools/sat/cp_model_checker.h @@ -14,6 +14,7 @@ #ifndef OR_TOOLS_SAT_CP_MODEL_CHECKER_H_ #define OR_TOOLS_SAT_CP_MODEL_CHECKER_H_ +#include #include #include @@ -40,7 +41,7 @@ std::string ValidateCpModel(const CpModelProto& model); // The last two arguments are optional and help debugging a failing constraint // due to presolve. bool SolutionIsFeasible(const CpModelProto& model, - const std::vector& variable_values, + const std::vector& variable_values, const CpModelProto* mapping_proto = nullptr, const std::vector* postsolve_mapping = nullptr); diff --git a/ortools/sat/cp_model_lns.cc b/ortools/sat/cp_model_lns.cc index 4807d1d422..42f77206cc 100644 --- a/ortools/sat/cp_model_lns.cc +++ b/ortools/sat/cp_model_lns.cc @@ -13,6 +13,7 @@ #include "ortools/sat/cp_model_lns.h" +#include #include #include #include @@ -53,20 +54,20 @@ void NeighborhoodGeneratorHelper::Synchronize() { absl::MutexLock mutex_lock(&mutex_); if (shared_bounds_ != nullptr) { std::vector model_variables; - std::vector new_lower_bounds; - std::vector new_upper_bounds; + std::vector new_lower_bounds; + std::vector new_upper_bounds; shared_bounds_->GetChangedBounds(shared_bounds_id_, &model_variables, &new_lower_bounds, &new_upper_bounds); for (int i = 0; i < model_variables.size(); ++i) { const int var = model_variables[i]; - const int64 new_lb = new_lower_bounds[i]; - const int64 new_ub = new_upper_bounds[i]; + const int64_t new_lb = new_lower_bounds[i]; + const int64_t new_ub = new_upper_bounds[i]; if (VLOG_IS_ON(3)) { const auto& domain = model_proto_with_only_variables_.variables(var).domain(); - const int64 old_lb = domain.Get(0); - const int64 old_ub = domain.Get(domain.size() - 1); + const int64_t old_lb = domain.Get(0); + const int64_t old_ub = domain.Get(domain.size() - 1); VLOG(3) << "Variable: " << var << " old domain: [" << old_lb << ", " << old_ub << "] new domain: [" << new_lb << ", " << new_ub << "]"; @@ -302,7 +303,7 @@ bool NeighborhoodGenerator::ReadyToGenerate() const { return (helper_.shared_response().SolutionsRepository().NumSolutions() > 0); } -double NeighborhoodGenerator::GetUCBScore(int64 total_num_calls) const { +double NeighborhoodGenerator::GetUCBScore(int64_t total_num_calls) const { absl::MutexLock mutex_lock(&mutex_); DCHECK_GE(total_num_calls, num_calls_); if (num_calls_ <= 10) return std::numeric_limits::infinity(); @@ -601,7 +602,7 @@ Neighborhood GenerateSchedulingNeighborhoodForRelaxation( for (const int c : helper.TypeToConstraints(ConstraintProto::kNoOverlap)) { // Sort all non-relaxed intervals of this constraint by current start // time. - std::vector> start_interval_pairs; + std::vector> start_interval_pairs; for (const int i : neighborhood.cp_model.constraints(c).no_overlap().intervals()) { if (ignored_intervals.count(i)) continue; @@ -612,7 +613,7 @@ Neighborhood GenerateSchedulingNeighborhoodForRelaxation( if (initial_solution.solution(size_var) == 0) continue; const int start_var = interval_ct.interval().start(); - const int64 start_value = initial_solution.solution(start_var); + const int64_t start_value = initial_solution.solution(start_var); start_interval_pairs.push_back({start_value, i}); } std::sort(start_interval_pairs.begin(), start_interval_pairs.end()); @@ -632,7 +633,7 @@ Neighborhood GenerateSchedulingNeighborhoodForRelaxation( LinearConstraintProto* linear = neighborhood.cp_model.add_constraints()->mutable_linear(); - linear->add_domain(kint64min); + linear->add_domain(std::numeric_limits::min()); linear->add_domain(0); linear->add_vars(before_var); linear->add_coeffs(1); @@ -669,11 +670,11 @@ Neighborhood SchedulingNeighborhoodGenerator::Generate( Neighborhood SchedulingTimeWindowNeighborhoodGenerator::Generate( const CpSolverResponse& initial_solution, double difficulty, absl::BitGenRef random) { - std::vector> start_interval_pairs; + std::vector> start_interval_pairs; for (const int i : helper_.GetActiveIntervals(initial_solution)) { const ConstraintProto& interval_ct = helper_.ModelProto().constraints(i); const int start_var = interval_ct.interval().start(); - const int64 start_value = initial_solution.solution(start_var); + const int64_t start_value = initial_solution.solution(start_var); start_interval_pairs.push_back({start_value, i}); } std::sort(start_interval_pairs.begin(), start_interval_pairs.end()); @@ -769,10 +770,10 @@ Neighborhood RelaxationInducedNeighborhoodGenerator::Generate( } // Fix the variables in the local model. - for (const std::pair fixed_var : + for (const std::pair fixed_var : rins_neighborhood.fixed_vars) { const int var = fixed_var.first; - const int64 value = fixed_var.second; + const int64_t value = fixed_var.second; if (var >= neighborhood.cp_model.variables_size()) continue; if (!helper_.IsActive(var)) continue; @@ -789,11 +790,12 @@ Neighborhood RelaxationInducedNeighborhoodGenerator::Generate( neighborhood.is_reduced = true; } - for (const std::pair> + for (const std::pair> reduced_var : rins_neighborhood.reduced_domain_vars) { const int var = reduced_var.first; - const int64 lb = reduced_var.second.first; - const int64 ub = reduced_var.second.second; + const int64_t lb = reduced_var.second.first; + const int64_t ub = reduced_var.second.second; if (var >= neighborhood.cp_model.variables_size()) continue; if (!helper_.IsActive(var)) continue; Domain domain = ReadDomainFromProto(neighborhood.cp_model.variables(var)); diff --git a/ortools/sat/cp_model_lns.h b/ortools/sat/cp_model_lns.h index 9aa4f7f685..47c547e8fe 100644 --- a/ortools/sat/cp_model_lns.h +++ b/ortools/sat/cp_model_lns.h @@ -14,6 +14,7 @@ #ifndef OR_TOOLS_SAT_CP_MODEL_LNS_H_ #define OR_TOOLS_SAT_CP_MODEL_LNS_H_ +#include #include #include "absl/container/flat_hash_map.h" @@ -48,7 +49,7 @@ struct Neighborhood { // Currently only used by WeightedRandomRelaxationNeighborhoodGenerator. // TODO(user): Make sure that the id is unique for each generated // neighborhood for each generator. - int64 id = 0; + int64_t id = 0; // Used for identifying the source of the neighborhood if it is generated // using solution repositories. @@ -71,7 +72,7 @@ class NeighborhoodGeneratorHelper : public SubSolver { // SubSolver interface. bool TaskIsAvailable() override { return false; } - std::function GenerateTask(int64 task_id) override { return {}; } + std::function GenerateTask(int64_t task_id) override { return {}; } void Synchronize() override; // Returns the LNS fragment where the given variables are fixed to the value @@ -225,13 +226,13 @@ class NeighborhoodGenerator { // If the generator is called less than 10 times then the method returns // infinity as score in order to get more data about the generator // performance. - double GetUCBScore(int64 total_num_calls) const; + double GetUCBScore(int64_t total_num_calls) const; // Adds solve data about one "solved" neighborhood. struct SolveData { // Neighborhood Id. Used to identify the neighborhood by a generator. // Currently only used by WeightedRandomRelaxationNeighborhoodGenerator. - int64 neighborhood_id = 0; + int64_t neighborhood_id = 0; // The status of the sub-solve. CpSolverStatus status = CpSolverStatus::UNKNOWN; @@ -289,13 +290,13 @@ class NeighborhoodGenerator { std::string name() const { return name_; } // Number of times this generator was called. - int64 num_calls() const { + int64_t num_calls() const { absl::MutexLock mutex_lock(&mutex_); return num_calls_; } // Number of time the neighborhood was fully solved (OPTIMAL/INFEASIBLE). - int64 num_fully_solved_calls() const { + int64_t num_fully_solved_calls() const { absl::MutexLock mutex_lock(&mutex_); return num_fully_solved_calls_; } @@ -338,9 +339,9 @@ class NeighborhoodGenerator { // Current statistics of the last solved neighborhood. // Only updated on Synchronize(). - int64 num_calls_ = 0; - int64 num_fully_solved_calls_ = 0; - int64 num_consecutive_non_improving_calls_ = 0; + int64_t num_calls_ = 0; + int64_t num_fully_solved_calls_ = 0; + int64_t num_consecutive_non_improving_calls_ = 0; double deterministic_time_ = 0.0; double current_average_ = 0.0; }; @@ -520,12 +521,12 @@ class WeightedRandomRelaxationNeighborhoodGenerator int num_removable_constraints_ = 0; // Indices of the removed constraints per generated neighborhood. - absl::flat_hash_map> removed_constraints_ + absl::flat_hash_map> removed_constraints_ ABSL_GUARDED_BY(mutex_); // TODO(user): Move this to parent class if other generators start using // feedbacks. - int64 next_available_id_ ABSL_GUARDED_BY(mutex_) = 0; + int64_t next_available_id_ ABSL_GUARDED_BY(mutex_) = 0; }; } // namespace sat diff --git a/ortools/sat/cp_model_loader.cc b/ortools/sat/cp_model_loader.cc index ff37458618..1d58472454 100644 --- a/ortools/sat/cp_model_loader.cc +++ b/ortools/sat/cp_model_loader.cc @@ -14,6 +14,8 @@ #include "ortools/sat/cp_model_loader.h" #include +#include +#include #include #include #include @@ -58,20 +60,20 @@ namespace { template std::vector ValuesFromProto(const Values& values) { - return std::vector(values.begin(), values.end()); + return std::vector(values.begin(), values.end()); } void ComputeLinearBounds(const LinearConstraintProto& proto, CpModelMapping* mapping, IntegerTrail* integer_trail, - int64* sum_min, int64* sum_max) { + int64_t* sum_min, int64_t* sum_max) { *sum_min = 0; *sum_max = 0; for (int i = 0; i < proto.vars_size(); ++i) { - const int64 coeff = proto.coeffs(i); + const int64_t coeff = proto.coeffs(i); const IntegerVariable var = mapping->Integer(proto.vars(i)); - const int64 lb = integer_trail->LowerBound(var).value(); - const int64 ub = integer_trail->UpperBound(var).value(); + const int64_t lb = integer_trail->LowerBound(var).value(); + const int64_t ub = integer_trail->UpperBound(var).value(); if (coeff >= 0) { (*sum_min) += coeff * lb; (*sum_max) += coeff * ub; @@ -90,16 +92,16 @@ bool ConstraintIsEq(const LinearConstraintProto& proto) { // We check if the constraint is a sum(ax * xi) != value. bool ConstraintIsNEq(const LinearConstraintProto& proto, CpModelMapping* mapping, IntegerTrail* integer_trail, - int64* single_value) { - int64 sum_min = 0; - int64 sum_max = 0; + int64_t* single_value) { + int64_t sum_min = 0; + int64_t sum_max = 0; ComputeLinearBounds(proto, mapping, integer_trail, &sum_min, &sum_max); const Domain complement = Domain(sum_min, sum_max) .IntersectionWith(ReadDomainFromProto(proto).Complement()); if (complement.IsEmpty()) return false; - const int64 value = complement.Min(); + const int64_t value = complement.Min(); if (complement.Size() == 1) { if (single_value != nullptr) { @@ -346,7 +348,7 @@ void CpModelMapping::ExtractEncoding(const CpModelProto& model_proto, struct EqualityDetectionHelper { const ConstraintProto* ct; sat::Literal literal; - int64 value; + int64_t value; bool is_equality; // false if != instead. bool operator<(const EqualityDetectionHelper& o) const { @@ -513,7 +515,7 @@ void CpModelMapping::ExtractEncoding(const CpModelProto& model_proto, if (encoding.empty()) continue; num_constraints += encoding.size(); - absl::flat_hash_set values; + absl::flat_hash_set values; for (int j = 0; j + 1 < encoding.size(); j++) { if ((encoding[j].value != encoding[j + 1].value) || (encoding[j].literal != encoding[j + 1].literal.Negated()) || @@ -584,8 +586,8 @@ void CpModelMapping::PropagateEncodingFromEquivalenceRelations( auto* sat_solver = m->GetOrCreate(); // Loop over all contraints and find affine ones. - int64 num_associations = 0; - int64 num_set_to_false = 0; + int64_t num_associations = 0; + int64_t num_set_to_false = 0; for (const ConstraintProto& ct : model_proto.constraints()) { if (!ct.enforcement_literal().empty()) continue; if (ct.constraint_case() != ConstraintProto::kLinear) continue; @@ -722,8 +724,8 @@ void CpModelMapping::DetectOptionalVariables(const CpModelProto& model_proto, auto* integer_trail = m->GetOrCreate(); for (int var = 0; var < num_proto_variables; ++var) { const IntegerVariableProto& var_proto = model_proto.variables(var); - const int64 min = var_proto.domain(0); - const int64 max = var_proto.domain(var_proto.domain().size() - 1); + const int64_t min = var_proto.domain(0); + const int64_t max = var_proto.domain(var_proto.domain().size() - 1); if (min == max) continue; if (min == 0 && max == 1) continue; if (enforcement_intersection[var].empty()) continue; @@ -753,7 +755,7 @@ class FullEncodingFixedPointComputer { void ComputeFixedPoint(); private: - DEFINE_INT_TYPE(ConstraintIndex, int32); + DEFINE_INT_TYPE(ConstraintIndex, int32_t); // Constraint ct is interested by (full-encoding) state of variable. void Register(ConstraintIndex ct_index, int variable) { @@ -852,13 +854,13 @@ void FullEncodingFixedPointComputer::ComputeFixedPoint() { if (!mapping_->IsInteger(var) || IsFullyEncoded(var)) continue; const IntegerVariableProto& int_var_proto = model_proto_.variables(var); const Domain domain = ReadDomainFromProto(int_var_proto); - int64 domain_size = domain.Size(); - int64 num_diff_or_equal_var_constraints = 0; - int64 num_potential_encoded_values_without_bounds = 0; + int64_t domain_size = domain.Size(); + int64_t num_diff_or_equal_var_constraints = 0; + int64_t num_potential_encoded_values_without_bounds = 0; if (domain_size <= 2) continue; - const absl::flat_hash_set& value_set = + const absl::flat_hash_set& value_set = mapping_->PotentialEncodedValues(var); for (const int value : value_set) { if (value > domain.Min() && value < domain.Max() && @@ -1154,7 +1156,7 @@ void LoadLinearConstraint(const ConstraintProto& ct, Model* m) { auto* integer_trail = m->GetOrCreate(); const std::vector vars = mapping->Integers(ct.linear().vars()); - const std::vector coeffs = ValuesFromProto(ct.linear().coeffs()); + const std::vector coeffs = ValuesFromProto(ct.linear().coeffs()); // Compute the min/max to relax the bounds if needed. // @@ -1195,7 +1197,7 @@ void LoadLinearConstraint(const ConstraintProto& ct, Model* m) { IntegerValue(ct.linear().domain(0)), m); } - int64 single_value = 0; + int64_t single_value = 0; if (params.boolean_encoding_level() > 0 && ConstraintIsNEq(ct.linear(), mapping, integer_trail, &single_value) && single_value != min_sum && single_value != max_sum && @@ -1215,10 +1217,10 @@ void LoadLinearConstraint(const ConstraintProto& ct, Model* m) { } if (ct.linear().domain_size() == 2) { - int64 lb = ct.linear().domain(0); - int64 ub = ct.linear().domain(1); - if (min_sum >= lb) lb = kint64min; - if (max_sum <= ub) ub = kint64max; + int64_t lb = ct.linear().domain(0); + int64_t ub = ct.linear().domain(1); + if (min_sum >= lb) lb = std::numeric_limits::min(); + if (max_sum <= ub) ub = std::numeric_limits::max(); if (!HasEnforcementLiteral(ct)) { if (all_booleans) { @@ -1231,21 +1233,21 @@ void LoadLinearConstraint(const ConstraintProto& ct, Model* m) { } m->Add(BooleanLinearConstraint(lb, ub, &cst)); } else { - if (lb != kint64min) { + if (lb != std::numeric_limits::min()) { m->Add(WeightedSumGreaterOrEqual(vars, coeffs, lb)); } - if (ub != kint64max) { + if (ub != std::numeric_limits::max()) { m->Add(WeightedSumLowerOrEqual(vars, coeffs, ub)); } } } else { const std::vector enforcement_literals = mapping->Literals(ct.enforcement_literal()); - if (lb != kint64min) { + if (lb != std::numeric_limits::min()) { m->Add(ConditionalWeightedSumGreaterOrEqual(enforcement_literals, vars, coeffs, lb)); } - if (ub != kint64max) { + if (ub != std::numeric_limits::max()) { m->Add(ConditionalWeightedSumLowerOrEqual(enforcement_literals, vars, coeffs, ub)); } @@ -1258,21 +1260,21 @@ void LoadLinearConstraint(const ConstraintProto& ct, Model* m) { std::vector clause; for (int i = 0; i < ct.linear().domain_size(); i += 2) { - int64 lb = ct.linear().domain(i); - int64 ub = ct.linear().domain(i + 1); - if (min_sum >= lb) lb = kint64min; - if (max_sum <= ub) ub = kint64max; + int64_t lb = ct.linear().domain(i); + int64_t ub = ct.linear().domain(i + 1); + if (min_sum >= lb) lb = std::numeric_limits::min(); + if (max_sum <= ub) ub = std::numeric_limits::max(); const Literal subdomain_literal( special_case && i > 0 ? clause.back().Negated() : Literal(m->Add(NewBooleanVariable()), true)); clause.push_back(subdomain_literal); - if (lb != kint64min) { + if (lb != std::numeric_limits::min()) { m->Add(ConditionalWeightedSumGreaterOrEqual({subdomain_literal}, vars, coeffs, lb)); } - if (ub != kint64max) { + if (ub != std::numeric_limits::max()) { m->Add(ConditionalWeightedSumLowerOrEqual({subdomain_literal}, vars, coeffs, ub)); } @@ -1293,13 +1295,13 @@ void LoadAllDiffConstraint(const ConstraintProto& ct, Model* m) { IntegerTrail* integer_trail = m->GetOrCreate(); IntegerEncoder* encoder = m->GetOrCreate(); int num_fully_encoded = 0; - int64 max_domain_size = 0; + int64_t max_domain_size = 0; for (const IntegerVariable variable : vars) { if (encoder->VariableIsFullyEncoded(variable)) num_fully_encoded++; IntegerValue lb = integer_trail->LowerBound(variable); IntegerValue ub = integer_trail->UpperBound(variable); - const int64 domain_size = ub.value() - lb.value() + 1; + const int64_t domain_size = ub.value() - lb.value() + 1; max_domain_size = std::max(max_domain_size, domain_size); } @@ -1511,10 +1513,10 @@ void LoadElementConstraintBounds(const ConstraintProto& ct, Model* m) { if (vars[i] == target) continue; if (m->Get(IsFixed(target))) { - const int64 value = m->Get(Value(target)); + const int64_t value = m->Get(Value(target)); m->Add(ImpliesInInterval(r, vars[i], value, value)); } else if (m->Get(IsFixed(vars[i]))) { - const int64 value = m->Get(Value(vars[i])); + const int64_t value = m->Get(Value(vars[i])); m->Add(ImpliesInInterval(r, target, value, value)); } else { m->Add(ConditionalLowerOrEqualWithOffset(vars[i], target, 0, r)); @@ -1744,10 +1746,10 @@ void LoadTableConstraint(const ConstraintProto& ct, Model* m) { auto* mapping = m->GetOrCreate(); const std::vector vars = mapping->Integers(ct.table().vars()); - const std::vector values = ValuesFromProto(ct.table().values()); + const std::vector values = ValuesFromProto(ct.table().values()); const int num_vars = vars.size(); const int num_tuples = values.size() / num_vars; - std::vector> tuples(num_tuples); + std::vector> tuples(num_tuples); int count = 0; for (int i = 0; i < num_tuples; ++i) { for (int j = 0; j < num_vars; ++j) { @@ -1767,7 +1769,7 @@ void LoadAutomatonConstraint(const ConstraintProto& ct, Model* m) { mapping->Integers(ct.automaton().vars()); const int num_transitions = ct.automaton().transition_tail_size(); - std::vector> transitions; + std::vector> transitions; transitions.reserve(num_transitions); for (int i = 0; i < num_transitions; ++i) { transitions.push_back({ct.automaton().transition_tail(i), @@ -1775,8 +1777,8 @@ void LoadAutomatonConstraint(const ConstraintProto& ct, Model* m) { ct.automaton().transition_head(i)}); } - const int64 starting_state = ct.automaton().starting_state(); - const std::vector final_states = + const int64_t starting_state = ct.automaton().starting_state(); + const std::vector final_states = ValuesFromProto(ct.automaton().final_states()); m->Add(TransitionConstraint(vars, transitions, starting_state, final_states)); } diff --git a/ortools/sat/cp_model_loader.h b/ortools/sat/cp_model_loader.h index 9bb49b59e4..ef69230ad0 100644 --- a/ortools/sat/cp_model_loader.h +++ b/ortools/sat/cp_model_loader.h @@ -14,6 +14,7 @@ #ifndef OR_TOOLS_SAT_CP_MODEL_LOADER_H_ #define OR_TOOLS_SAT_CP_MODEL_LOADER_H_ +#include #include #include @@ -216,7 +217,7 @@ class CpModelMapping { // variable when the constraints will be loaded. // Note that the pointer is not stable across calls. // It returns nullptr if the set is empty. - const absl::flat_hash_set& PotentialEncodedValues(int var) { + const absl::flat_hash_set& PotentialEncodedValues(int var) { const auto& it = variables_to_encoded_values_.find(var); if (it != variables_to_encoded_values_.end()) { return it->second; @@ -242,9 +243,9 @@ class CpModelMapping { absl::flat_hash_set already_loaded_ct_; absl::flat_hash_set is_half_encoding_ct_; - absl::flat_hash_map> + absl::flat_hash_map> variables_to_encoded_values_; - const absl::flat_hash_set empty_set_; + const absl::flat_hash_set empty_set_; }; // Inspects the model and use some heuristic to decide which variable, if any, diff --git a/ortools/sat/cp_model_objective.cc b/ortools/sat/cp_model_objective.cc index 6f686ecda5..9449e3797a 100644 --- a/ortools/sat/cp_model_objective.cc +++ b/ortools/sat/cp_model_objective.cc @@ -13,6 +13,8 @@ #include "ortools/sat/cp_model_objective.h" +#include + #include "ortools/sat/cp_model_utils.h" namespace operations_research { @@ -25,7 +27,7 @@ void EncodeObjectiveAsSingleVariable(CpModelProto* cp_model) { // Canonicalize the objective to make it easier on us by always making the // coefficient equal to 1.0. const int old_ref = cp_model->objective().vars(0); - const int64 old_coeff = cp_model->objective().coeffs(0); + const int64_t old_coeff = cp_model->objective().coeffs(0); const double muliplier = static_cast(std::abs(old_coeff)); if (old_coeff < 0) { cp_model->mutable_objective()->set_vars(0, NegatedRef(old_ref)); @@ -48,17 +50,17 @@ void EncodeObjectiveAsSingleVariable(CpModelProto* cp_model) { // overflow checker might not be happy with the new constraint we are about // to create. Note that the model validator should make sure that there is no // overflow in the computation below. - int64 min_obj = 0; - int64 max_obj = 0; + int64_t min_obj = 0; + int64_t max_obj = 0; for (int i = 0; i < cp_model->objective().vars_size(); ++i) { const int ref = cp_model->objective().vars(i); const int var = PositiveRef(ref); - const int64 coeff = + const int64_t coeff = cp_model->objective().coeffs(i) * (RefIsPositive(ref) ? 1 : -1); - const int64 value1 = cp_model->variables(var).domain(0) * coeff; - const int64 value2 = cp_model->variables(var).domain( - cp_model->variables(var).domain_size() - 1) * - coeff; + const int64_t value1 = cp_model->variables(var).domain(0) * coeff; + const int64_t value2 = cp_model->variables(var).domain( + cp_model->variables(var).domain_size() - 1) * + coeff; min_obj += std::min(value1, value2); max_obj += std::max(value1, value2); } diff --git a/ortools/sat/cp_model_postsolve.cc b/ortools/sat/cp_model_postsolve.cc index 1665c72517..0fbffb97a1 100644 --- a/ortools/sat/cp_model_postsolve.cc +++ b/ortools/sat/cp_model_postsolve.cc @@ -13,6 +13,9 @@ #include "ortools/sat/cp_model_postsolve.h" +#include +#include + #include "ortools/sat/cp_model_utils.h" namespace operations_research { @@ -81,13 +84,13 @@ void PostsolveExactlyOne(const ConstraintProto& ct, void PostsolveLinear(const ConstraintProto& ct, const std::vector& prefer_lower_value, std::vector* domains) { - int64 fixed_activity = 0; + int64_t fixed_activity = 0; const int size = ct.linear().vars().size(); std::vector free_vars; - std::vector free_coeffs; + std::vector free_coeffs; for (int i = 0; i < size; ++i) { const int var = ct.linear().vars(i); - const int64 coeff = ct.linear().coeffs(i); + const int64_t coeff = ct.linear().coeffs(i); CHECK_LT(var, domains->size()); if (coeff == 0) continue; if ((*domains)[var].IsFixed()) { @@ -106,7 +109,7 @@ void PostsolveLinear(const ConstraintProto& ct, const Domain domain = initial_rhs.AdditionWith(Domain(-fixed_activity)) .InverseMultiplicationBy(free_coeffs[0]) .IntersectionWith((*domains)[var]); - const int64 value = prefer_lower_value[var] ? domain.Min() : domain.Max(); + const int64_t value = prefer_lower_value[var] ? domain.Min() : domain.Max(); (*domains)[var] = Domain(value); return; } @@ -134,7 +137,7 @@ void PostsolveLinear(const ConstraintProto& ct, // fixed_activity. This will crash if the intersection is empty, but it // shouldn't be. const int var = free_vars[i]; - const int64 coeff = free_coeffs[i]; + const int64_t coeff = free_coeffs[i]; const Domain domain = rhs_domains[i] .AdditionWith(Domain(-fixed_activity)) .InverseMultiplicationBy(coeff) @@ -144,7 +147,7 @@ void PostsolveLinear(const ConstraintProto& ct, // case, so if this fail, it might indicate an issue here and not in the // presolve/solver code. CHECK(!domain.IsEmpty()) << ct.ShortDebugString(); - const int64 value = prefer_lower_value[var] ? domain.Min() : domain.Max(); + const int64_t value = prefer_lower_value[var] ? domain.Min() : domain.Max(); (*domains)[var] = Domain(value); fixed_activity += coeff * value; @@ -155,17 +158,17 @@ void PostsolveLinear(const ConstraintProto& ct, // We assign any non fixed lhs variables to their minimum value. Then we assign // the target to the max. This should always be feasible. void PostsolveIntMax(const ConstraintProto& ct, std::vector* domains) { - int64 m = kint64min; + int64_t m = std::numeric_limits::min(); for (const int ref : ct.int_max().vars()) { const int var = PositiveRef(ref); if (!(*domains)[var].IsFixed()) { // Assign to minimum value. - const int64 value = + const int64_t value = RefIsPositive(ref) ? (*domains)[var].Min() : (*domains)[var].Max(); (*domains)[var] = Domain(value); } - const int64 value = (*domains)[var].FixedValue(); + const int64_t value = (*domains)[var].FixedValue(); m = std::max(m, RefIsPositive(ref) ? value : -value); } const int target_ref = ct.int_max().target(); @@ -190,7 +193,7 @@ void PostsolveElement(const ConstraintProto& ct, std::vector* domains) { // whatever the value of the index and selected variable, we can choose a // valid target, so we just fix the index to its min value in this case. if (!(*domains)[target_var].IsFixed() && !(*domains)[index_var].IsFixed()) { - const int64 index_value = (*domains)[index_var].Min(); + const int64_t index_value = (*domains)[index_var].Min(); (*domains)[index_var] = Domain(index_value); // If the selected variable is not fixed, we also need to fix it. @@ -204,11 +207,11 @@ void PostsolveElement(const ConstraintProto& ct, std::vector* domains) { // Deal with fixed index (and constant vars). if ((*domains)[index_var].IsFixed()) { - const int64 index_value = (*domains)[index_var].FixedValue(); + const int64_t index_value = (*domains)[index_var].FixedValue(); const int selected_ref = ct.element().vars( RefIsPositive(index_ref) ? index_value : -index_value); const int selected_var = PositiveRef(selected_ref); - const int64 selected_value = (*domains)[selected_var].FixedValue(); + const int64_t selected_value = (*domains)[selected_var].FixedValue(); (*domains)[target_var] = (*domains)[target_var].IntersectionWith( Domain(RefIsPositive(target_ref) == RefIsPositive(selected_ref) ? selected_value @@ -218,12 +221,12 @@ void PostsolveElement(const ConstraintProto& ct, std::vector* domains) { } // Deal with fixed target (and constant vars). - const int64 target_value = (*domains)[target_var].FixedValue(); + const int64_t target_value = (*domains)[target_var].FixedValue(); int selected_index_value = -1; for (int i = 0; i < ct.element().vars().size(); ++i) { const int ref = ct.element().vars(i); const int var = PositiveRef(ref); - const int64 value = (*domains)[var].FixedValue(); + const int64_t value = (*domains)[var].FixedValue(); if (RefIsPositive(target_ref) == RefIsPositive(ref)) { if (value == target_value) { selected_index_value = i; @@ -243,7 +246,7 @@ void PostsolveElement(const ConstraintProto& ct, std::vector* domains) { DCHECK(!(*domains)[index_var].IsEmpty()); } -void PostsolveResponse(const int64 num_variables_in_original_model, +void PostsolveResponse(const int64_t num_variables_in_original_model, const CpModelProto& mapping_proto, const std::vector& postsolve_mapping, CpSolverResponse* response) { @@ -285,7 +288,7 @@ void PostsolveResponse(const int64 num_variables_in_original_model, const int size = mapping_proto.objective().vars().size(); for (int i = 0; i < size; ++i) { int var = mapping_proto.objective().vars(i); - int64 coeff = mapping_proto.objective().coeffs(i); + int64_t coeff = mapping_proto.objective().coeffs(i); if (!RefIsPositive(var)) { var = PositiveRef(var); coeff = -coeff; diff --git a/ortools/sat/cp_model_postsolve.h b/ortools/sat/cp_model_postsolve.h index f82b1103f5..dbd791f860 100644 --- a/ortools/sat/cp_model_postsolve.h +++ b/ortools/sat/cp_model_postsolve.h @@ -14,6 +14,7 @@ #ifndef OR_TOOLS_SAT_CP_MODEL_POSTSOLVE_H_ #define OR_TOOLS_SAT_CP_MODEL_POSTSOLVE_H_ +#include #include #include "ortools/base/integral_types.h" @@ -40,7 +41,7 @@ namespace sat { // // TODO(user): We could use the search strategy to fix free variables to some // chosen values? The feature might never be needed though. -void PostsolveResponse(const int64 num_variables_in_original_model, +void PostsolveResponse(const int64_t num_variables_in_original_model, const CpModelProto& mapping_proto, const std::vector& postsolve_mapping, CpSolverResponse* response); diff --git a/ortools/sat/cp_model_presolve.cc b/ortools/sat/cp_model_presolve.cc index 1433213a13..d1c078f032 100644 --- a/ortools/sat/cp_model_presolve.cc +++ b/ortools/sat/cp_model_presolve.cc @@ -16,8 +16,10 @@ #include #include +#include #include #include +#include #include #include #include @@ -119,7 +121,7 @@ bool CpModelPresolver::PresolveEnforcementLiteral(ConstraintProto* ct) { // to false. TODO(user): generalize if the literal always appear with the // same polarity. if (context_->VariableWithCostIsUniqueAndRemovable(literal)) { - const int64 obj_coeff = + const int64_t obj_coeff = gtl::FindOrDie(context_->ObjectiveMap(), PositiveRef(literal)); if (RefIsPositive(literal) == (obj_coeff > 0)) { // It is just more advantageous to set it to false! @@ -142,7 +144,7 @@ bool CpModelPresolver::PresolveBoolXor(ConstraintProto* ct) { int new_size = 0; bool changed = false; int num_true_literals = 0; - int true_literal = kint32min; + int true_literal = std::numeric_limits::min(); for (const int literal : ct->bool_xor().literals()) { // TODO(user): More generally, if a variable appear in only bool xor // constraints, we can simply eliminate it using linear algebra on Z/2Z. @@ -172,7 +174,7 @@ bool CpModelPresolver::PresolveBoolXor(ConstraintProto* ct) { context_->UpdateRuleStats("TODO bool_xor: two active literals"); } if (num_true_literals % 2 == 1) { - CHECK_NE(true_literal, kint32min); + CHECK_NE(true_literal, std::numeric_limits::min()); ct->mutable_bool_xor()->set_literals(new_size++, true_literal); } if (num_true_literals > 1) { @@ -327,7 +329,7 @@ bool CpModelPresolver::PresolveBoolAnd(ConstraintProto* ct) { const int enforcement = ct->enforcement_literal(0); if (context_->VariableWithCostIsUniqueAndRemovable(enforcement)) { int var = PositiveRef(enforcement); - int64 obj_coeff = gtl::FindOrDie(context_->ObjectiveMap(), var); + int64_t obj_coeff = gtl::FindOrDie(context_->ObjectiveMap(), var); if (!RefIsPositive(enforcement)) obj_coeff = -obj_coeff; // The other case where the constraint is redundant is treated elsewhere. @@ -414,7 +416,7 @@ bool CpModelPresolver::PresolveAtMostOrExactlyOne(ConstraintProto* ct) { context_->VariableWithCostIsUniqueAndRemovable(literal)) { const auto it = context_->ObjectiveMap().find(PositiveRef(literal)); CHECK(it != context_->ObjectiveMap().end()); - const int64 coeff = it->second; + const int64_t coeff = it->second; // Fixing it to zero need to go in the correct direction. is_removable = (coeff > 0) == RefIsPositive(literal); @@ -515,8 +517,8 @@ bool CpModelPresolver::PresolveIntMax(ConstraintProto* ct) { const int target_ref = ct->int_max().target(); // Pass 1, compute the infered min of the target, and remove duplicates. - int64 infered_min = kint64min; - int64 infered_max = kint64min; + int64_t infered_min = std::numeric_limits::min(); + int64_t infered_max = std::numeric_limits::min(); bool contains_target_ref = false; std::set used_ref; int new_size = 0; @@ -525,7 +527,7 @@ bool CpModelPresolver::PresolveIntMax(ConstraintProto* ct) { if (gtl::ContainsKey(used_ref, ref)) continue; if (gtl::ContainsKey(used_ref, NegatedRef(ref)) || ref == NegatedRef(target_ref)) { - infered_min = std::max(infered_min, int64{0}); + infered_min = std::max(infered_min, int64_t{0}); } used_ref.insert(ref); ct->mutable_int_max()->set_vars(new_size++, ref); @@ -548,7 +550,7 @@ bool CpModelPresolver::PresolveIntMax(ConstraintProto* ct) { arg->add_vars(ref); arg->add_coeffs(-1); arg->add_domain(0); - arg->add_domain(kint64max); + arg->add_domain(std::numeric_limits::max()); } return RemoveConstraint(ct); } @@ -574,7 +576,9 @@ bool CpModelPresolver::PresolveIntMax(ConstraintProto* ct) { // then the constraint is really max(...) <= target_ub and we can simplify it. if (context_->VariableIsUniqueAndRemovable(target_ref)) { const Domain& target_domain = context_->DomainOf(target_ref); - if (infered_domain.IntersectionWith(Domain(kint64min, target_domain.Max())) + if (infered_domain + .IntersectionWith(Domain(std::numeric_limits::min(), + target_domain.Max())) .IsIncludedIn(target_domain)) { if (infered_domain.Max() <= target_domain.Max()) { // The constraint is always satisfiable. @@ -584,7 +588,8 @@ bool CpModelPresolver::PresolveIntMax(ConstraintProto* ct) { for (const int ref : ct->int_max().vars()) { context_->UpdateRuleStats("int_max: lower than constant"); if (!context_->IntersectDomainWith( - ref, Domain(kint64min, target_domain.Max()))) { + ref, Domain(std::numeric_limits::min(), + target_domain.Max()))) { return false; } } @@ -597,7 +602,7 @@ bool CpModelPresolver::PresolveIntMax(ConstraintProto* ct) { *(new_ct->mutable_enforcement_literal()) = ct->enforcement_literal(); ct->mutable_linear()->add_vars(ref); ct->mutable_linear()->add_coeffs(1); - ct->mutable_linear()->add_domain(kint64min); + ct->mutable_linear()->add_domain(std::numeric_limits::min()); ct->mutable_linear()->add_domain(target_domain.Max()); } } @@ -612,11 +617,12 @@ bool CpModelPresolver::PresolveIntMax(ConstraintProto* ct) { // Pass 2, update the argument domains. Filter them eventually. new_size = 0; const int size = ct->int_max().vars_size(); - const int64 target_max = context_->MaxOf(target_ref); + const int64_t target_max = context_->MaxOf(target_ref); for (const int ref : ct->int_max().vars()) { if (!HasEnforcementLiteral(*ct)) { - if (!context_->IntersectDomainWith(ref, Domain(kint64min, target_max), - &domain_reduced)) { + if (!context_->IntersectDomainWith( + ref, Domain(std::numeric_limits::min(), target_max), + &domain_reduced)) { return true; } } @@ -691,7 +697,7 @@ bool CpModelPresolver::PresolveLinMax(ConstraintProto* ct) { // TODO(user): Remove duplicate expressions. This might be expensive. // Pass 1, Compute the infered min of the target. - int64 infered_min = context_->MinOf(ct->lin_max().target()); + int64_t infered_min = context_->MinOf(ct->lin_max().target()); for (const LinearExpressionProto& expr : ct->lin_max().exprs()) { // TODO(user): Check if the expressions contain target. @@ -729,8 +735,9 @@ bool CpModelPresolver::PresolveIntAbs(ConstraintProto* ct) { // Propagate from the variable domain to the target variable. const Domain var_domain = context_->DomainOf(var); - const Domain new_target_domain = var_domain.UnionWith(var_domain.Negation()) - .IntersectionWith({0, kint64max}); + const Domain new_target_domain = + var_domain.UnionWith(var_domain.Negation()) + .IntersectionWith({0, std::numeric_limits::max()}); if (!context_->DomainOf(target_ref).IsIncludedIn(new_target_domain)) { if (!context_->IntersectDomainWith(target_ref, new_target_domain)) { return true; @@ -824,7 +831,7 @@ bool CpModelPresolver::PresolveIntProd(ConstraintProto* ct) { // Replace any affine relation without offset. // TODO(user): Also remove constant rhs variables. - int64 constant = 1; + int64_t constant = 1; for (int i = 0; i < ct->int_prod().vars().size(); ++i) { const int ref = ct->int_prod().vars(i); const AffineRelation::Relation& r = context_->GetAffineRelation(ref); @@ -902,7 +909,7 @@ bool CpModelPresolver::PresolveIntProd(ConstraintProto* ct) { if (context_->IsFixed(b)) std::swap(a, b); if (context_->IsFixed(a)) { - const int64 value_a = context_->MinOf(a); + const int64_t value_a = context_->MinOf(a); if (value_a == 0) { // Fix target to 0. if (!context_->IntersectDomainWith(product, Domain(0, 0))) { return false; @@ -986,7 +993,7 @@ bool CpModelPresolver::PresolveIntDiv(ConstraintProto* ct) { return false; } - const int64 divisor = context_->MinOf(ref_div); + const int64_t divisor = context_->MinOf(ref_div); if (divisor == 1) { LinearConstraintProto* const lin = context_->working_model->add_constraints()->mutable_linear(); @@ -1095,10 +1102,10 @@ void CpModelPresolver::DivideLinearByGcd(ConstraintProto* ct) { if (context_->ModelIsUnsat()) return; // Compute the GCD of all coefficients. - int64 gcd = 0; + int64_t gcd = 0; const int num_vars = ct->linear().vars().size(); for (int i = 0; i < num_vars; ++i) { - const int64 magnitude = std::abs(ct->linear().coeffs(i)); + const int64_t magnitude = std::abs(ct->linear().coeffs(i)); gcd = MathUtil::GCD64(gcd, magnitude); if (gcd == 1) break; } @@ -1125,7 +1132,7 @@ void CpModelPresolver::PresolveLinearEqualityModuloTwo(ConstraintProto* ct) { // The case modulo 2 is interesting if the non-zero terms are Booleans. std::vector literals; for (int i = 0; i < ct->linear().vars().size(); ++i) { - const int64 coeff = ct->linear().coeffs(i); + const int64_t coeff = ct->linear().coeffs(i); const int ref = ct->linear().vars(i); if (coeff % 2 == 0) continue; if (!context_->CanBeUsedAsLiteral(ref)) return; @@ -1133,11 +1140,11 @@ void CpModelPresolver::PresolveLinearEqualityModuloTwo(ConstraintProto* ct) { if (literals.size() > 2) return; } if (literals.size() == 1) { - const int64 rhs = std::abs(ct->linear().domain(0)); + const int64_t rhs = std::abs(ct->linear().domain(0)); context_->UpdateRuleStats("linear: only one odd Boolean in equality"); if (!context_->IntersectDomainWith(literals[0], Domain(rhs % 2))) return; } else if (literals.size() == 2) { - const int64 rhs = std::abs(ct->linear().domain(0)); + const int64_t rhs = std::abs(ct->linear().domain(0)); context_->UpdateRuleStats("linear: only two odd Booleans in equality"); if (rhs % 2) { context_->StoreBooleanEqualityRelation(literals[0], @@ -1150,20 +1157,20 @@ void CpModelPresolver::PresolveLinearEqualityModuloTwo(ConstraintProto* ct) { template bool CpModelPresolver::CanonicalizeLinearExpressionInternal( - const ConstraintProto& ct, ProtoWithVarsAndCoeffs* proto, int64* offset) { + const ConstraintProto& ct, ProtoWithVarsAndCoeffs* proto, int64_t* offset) { // First regroup the terms on the same variables and sum the fixed ones. // // TODO(user): Add a quick pass to skip most of the work below if the // constraint is already in canonical form? tmp_terms_.clear(); - int64 sum_of_fixed_terms = 0; + int64_t sum_of_fixed_terms = 0; bool remapped = false; const int old_size = proto->vars().size(); DCHECK_EQ(old_size, proto->coeffs().size()); for (int i = 0; i < old_size; ++i) { const int ref = proto->vars(i); const int var = PositiveRef(ref); - const int64 coeff = + const int64_t coeff = RefIsPositive(ref) ? proto->coeffs(i) : -proto->coeffs(i); if (coeff == 0) continue; @@ -1203,7 +1210,7 @@ bool CpModelPresolver::CanonicalizeLinearExpressionInternal( proto->clear_coeffs(); std::sort(tmp_terms_.begin(), tmp_terms_.end()); int current_var = 0; - int64 current_coeff = 0; + int64_t current_coeff = 0; for (const auto entry : tmp_terms_) { CHECK(RefIsPositive(entry.first)); if (entry.first == current_var) { @@ -1233,7 +1240,7 @@ bool CpModelPresolver::CanonicalizeLinearExpressionInternal( bool CpModelPresolver::CanonicalizeLinearExpression( const ConstraintProto& ct, LinearExpressionProto* exp) { - int64 offset = 0; + int64_t offset = 0; const bool result = CanonicalizeLinearExpressionInternal(ct, exp, &offset); exp->set_offset(exp->offset() + offset); return result; @@ -1244,7 +1251,7 @@ bool CpModelPresolver::CanonicalizeLinear(ConstraintProto* ct) { context_->ModelIsUnsat()) { return false; } - int64 offset = 0; + int64_t offset = 0; const bool result = CanonicalizeLinearExpressionInternal(*ct, ct->mutable_linear(), &offset); if (offset != 0) { @@ -1271,7 +1278,7 @@ bool CpModelPresolver::RemoveSingletonInLinear(ConstraintProto* ct) { // in which they will be removed. for (int i = 0; i < num_vars; ++i) { const int var = ct->linear().vars(i); - const int64 coeff = ct->linear().coeffs(i); + const int64_t coeff = ct->linear().coeffs(i); CHECK(RefIsPositive(var)); if (context_->VariableIsUniqueAndRemovable(var)) { bool exact; @@ -1306,7 +1313,7 @@ bool CpModelPresolver::RemoveSingletonInLinear(ConstraintProto* ct) { for (int i = 0; i < num_vars; ++i) { const int var = ct->linear().vars(i); - const int64 coeff = ct->linear().coeffs(i); + const int64_t coeff = ct->linear().coeffs(i); CHECK(RefIsPositive(var)); // If the variable appear only in the objective and we have an equality, @@ -1324,7 +1331,7 @@ bool CpModelPresolver::RemoveSingletonInLinear(ConstraintProto* ct) { // // TODO(user): If the objective is a single variable, we can actually // "absorb" any factor into the objective scaling. - const int64 objective_coeff = + const int64_t objective_coeff = gtl::FindOrDie(context_->ObjectiveMap(), var); CHECK_NE(coeff, 0); if (objective_coeff % coeff != 0) continue; @@ -1435,7 +1442,7 @@ bool CpModelPresolver::PresolveSmallLinear(ConstraintProto* ct) { context_->UpdateRuleStats("linear: remove abs from abs(x) in domain"); const Domain implied_abs_target_domain = ReadDomainFromProto(ct->linear()) - .IntersectionWith({0, kint64max}) + .IntersectionWith({0, std::numeric_limits::max()}) .IntersectionWith(context_->DomainOf(ct->linear().vars(0))); if (implied_abs_target_domain.IsEmpty()) { @@ -1474,12 +1481,12 @@ bool CpModelPresolver::PresolveSmallLinear(ConstraintProto* ct) { const LinearConstraintProto& linear = ct->linear(); const int ref = linear.vars(0); const int var = PositiveRef(ref); - const int64 coeff = + const int64_t coeff = RefIsPositive(ref) ? ct->linear().coeffs(0) : -ct->linear().coeffs(0); if (linear.domain_size() == 2 && linear.domain(0) == linear.domain(1)) { - const int64 value = RefIsPositive(ref) ? linear.domain(0) * coeff - : -linear.domain(0) * coeff; + const int64_t value = RefIsPositive(ref) ? linear.domain(0) * coeff + : -linear.domain(0) * coeff; if (context_->StoreLiteralImpliesVarEqValue(literal, var, value)) { // The domain is not actually modified, but we want to rescan the // constraints linked to this variable. See TODO below. @@ -1489,8 +1496,8 @@ bool CpModelPresolver::PresolveSmallLinear(ConstraintProto* ct) { const Domain complement = context_->DomainOf(ref).IntersectionWith( ReadDomainFromProto(linear).Complement()); if (complement.Size() != 1) return false; - const int64 value = RefIsPositive(ref) ? complement.Min() * coeff - : -complement.Min() * coeff; + const int64_t value = RefIsPositive(ref) ? complement.Min() * coeff + : -complement.Min() * coeff; if (context_->StoreLiteralImpliesVarNEqValue(literal, var, value)) { // The domain is not actually modified, but we want to rescan the // constraints linked to this variable. See TODO below. @@ -1506,9 +1513,9 @@ bool CpModelPresolver::PresolveSmallLinear(ConstraintProto* ct) { // Size one constraint? if (ct->linear().vars().size() == 1) { - const int64 coeff = RefIsPositive(ct->linear().vars(0)) - ? ct->linear().coeffs(0) - : -ct->linear().coeffs(0); + const int64_t coeff = RefIsPositive(ct->linear().vars(0)) + ? ct->linear().coeffs(0) + : -ct->linear().coeffs(0); context_->UpdateRuleStats("linear: size one"); const int var = PositiveRef(ct->linear().vars(0)); const Domain rhs = ReadDomainFromProto(ct->linear()); @@ -1526,13 +1533,13 @@ bool CpModelPresolver::PresolveSmallLinear(ConstraintProto* ct) { const LinearConstraintProto& arg = ct->linear(); if (arg.vars_size() == 2) { const Domain rhs = ReadDomainFromProto(ct->linear()); - const int64 rhs_min = rhs.Min(); - const int64 rhs_max = rhs.Max(); + const int64_t rhs_min = rhs.Min(); + const int64_t rhs_max = rhs.Max(); if (rhs_min == rhs_max) { const int v1 = arg.vars(0); const int v2 = arg.vars(1); - const int64 coeff1 = arg.coeffs(0); - const int64 coeff2 = arg.coeffs(1); + const int64_t coeff1 = arg.coeffs(0); + const int64_t coeff2 = arg.coeffs(1); bool added = false; if (coeff1 == 1) { added = context_->StoreAffineRelation(v1, v2, -coeff2, rhs_max); @@ -1554,20 +1561,24 @@ namespace { // Return true if the given domain only restrict the values with an upper bound. bool IsLeConstraint(const Domain& domain, const Domain& all_values) { - return all_values.IntersectionWith(Domain(kint64min, domain.Max())) + return all_values + .IntersectionWith( + Domain(std::numeric_limits::min(), domain.Max())) .IsIncludedIn(domain); } // Same as IsLeConstraint() but in the other direction. bool IsGeConstraint(const Domain& domain, const Domain& all_values) { - return all_values.IntersectionWith(Domain(domain.Min(), kint64max)) + return all_values + .IntersectionWith( + Domain(domain.Min(), std::numeric_limits::max())) .IsIncludedIn(domain); } // In the equation terms + coeff * var_domain \included rhs, returns true if can // we always fix rhs to its min value for any value in terms. It is okay to // not be as generic as possible here. -bool RhsCanBeFixedToMin(int64 coeff, const Domain& var_domain, +bool RhsCanBeFixedToMin(int64_t coeff, const Domain& var_domain, const Domain& terms, const Domain& rhs) { if (var_domain.NumIntervals() != 1) return false; if (std::abs(coeff) != 1) return false; @@ -1587,7 +1598,7 @@ bool RhsCanBeFixedToMin(int64 coeff, const Domain& var_domain, return false; } -bool RhsCanBeFixedToMax(int64 coeff, const Domain& var_domain, +bool RhsCanBeFixedToMax(int64_t coeff, const Domain& var_domain, const Domain& terms, const Domain& rhs) { if (var_domain.NumIntervals() != 1) return false; if (std::abs(coeff) != 1) return false; @@ -1629,7 +1640,7 @@ bool CpModelPresolver::PropagateDomainsInLinear(int c, ConstraintProto* ct) { left_domains[0] = Domain(0); for (int i = 0; i < num_vars; ++i) { const int var = ct->linear().vars(i); - const int64 coeff = ct->linear().coeffs(i); + const int64_t coeff = ct->linear().coeffs(i); CHECK(RefIsPositive(var)); term_domains[i] = context_->DomainOf(var).MultiplicationBy(coeff); left_domains[i + 1] = @@ -1673,7 +1684,7 @@ bool CpModelPresolver::PropagateDomainsInLinear(int c, ConstraintProto* ct) { term_domains[num_vars] = Domain(0); for (int i = num_vars - 1; i >= 0; --i) { const int var = ct->linear().vars(i); - const int64 var_coeff = ct->linear().coeffs(i); + const int64_t var_coeff = ct->linear().coeffs(i); right_domain = right_domain.AdditionWith(term_domains[i + 1]).RelaxIfTooComplex(); implied_term_domain = left_domains[i].AdditionWith(right_domain); @@ -1721,7 +1732,7 @@ bool CpModelPresolver::PropagateDomainsInLinear(int c, ConstraintProto* ct) { context_->VarToConstraints(var).contains(-1); const int size = context_->VarToConstraints(var).size() - (is_in_objective ? 1 : 0); - const int64 obj_coeff = + const int64_t obj_coeff = is_in_objective ? gtl::FindOrDie(context_->ObjectiveMap(), var) : 0; // We cannot fix anything if the domain of the objective is excluding @@ -1776,7 +1787,7 @@ bool CpModelPresolver::PropagateDomainsInLinear(int c, ConstraintProto* ct) { // variable altogether. if (rhs.Min() != rhs.Max() && context_->VariableWithCostIsUniqueAndRemovable(var)) { - const int64 obj_coeff = gtl::FindOrDie(context_->ObjectiveMap(), var); + const int64_t obj_coeff = gtl::FindOrDie(context_->ObjectiveMap(), var); const bool same_sign = (var_coeff > 0) == (obj_coeff > 0); bool fixed = false; if (same_sign && RhsCanBeFixedToMin(var_coeff, context_->DomainOf(var), @@ -1954,14 +1965,14 @@ void CpModelPresolver::ExtractEnforcementLiteralFromLinearConstraint( // We also do not want to split them in two. if (num_vars <= 1) return; - int64 min_sum = 0; - int64 max_sum = 0; - int64 max_coeff_magnitude = 0; + int64_t min_sum = 0; + int64_t max_sum = 0; + int64_t max_coeff_magnitude = 0; for (int i = 0; i < num_vars; ++i) { const int ref = arg.vars(i); - const int64 coeff = arg.coeffs(i); - const int64 term_a = coeff * context_->MinOf(ref); - const int64 term_b = coeff * context_->MaxOf(ref); + const int64_t coeff = arg.coeffs(i); + const int64_t term_a = coeff * context_->MinOf(ref); + const int64_t term_b = coeff * context_->MaxOf(ref); max_coeff_magnitude = std::max(max_coeff_magnitude, std::abs(coeff)); min_sum += std::min(term_a, term_b); max_sum += std::max(term_a, term_b); @@ -1974,8 +1985,8 @@ void CpModelPresolver::ExtractEnforcementLiteralFromLinearConstraint( // same. This is maybe not too important, we just don't split as often as we // could, but it is still unclear if splitting is good. const auto& domain = ct->linear().domain(); - const int64 ub_threshold = domain[domain.size() - 2] - min_sum; - const int64 lb_threshold = max_sum - domain[1]; + const int64_t ub_threshold = domain[domain.size() - 2] - min_sum; + const int64_t lb_threshold = max_sum - domain[1]; const Domain rhs_domain = ReadDomainFromProto(ct->linear()); if (max_coeff_magnitude < std::max(ub_threshold, lb_threshold)) return; @@ -2024,7 +2035,7 @@ void CpModelPresolver::ExtractEnforcementLiteralFromLinearConstraint( // Any coefficient greater than this will cause the constraint to be trivially // satisfied when the variable move away from its bound. Note that as we // remove coefficient, the threshold do not change! - const int64 threshold = lower_bounded ? ub_threshold : lb_threshold; + const int64_t threshold = lower_bounded ? ub_threshold : lb_threshold; // Do we only extract Booleans? const bool only_booleans = @@ -2033,12 +2044,12 @@ void CpModelPresolver::ExtractEnforcementLiteralFromLinearConstraint( // To avoid a quadratic loop, we will rewrite the linear expression at the // same time as we extract enforcement literals. int new_size = 0; - int64 rhs_offset = 0; + int64_t rhs_offset = 0; bool some_integer_encoding_were_extracted = false; LinearConstraintProto* mutable_arg = ct->mutable_linear(); for (int i = 0; i < arg.vars_size(); ++i) { int ref = arg.vars(i); - int64 coeff = arg.coeffs(i); + int64_t coeff = arg.coeffs(i); if (coeff < 0) { ref = NegatedRef(ref); coeff = -coeff; @@ -2091,13 +2102,13 @@ void CpModelPresolver::ExtractAtMostOneFromLinear(ConstraintProto* ct) { const LinearConstraintProto& arg = ct->linear(); const int num_vars = arg.vars_size(); - int64 min_sum = 0; - int64 max_sum = 0; + int64_t min_sum = 0; + int64_t max_sum = 0; for (int i = 0; i < num_vars; ++i) { const int ref = arg.vars(i); - const int64 coeff = arg.coeffs(i); - const int64 term_a = coeff * context_->MinOf(ref); - const int64 term_b = coeff * context_->MaxOf(ref); + const int64_t coeff = arg.coeffs(i); + const int64_t term_a = coeff * context_->MinOf(ref); + const int64_t term_b = coeff * context_->MaxOf(ref); min_sum += std::min(term_a, term_b); max_sum += std::max(term_a, term_b); } @@ -2105,7 +2116,7 @@ void CpModelPresolver::ExtractAtMostOneFromLinear(ConstraintProto* ct) { std::vector at_most_one; for (int i = 0; i < num_vars; ++i) { const int ref = arg.vars(i); - const int64 coeff = arg.coeffs(i); + const int64_t coeff = arg.coeffs(i); if (context_->MinOf(ref) != 0) continue; if (context_->MaxOf(ref) != 1) continue; @@ -2147,14 +2158,14 @@ bool CpModelPresolver::PresolveLinearOnBooleans(ConstraintProto* ct) { const LinearConstraintProto& arg = ct->linear(); const int num_vars = arg.vars_size(); - int64 min_coeff = kint64max; - int64 max_coeff = 0; - int64 min_sum = 0; - int64 max_sum = 0; + int64_t min_coeff = std::numeric_limits::max(); + int64_t max_coeff = 0; + int64_t min_sum = 0; + int64_t max_sum = 0; for (int i = 0; i < num_vars; ++i) { // We assume we already ran PresolveLinear(). const int var = arg.vars(i); - const int64 coeff = arg.coeffs(i); + const int64_t coeff = arg.coeffs(i); CHECK(RefIsPositive(var)); CHECK_NE(coeff, 0); if (context_->MinOf(var) != 0) return false; @@ -2306,7 +2317,7 @@ bool CpModelPresolver::PresolveLinearOnBooleans(ConstraintProto* ct) { // is false. TODO(user): the encoding could be made better in some cases. const int max_mask = (1 << arg.vars_size()); for (int mask = 0; mask < max_mask; ++mask) { - int64 value = 0; + int64_t value = 0; for (int i = 0; i < num_vars; ++i) { if ((mask >> i) & 1) value += arg.coeffs(i); } @@ -2330,7 +2341,7 @@ bool CpModelPresolver::PresolveLinearOnBooleans(ConstraintProto* ct) { namespace { -void AddLinearExpression(int64 coeff, const LinearExpressionProto& exp, +void AddLinearExpression(int64_t coeff, const LinearExpressionProto& exp, LinearConstraintProto* linear_ct) { const int size = exp.vars().size(); for (int i = 0; i < size; ++i) { @@ -2475,7 +2486,7 @@ bool CpModelPresolver::PresolveElement(ConstraintProto* ct) { if (HasEnforcementLiteral(*ct)) return false; bool all_constants = true; - absl::flat_hash_set constant_set; + absl::flat_hash_set constant_set; bool all_included_in_target_domain = true; { @@ -2490,13 +2501,13 @@ bool CpModelPresolver::PresolveElement(ConstraintProto* ct) { // // Note that this must be done before the unique_index/target rule. if (PositiveRef(target_ref) == PositiveRef(index_ref)) { - std::vector possible_indices; + std::vector possible_indices; const Domain& index_domain = context_->DomainOf(index_ref); for (const ClosedInterval& interval : index_domain) { - for (int64 index_value = interval.start; index_value <= interval.end; + for (int64_t index_value = interval.start; index_value <= interval.end; ++index_value) { const int ref = ct->element().vars(index_value); - const int64 target_value = + const int64_t target_value = target_ref == index_ref ? index_value : -index_value; if (context_->DomainContains(ref, target_value)) { possible_indices.push_back(target_value); @@ -2518,7 +2529,7 @@ bool CpModelPresolver::PresolveElement(ConstraintProto* ct) { Domain infered_domain; const Domain& initial_index_domain = context_->DomainOf(index_ref); const Domain& target_domain = context_->DomainOf(target_ref); - std::vector possible_indices; + std::vector possible_indices; for (const ClosedInterval interval : initial_index_domain) { for (int value = interval.start; value <= interval.end; ++value) { CHECK_GE(value, 0); @@ -2586,8 +2597,8 @@ bool CpModelPresolver::PresolveElement(ConstraintProto* ct) { // variables. if (context_->MinOf(index_ref) == 0 && context_->MaxOf(index_ref) == 1 && all_constants) { - const int64 v0 = context_->MinOf(ct->element().vars(0)); - const int64 v1 = context_->MinOf(ct->element().vars(1)); + const int64_t v0 = context_->MinOf(ct->element().vars(0)); + const int64_t v1 = context_->MinOf(ct->element().vars(1)); LinearConstraintProto* const lin = context_->working_model->add_constraints()->mutable_linear(); @@ -2613,8 +2624,8 @@ bool CpModelPresolver::PresolveElement(ConstraintProto* ct) { return true; } const int r_ref = r_index.representative; - const int64 r_min = context_->MinOf(r_ref); - const int64 r_max = context_->MaxOf(r_ref); + const int64_t r_min = context_->MinOf(r_ref); + const int64_t r_max = context_->MaxOf(r_ref); const int array_size = ct->element().vars_size(); if (r_min != 0) { context_->UpdateRuleStats("TODO element: representative has bad domain"); @@ -2624,8 +2635,8 @@ bool CpModelPresolver::PresolveElement(ConstraintProto* ct) { // This will happen eventually when domains are synchronized. ElementConstraintProto* const element = context_->working_model->add_constraints()->mutable_element(); - for (int64 v = 0; v <= r_max; ++v) { - const int64 scaled_index = v * r_index.coeff + r_index.offset; + for (int64_t v = 0; v <= r_max; ++v) { + const int64_t scaled_index = v * r_index.coeff + r_index.offset; CHECK_GE(scaled_index, 0); CHECK_LT(scaled_index, array_size); element->add_vars(ct->element().vars(scaled_index)); @@ -2688,10 +2699,10 @@ bool CpModelPresolver::PresolveTable(ConstraintProto* ct) { // TODO(user): this is not supper efficient. Optimize if needed. const int num_vars = ct->table().vars_size(); const int num_tuples = ct->table().values_size() / num_vars; - std::vector tuple(num_vars); - std::vector> new_tuples; + std::vector tuple(num_vars); + std::vector> new_tuples; new_tuples.reserve(num_tuples); - std::vector> new_domains(num_vars); + std::vector> new_domains(num_vars); std::vector affine_relations; absl::flat_hash_set visited; @@ -2718,10 +2729,10 @@ bool CpModelPresolver::PresolveTable(ConstraintProto* ct) { std::string tmp; for (int j = 0; j < num_vars; ++j) { const int ref = ct->table().vars(j); - int64 v = ct->table().values(i * num_vars + j); + int64_t v = ct->table().values(i * num_vars + j); const AffineRelation::Relation& r = affine_relations[j]; if (r.representative != ref) { - const int64 inverse_value = (v - r.offset) / r.coeff; + const int64_t inverse_value = (v - r.offset) / r.coeff; if (inverse_value * r.coeff + r.offset != v) { // Bad rounding. delete_row = true; @@ -2738,7 +2749,7 @@ bool CpModelPresolver::PresolveTable(ConstraintProto* ct) { if (delete_row) continue; new_tuples.push_back(tuple); for (int j = 0; j < num_vars; ++j) { - const int64 v = tuple[j]; + const int64_t v = tuple[j]; new_domains[j].insert(v); } } @@ -2747,8 +2758,8 @@ bool CpModelPresolver::PresolveTable(ConstraintProto* ct) { // Update the list of tuples if needed. if (new_tuples.size() < num_tuples || modified_variables) { ct->mutable_table()->clear_values(); - for (const std::vector& t : new_tuples) { - for (const int64 v : t) { + for (const std::vector& t : new_tuples) { + for (const int64_t v : t) { ct->mutable_table()->add_values(v); } } @@ -2777,8 +2788,8 @@ bool CpModelPresolver::PresolveTable(ConstraintProto* ct) { const int ref = ct->table().vars(j); if (!context_->IntersectDomainWith( PositiveRef(ref), - Domain::FromValues(std::vector(new_domains[j].begin(), - new_domains[j].end())), + Domain::FromValues(std::vector(new_domains[j].begin(), + new_domains[j].end())), &changed)) { return true; } @@ -2805,11 +2816,11 @@ bool CpModelPresolver::PresolveTable(ConstraintProto* ct) { // it could. if (new_tuples.size() > 0.7 * prod) { // Enumerate all tuples. - std::vector> var_to_values(num_vars); + std::vector> var_to_values(num_vars); for (int j = 0; j < num_vars; ++j) { var_to_values[j].assign(new_domains[j].begin(), new_domains[j].end()); } - std::vector> all_tuples(prod); + std::vector> all_tuples(prod); for (int i = 0; i < prod; ++i) { all_tuples[i].resize(num_vars); int index = i; @@ -2821,15 +2832,15 @@ bool CpModelPresolver::PresolveTable(ConstraintProto* ct) { gtl::STLSortAndRemoveDuplicates(&all_tuples); // Compute the complement of new_tuples. - std::vector> diff(prod - new_tuples.size()); + std::vector> diff(prod - new_tuples.size()); std::set_difference(all_tuples.begin(), all_tuples.end(), new_tuples.begin(), new_tuples.end(), diff.begin()); // Negate the constraint. ct->mutable_table()->set_negated(!ct->table().negated()); ct->mutable_table()->clear_values(); - for (const std::vector& t : diff) { - for (const int64 v : t) ct->mutable_table()->add_values(v); + for (const std::vector& t : diff) { + for (const int64_t v : t) ct->mutable_table()->add_values(v); } context_->UpdateRuleStats("table: negated"); } @@ -2862,7 +2873,7 @@ bool CpModelPresolver::PresolveAllDiff(ConstraintProto* ct) { continue; } - const int64 value = context_->MinOf(all_diff.vars(i)); + const int64_t value = context_->MinOf(all_diff.vars(i)); bool propagated = false; for (int j = 0; j < size; ++j) { if (i == j) continue; @@ -2906,10 +2917,10 @@ bool CpModelPresolver::PresolveAllDiff(ConstraintProto* ct) { domain = domain.UnionWith(context_->DomainOf(all_diff.vars(i))); } if (all_diff.vars_size() == domain.Size()) { - absl::flat_hash_map> value_to_refs; + absl::flat_hash_map> value_to_refs; for (const int ref : all_diff.vars()) { for (const ClosedInterval& interval : context_->DomainOf(ref)) { - for (int64 v = interval.start; v <= interval.end; ++v) { + for (int64_t v = interval.start; v <= interval.end; ++v) { value_to_refs[v].push_back(ref); } } @@ -3019,23 +3030,26 @@ void ExtractClauses(bool use_bool_and, const ClauseContainer& container, } // namespace -int64 CpModelPresolver::StartMin( +int64_t CpModelPresolver::StartMin( const IntervalConstraintProto& interval) const { if (interval.has_start_view()) return context_->MinOf(interval.start_view()); return context_->MinOf(interval.start()); } -int64 CpModelPresolver::EndMax(const IntervalConstraintProto& interval) const { +int64_t CpModelPresolver::EndMax( + const IntervalConstraintProto& interval) const { if (interval.has_end_view()) return context_->MaxOf(interval.end_view()); return context_->MaxOf(interval.end()); } -int64 CpModelPresolver::SizeMin(const IntervalConstraintProto& interval) const { +int64_t CpModelPresolver::SizeMin( + const IntervalConstraintProto& interval) const { if (interval.has_size_view()) return context_->MinOf(interval.size_view()); return context_->MinOf(interval.size()); } -int64 CpModelPresolver::SizeMax(const IntervalConstraintProto& interval) const { +int64_t CpModelPresolver::SizeMax( + const IntervalConstraintProto& interval) const { if (interval.has_size_view()) return context_->MaxOf(interval.size_view()); return context_->MaxOf(interval.size()); } @@ -3071,13 +3085,13 @@ bool CpModelPresolver::PresolveNoOverlap(ConstraintProto* ct) { // // TODO(user): We might also want to split this constraints into many // independent no overlap constraints. - int64 end_max_so_far = kint64min; + int64_t end_max_so_far = std::numeric_limits::min(); new_size = 0; for (int i = 0; i < proto.intervals_size(); ++i) { const int interval_index = proto.intervals(i); const IntervalConstraintProto& interval = context_->working_model->constraints(interval_index).interval(); - const int64 end_max_of_previous_intervals = end_max_so_far; + const int64_t end_max_of_previous_intervals = end_max_so_far; end_max_so_far = std::max(end_max_so_far, EndMax(interval)); if (StartMin(interval) >= end_max_of_previous_intervals && (i + 1 == proto.intervals_size() || @@ -3121,7 +3135,7 @@ bool CpModelPresolver::PresolveCumulative(ConstraintProto* ct) { } const int demand_ref = proto.demands(i); - const int64 demand_max = context_->MaxOf(demand_ref); + const int64_t demand_max = context_->MaxOf(demand_ref); if (demand_max == 0) { num_zero_demand_removed++; continue; @@ -3157,6 +3171,7 @@ bool CpModelPresolver::PresolveCumulative(ConstraintProto* ct) { } if (HasEnforcementLiteral(*ct)) return changed; + const int64_t capacity = context_->MinOf(proto.capacity()); const int num_intervals = proto.intervals_size(); bool with_start_view = false; @@ -3183,9 +3198,8 @@ bool CpModelPresolver::PresolveCumulative(ConstraintProto* ct) { // the no-overlap and the cumulative constraint. return changed; } - - const int64 demand_min = context_->MinOf(demand_ref); - const int64 demand_max = context_->MaxOf(demand_ref); + const int64_t demand_min = context_->MinOf(demand_ref); + const int64_t demand_max = context_->MaxOf(demand_ref); if (demand_min > capacity_max / 2) { num_greater_half_capacity++; } @@ -3204,8 +3218,9 @@ bool CpModelPresolver::PresolveCumulative(ConstraintProto* ct) { if (ct.enforcement_literal().empty()) { context_->UpdateRuleStats( "cumulative: demand_max exceeds capacity max."); - if (!context_->IntersectDomainWith(demand_ref, - Domain(kint64min, capacity_max))) { + if (!context_->IntersectDomainWith( + demand_ref, + Domain(std::numeric_limits::min(), capacity_max))) { return true; } } else { @@ -3217,7 +3232,6 @@ bool CpModelPresolver::PresolveCumulative(ConstraintProto* ct) { } } } - if (num_greater_half_capacity == num_intervals) { if (num_duration_one == num_intervals && !has_optional_interval && !with_start_view) { @@ -3487,8 +3501,8 @@ bool CpModelPresolver::PresolveAutomaton(ConstraintProto* ct) { const AffineRelation::Relation rep = affine_relations.front(); int new_size = 0; for (int t = 0; t < proto.transition_tail_size(); ++t) { - const int64 label = proto.transition_label(t); - int64 inverse_label = (label - rep.offset) / rep.coeff; + const int64_t label = proto.transition_label(t); + int64_t inverse_label = (label - rep.offset) / rep.coeff; if (inverse_label * rep.coeff + rep.offset == label) { if (new_size != t) { proto.set_transition_tail(new_size, proto.transition_tail(t)); @@ -3515,7 +3529,7 @@ bool CpModelPresolver::PresolveAutomaton(ConstraintProto* ct) { int new_size = 0; for (int t = 0; t < proto.transition_tail_size(); ++t) { - const int64 label = proto.transition_label(t); + const int64_t label = proto.transition_label(t); if (hull.Contains(label)) { if (new_size != t) { proto.set_transition_tail(new_size, proto.transition_tail(t)); @@ -3537,7 +3551,7 @@ bool CpModelPresolver::PresolveAutomaton(ConstraintProto* ct) { const std::vector vars = {proto.vars().begin(), proto.vars().end()}; // Compute the set of reachable state at each time point. - std::vector> reachable_states(n + 1); + std::vector> reachable_states(n + 1); reachable_states[0].insert(proto.starting_state()); reachable_states[n] = {proto.final_states().begin(), proto.final_states().end()}; @@ -3548,24 +3562,24 @@ bool CpModelPresolver::PresolveAutomaton(ConstraintProto* ct) { // all the possible transitions. for (int time = 0; time + 1 < n; ++time) { for (int t = 0; t < proto.transition_tail_size(); ++t) { - const int64 tail = proto.transition_tail(t); - const int64 label = proto.transition_label(t); - const int64 head = proto.transition_head(t); + const int64_t tail = proto.transition_tail(t); + const int64_t label = proto.transition_label(t); + const int64_t head = proto.transition_head(t); if (!gtl::ContainsKey(reachable_states[time], tail)) continue; if (!context_->DomainContains(vars[time], label)) continue; reachable_states[time + 1].insert(head); } } - std::vector> reached_values(n); + std::vector> reached_values(n); // Backward. for (int time = n - 1; time >= 0; --time) { - std::set new_set; + std::set new_set; for (int t = 0; t < proto.transition_tail_size(); ++t) { - const int64 tail = proto.transition_tail(t); - const int64 label = proto.transition_label(t); - const int64 head = proto.transition_head(t); + const int64_t tail = proto.transition_tail(t); + const int64_t label = proto.transition_label(t); + const int64_t head = proto.transition_head(t); if (!gtl::ContainsKey(reachable_states[time], tail)) continue; if (!context_->DomainContains(vars[time], label)) continue; @@ -3638,16 +3652,16 @@ bool CpModelPresolver::PresolveReservoir(ConstraintProto* ct) { } const int num_events = mutable_reservoir.demands_size(); - int64 gcd = mutable_reservoir.demands().empty() - ? 0 - : std::abs(mutable_reservoir.demands(0)); + int64_t gcd = mutable_reservoir.demands().empty() + ? 0 + : std::abs(mutable_reservoir.demands(0)); int num_positives = 0; int num_negatives = 0; - int64 sum_of_demands = 0; - int64 max_sum_of_positive_demands = 0; - int64 min_sum_of_negative_demands = 0; + int64_t sum_of_demands = 0; + int64_t max_sum_of_positive_demands = 0; + int64_t min_sum_of_negative_demands = 0; for (int i = 0; i < num_events; ++i) { - const int64 demand = mutable_reservoir.demands(i); + const int64_t demand = mutable_reservoir.demands(i); sum_of_demands += demand; gcd = MathUtil::GCD64(gcd, std::abs(demand)); if (demand > 0) { @@ -3690,9 +3704,9 @@ bool CpModelPresolver::PresolveReservoir(ConstraintProto* ct) { // always feasible, we do not care about the order, just the sum. auto* const sum = context_->working_model->add_constraints()->mutable_linear(); - int64 fixed_contrib = 0; + int64_t fixed_contrib = 0; for (int i = 0; i < mutable_reservoir.demands_size(); ++i) { - const int64 demand = mutable_reservoir.demands(i); + const int64_t demand = mutable_reservoir.demands(i); DCHECK_NE(demand, 0); const int active = mutable_reservoir.actives(i); @@ -4148,8 +4162,8 @@ void CpModelPresolver::ExpandObjective() { var_to_process.erase(objective_var); int expanded_linear_index = -1; - int64 objective_coeff_in_expanded_constraint; - int64 size_of_expanded_constraint = 0; + int64_t objective_coeff_in_expanded_constraint; + int64_t size_of_expanded_constraint = 0; const auto& non_deterministic_list = context_->VarToConstraints(objective_var); std::vector constraints_with_objective(non_deterministic_list.begin(), @@ -4179,10 +4193,10 @@ void CpModelPresolver::ExpandObjective() { // beginning of the function when this is the case we should be safe. // However, it might be more robust to just handle this case properly. bool is_present = false; - int64 objective_coeff; + int64_t objective_coeff; for (int i = 0; i < num_terms; ++i) { const int ref = ct.linear().vars(i); - const int64 coeff = ct.linear().coeffs(i); + const int64_t coeff = ct.linear().coeffs(i); if (PositiveRef(ref) == objective_var) { CHECK(!is_present) << "Duplicate variables not supported."; is_present = true; @@ -4642,7 +4656,7 @@ bool CpModelPresolver::ProcessSetPPC() { // Signatures of all the constraints. In the signature the bit i is 1 if it // contains a literal l such that l%64 = i. - std::vector signatures; + std::vector signatures; // Graph of constraints to literals. constraint_literals[c] contains all the // literals in constraint indexed by 'c' in sorted order. @@ -4680,10 +4694,10 @@ bool CpModelPresolver::ProcessSetPPC() { ct->constraint_case() == ConstraintProto::ConstraintCase::kExactlyOne) { constraint_literals.push_back(GetLiteralsFromSetPPCConstraint(*ct)); - uint64 signature = 0; + uint64_t signature = 0; for (const int literal : constraint_literals.back()) { const int positive_literal = PositiveRef(literal); - signature |= (int64{1} << (positive_literal % 64)); + signature |= (int64_t{1} << (positive_literal % 64)); DCHECK_GE(positive_literal, 0); if (positive_literal >= literals_to_constraints.size()) { literals_to_constraints.resize(positive_literal + 1); @@ -4792,12 +4806,12 @@ void CpModelPresolver::TryToSimplifyDomain(int var) { if (domain.NumIntervals() != domain.Size()) return; - const int64 var_min = domain.Min(); - int64 gcd = domain[1].start - var_min; + const int64_t var_min = domain.Min(); + int64_t gcd = domain[1].start - var_min; for (int index = 2; index < domain.NumIntervals(); ++index) { const ClosedInterval& i = domain[index]; CHECK_EQ(i.start, i.end); - const int64 shifted_value = i.start - var_min; + const int64_t shifted_value = i.start - var_min; CHECK_GE(shifted_value, 0); gcd = MathUtil::GCD64(gcd, shifted_value); @@ -4807,11 +4821,11 @@ void CpModelPresolver::TryToSimplifyDomain(int var) { int new_var_index; { - std::vector scaled_values; + std::vector scaled_values; for (int index = 0; index < domain.NumIntervals(); ++index) { const ClosedInterval& i = domain[index]; CHECK_EQ(i.start, i.end); - const int64 shifted_value = i.start - var_min; + const int64_t shifted_value = i.start - var_min; scaled_values.push_back(shifted_value / gcd); } new_var_index = context_->NewIntVar(Domain::FromValues(scaled_values)); @@ -4825,7 +4839,7 @@ void CpModelPresolver::TryToSimplifyDomain(int var) { // Adds all affine relations to our model for the variables that are still used. void CpModelPresolver::EncodeAllAffineRelations() { - int64 num_added = 0; + int64_t num_added = 0; for (int var = 0; var < context_->working_model->variables_size(); ++var) { if (context_->IsFixed(var)) continue; @@ -4903,10 +4917,10 @@ void CpModelPresolver::PresolveToFixPoint() { if (context_->ModelIsUnsat()) return; // Limit on number of operations. - const int64 max_num_operations = + const int64_t max_num_operations = context_->params().cp_model_max_num_presolve_operations() > 0 ? context_->params().cp_model_max_num_presolve_operations() - : kint64max; + : std::numeric_limits::max(); // This is used for constraint having unique variables in them (i.e. not // appearing anywhere else) to not call the presolve more than once for this @@ -5237,7 +5251,7 @@ bool CpModelPresolver::Presolve() { ++iter) { context_->UpdateRuleStats("presolve: iteration"); // Save some quantities to decide if we abort early the iteration loop. - const int64 old_num_presolve_op = context_->num_presolve_operations; + const int64_t old_num_presolve_op = context_->num_presolve_operations; int old_num_non_empty_constraints = 0; for (int c = 0; c < context_->working_model->constraints_size(); ++c) { const auto type = @@ -5545,13 +5559,13 @@ void ApplyVariableMapping(const std::vector& mapping, int new_size = 0; for (int i = 0; i < mutable_hint->vars_size(); ++i) { const int old_ref = mutable_hint->vars(i); - const int64 old_value = mutable_hint->values(i); + const int64_t old_value = mutable_hint->values(i); // Note that if (old_value - r.offset) is not divisible by r.coeff, then // the hint is clearly infeasible, but we still set it to a "close" value. const AffineRelation::Relation r = context.GetAffineRelation(old_ref); const int var = r.representative; - const int64 value = (old_value - r.offset) / r.coeff; + const int64_t value = (old_value - r.offset) / r.coeff; const int image = mapping[var]; if (image >= 0) { @@ -5594,7 +5608,7 @@ std::vector FindDuplicateConstraints(const CpModelProto& model_proto) { // We use a map hash: serialized_constraint_proto hash -> constraint index. ConstraintProto copy; - absl::flat_hash_map equiv_constraints; + absl::flat_hash_map equiv_constraints; std::string s; const int num_constraints = model_proto.constraints().size(); diff --git a/ortools/sat/cp_model_presolve.h b/ortools/sat/cp_model_presolve.h index 22f2d6298d..37d0114f83 100644 --- a/ortools/sat/cp_model_presolve.h +++ b/ortools/sat/cp_model_presolve.h @@ -14,6 +14,7 @@ #ifndef OR_TOOLS_SAT_CP_MODEL_PRESOLVE_H_ #define OR_TOOLS_SAT_CP_MODEL_PRESOLVE_H_ +#include #include #include "ortools/sat/cp_model.pb.h" @@ -126,7 +127,7 @@ class CpModelPresolver { template bool CanonicalizeLinearExpressionInternal(const ConstraintProto& ct, ProtoWithVarsAndCoeffs* proto, - int64* offset); + int64_t* offset); bool CanonicalizeLinearExpression(const ConstraintProto& ct, LinearExpressionProto* exp); @@ -139,10 +140,10 @@ class CpModelPresolver { void PresolveLinearEqualityModuloTwo(ConstraintProto* ct); // To simplify dealing with the two kind of intervals. - int64 StartMin(const IntervalConstraintProto& interval) const; - int64 EndMax(const IntervalConstraintProto& interval) const; - int64 SizeMin(const IntervalConstraintProto& interval) const; - int64 SizeMax(const IntervalConstraintProto& interval) const; + int64_t StartMin(const IntervalConstraintProto& interval) const; + int64_t EndMax(const IntervalConstraintProto& interval) const; + int64_t SizeMin(const IntervalConstraintProto& interval) const; + int64_t SizeMax(const IntervalConstraintProto& interval) const; // SetPPC is short for set packing, partitioning and covering constraints. // These are sum of booleans <=, = and >= 1 respectively. @@ -192,7 +193,7 @@ class CpModelPresolver { PresolveContext* context_; // Used by CanonicalizeLinearExpressionInternal(). - std::vector> tmp_terms_; + std::vector> tmp_terms_; }; // Convenient wrapper to call the full presolve. diff --git a/ortools/sat/cp_model_search.cc b/ortools/sat/cp_model_search.cc index ae60d4e735..7f7ac54f18 100644 --- a/ortools/sat/cp_model_search.cc +++ b/ortools/sat/cp_model_search.cc @@ -13,6 +13,7 @@ #include "ortools/sat/cp_model_search.h" +#include #include #include "absl/container/flat_hash_map.h" @@ -40,7 +41,7 @@ struct VarValue { }; const std::function ConstructSearchStrategyInternal( - const absl::flat_hash_map>& + const absl::flat_hash_map>& var_to_coeff_offset_pair, const std::vector& strategies, Model* model) { IntegerEncoder* const integer_encoder = model->GetOrCreate(); @@ -196,7 +197,8 @@ std::function ConstructSearchStrategy( } std::vector strategies; - absl::flat_hash_map> var_to_coeff_offset_pair; + absl::flat_hash_map> + var_to_coeff_offset_pair; for (const DecisionStrategyProto& proto : cp_model_proto.search_strategy()) { strategies.push_back(Strategy()); Strategy& strategy = strategies.back(); @@ -244,7 +246,7 @@ std::function InstrumentSearchStrategy( cp_model_proto.variables(j).name(); }); - std::vector> old_domains(variable_mapping.size()); + std::vector> old_domains(variable_mapping.size()); return [instrumented_strategy, model, variable_mapping, cp_model_proto, old_domains, ref_to_display]() mutable { const BooleanOrIntegerLiteral decision = instrumented_strategy(); diff --git a/ortools/sat/cp_model_solver.cc b/ortools/sat/cp_model_solver.cc index 05644be882..71f49bea20 100644 --- a/ortools/sat/cp_model_solver.cc +++ b/ortools/sat/cp_model_solver.cc @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -192,7 +193,7 @@ std::string CpModelStats(const CpModelProto& model_proto) { } int num_constants = 0; - std::set constant_values; + std::set constant_values; std::map num_vars_per_domains; for (const IntegerVariableProto& var : model_proto.variables()) { if (var.domain_size() == 2 && var.domain(0) == var.domain(1)) { @@ -238,14 +239,14 @@ std::string CpModelStats(const CpModelProto& model_proto) { absl::StrAppend(&result, Summarize(temp)); } } else { - int64 max_complexity = 0; - int64 min = kint64max; - int64 max = kint64min; + int64_t max_complexity = 0; + int64_t min = std::numeric_limits::max(); + int64_t max = std::numeric_limits::min(); for (const auto& entry : num_vars_per_domains) { min = std::min(min, entry.first.Min()); max = std::max(max, entry.first.Max()); - max_complexity = std::max(max_complexity, - static_cast(entry.first.NumIntervals())); + max_complexity = std::max( + max_complexity, static_cast(entry.first.NumIntervals())); } absl::StrAppend(&result, " - ", num_vars_per_domains.size(), " different domains in [", min, ",", max, @@ -334,7 +335,7 @@ void FillSolutionInResponse(const CpModelProto& model_proto, const Model& model, auto* trail = model.Get(); auto* integer_trail = model.Get(); - std::vector solution; + std::vector solution; for (int i = 0; i < model_proto.variables_size(); ++i) { if (mapping->IsInteger(i)) { const IntegerVariable var = mapping->Integer(i); @@ -368,7 +369,7 @@ void FillSolutionInResponse(const CpModelProto& model_proto, const Model& model, // TODO(user): Checks against initial model. CHECK(SolutionIsFeasible(model_proto, solution)); } - for (const int64 value : solution) response->add_solution(value); + for (const int64_t value : solution) response->add_solution(value); } else { // Not all variables are fixed. // We fill instead the lb/ub of each variables. @@ -396,7 +397,8 @@ void FillSolutionInResponse(const CpModelProto& model_proto, const Model& model, namespace { IntegerVariable GetOrCreateVariableWithTightBound( - const std::vector>& terms, Model* model) { + const std::vector>& terms, + Model* model) { if (terms.empty()) return model->Add(ConstantIntegerVariable(0)); if (terms.size() == 1 && terms.front().second == 1) { return terms.front().first; @@ -405,14 +407,14 @@ IntegerVariable GetOrCreateVariableWithTightBound( return NegationOf(terms.front().first); } - int64 sum_min = 0; - int64 sum_max = 0; - for (const std::pair var_coeff : terms) { - const int64 min_domain = model->Get(LowerBound(var_coeff.first)); - const int64 max_domain = model->Get(UpperBound(var_coeff.first)); - const int64 coeff = var_coeff.second; - const int64 prod1 = min_domain * coeff; - const int64 prod2 = max_domain * coeff; + int64_t sum_min = 0; + int64_t sum_max = 0; + for (const std::pair var_coeff : terms) { + const int64_t min_domain = model->Get(LowerBound(var_coeff.first)); + const int64_t max_domain = model->Get(UpperBound(var_coeff.first)); + const int64_t coeff = var_coeff.second; + const int64_t prod1 = min_domain * coeff; + const int64_t prod2 = max_domain * coeff; sum_min += std::min(prod1, prod2); sum_max += std::max(prod1, prod2); } @@ -420,7 +422,8 @@ IntegerVariable GetOrCreateVariableWithTightBound( } IntegerVariable GetOrCreateVariableGreaterOrEqualToSumOf( - const std::vector>& terms, Model* model) { + const std::vector>& terms, + Model* model) { if (terms.empty()) return model->Add(ConstantIntegerVariable(0)); if (terms.size() == 1 && terms.front().second == 1) { return terms.front().first; @@ -433,7 +436,7 @@ IntegerVariable GetOrCreateVariableGreaterOrEqualToSumOf( const IntegerVariable new_var = GetOrCreateVariableWithTightBound(terms, model); std::vector vars; - std::vector coeffs; + std::vector coeffs; for (const auto& term : terms) { vars.push_back(term.first); coeffs.push_back(term.second); @@ -481,8 +484,8 @@ void TryToAddCutGenerators(const CpModelProto& model_proto, CreateStronglyConnectedGraphCutGenerator(num_nodes, tails, heads, literals, m)); } else { - const std::vector demands(ct.routes().demands().begin(), - ct.routes().demands().end()); + const std::vector demands(ct.routes().demands().begin(), + ct.routes().demands().end()); relaxation->cut_generators.push_back( CreateCVRPCutGenerator(num_nodes, tails, heads, literals, demands, ct.routes().capacity(), m)); @@ -852,9 +855,9 @@ IntegerVariable AddLPConstraints(const CpModelProto& model_proto, } // Add the objective. - std::vector>> + std::vector>> component_to_cp_terms(num_components); - std::vector> top_level_cp_terms; + std::vector> top_level_cp_terms; int num_components_containing_objective = 0; if (model_proto.has_objective()) { // First pass: set objective coefficients on the lp constraints, and store @@ -862,7 +865,7 @@ IntegerVariable AddLPConstraints(const CpModelProto& model_proto, for (int i = 0; i < model_proto.objective().coeffs_size(); ++i) { const IntegerVariable var = mapping->Integer(model_proto.objective().vars(i)); - const int64 coeff = model_proto.objective().coeffs(i); + const int64_t coeff = model_proto.objective().coeffs(i); const int c = index_to_component[get_var_index(var)]; if (lp_constraints[c] != nullptr) { lp_constraints[c]->SetObjectiveCoefficient(var, IntegerValue(coeff)); @@ -1293,7 +1296,7 @@ void LoadFeasibilityPump(const CpModelProto& model_proto, for (int i = 0; i < model_proto.objective().coeffs_size(); ++i) { const IntegerVariable var = mapping->Integer(model_proto.objective().vars(i)); - const int64 coeff = model_proto.objective().coeffs(i); + const int64_t coeff = model_proto.objective().coeffs(i); feasibility_pump->SetObjectiveCoefficient(var, IntegerValue(coeff)); } } @@ -1355,7 +1358,7 @@ void LoadCpModel(const CpModelProto& model_proto, AddLPConstraints(model_proto, parameters.linearization_level(), model); } else if (model_proto.has_objective()) { const CpObjectiveProto& obj = model_proto.objective(); - std::vector> terms; + std::vector> terms; terms.reserve(obj.vars_size()); for (int i = 0; i < obj.vars_size(); ++i) { terms.push_back( @@ -1432,7 +1435,7 @@ void LoadCpModel(const CpModelProto& model_proto, // user specified upper bound. if (!automatic_domain.IsIncludedIn(user_domain)) { std::vector vars; - std::vector coeffs; + std::vector coeffs; const CpObjectiveProto& obj = model_proto.objective(); for (int i = 0; i < obj.vars_size(); ++i) { vars.push_back(mapping->Integer(obj.vars(i))); @@ -1740,15 +1743,16 @@ void MinimizeL1DistanceWithHint(const CpModelProto& model_proto, // TODO(user): For boolean variables we can avoid creating new variables. for (int i = 0; i < model_proto.solution_hint().vars_size(); ++i) { const int var = model_proto.solution_hint().vars(i); - const int64 value = model_proto.solution_hint().values(i); + const int64_t value = model_proto.solution_hint().values(i); // Add a new var to represent the difference between var and value. const int new_var_index = updated_model_proto.variables_size(); IntegerVariableProto* var_proto = updated_model_proto.add_variables(); - const int64 min_domain = model_proto.variables(var).domain(0) - value; - const int64 max_domain = model_proto.variables(var).domain( - model_proto.variables(var).domain_size() - 1) - - value; + const int64_t min_domain = model_proto.variables(var).domain(0) - value; + const int64_t max_domain = + model_proto.variables(var).domain( + model_proto.variables(var).domain_size() - 1) - + value; var_proto->add_domain(min_domain); var_proto->add_domain(max_domain); @@ -1766,8 +1770,8 @@ void MinimizeL1DistanceWithHint(const CpModelProto& model_proto, // abs_var = abs(new_var). const int abs_var_index = updated_model_proto.variables_size(); IntegerVariableProto* abs_var_proto = updated_model_proto.add_variables(); - const int64 abs_min_domain = 0; - const int64 abs_max_domain = + const int64_t abs_min_domain = 0; + const int64_t abs_max_domain = std::max(std::abs(min_domain), std::abs(max_domain)); abs_var_proto->add_domain(abs_min_domain); abs_var_proto->add_domain(abs_max_domain); @@ -1818,7 +1822,7 @@ void MinimizeL1DistanceWithHint(const CpModelProto& model_proto, // before postsolving it. Note that 'num_variables_in_original_model' refers to // the model before presolve. void PostsolveResponseWithFullSolver( - const int64 num_variables_in_original_model, CpModelProto mapping_proto, + const int64_t num_variables_in_original_model, CpModelProto mapping_proto, const std::vector& postsolve_mapping, WallTimer* wall_timer, CpSolverResponse* response) { if (response->status() != CpSolverStatus::FEASIBLE && @@ -1888,7 +1892,7 @@ void PostsolveResponseWithFullSolver( } void PostsolveResponseWrapper(const SatParameters& params, - const int64 num_variables_in_original_model, + const int64_t num_variables_in_original_model, const CpModelProto& mapping_proto, const std::vector& postsolve_mapping, WallTimer* wall_timer, @@ -2061,9 +2065,9 @@ CpSolverResponse SolvePureSatModel(const CpModelProto& model_proto, break; } case SatSolver::FEASIBLE: { - CHECK(SolutionIsFeasible(model_proto, - std::vector(response.solution().begin(), - response.solution().end()))); + CHECK(SolutionIsFeasible( + model_proto, std::vector(response.solution().begin(), + response.solution().end()))); response.set_status(CpSolverStatus::OPTIMAL); break; } @@ -2182,7 +2186,7 @@ class FullProblemSolver : public SubSolver { return previous_task_is_completed_; } - std::function GenerateTask(int64 task_id) override { + std::function GenerateTask(int64_t task_id) override { { absl::MutexLock mutex_lock(&mutex_); previous_task_is_completed_ = false; @@ -2320,7 +2324,7 @@ class FeasibilityPumpSolver : public SubSolver { return previous_task_is_completed_; } - std::function GenerateTask(int64 task_id) override { + std::function GenerateTask(int64_t task_id) override { return [this]() { { absl::MutexLock mutex_lock(&mutex_); @@ -2406,7 +2410,7 @@ class LnsSolver : public SubSolver { return generator_->ReadyToGenerate(); } - std::function GenerateTask(int64 task_id) override { + std::function GenerateTask(int64_t task_id) override { return [task_id, this]() { if (shared_->SearchIsDone()) return; @@ -3179,7 +3183,7 @@ CpSolverResponse SolveCpModel(const CpModelProto& model_proto, Model* model) { #endif // __PORTABLE_PLATFORM__ if (params.stop_after_presolve() || shared_time_limit.LimitReached()) { - int64 num_terms = 0; + int64_t num_terms = 0; for (const ConstraintProto& ct : new_cp_model_proto.constraints()) { num_terms += UsedVariables(ct).size(); } @@ -3241,8 +3245,8 @@ CpSolverResponse SolveCpModel(const CpModelProto& model_proto, Model* model) { postprocess_solution(&final_response); if (!final_response.solution().empty()) { CHECK(SolutionIsFeasible( - model_proto, std::vector(final_response.solution().begin(), - final_response.solution().end()))); + model_proto, std::vector(final_response.solution().begin(), + final_response.solution().end()))); } if (degraded_assumptions_support && final_response.status() == CpSolverStatus::INFEASIBLE) { diff --git a/ortools/sat/cp_model_symmetries.cc b/ortools/sat/cp_model_symmetries.cc index 930f674529..8726481e8b 100644 --- a/ortools/sat/cp_model_symmetries.cc +++ b/ortools/sat/cp_model_symmetries.cc @@ -13,6 +13,8 @@ #include "ortools/sat/cp_model_symmetries.h" +#include +#include #include #include "absl/container/flat_hash_map.h" @@ -29,9 +31,9 @@ namespace sat { namespace { struct VectorHash { - std::size_t operator()(const std::vector& values) const { + std::size_t operator()(const std::vector& values) const { size_t hash = 0; - for (const int64 value : values) { + for (const int64_t value : values) { hash = util_hash::Hash(value, hash); } return hash; @@ -46,14 +48,14 @@ class IdGenerator { // If the color was never seen before, then generate a new id, otherwise // return the previously generated id. - int GetId(const std::vector& color) { + int GetId(const std::vector& color) { return gtl::LookupOrInsert(&id_map_, color, id_map_.size()); } int NextFreeId() const { return id_map_.size(); } private: - absl::flat_hash_map, int, VectorHash> id_map_; + absl::flat_hash_map, int, VectorHash> id_map_; }; // Appends values in `repeated_field` to `vector`. @@ -124,17 +126,17 @@ std::unique_ptr GenerateGraphForSymmetryDetection( // TODO(user): We could ignore the objective coefficients, and just make sure // that when we break symmetry amongst variables, we choose the possibility // with the smallest cost? - std::vector objective_by_var(num_variables, 0); + std::vector objective_by_var(num_variables, 0); for (int i = 0; i < problem.objective().vars_size(); ++i) { const int ref = problem.objective().vars(i); const int var = PositiveRef(ref); - const int64 coeff = problem.objective().coeffs(i); + const int64_t coeff = problem.objective().coeffs(i); objective_by_var[var] = RefIsPositive(ref) ? coeff : -coeff; } // Create one node for each variable. Note that the code rely on the fact that // the index of a VARIABLE_NODE type is the same as the variable index. - std::vector tmp_color; + std::vector tmp_color; for (int v = 0; v < num_variables; ++v) { tmp_color = {VARIABLE_NODE, objective_by_var[v]}; Append(problem.variables(v).domain(), &tmp_color); @@ -213,7 +215,8 @@ std::unique_ptr GenerateGraphForSymmetryDetection( // Add constraints to the graph. for (const ConstraintProto& constraint : problem.constraints()) { const int constraint_node = initial_equivalence_classes->size(); - std::vector color = {CONSTRAINT_NODE, constraint.constraint_case()}; + std::vector color = {CONSTRAINT_NODE, + constraint.constraint_case()}; switch (constraint.constraint_case()) { case ConstraintProto::CONSTRAINT_NOT_SET: @@ -228,9 +231,9 @@ std::unique_ptr GenerateGraphForSymmetryDetection( for (int i = 0; i < constraint.linear().vars_size(); ++i) { const int ref = constraint.linear().vars(i); const int variable_node = PositiveRef(ref); - const int64 coeff = RefIsPositive(ref) - ? constraint.linear().coeffs(i) - : -constraint.linear().coeffs(i); + const int64_t coeff = RefIsPositive(ref) + ? constraint.linear().coeffs(i) + : -constraint.linear().coeffs(i); graph->AddArc(get_coefficient_node(variable_node, coeff), constraint_node); } @@ -511,7 +514,7 @@ bool DetectAndExploitSymmetriesInPresolve(PresolveContext* context) { // Tricky: the equivalence relation are not part of the proto. // We thus add them temporarily to compute the symmetry. - int64 num_added = 0; + int64_t num_added = 0; const int initial_ct_index = proto.constraints().size(); for (int var = 0; var < num_vars; ++var) { if (context->IsFixed(var)) continue; @@ -547,7 +550,7 @@ bool DetectAndExploitSymmetriesInPresolve(PresolveContext* context) { // Note(user): This relies on the fact that the pointers remain stable when // we adds new constraints. It should be the case, but it is a bit unsafe. // On the other hand it is annoying to deal with both cases below. - std::vector*> at_most_ones; + std::vector*> at_most_ones; for (int i = 0; i < proto.constraints_size(); ++i) { if (proto.constraints(i).constraint_case() == ConstraintProto::kAtMostOne) { at_most_ones.push_back(&proto.constraints(i).at_most_one().literals()); @@ -577,7 +580,7 @@ bool DetectAndExploitSymmetriesInPresolve(PresolveContext* context) { std::vector tmp_to_clear; std::vector tmp_sizes(num_vars, 0); - for (const google::protobuf::RepeatedField* literals : + for (const google::protobuf::RepeatedField* literals : at_most_ones) { tmp_to_clear.clear(); @@ -680,7 +683,8 @@ bool DetectAndExploitSymmetriesInPresolve(PresolveContext* context) { // TODO(user): The code below requires that no variable appears twice in the // same at most one. In particular lit and not(lit) cannot appear in the same // at most one. - for (const google::protobuf::RepeatedField* literals : at_most_ones) { + for (const google::protobuf::RepeatedField* literals : + at_most_ones) { for (const int lit : *literals) { const int var = PositiveRef(lit); CHECK_NE(tmp_sizes[var], 1); @@ -730,11 +734,11 @@ bool DetectAndExploitSymmetriesInPresolve(PresolveContext* context) { // the set of best rows on which we have an at most one (or at most one // zero) on all their entries. bool at_most_one_in_best_rows; // The alternative is at most one zero. - int64 best_score = 0; + int64_t best_score = 0; std::vector best_rows; std::vector rows_in_at_most_one; - for (const google::protobuf::RepeatedField* literals : + for (const google::protobuf::RepeatedField* literals : at_most_ones) { tmp_to_clear.clear(); for (const int literal : *literals) { @@ -796,7 +800,7 @@ bool DetectAndExploitSymmetriesInPresolve(PresolveContext* context) { // we fix before choosing the next row to break symmetry on. If there are // multiple row involved, we could also take the intersection instead of // probably counting the same constraints more than once. - int64 score = 0; + int64_t score = 0; for (const int row : rows_in_at_most_one) { score += context->VarToConstraints(PositiveRef(orbitope[row][0])).size(); @@ -897,7 +901,7 @@ bool DetectAndExploitSymmetriesInPresolve(PresolveContext* context) { ct->mutable_linear()->add_coeffs(-1); ct->mutable_linear()->add_vars(orbitope[0][i + 1]); ct->mutable_linear()->add_domain(0); - ct->mutable_linear()->add_domain(kint64max); + ct->mutable_linear()->add_domain(std::numeric_limits::max()); context->UpdateRuleStats("symmetry: added symmetry breaking inequality"); } context->UpdateNewConstraintsVariableUsage(); diff --git a/ortools/sat/cp_model_utils.cc b/ortools/sat/cp_model_utils.cc index 45c8263057..350d607fd8 100644 --- a/ortools/sat/cp_model_utils.cc +++ b/ortools/sat/cp_model_utils.cc @@ -13,6 +13,8 @@ #include "ortools/sat/cp_model_utils.h" +#include + #include "ortools/base/stl_util.h" namespace operations_research { @@ -535,14 +537,14 @@ std::vector UsedIntervals(const ConstraintProto& ct) { return used_intervals; } -int64 ComputeInnerObjective(const CpObjectiveProto& objective, - const CpSolverResponse& response) { - int64 objective_value = 0; +int64_t ComputeInnerObjective(const CpObjectiveProto& objective, + const CpSolverResponse& response) { + int64_t objective_value = 0; auto& repeated_field_values = response.solution().empty() ? response.solution_lower_bounds() : response.solution(); for (int i = 0; i < objective.vars_size(); ++i) { - int64 coeff = objective.coeffs(i); + int64_t coeff = objective.coeffs(i); const int ref = objective.vars(i); const int var = PositiveRef(ref); if (!RefIsPositive(ref)) coeff = -coeff; diff --git a/ortools/sat/cp_model_utils.h b/ortools/sat/cp_model_utils.h index dc66024674..f05b126b2a 100644 --- a/ortools/sat/cp_model_utils.h +++ b/ortools/sat/cp_model_utils.h @@ -15,7 +15,9 @@ #define OR_TOOLS_SAT_CP_MODEL_UTILS_H_ #include +#include #include +#include #include #include @@ -79,7 +81,7 @@ std::vector UsedIntervals(const ConstraintProto& ct); // Returns true if a proto.domain() contain the given value. // The domain is expected to be encoded as a sorted disjoint interval list. template -bool DomainInProtoContains(const ProtoWithDomain& proto, int64 value) { +bool DomainInProtoContains(const ProtoWithDomain& proto, int64_t value) { for (int i = 0; i < proto.domain_size(); i += 2) { if (value >= proto.domain(i) && value <= proto.domain(i + 1)) return true; } @@ -113,10 +115,10 @@ Domain ReadDomainFromProto(const ProtoWithDomain& proto) { // // TODO(user): work directly on the Domain class instead. template -std::vector AllValuesInDomain(const ProtoWithDomain& proto) { - std::vector result; +std::vector AllValuesInDomain(const ProtoWithDomain& proto) { + std::vector result; for (int i = 0; i < proto.domain_size(); i += 2) { - for (int64 v = proto.domain(i); v <= proto.domain(i + 1); ++v) { + for (int64_t v = proto.domain(i); v <= proto.domain(i + 1); ++v) { CHECK_LE(result.size(), 1e6); result.push_back(v); } @@ -125,10 +127,13 @@ std::vector AllValuesInDomain(const ProtoWithDomain& proto) { } // Scales back a objective value to a double value from the original model. -inline double ScaleObjectiveValue(const CpObjectiveProto& proto, int64 value) { +inline double ScaleObjectiveValue(const CpObjectiveProto& proto, + int64_t value) { double result = static_cast(value); - if (value == kint64min) result = -std::numeric_limits::infinity(); - if (value == kint64max) result = std::numeric_limits::infinity(); + if (value == std::numeric_limits::min()) + result = -std::numeric_limits::infinity(); + if (value == std::numeric_limits::max()) + result = std::numeric_limits::infinity(); result += proto.offset(); if (proto.scaling_factor() == 0) return result; return proto.scaling_factor() * result; @@ -147,8 +152,8 @@ inline double UnscaleObjectiveValue(const CpObjectiveProto& proto, // Computes the "inner" objective of a response that contains a solution. // This is the objective without offset and scaling. Call ScaleObjectiveValue() // to get the user facing objective. -int64 ComputeInnerObjective(const CpObjectiveProto& objective, - const CpSolverResponse& response); +int64_t ComputeInnerObjective(const CpObjectiveProto& objective, + const CpSolverResponse& response); } // namespace sat } // namespace operations_research diff --git a/ortools/sat/cuts.cc b/ortools/sat/cuts.cc index 208479b321..466bc69907 100644 --- a/ortools/sat/cuts.cc +++ b/ortools/sat/cuts.cc @@ -15,7 +15,9 @@ #include #include +#include #include +#include #include #include #include @@ -99,7 +101,7 @@ bool SmallRangeAndAllCoefficientsMagnitudeAreTheSame( const LinearConstraint& constraint, IntegerTrail* integer_trail) { if (constraint.vars.empty()) return true; - const int64 magnitude = std::abs(constraint.coeffs[0].value()); + const int64_t magnitude = std::abs(constraint.coeffs[0].value()); for (int i = 1; i < constraint.coeffs.size(); ++i) { const IntegerVariable var = constraint.vars[i]; if (integer_trail->LevelZeroUpperBound(var) - @@ -633,7 +635,8 @@ std::function GetSuperAdditiveRoundingFunction( // Make sure we don't have an integer overflow below. Note that we assume that // divisor and the maximum coeff magnitude are not too different (maybe a // factor 1000 at most) so that the final result will never overflow. - max_scaling = std::min(max_scaling, kint64max / divisor); + max_scaling = + std::min(max_scaling, std::numeric_limits::max() / divisor); const IntegerValue size = divisor - rhs_remainder; if (max_scaling == 1 || size == 1) { @@ -1102,7 +1105,8 @@ void IntegerRoundingCutHelper::ComputeCut( // Avoid overflow. if (CapProd(CapProd(std::abs(coeff.value()), factor_t.value()), - info.bound_diff.value()) == kint64max) { + info.bound_diff.value()) == + std::numeric_limits::max()) { continue; } @@ -1590,7 +1594,7 @@ void ImpliedBoundsProcessor::ProcessUpperBoundedConstraintWithSlackCreation( bool changed = false; // TODO(user): we could relax a bit this test. - int64 overflow_detection = 0; + int64_t overflow_detection = 0; const int size = cut->vars.size(); for (int i = 0; i < size; ++i) { @@ -1623,7 +1627,7 @@ void ImpliedBoundsProcessor::ProcessUpperBoundedConstraintWithSlackCreation( bool keep_term = false; if (info.bool_var == kNoIntegerVariable) keep_term = true; if (CapProd(std::abs(coeff.value()), info.bound_diff.value()) == - kint64max) { + std::numeric_limits::max()) { keep_term = true; } @@ -1792,9 +1796,9 @@ void TryToGenerateAllDiffCut( current_union = current_union.UnionWith(integer_trail.InitialVariableDomain(var)); current_set_vars.push_back(var); - const int64 required_min_sum = + const int64_t required_min_sum = SumOfKMinValueInDomain(current_union, current_set_vars.size()); - const int64 required_max_sum = + const int64_t required_max_sum = SumOfKMaxValueInDomain(current_union, current_set_vars.size()); if (sum < required_min_sum || sum > required_max_sum) { LinearConstraint cut; @@ -2449,8 +2453,9 @@ CutGenerator CreateCliqueCutGenerator( // We need to express such "at most one" in term of the initial // variables, so we do not use the // LinearConstraintBuilder::AddLiteralTerm() here. - LinearConstraintBuilder builder(model, IntegerValue(kint64min), - IntegerValue(1)); + LinearConstraintBuilder builder( + model, IntegerValue(std::numeric_limits::min()), + IntegerValue(1)); for (const Literal l : at_most_one) { if (ContainsKey(positive_map, l.Index())) { builder.AddTerm(positive_map.at(l.Index()), IntegerValue(1)); diff --git a/ortools/sat/diffn.cc b/ortools/sat/diffn.cc index a171c3a5f0..b621fa3f83 100644 --- a/ortools/sat/diffn.cc +++ b/ortools/sat/diffn.cc @@ -14,6 +14,8 @@ #include "ortools/sat/diffn.h" #include +#include +#include #include "absl/container/flat_hash_map.h" #include "absl/strings/str_join.h" @@ -77,8 +79,8 @@ void AddIsEqualToMaxOf(IntegerVariable max_var, void AddCumulativeRelaxation(const std::vector& x_intervals, SchedulingConstraintHelper* x, SchedulingConstraintHelper* y, Model* model) { - int64 min_starts = kint64max; - int64 max_ends = kint64min; + int64_t min_starts = std::numeric_limits::max(); + int64_t max_ends = std::numeric_limits::min(); std::vector sizes; for (int box = 0; box < y->NumTasks(); ++box) { min_starts = std::min(min_starts, y->StartMin(box).value()); @@ -97,7 +99,7 @@ void AddCumulativeRelaxation(const std::vector& x_intervals, // (max_end - min_start) >= capacity. const AffineExpression capacity( model->Add(NewIntegerVariable(0, CapSub(max_ends, min_starts)))); - const std::vector coeffs = {-capacity.coeff.value(), -1, 1}; + const std::vector coeffs = {-capacity.coeff.value(), -1, 1}; model->Add( WeightedSumGreaterOrEqual({capacity.var, min_start_var, max_end_var}, coeffs, capacity.constant.value())); @@ -118,7 +120,7 @@ IntegerValue FindCanonicalValue(IntegerValue lb, IntegerValue ub) { return -FindCanonicalValue(-ub, -lb); } - int64 mask = 0; + int64_t mask = 0; IntegerValue candidate = ub; for (int o = 0; o < 62; ++o) { mask = 2 * mask + 1; @@ -424,8 +426,8 @@ bool NonOverlappingRectanglesDisjunctivePropagator:: y_.ResetFromSubset(y, boxes); // Collect the common overlapping coordinates of all boxes. - IntegerValue lb(kint64min); - IntegerValue ub(kint64max); + IntegerValue lb(std::numeric_limits::min()); + IntegerValue ub(std::numeric_limits::max()); for (int i = 0; i < y_.NumTasks(); ++i) { lb = std::max(lb, y_.StartMax(i)); ub = std::min(ub, y_.EndMin(i) - 1); diff --git a/ortools/sat/doc/integer_arithmetic.md b/ortools/sat/doc/integer_arithmetic.md index 8aa99d076d..c4d3207ead 100644 --- a/ortools/sat/doc/integer_arithmetic.md +++ b/ortools/sat/doc/integer_arithmetic.md @@ -403,6 +403,8 @@ earliness_tardiness_cost_sample_sat() ### C++ code ```cpp +#include + #include "ortools/sat/cp_model.h" #include "ortools/sat/model.h" #include "ortools/sat/sat_parameters.pb.h" @@ -411,10 +413,10 @@ namespace operations_research { namespace sat { void EarlinessTardinessCostSampleSat() { - const int64 kEarlinessDate = 5; - const int64 kEarlinessCost = 8; - const int64 kLatenessDate = 15; - const int64 kLatenessCost = 12; + const int64_t kEarlinessDate = 5; + const int64_t kEarlinessCost = 8; + const int64_t kLatenessDate = 15; + const int64_t kLatenessCost = 12; // Create the CP-SAT model. CpModelBuilder cp_model; @@ -428,7 +430,7 @@ void EarlinessTardinessCostSampleSat() { // \______/ // ed ld // - const int64 kLargeConstant = 1000; + const int64_t kLargeConstant = 1000; const IntVar expr = cp_model.NewIntVar({0, kLargeConstant}); // First segment. diff --git a/ortools/sat/doc/scheduling.md b/ortools/sat/doc/scheduling.md index e923ae9f17..ccbae05c38 100644 --- a/ortools/sat/doc/scheduling.md +++ b/ortools/sat/doc/scheduling.md @@ -363,6 +363,8 @@ NoOverlapSampleSat() ### C++ code ```cpp +#include + #include "ortools/sat/cp_model.h" namespace operations_research { @@ -370,7 +372,7 @@ namespace sat { void NoOverlapSampleSat() { CpModelBuilder cp_model; - const int64 kHorizon = 21; // 3 weeks. + const int64_t kHorizon = 21; // 3 weeks. const Domain horizon(0, kHorizon); // Task 0, duration 2. diff --git a/ortools/sat/drat_checker.cc b/ortools/sat/drat_checker.cc index 492aadfa57..65d3e8698d 100644 --- a/ortools/sat/drat_checker.cc +++ b/ortools/sat/drat_checker.cc @@ -14,6 +14,7 @@ #include "ortools/sat/drat_checker.h" #include +#include #include #include "absl/strings/numbers.h" @@ -151,7 +152,7 @@ DratChecker::Status DratChecker::Check(double max_time_in_seconds) { // to check it. In turn, only these marked clauses need to be checked (and so // on recursively). By contrast, a forward iteration needs to check all the // clauses. - const int64 start_time_nanos = absl::GetCurrentTimeNanos(); + const int64_t start_time_nanos = absl::GetCurrentTimeNanos(); TimeLimit time_limit(max_time_in_seconds); Init(); for (ClauseIndex i(clauses_.size() - 1); i >= first_infered_clause_index_; @@ -435,7 +436,7 @@ void DratChecker::MarkAsNeededForProof(Clause* clause) { } } -void DratChecker::LogStatistics(int64 duration_nanos) const { +void DratChecker::LogStatistics(int64_t duration_nanos) const { int problem_clauses_needed_for_proof = 0; int infered_clauses_needed_for_proof = 0; for (ClauseIndex i(0); i < clauses_.size(); ++i) { diff --git a/ortools/sat/drat_checker.h b/ortools/sat/drat_checker.h index 959fc78a88..d7e305d4bd 100644 --- a/ortools/sat/drat_checker.h +++ b/ortools/sat/drat_checker.h @@ -14,6 +14,7 @@ #ifndef OR_TOOLS_SAT_DRAT_CHECKER_H_ #define OR_TOOLS_SAT_DRAT_CHECKER_H_ +#include #include #include @@ -216,7 +217,7 @@ class DratChecker { std::vector> GetClausesNeededForProof( ClauseIndex begin, ClauseIndex end) const; - void LogStatistics(int64 duration_nanos) const; + void LogStatistics(int64_t duration_nanos) const; // The index of the first infered clause in 'clauses_', or kNoClauseIndex if // there is no infered clause. diff --git a/ortools/sat/encoding.cc b/ortools/sat/encoding.cc index 66fb67d8e6..989f0d853a 100644 --- a/ortools/sat/encoding.cc +++ b/ortools/sat/encoding.cc @@ -14,6 +14,7 @@ #include "ortools/sat/encoding.h" #include +#include #include #include #include @@ -94,7 +95,7 @@ int EncodingNode::Reduce(const SatSolver& solver) { return i; } -void EncodingNode::ApplyUpperBound(int64 upper_bound, SatSolver* solver) { +void EncodingNode::ApplyUpperBound(int64_t upper_bound, SatSolver* solver) { if (size() <= upper_bound) return; for (int i = upper_bound; i < size(); ++i) { solver->AddUnitClause(literal(i).Negated()); diff --git a/ortools/sat/encoding.h b/ortools/sat/encoding.h index 14e99a3c06..7d7957485d 100644 --- a/ortools/sat/encoding.h +++ b/ortools/sat/encoding.h @@ -18,6 +18,7 @@ #ifndef OR_TOOLS_SAT_ENCODING_H_ #define OR_TOOLS_SAT_ENCODING_H_ +#include #include #include @@ -100,7 +101,7 @@ class EncodingNode { // Fix the right-side variables with indices >= to the given upper_bound to // false. - void ApplyUpperBound(int64 upper_bound, SatSolver* solver); + void ApplyUpperBound(int64_t upper_bound, SatSolver* solver); void set_weight(Coefficient w) { weight_ = w; } Coefficient weight() const { return weight_; } diff --git a/ortools/sat/feasibility_pump.cc b/ortools/sat/feasibility_pump.cc index e6a0f89556..05652d07ec 100644 --- a/ortools/sat/feasibility_pump.cc +++ b/ortools/sat/feasibility_pump.cc @@ -13,6 +13,7 @@ #include "ortools/sat/feasibility_pump.h" +#include #include #include @@ -425,7 +426,8 @@ double FeasibilityPump::GetVariableValueAtCpScale(ColIndex var) { // -------------------Rounding------------------------------------- // ---------------------------------------------------------------- -int64 FeasibilityPump::GetIntegerSolutionValue(IntegerVariable variable) const { +int64_t FeasibilityPump::GetIntegerSolutionValue( + IntegerVariable variable) const { return integer_solution_[gtl::FindOrDie(mirror_lp_variable_, variable) .value()]; } @@ -451,7 +453,7 @@ bool FeasibilityPump::Round() { bool FeasibilityPump::NearestIntegerRounding() { if (!lp_solution_is_set_) return false; for (int i = 0; i < lp_solution_.size(); ++i) { - integer_solution_[i] = static_cast(std::round(lp_solution_[i])); + integer_solution_[i] = static_cast(std::round(lp_solution_[i])); } integer_solution_is_set_ = true; return true; @@ -489,11 +491,11 @@ bool FeasibilityPump::LockBasedRounding() { for (int i = 0; i < lp_solution_.size(); ++i) { if (std::abs(lp_solution_[i] - std::round(lp_solution_[i])) < 0.1 || var_up_locks_[i] == var_down_locks_[i]) { - integer_solution_[i] = static_cast(std::round(lp_solution_[i])); + integer_solution_[i] = static_cast(std::round(lp_solution_[i])); } else if (var_up_locks_[i] > var_down_locks_[i]) { - integer_solution_[i] = static_cast(std::floor(lp_solution_[i])); + integer_solution_[i] = static_cast(std::floor(lp_solution_[i])); } else { - integer_solution_[i] = static_cast(std::ceil(lp_solution_[i])); + integer_solution_[i] = static_cast(std::ceil(lp_solution_[i])); } } integer_solution_is_set_ = true; @@ -509,7 +511,7 @@ bool FeasibilityPump::ActiveLockBasedRounding() { // constraint that is tight for the current lp solution. for (int i = 0; i < num_vars; ++i) { if (std::abs(lp_solution_[i] - std::round(lp_solution_[i])) < 0.1) { - integer_solution_[i] = static_cast(std::round(lp_solution_[i])); + integer_solution_[i] = static_cast(std::round(lp_solution_[i])); } int up_locks = 0; @@ -532,11 +534,11 @@ bool FeasibilityPump::ActiveLockBasedRounding() { } } if (up_locks == down_locks) { - integer_solution_[i] = static_cast(std::round(lp_solution_[i])); + integer_solution_[i] = static_cast(std::round(lp_solution_[i])); } else if (up_locks > down_locks) { - integer_solution_[i] = static_cast(std::floor(lp_solution_[i])); + integer_solution_[i] = static_cast(std::floor(lp_solution_[i])); } else { - integer_solution_[i] = static_cast(std::ceil(lp_solution_[i])); + integer_solution_[i] = static_cast(std::ceil(lp_solution_[i])); } } @@ -588,12 +590,12 @@ bool FeasibilityPump::PropagationRounding() { continue; } - const int64 rounded_value = - static_cast(std::round(lp_solution_[var_index])); - const int64 floor_value = - static_cast(std::floor(lp_solution_[var_index])); - const int64 ceil_value = - static_cast(std::ceil(lp_solution_[var_index])); + const int64_t rounded_value = + static_cast(std::round(lp_solution_[var_index])); + const int64_t floor_value = + static_cast(std::floor(lp_solution_[var_index])); + const int64_t ceil_value = + static_cast(std::ceil(lp_solution_[var_index])); const bool floor_is_in_domain = (domain.Contains(floor_value) && lb.value() <= floor_value); @@ -620,11 +622,11 @@ bool FeasibilityPump::PropagationRounding() { const std::pair values_in_domain = integer_encoder_->Canonicalize( IntegerLiteral::GreaterOrEqual(var, IntegerValue(rounded_value))); - const int64 lower_value = values_in_domain.first.bound.value(); - const int64 higher_value = -values_in_domain.second.bound.value(); - const int64 distance_from_lower_value = + const int64_t lower_value = values_in_domain.first.bound.value(); + const int64_t higher_value = -values_in_domain.second.bound.value(); + const int64_t distance_from_lower_value = std::abs(lower_value - rounded_value); - const int64 distance_from_higher_value = + const int64_t distance_from_higher_value = std::abs(higher_value - rounded_value); integer_solution_[var_index] = @@ -684,26 +686,31 @@ void FeasibilityPump::FillIntegerSolutionStats() { num_infeasible_constraints_ = 0; integer_solution_infeasibility_ = 0; for (RowIndex i(0); i < integer_lp_.size(); ++i) { - int64 activity = 0; + int64_t activity = 0; for (const auto& term : integer_lp_[i].terms) { - const int64 prod = + const int64_t prod = CapProd(integer_solution_[term.first.value()], term.second.value()); - if (prod <= kint64min || prod >= kint64max) { + if (prod <= std::numeric_limits::min() || + prod >= std::numeric_limits::max()) { activity = prod; break; } activity = CapAdd(activity, prod); - if (activity <= kint64min || activity >= kint64max) break; + if (activity <= std::numeric_limits::min() || + activity >= std::numeric_limits::max()) + break; } if (activity > integer_lp_[i].ub || activity < integer_lp_[i].lb) { integer_solution_is_feasible_ = false; num_infeasible_constraints_++; - const int64 ub_infeasibility = activity > integer_lp_[i].ub.value() - ? activity - integer_lp_[i].ub.value() - : 0; - const int64 lb_infeasibility = activity < integer_lp_[i].lb.value() - ? integer_lp_[i].lb.value() - activity - : 0; + const int64_t ub_infeasibility = + activity > integer_lp_[i].ub.value() + ? activity - integer_lp_[i].ub.value() + : 0; + const int64_t lb_infeasibility = + activity < integer_lp_[i].lb.value() + ? integer_lp_[i].lb.value() - activity + : 0; integer_solution_infeasibility_ = std::max(integer_solution_infeasibility_, std::max(ub_infeasibility, lb_infeasibility)); diff --git a/ortools/sat/feasibility_pump.h b/ortools/sat/feasibility_pump.h index 454753f2cb..89d8685df9 100644 --- a/ortools/sat/feasibility_pump.h +++ b/ortools/sat/feasibility_pump.h @@ -14,6 +14,8 @@ #ifndef OR_TOOLS_SAT_FEASIBILITY_PUMP_H_ #define OR_TOOLS_SAT_FEASIBILITY_PUMP_H_ +#include + #include "ortools/base/strong_vector.h" #include "ortools/glop/revised_simplex.h" #include "ortools/lp_data/lp_data.h" @@ -61,13 +63,13 @@ class FeasibilityPump { // solution. These functions should only be called when HasIntegerSolution() // is true. bool HasIntegerSolution() const { return integer_solution_is_set_; } - int64 IntegerSolutionObjectiveValue() const { + int64_t IntegerSolutionObjectiveValue() const { return integer_solution_objective_; } bool IntegerSolutionIsFeasible() const { return integer_solution_is_feasible_; } - int64 GetIntegerSolutionValue(IntegerVariable variable) const; + int64_t GetIntegerSolutionValue(IntegerVariable variable) const; // Returns false if the model is proven to be infeasible. bool Solve(); @@ -213,16 +215,16 @@ class FeasibilityPump { // Rounded Integer solution. This might not be feasible. bool integer_solution_is_set_ = false; bool integer_solution_is_feasible_ = false; - int64 integer_solution_objective_; - std::vector integer_solution_; - std::vector best_integer_solution_; + int64_t integer_solution_objective_; + std::vector integer_solution_; + std::vector best_integer_solution_; int num_infeasible_constraints_; // We use max infeasibility of all constraints. - int64 integer_solution_infeasibility_; + int64_t integer_solution_infeasibility_; // Sum of all simplex iterations performed by this class. This is useful to // test the incrementality and compare to other solvers. - int64 total_num_simplex_iterations_ = 0; + int64_t total_num_simplex_iterations_ = 0; // TODO(user): Tune default value. Expose as parameter. int max_fp_iterations_ = 20; diff --git a/ortools/sat/implied_bounds.h b/ortools/sat/implied_bounds.h index 0089567308..9018007216 100644 --- a/ortools/sat/implied_bounds.h +++ b/ortools/sat/implied_bounds.h @@ -15,6 +15,7 @@ #define OR_TOOLS_SAT_IMPLIED_BOUNDS_H_ #include +#include #include #include "absl/container/flat_hash_map.h" @@ -157,8 +158,8 @@ class ImpliedBounds { SparseBitset new_level_zero_bounds_; // Stats. - int64 num_deductions_ = 0; - int64 num_enqueued_in_var_to_bounds_ = 0; + int64_t num_deductions_ = 0; + int64_t num_enqueued_in_var_to_bounds_ = 0; }; } // namespace sat diff --git a/ortools/sat/integer.cc b/ortools/sat/integer.cc index ed5cce6d7f..319ba15ec2 100644 --- a/ortools/sat/integer.cc +++ b/ortools/sat/integer.cc @@ -14,6 +14,8 @@ #include "ortools/sat/integer.h" #include +#include +#include #include #include @@ -77,7 +79,7 @@ bool IntegerEncoder::VariableIsFullyEncoded(IntegerVariable var) const { // It might not be needed since if the variable is not fully encoded, then // PartialDomainEncoding() will filter unreachable values, and so the size // check will be false until further value have been encoded. - const int64 initial_domain_size = (*domains_)[var].Size(); + const int64_t initial_domain_size = (*domains_)[var].Size(); if (equality_by_var_[index].size() < initial_domain_size) return false; // This cleans equality_by_var_[index] as a side effect and in particular, @@ -90,7 +92,7 @@ bool IntegerEncoder::VariableIsFullyEncoded(IntegerVariable var) const { const auto& ref = equality_by_var_[index]; int i = 0; for (const ClosedInterval interval : (*domains_)[var]) { - for (int64 v = interval.start; v <= interval.end; ++v) { + for (int64_t v = interval.start; v <= interval.end; ++v) { if (i < ref.size() && v == ref[i].value) { i++; } @@ -188,7 +190,7 @@ std::pair IntegerEncoder::Canonicalize( IntegerValue before(i_lit.bound - 1); CHECK_GE(before, (*domains_)[var].Min()); CHECK_LE(after, (*domains_)[var].Max()); - int64 previous = kint64min; + int64_t previous = std::numeric_limits::min(); for (const ClosedInterval& interval : (*domains_)[var]) { if (before > previous && before < interval.start) before = previous; if (after > previous && after < interval.start) after = interval.start; @@ -605,7 +607,8 @@ IntegerVariable IntegerTrail::AddIntegerVariable(IntegerValue lower_bound, DCHECK_GE(lower_bound, kMinIntegerValue); DCHECK_LE(lower_bound, upper_bound); DCHECK_LE(upper_bound, kMaxIntegerValue); - DCHECK(lower_bound >= 0 || lower_bound + kint64max >= upper_bound); + DCHECK(lower_bound >= 0 || + lower_bound + std::numeric_limits::max() >= upper_bound); DCHECK(integer_search_levels_.empty()); DCHECK_EQ(vars_.size(), integer_trail_.size()); @@ -720,7 +723,8 @@ int IntegerTrail::FindTrailIndexOfVarBefore(IntegerVariable var, // for this var. const int index_in_queue = tmp_var_to_trail_index_in_queue_[var]; if (threshold <= index_in_queue) { - if (index_in_queue != kint32max) has_dependency_ = true; + if (index_in_queue != std::numeric_limits::max()) + has_dependency_ = true; return -1; } @@ -857,7 +861,7 @@ void IntegerTrail::RelaxLinearReason(IntegerValue slack, // Note that both terms of the product are positive. const TrailEntry& previous_entry = integer_trail_[entry.prev_trail_index]; - const int64 diff = + const int64_t diff = CapProd(coeff.value(), (entry.bound - previous_entry.bound).value()); if (diff > slack) { (*trail_indices)[new_size++] = index; @@ -898,8 +902,8 @@ void IntegerTrail::RelaxLinearReason(IntegerValue slack, } const TrailEntry& previous_entry = integer_trail_[entry.prev_trail_index]; - const int64 diff = CapProd(heap_entry.coeff.value(), - (entry.bound - previous_entry.bound).value()); + const int64_t diff = CapProd(heap_entry.coeff.value(), + (entry.bound - previous_entry.bound).value()); if (diff > slack) { trail_indices->push_back(index); continue; @@ -1684,7 +1688,8 @@ void IntegerTrail::MergeReasonIntoInternal(std::vector* output) const { // in the queue refering to the same variable. const int index_in_queue = tmp_var_to_trail_index_in_queue_[next_entry.var]; - if (index_in_queue != kint32max) has_dependency_ = true; + if (index_in_queue != std::numeric_limits::max()) + has_dependency_ = true; if (next_trail_index > index_in_queue) { tmp_var_to_trail_index_in_queue_[next_entry.var] = next_trail_index; tmp_queue_.push_back(next_trail_index); @@ -1695,7 +1700,8 @@ void IntegerTrail::MergeReasonIntoInternal(std::vector* output) const { // Special case for a "leaf", we will never need this variable again. if (!has_dependency_) { tmp_to_clear_.push_back(entry.var); - tmp_var_to_trail_index_in_queue_[entry.var] = kint32max; + tmp_var_to_trail_index_in_queue_[entry.var] = + std::numeric_limits::max(); } } @@ -1854,8 +1860,8 @@ bool GenericLiteralWatcher::Propagate(Trail* trail) { } // This is needed to detect if the propagator propagated anything or not. - const int64 old_integer_timestamp = integer_trail_->num_enqueues(); - const int64 old_boolean_timestamp = trail->Index(); + const int64_t old_integer_timestamp = integer_trail_->num_enqueues(); + const int64_t old_boolean_timestamp = trail->Index(); // TODO(user): Maybe just provide one function Propagate(watch_indices) ? std::vector& watch_indices_ref = id_to_watch_indices_[id]; diff --git a/ortools/sat/integer.h b/ortools/sat/integer.h index 5475063c61..e49808e47f 100644 --- a/ortools/sat/integer.h +++ b/ortools/sat/integer.h @@ -14,6 +14,7 @@ #ifndef OR_TOOLS_SAT_INTEGER_H_ #define OR_TOOLS_SAT_INTEGER_H_ +#include #include #include #include @@ -53,7 +54,7 @@ namespace sat { // Note that both bounds are inclusive, which allows to write many propagation // algorithms for just one of the bound and apply it to the negated variables to // get the symmetric algorithm for the other bound. -DEFINE_INT_TYPE(IntegerValue, int64); +DEFINE_INT_TYPE(IntegerValue, int64_t); // The max range of an integer variable is [kMinIntegerValue, kMaxIntegerValue]. // @@ -108,10 +109,14 @@ inline IntegerValue PositiveRemainder(IntegerValue dividend, // Computes result += a * b, and return false iff there is an overflow. inline bool AddProductTo(IntegerValue a, IntegerValue b, IntegerValue* result) { - const int64 prod = CapProd(a.value(), b.value()); - if (prod == kint64min || prod == kint64max) return false; - const int64 add = CapAdd(prod, result->value()); - if (add == kint64min || add == kint64max) return false; + const int64_t prod = CapProd(a.value(), b.value()); + if (prod == std::numeric_limits::min() || + prod == std::numeric_limits::max()) + return false; + const int64_t add = CapAdd(prod, result->value()); + if (add == std::numeric_limits::min() || + add == std::numeric_limits::max()) + return false; *result = IntegerValue(add); return true; } @@ -121,7 +126,7 @@ inline bool AddProductTo(IntegerValue a, IntegerValue b, IntegerValue* result) { // Each time we create an IntegerVariable we also create its negation. This is // done like that so internally we only stores and deal with lower bound. The // upper bound beeing the lower bound of the negated variable. -DEFINE_INT_TYPE(IntegerVariable, int32); +DEFINE_INT_TYPE(IntegerVariable, int32_t); const IntegerVariable kNoIntegerVariable(-1); inline IntegerVariable NegationOf(IntegerVariable i) { return IntegerVariable(i.value() ^ 1); @@ -136,7 +141,7 @@ inline IntegerVariable PositiveVariable(IntegerVariable i) { } // Special type for storing only one thing for var and NegationOf(var). -DEFINE_INT_TYPE(PositiveOnlyIndex, int32); +DEFINE_INT_TYPE(PositiveOnlyIndex, int32_t); inline PositiveOnlyIndex GetPositiveOnlyIndex(IntegerVariable var) { return PositiveOnlyIndex(var.value() / 2); } @@ -485,7 +490,7 @@ class IntegerEncoder { IntegerDomains* domains_; bool add_implications_ = true; - int64 num_created_variables_ = 0; + int64_t num_created_variables_ = 0; // We keep all the literals associated to an Integer variable in a map ordered // by bound (so we can properly add implications between the literals @@ -791,11 +796,11 @@ class IntegerTrail : public SatPropagator { // Note(user): this can be used to see if any of the bounds changed. Just // looking at the integer trail index is not enough because at level zero it // doesn't change since we directly update the "fixed" bounds. - int64 num_enqueues() const { return num_enqueues_; } - int64 timestamp() const { return num_enqueues_ + num_untrails_; } + int64_t num_enqueues() const { return num_enqueues_; } + int64_t timestamp() const { return num_enqueues_ + num_untrails_; } // Same as num_enqueues but only count the level zero changes. - int64 num_level_zero_enqueues() const { return num_level_zero_enqueues_; } + int64_t num_level_zero_enqueues() const { return num_level_zero_enqueues_; } // All the registered bitsets will be set to one each time a LbVar is // modified. It is up to the client to clear it if it wants to be notified @@ -955,12 +960,12 @@ class IntegerTrail : public SatPropagator { struct TrailEntry { IntegerValue bound; IntegerVariable var; - int32 prev_trail_index; + int32_t prev_trail_index; // Index in literals_reason_start_/bounds_reason_starts_ If this is -1, then // this was a propagation with a lazy reason, and the reason can be // re-created by calling the function lazy_reasons_[trail_index]. - int32 reason_index; + int32_t reason_index; }; std::vector integer_trail_; std::vector lazy_reasons_; @@ -1021,7 +1026,7 @@ class IntegerTrail : public SatPropagator { struct RelaxHeapEntry { int index; IntegerValue coeff; - int64 diff; + int64_t diff; bool operator<(const RelaxHeapEntry& o) const { return index < o.index; } }; mutable std::vector relax_heap_; @@ -1040,10 +1045,10 @@ class IntegerTrail : public SatPropagator { // This is reverted as we backtrack over it. int first_level_without_full_propagation_ = -1; - int64 num_enqueues_ = 0; - int64 num_untrails_ = 0; - int64 num_level_zero_enqueues_ = 0; - mutable int64 num_decisions_to_break_loop_ = 0; + int64_t num_enqueues_ = 0; + int64_t num_untrails_ = 0; + int64_t num_level_zero_enqueues_ = 0; + mutable int64_t num_decisions_to_break_loop_ = 0; std::vector*> watchers_; std::vector reversible_classes_; @@ -1236,7 +1241,7 @@ class GenericLiteralWatcher : public SatPropagator { std::vector in_queue_; // Data for each propagator. - DEFINE_INT_TYPE(IdType, int32); + DEFINE_INT_TYPE(IdType, int32_t); std::vector id_to_level_at_last_call_; RevVector id_to_greatest_common_level_since_last_call_; std::vector> id_to_reversible_classes_; @@ -1416,15 +1421,15 @@ inline std::function NewBooleanVariable() { } inline std::function ConstantIntegerVariable( - int64 value) { + int64_t value) { return [=](Model* model) { return model->GetOrCreate() ->GetOrCreateConstantIntegerVariable(IntegerValue(value)); }; } -inline std::function NewIntegerVariable(int64 lb, - int64 ub) { +inline std::function NewIntegerVariable(int64_t lb, + int64_t ub) { return [=](Model* model) { CHECK_LE(lb, ub); return model->GetOrCreate()->AddIntegerVariable( @@ -1464,13 +1469,13 @@ inline std::function NewIntegerVariableFromLiteral( }; } -inline std::function LowerBound(IntegerVariable v) { +inline std::function LowerBound(IntegerVariable v) { return [=](const Model& model) { return model.Get()->LowerBound(v).value(); }; } -inline std::function UpperBound(IntegerVariable v) { +inline std::function UpperBound(IntegerVariable v) { return [=](const Model& model) { return model.Get()->UpperBound(v).value(); }; @@ -1484,7 +1489,7 @@ inline std::function IsFixed(IntegerVariable v) { } // This checks that the variable is fixed. -inline std::function Value(IntegerVariable v) { +inline std::function Value(IntegerVariable v) { return [=](const Model& model) { const IntegerTrail* trail = model.Get(); CHECK_EQ(trail->LowerBound(v), trail->UpperBound(v)) << v; @@ -1492,7 +1497,8 @@ inline std::function Value(IntegerVariable v) { }; } -inline std::function GreaterOrEqual(IntegerVariable v, int64 lb) { +inline std::function GreaterOrEqual(IntegerVariable v, + int64_t lb) { return [=](Model* model) { if (!model->GetOrCreate()->Enqueue( IntegerLiteral::GreaterOrEqual(v, IntegerValue(lb)), @@ -1506,7 +1512,7 @@ inline std::function GreaterOrEqual(IntegerVariable v, int64 lb) { }; } -inline std::function LowerOrEqual(IntegerVariable v, int64 ub) { +inline std::function LowerOrEqual(IntegerVariable v, int64_t ub) { return [=](Model* model) { if (!model->GetOrCreate()->Enqueue( IntegerLiteral::LowerOrEqual(v, IntegerValue(ub)), @@ -1521,7 +1527,7 @@ inline std::function LowerOrEqual(IntegerVariable v, int64 ub) { } // Fix v to a given value. -inline std::function Equality(IntegerVariable v, int64 value) { +inline std::function Equality(IntegerVariable v, int64_t value) { return [=](Model* model) { model->Add(LowerOrEqual(v, value)); model->Add(GreaterOrEqual(v, value)); @@ -1563,7 +1569,7 @@ inline std::function Implication( // in_interval => v in [lb, ub]. inline std::function ImpliesInInterval(Literal in_interval, IntegerVariable v, - int64 lb, int64 ub) { + int64_t lb, int64_t ub) { return [=](Model* model) { if (lb == ub) { IntegerEncoder* encoder = model->GetOrCreate(); diff --git a/ortools/sat/integer_expr.cc b/ortools/sat/integer_expr.cc index 0f15c5bc99..7ad5193cbc 100644 --- a/ortools/sat/integer_expr.cc +++ b/ortools/sat/integer_expr.cc @@ -14,6 +14,7 @@ #include "ortools/sat/integer_expr.h" #include +#include #include #include @@ -279,7 +280,7 @@ bool LevelZeroEquality::Propagate() { // miplib problem that we close quickly, so I didn't add the extra code yet. if (trail_->CurrentDecisionLevel() != 0) return true; - int64 gcd = 0; + int64_t gcd = 0; IntegerValue sum(0); for (int i = 0; i < vars_.size(); ++i) { if (integer_trail_->IsFixed(vars_[i])) { @@ -693,7 +694,7 @@ namespace { // TODO(user): Find better implementation? IntegerValue FloorSquareRoot(IntegerValue a) { - IntegerValue result(static_cast(std::floor(std::sqrt(ToDouble(a))))); + IntegerValue result(static_cast(std::floor(std::sqrt(ToDouble(a))))); while (result * result > a) --result; while ((result + 1) * (result + 1) <= a) ++result; return result; @@ -701,7 +702,7 @@ IntegerValue FloorSquareRoot(IntegerValue a) { // TODO(user): Find better implementation? IntegerValue CeilSquareRoot(IntegerValue a) { - IntegerValue result(static_cast(std::ceil(std::sqrt(ToDouble(a))))); + IntegerValue result(static_cast(std::ceil(std::sqrt(ToDouble(a))))); while (result * result < a) ++result; while ((result - 1) * (result - 1) >= a) --result; return result; diff --git a/ortools/sat/integer_expr.h b/ortools/sat/integer_expr.h index 972771ade0..5fbc7eb597 100644 --- a/ortools/sat/integer_expr.h +++ b/ortools/sat/integer_expr.h @@ -14,6 +14,7 @@ #ifndef OR_TOOLS_SAT_INTEGER_EXPR_H_ #define OR_TOOLS_SAT_INTEGER_EXPR_H_ +#include #include #include @@ -298,11 +299,11 @@ class SquarePropagator : public PropagatorInterface { template inline std::function WeightedSumLowerOrEqual( const std::vector& vars, const VectorInt& coefficients, - int64 upper_bound) { + int64_t upper_bound) { // Special cases. CHECK_GE(vars.size(), 1); if (vars.size() == 1) { - const int64 c = coefficients[0]; + const int64_t c = coefficients[0]; CHECK_NE(c, 0); if (c > 0) { return LowerOrEqual( @@ -403,10 +404,10 @@ inline std::function WeightedSumLowerOrEqual( template inline std::function WeightedSumGreaterOrEqual( const std::vector& vars, const VectorInt& coefficients, - int64 lower_bound) { + int64_t lower_bound) { // We just negate everything and use an <= constraints. - std::vector negated_coeffs(coefficients.begin(), coefficients.end()); - for (int64& ref : negated_coeffs) ref = -ref; + std::vector negated_coeffs(coefficients.begin(), coefficients.end()); + for (int64_t& ref : negated_coeffs) ref = -ref; return WeightedSumLowerOrEqual(vars, negated_coeffs, -lower_bound); } @@ -414,7 +415,7 @@ inline std::function WeightedSumGreaterOrEqual( template inline std::function FixedWeightedSum( const std::vector& vars, const VectorInt& coefficients, - int64 value) { + int64_t value) { return [=](Model* model) { model->Add(WeightedSumGreaterOrEqual(vars, coefficients, value)); model->Add(WeightedSumLowerOrEqual(vars, coefficients, value)); @@ -426,7 +427,7 @@ template inline std::function ConditionalWeightedSumLowerOrEqual( const std::vector& enforcement_literals, const std::vector& vars, const VectorInt& coefficients, - int64 upper_bound) { + int64_t upper_bound) { // Special cases. CHECK_GE(vars.size(), 1); if (vars.size() == 1) { @@ -514,10 +515,10 @@ template inline std::function ConditionalWeightedSumGreaterOrEqual( const std::vector& enforcement_literals, const std::vector& vars, const VectorInt& coefficients, - int64 lower_bound) { + int64_t lower_bound) { // We just negate everything and use an <= constraint. - std::vector negated_coeffs(coefficients.begin(), coefficients.end()); - for (int64& ref : negated_coeffs) ref = -ref; + std::vector negated_coeffs(coefficients.begin(), coefficients.end()); + for (int64_t& ref : negated_coeffs) ref = -ref; return ConditionalWeightedSumLowerOrEqual(enforcement_literals, vars, negated_coeffs, -lower_bound); } @@ -526,7 +527,7 @@ inline std::function ConditionalWeightedSumGreaterOrEqual( template inline std::function WeightedSumLowerOrEqualReif( Literal is_le, const std::vector& vars, - const VectorInt& coefficients, int64 upper_bound) { + const VectorInt& coefficients, int64_t upper_bound) { return [=](Model* model) { model->Add(ConditionalWeightedSumLowerOrEqual({is_le}, vars, coefficients, upper_bound)); @@ -539,7 +540,7 @@ inline std::function WeightedSumLowerOrEqualReif( template inline std::function WeightedSumGreaterOrEqualReif( Literal is_ge, const std::vector& vars, - const VectorInt& coefficients, int64 lower_bound) { + const VectorInt& coefficients, int64_t lower_bound) { return [=](Model* model) { model->Add(ConditionalWeightedSumGreaterOrEqual({is_ge}, vars, coefficients, lower_bound)); @@ -557,7 +558,7 @@ inline void LoadLinearConstraint(const LinearConstraint& cst, Model* model) { } // TODO(user): Remove the conversion! - std::vector converted_coeffs; + std::vector converted_coeffs; for (const IntegerValue v : cst.coeffs) converted_coeffs.push_back(v.value()); if (cst.ub < kMaxIntegerValue) { model->Add( @@ -583,7 +584,7 @@ inline void LoadConditionalLinearConstraint( // TODO(user): Remove the conversion! std::vector converted_literals(enforcement_literals.begin(), enforcement_literals.end()); - std::vector converted_coeffs; + std::vector converted_coeffs; for (const IntegerValue v : cst.coeffs) converted_coeffs.push_back(v.value()); if (cst.ub < kMaxIntegerValue) { @@ -601,7 +602,7 @@ inline void LoadConditionalLinearConstraint( template inline std::function FixedWeightedSumReif( Literal is_eq, const std::vector& vars, - const VectorInt& coefficients, int64 value) { + const VectorInt& coefficients, int64_t value) { return [=](Model* model) { // We creates two extra Boolean variables in this case. The alternative is // to code a custom propagator for the direction equality => reified. @@ -618,7 +619,7 @@ inline std::function FixedWeightedSumReif( template inline std::function WeightedSumNotEqual( const std::vector& vars, const VectorInt& coefficients, - int64 value) { + int64_t value) { return [=](Model* model) { // Exactly one of these alternative must be true. const Literal is_lt = Literal(model->Add(NewBooleanVariable()), true); diff --git a/ortools/sat/integer_search.cc b/ortools/sat/integer_search.cc index 2bf6039af5..42ca27ca54 100644 --- a/ortools/sat/integer_search.cc +++ b/ortools/sat/integer_search.cc @@ -14,6 +14,7 @@ #include "ortools/sat/integer_search.h" #include +#include #include #include @@ -117,7 +118,7 @@ IntegerLiteral SplitAroundLpValue(IntegerVariable var, Model* model) { // // TODO(user): Why is the reduced cost doing things differently? const IntegerValue value = IntegerValue( - static_cast(std::round(lp->GetSolutionValue(positive_var)))); + static_cast(std::round(lp->GetSolutionValue(positive_var)))); // Because our lp solution might be from higher up in the tree, it // is possible that value is now outside the domain of positive_var. @@ -126,7 +127,7 @@ IntegerLiteral SplitAroundLpValue(IntegerVariable var, Model* model) { } IntegerLiteral SplitUsingBestSolutionValueInRepository( - IntegerVariable var, const SharedSolutionRepository& solution_repo, + IntegerVariable var, const SharedSolutionRepository& solution_repo, Model* model) { if (solution_repo.NumSolutions() == 0) { return IntegerLiteral(); @@ -691,10 +692,10 @@ SatSolver::Status SolveIntegerProblem(Model* model) { const SatParameters& sat_parameters = *(model->GetOrCreate()); // Main search loop. - const int64 old_num_conflicts = sat_solver->num_failures(); - const int64 conflict_limit = sat_parameters.max_number_of_conflicts(); - int64 num_decisions_since_last_lp_record_ = 0; - int64 num_decisions_without_probing = 0; + const int64_t old_num_conflicts = sat_solver->num_failures(); + const int64_t conflict_limit = sat_parameters.max_number_of_conflicts(); + int64_t num_decisions_since_last_lp_record_ = 0; + int64_t num_decisions_without_probing = 0; while (!time_limit->LimitReached() && (sat_solver->num_failures() - old_num_conflicts < conflict_limit)) { // If needed, restart and switch decision_policy. diff --git a/ortools/sat/intervals.h b/ortools/sat/intervals.h index 95b3abe7e8..52e7ef5489 100644 --- a/ortools/sat/intervals.h +++ b/ortools/sat/intervals.h @@ -14,6 +14,7 @@ #ifndef OR_TOOLS_SAT_INTERVALS_H_ #define OR_TOOLS_SAT_INTERVALS_H_ +#include #include #include @@ -35,7 +36,7 @@ namespace operations_research { namespace sat { -DEFINE_INT_TYPE(IntervalVariable, int32); +DEFINE_INT_TYPE(IntervalVariable, int32_t); const IntervalVariable kNoIntervalVariable(-1); // This class maintains a set of intervals which correspond to three integer @@ -604,13 +605,13 @@ inline std::function SizeVar( }; } -inline std::function MinSize(IntervalVariable v) { +inline std::function MinSize(IntervalVariable v) { return [=](const Model& model) { return model.Get()->MinSize(v).value(); }; } -inline std::function MaxSize(IntervalVariable v) { +inline std::function MaxSize(IntervalVariable v) { return [=](const Model& model) { return model.Get()->MaxSize(v).value(); }; @@ -629,9 +630,9 @@ inline std::function IsPresentLiteral( }; } -inline std::function NewInterval(int64 min_start, - int64 max_end, - int64 size) { +inline std::function NewInterval(int64_t min_start, + int64_t max_end, + int64_t size) { return [=](Model* model) { return model->GetOrCreate()->CreateInterval( model->Add(NewIntegerVariable(min_start, max_end)), @@ -649,7 +650,7 @@ inline std::function NewInterval( } inline std::function NewIntervalWithVariableSize( - int64 min_start, int64 max_end, int64 min_size, int64 max_size) { + int64_t min_start, int64_t max_end, int64_t min_size, int64_t max_size) { return [=](Model* model) { return model->GetOrCreate()->CreateInterval( model->Add(NewIntegerVariable(min_start, max_end)), @@ -660,7 +661,7 @@ inline std::function NewIntervalWithVariableSize( } inline std::function NewOptionalInterval( - int64 min_start, int64 max_end, int64 size, Literal is_present) { + int64_t min_start, int64_t max_end, int64_t size, Literal is_present) { return [=](Model* model) { return model->GetOrCreate()->CreateInterval( model->Add(NewIntegerVariable(min_start, max_end)), @@ -670,8 +671,8 @@ inline std::function NewOptionalInterval( } inline std::function -NewOptionalIntervalWithOptionalVariables(int64 min_start, int64 max_end, - int64 size, Literal is_present) { +NewOptionalIntervalWithOptionalVariables(int64_t min_start, int64_t max_end, + int64_t size, Literal is_present) { return [=](Model* model) { // Note that we need to mark the optionality first. const IntegerVariable start = @@ -696,8 +697,8 @@ inline std::function NewOptionalInterval( } inline std::function -NewOptionalIntervalWithVariableSize(int64 min_start, int64 max_end, - int64 min_size, int64 max_size, +NewOptionalIntervalWithVariableSize(int64_t min_start, int64_t max_end, + int64_t min_size, int64_t max_size, Literal is_present) { return [=](Model* model) { return model->GetOrCreate()->CreateInterval( diff --git a/ortools/sat/linear_constraint.cc b/ortools/sat/linear_constraint.cc index f316403791..eb5a46a8b4 100644 --- a/ortools/sat/linear_constraint.cc +++ b/ortools/sat/linear_constraint.cc @@ -13,6 +13,8 @@ #include "ortools/sat/linear_constraint.h" +#include + #include "ortools/base/mathutil.h" #include "ortools/base/strong_vector.h" #include "ortools/sat/integer.h" @@ -175,7 +177,7 @@ namespace { // TODO(user): Template for any integer type and expose this? IntegerValue ComputeGcd(const std::vector& values) { if (values.empty()) return IntegerValue(1); - int64 gcd = 0; + int64_t gcd = 0; for (const IntegerValue value : values) { gcd = MathUtil::GCD64(gcd, std::abs(value.value())); if (gcd == 1) break; diff --git a/ortools/sat/linear_constraint_manager.h b/ortools/sat/linear_constraint_manager.h index f779f99e46..d724a384f9 100644 --- a/ortools/sat/linear_constraint_manager.h +++ b/ortools/sat/linear_constraint_manager.h @@ -15,6 +15,7 @@ #define OR_TOOLS_SAT_LINEAR_CONSTRAINT_MANAGER_H_ #include +#include #include #include "absl/container/flat_hash_map.h" @@ -43,7 +44,7 @@ class LinearConstraintManager { struct ConstraintInfo { LinearConstraint constraint; double l2_norm = 0.0; - int64 inactive_count = 0; + int64_t inactive_count = 0; double objective_parallelism = 0.0; bool objective_parallelism_computed = false; bool is_in_lp = false; @@ -75,7 +76,7 @@ class LinearConstraintManager { // basic preprocessing. If added is given, it will be set to true if this // constraint was actually a new one and to false if it was dominated by an // already existing one. - DEFINE_INT_TYPE(ConstraintIndex, int32); + DEFINE_INT_TYPE(ConstraintIndex, int32_t); ConstraintIndex Add(LinearConstraint ct, bool* added = nullptr); // Same as Add(), but logs some information about the newly added constraint. @@ -122,9 +123,11 @@ class LinearConstraintManager { return lp_constraints_; } - int64 num_cuts() const { return num_cuts_; } - int64 num_shortened_constraints() const { return num_shortened_constraints_; } - int64 num_coeff_strenghtening() const { return num_coeff_strenghtening_; } + int64_t num_cuts() const { return num_cuts_; } + int64_t num_shortened_constraints() const { + return num_shortened_constraints_; + } + int64_t num_coeff_strenghtening() const { return num_coeff_strenghtening_; } // If a debug solution has been loaded, this checks if the given constaint cut // it or not. Returns true iff everything is fine and the cut does not violate @@ -170,7 +173,7 @@ class LinearConstraintManager { bool current_lp_is_changed_ = false; // Optimization to avoid calling SimplifyConstraint() when not needed. - int64 last_simplification_timestamp_ = 0; + int64_t last_simplification_timestamp_ = 0; absl::StrongVector constraint_infos_; @@ -184,14 +187,14 @@ class LinearConstraintManager { // constraints. absl::flat_hash_map equiv_constraints_; - int64 num_simplifications_ = 0; - int64 num_merged_constraints_ = 0; - int64 num_shortened_constraints_ = 0; - int64 num_splitted_constraints_ = 0; - int64 num_coeff_strenghtening_ = 0; + int64_t num_simplifications_ = 0; + int64_t num_merged_constraints_ = 0; + int64_t num_shortened_constraints_ = 0; + int64_t num_splitted_constraints_ = 0; + int64_t num_coeff_strenghtening_ = 0; - int64 num_cuts_ = 0; - int64 num_add_cut_calls_ = 0; + int64_t num_cuts_ = 0; + int64_t num_add_cut_calls_ = 0; std::map type_to_num_cuts_; bool objective_is_defined_ = false; @@ -220,7 +223,7 @@ class LinearConstraintManager { // management. double constraint_active_count_increase_ = 1.0; - int32 num_deletable_constraints_ = 0; + int32_t num_deletable_constraints_ = 0; }; // Keep the top n elements from a stream of elements. diff --git a/ortools/sat/linear_programming_constraint.cc b/ortools/sat/linear_programming_constraint.cc index d00cb59247..164799a1b2 100644 --- a/ortools/sat/linear_programming_constraint.cc +++ b/ortools/sat/linear_programming_constraint.cc @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -65,8 +66,10 @@ void ScatteredIntegerVector::ClearAndResize(int size) { } bool ScatteredIntegerVector::Add(glop::ColIndex col, IntegerValue value) { - const int64 add = CapAdd(value.value(), dense_vector_[col].value()); - if (add == kint64min || add == kint64max) return false; + const int64_t add = CapAdd(value.value(), dense_vector_[col].value()); + if (add == std::numeric_limits::min() || + add == std::numeric_limits::max()) + return false; dense_vector_[col] = IntegerValue(add); if (is_sparse_ && is_zeros_[col]) { is_zeros_[col] = false; @@ -392,7 +395,7 @@ LPSolveInfo LinearProgrammingConstraint::SolveLpForBranching() { // Record the objective bound. info.lp_objective = simplex_.GetObjectiveValue(); info.new_obj_bound = IntegerValue( - static_cast(std::ceil(info.lp_objective - kCpEpsilon))); + static_cast(std::ceil(info.lp_objective - kCpEpsilon))); } return info; } @@ -1268,7 +1271,8 @@ void LinearProgrammingConstraint::AddMirCuts() { } if (CapAdd(CapProd(max_magnitude.value(), std::abs(mult1.value())), CapProd(infinity_norms_[row_to_combine].value(), - std::abs(mult2.value()))) == kint64max) { + std::abs(mult2.value()))) == + std::numeric_limits::max()) { break; } @@ -1339,27 +1343,27 @@ void LinearProgrammingConstraint::AddZeroHalfCuts() { } void LinearProgrammingConstraint::UpdateSimplexIterationLimit( - const int64 min_iter, const int64 max_iter) { + const int64_t min_iter, const int64_t max_iter) { if (sat_parameters_.linearization_level() < 2) return; - const int64 num_degenerate_columns = CalculateDegeneracy(); - const int64 num_cols = simplex_.GetProblemNumCols().value(); + const int64_t num_degenerate_columns = CalculateDegeneracy(); + const int64_t num_cols = simplex_.GetProblemNumCols().value(); if (num_cols <= 0) { return; } CHECK_GT(num_cols, 0); - const int64 decrease_factor = (10 * num_degenerate_columns) / num_cols; + const int64_t decrease_factor = (10 * num_degenerate_columns) / num_cols; if (simplex_.GetProblemStatus() == glop::ProblemStatus::DUAL_FEASIBLE) { // We reached here probably because we predicted wrong. We use this as a // signal to increase the iterations or punish less for degeneracy compare // to the other part. if (is_degenerate_) { - next_simplex_iter_ /= std::max(int64{1}, decrease_factor); + next_simplex_iter_ /= std::max(int64_t{1}, decrease_factor); } else { next_simplex_iter_ *= 2; } } else if (simplex_.GetProblemStatus() == glop::ProblemStatus::OPTIMAL) { if (is_degenerate_) { - next_simplex_iter_ /= std::max(int64{1}, 2 * decrease_factor); + next_simplex_iter_ /= std::max(int64_t{1}, 2 * decrease_factor); } else { // This is the most common case. We use the size of the problem to // determine the limit and ignore the previous limit. @@ -1492,8 +1496,8 @@ bool LinearProgrammingConstraint::Propagate() { // already take care of the scaling so that it returns an objective in the // CP world. const double relaxed_optimal_objective = simplex_.GetObjectiveValue(); - const IntegerValue approximate_new_lb( - static_cast(std::ceil(relaxed_optimal_objective - kCpEpsilon))); + const IntegerValue approximate_new_lb(static_cast( + std::ceil(relaxed_optimal_objective - kCpEpsilon))); // TODO(user): Maybe do a bit less computation when we cannot propagate // anything. @@ -1665,8 +1669,9 @@ bool LinearProgrammingConstraint::PossibleOverflow( return true; } } - const int64 slack = CapAdd(lower_bound.value(), -constraint.ub.value()); - if (slack == kint64min || slack == kint64max) { + const int64_t slack = CapAdd(lower_bound.value(), -constraint.ub.value()); + if (slack == std::numeric_limits::min() || + slack == std::numeric_limits::max()) { return true; } return false; @@ -1740,7 +1745,7 @@ void LinearProgrammingConstraint::PreventOverflow(LinearConstraint* constraint, constraint->vars.resize(new_size); constraint->coeffs.resize(new_size); - constraint->ub = IntegerValue(static_cast( + constraint->ub = IntegerValue(static_cast( FloorRatio128(absl::int128(constraint->ub.value()) - adjust, divisor))); } @@ -2136,7 +2141,7 @@ bool LinearProgrammingConstraint::FillExactDualRayReason() { return true; } -int64 LinearProgrammingConstraint::CalculateDegeneracy() { +int64_t LinearProgrammingConstraint::CalculateDegeneracy() { const glop::ColIndex num_vars = simplex_.GetProblemNumCols(); int num_non_basic_with_zero_rc = 0; for (glop::ColIndex i(0); i < num_vars; ++i) { @@ -2147,7 +2152,7 @@ int64 LinearProgrammingConstraint::CalculateDegeneracy() { } num_non_basic_with_zero_rc++; } - const int64 num_cols = simplex_.GetProblemNumCols().value(); + const int64_t num_cols = simplex_.GetProblemNumCols().value(); is_degenerate_ = num_non_basic_with_zero_rc >= 0.3 * num_cols; return num_non_basic_with_zero_rc; } @@ -2206,7 +2211,7 @@ void AddOutgoingCut( int num_nodes, int subset_size, const std::vector& in_subset, const std::vector& tails, const std::vector& heads, const std::vector& literals, - const std::vector& literal_lp_values, int64 rhs_lower_bound, + const std::vector& literal_lp_values, int64_t rhs_lower_bound, const absl::StrongVector& lp_values, LinearConstraintManager* manager, Model* model) { // A node is said to be optional if it can be excluded from the subcircuit, @@ -2301,7 +2306,7 @@ void SeparateSubtourInequalities( int num_nodes, const std::vector& tails, const std::vector& heads, const std::vector& literals, const absl::StrongVector& lp_values, - absl::Span demands, int64 capacity, + absl::Span demands, int64_t capacity, LinearConstraintManager* manager, Model* model) { if (num_nodes <= 2) return; @@ -2433,9 +2438,9 @@ void SeparateSubtourInequalities( // Compute the total demands in order to know the minimum incoming/outgoing // flow. - int64 total_demands = 0; + int64_t total_demands = 0; if (!demands.empty()) { - for (const int64 demand : demands) total_demands += demand; + for (const int64_t demand : demands) total_demands += demand; } // Process each subsets and add any violated cut. @@ -2447,7 +2452,7 @@ void SeparateSubtourInequalities( // These fields will be left untouched if demands.empty(). bool contain_depot = false; - int64 subset_demand = 0; + int64_t subset_demand = 0; // Initialize "in_subset" and the subset demands. for (const int n : subset) { @@ -2471,7 +2476,7 @@ void SeparateSubtourInequalities( // [edge => value_head >= value_tail + edge_weight]. // We could take the minimum incoming edge weight per node in the set, and // use the cumul variable domain to infer some capacity. - int64 min_outgoing_flow = 1; + int64_t min_outgoing_flow = 1; if (!demands.empty()) { min_outgoing_flow = contain_depot @@ -2482,7 +2487,7 @@ void SeparateSubtourInequalities( // We still need to serve nodes with a demand of zero, and in the corner // case where all node in subset have a zero demand, the formula above // result in a min_outgoing_flow of zero. - min_outgoing_flow = std::max(min_outgoing_flow, int64{1}); + min_outgoing_flow = std::max(min_outgoing_flow, int64_t{1}); // Compute the current outgoing flow out of the subset. // @@ -2558,8 +2563,8 @@ CutGenerator CreateCVRPCutGenerator(int num_nodes, const std::vector& tails, const std::vector& heads, const std::vector& literals, - const std::vector& demands, - int64 capacity, Model* model) { + const std::vector& demands, + int64_t capacity, Model* model) { CutGenerator result; result.vars = GetAssociatedVariables(literals, model); result.generate_cuts = diff --git a/ortools/sat/linear_programming_constraint.h b/ortools/sat/linear_programming_constraint.h index 5585449220..936c84e8b0 100644 --- a/ortools/sat/linear_programming_constraint.h +++ b/ortools/sat/linear_programming_constraint.h @@ -14,6 +14,7 @@ #ifndef OR_TOOLS_SAT_LINEAR_PROGRAMMING_CONSTRAINT_H_ #define OR_TOOLS_SAT_LINEAR_PROGRAMMING_CONSTRAINT_H_ +#include #include #include #include @@ -215,7 +216,7 @@ class LinearProgrammingConstraint : public PropagatorInterface, return average_degeneracy_.CurrentAverage(); } - int64 total_num_simplex_iterations() const { + int64_t total_num_simplex_iterations() const { return total_num_simplex_iterations_; } @@ -279,7 +280,7 @@ class LinearProgrammingConstraint : public PropagatorInterface, bool FillExactDualRayReason(); // Returns number of non basic variables with zero reduced costs. - int64 CalculateDegeneracy(); + int64_t CalculateDegeneracy(); // From a set of row multipliers (at LP scale), scale them back to the CP // world and then make them integer (eventually multiplying them by a new @@ -367,7 +368,8 @@ class LinearProgrammingConstraint : public PropagatorInterface, // DUAL_FEASIBLE status as a signal to correct the prediction. The next limit // is capped by 'min_iter' and 'max_iter'. Note that this is enabled only for // linearization level 2 and above. - void UpdateSimplexIterationLimit(const int64 min_iter, const int64 max_iter); + void UpdateSimplexIterationLimit(const int64_t min_iter, + const int64_t max_iter); // This epsilon is related to the precision of the value/reduced_cost returned // by the LP once they have been scaled back into the CP domain. So for large @@ -401,7 +403,7 @@ class LinearProgrammingConstraint : public PropagatorInterface, // Underlying LP solver API. glop::LinearProgram lp_data_; glop::RevisedSimplex simplex_; - int64 next_simplex_iter_ = 500; + int64_t next_simplex_iter_ = 500; // For the scaling. glop::LpScalingHelper scaler_; @@ -514,14 +516,14 @@ class LinearProgrammingConstraint : public PropagatorInterface, // Used by the strong branching heuristic. int branching_frequency_ = 1; - int64 count_since_last_branching_ = 0; + int64_t count_since_last_branching_ = 0; // Sum of all simplex iterations performed by this class. This is useful to // test the incrementality and compare to other solvers. - int64 total_num_simplex_iterations_ = 0; + int64_t total_num_simplex_iterations_ = 0; // Some stats on the LP statuses encountered. - std::vector num_solves_by_status_; + std::vector num_solves_by_status_; }; // A class that stores which LP propagator is associated to each variable. @@ -562,8 +564,8 @@ CutGenerator CreateCVRPCutGenerator(int num_nodes, const std::vector& tails, const std::vector& heads, const std::vector& literals, - const std::vector& demands, - int64 capacity, Model* model); + const std::vector& demands, + int64_t capacity, Model* model); } // namespace sat } // namespace operations_research diff --git a/ortools/sat/linear_relaxation.cc b/ortools/sat/linear_relaxation.cc index 5bb94984e1..743936b165 100644 --- a/ortools/sat/linear_relaxation.cc +++ b/ortools/sat/linear_relaxation.cc @@ -13,6 +13,8 @@ #include "ortools/sat/linear_relaxation.h" +#include +#include #include #include "absl/container/flat_hash_set.h" @@ -825,13 +827,15 @@ void AppendLinearConstraintRelaxation(const ConstraintProto& constraint_proto, const IntegerValue rhs_domain_max = IntegerValue(constraint_proto.linear().domain( constraint_proto.linear().domain_size() - 1)); - if (rhs_domain_min == kint64min && rhs_domain_max == kint64max) return; + if (rhs_domain_min == std::numeric_limits::min() && + rhs_domain_max == std::numeric_limits::max()) + return; if (!HasEnforcementLiteral(constraint_proto)) { LinearConstraintBuilder lc(&model, rhs_domain_min, rhs_domain_max); for (int i = 0; i < constraint_proto.linear().vars_size(); i++) { const int ref = constraint_proto.linear().vars(i); - const int64 coeff = constraint_proto.linear().coeffs(i); + const int64_t coeff = constraint_proto.linear().coeffs(i); lc.AddTerm(mapping->Integer(ref), IntegerValue(coeff)); } relaxation->linear_constraints.push_back(lc.Build()); diff --git a/ortools/sat/lp_utils.cc b/ortools/sat/lp_utils.cc index 6242db95f7..cd94b82b43 100644 --- a/ortools/sat/lp_utils.cc +++ b/ortools/sat/lp_utils.cc @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -197,7 +198,7 @@ void RemoveNearZeroTerms(const SatParameters& params, MPModelProto* mp_model) { // to zero coefficient around 1e-7. But for large domain, we need lower coeff // than that, around 1e-12 with the default params.mip_max_bound(). This also // depends on the size of the constraint. - int64 num_removed = 0; + int64_t num_removed = 0; double largest_removed = 0.0; const int num_constraints = mp_model->constraint_size(); for (int c = 0; c < num_constraints; ++c) { @@ -491,7 +492,7 @@ struct ConstraintScaler { double max_scaling_factor = 0.0; double wanted_precision = 1e-6; - int64 scaling_target = int64{1} << 50; + int64_t scaling_target = int64_t{1} << 50; std::vector var_indices; std::vector coefficients; std::vector lower_bounds; @@ -534,8 +535,8 @@ ConstraintProto* ConstraintScaler::AddConstraint( const int num_coeffs = mp_constraint.coefficient_size(); for (int i = 0; i < num_coeffs; ++i) { const auto& var_proto = cp_model->variables(mp_constraint.var_index(i)); - const int64 lb = var_proto.domain(0); - const int64 ub = var_proto.domain(var_proto.domain_size() - 1); + const int64_t lb = var_proto.domain(0); + const int64_t ub = var_proto.domain(var_proto.domain_size() - 1); if (lb == 0 && ub == 0) continue; const double coeff = mp_constraint.coefficient(i); @@ -584,7 +585,7 @@ ConstraintProto* ConstraintScaler::AddConstraint( } } - const int64 gcd = ComputeGcdOfRoundedDoubles(coefficients, scaling_factor); + const int64_t gcd = ComputeGcdOfRoundedDoubles(coefficients, scaling_factor); max_relative_coeff_error = std::max(relative_coeff_error, max_relative_coeff_error); max_scaling_factor = std::max(scaling_factor / gcd, max_scaling_factor); @@ -595,7 +596,7 @@ ConstraintProto* ConstraintScaler::AddConstraint( for (int i = 0; i < coefficients.size(); ++i) { const double scaled_value = coefficients[i] * scaling_factor; - const int64 value = static_cast(std::round(scaled_value)) / gcd; + const int64_t value = static_cast(std::round(scaled_value)) / gcd; if (value != 0) { if (!mp_model.variable(var_indices[i]).is_integer()) { relax_bound = true; @@ -614,10 +615,10 @@ ConstraintProto* ConstraintScaler::AddConstraint( lb -= std::max(std::abs(lb), 1.0) * wanted_precision; } const Fractional scaled_lb = std::ceil(lb * scaling_factor); - if (lb == -kInfinity || scaled_lb <= kint64min) { - arg->add_domain(kint64min); + if (lb == -kInfinity || scaled_lb <= std::numeric_limits::min()) { + arg->add_domain(std::numeric_limits::min()); } else { - arg->add_domain(CeilRatio(IntegerValue(static_cast(scaled_lb)), + arg->add_domain(CeilRatio(IntegerValue(static_cast(scaled_lb)), IntegerValue(gcd)) .value()); } @@ -626,10 +627,10 @@ ConstraintProto* ConstraintScaler::AddConstraint( ub += std::max(std::abs(ub), 1.0) * wanted_precision; } const Fractional scaled_ub = std::floor(ub * scaling_factor); - if (ub == kInfinity || scaled_ub >= kint64max) { - arg->add_domain(kint64max); + if (ub == kInfinity || scaled_ub >= std::numeric_limits::max()) { + arg->add_domain(std::numeric_limits::max()); } else { - arg->add_domain(FloorRatio(IntegerValue(static_cast(scaled_ub)), + arg->add_domain(FloorRatio(IntegerValue(static_cast(scaled_ub)), IntegerValue(gcd)) .value()); } @@ -658,11 +659,12 @@ bool ConvertMPModelProtoToCpModelProto(const SatParameters& params, // similar condition in disguise because problem with a difference of more // than 6 magnitudes between the variable values will likely run into numeric // trouble. - const int64 kMaxVariableBound = static_cast(params.mip_max_bound()); + const int64_t kMaxVariableBound = + static_cast(params.mip_max_bound()); int num_truncated_bounds = 0; int num_small_domains = 0; - const int64 kSmallDomainSize = 1000; + const int64_t kSmallDomainSize = 1000; const double kWantedPrecision = params.mip_wanted_precision(); // Add the variables. @@ -680,14 +682,16 @@ bool ConvertMPModelProtoToCpModelProto(const SatParameters& params, if (mp_var.lower_bound() > kMaxVariableBound) { // Fix var to its lower bound. ++num_truncated_bounds; - const int64 value = static_cast(std::round(mp_var.lower_bound())); + const int64_t value = + static_cast(std::round(mp_var.lower_bound())); cp_var->add_domain(value); cp_var->add_domain(value); continue; } else if (mp_var.upper_bound() < -kMaxVariableBound) { // Fix var to its upper_bound. ++num_truncated_bounds; - const int64 value = static_cast(std::round(mp_var.upper_bound())); + const int64_t value = + static_cast(std::round(mp_var.upper_bound())); cp_var->add_domain(value); cp_var->add_domain(value); continue; @@ -704,8 +708,8 @@ bool ConvertMPModelProtoToCpModelProto(const SatParameters& params, // Note that the cast is "perfect" because we forbid large values. cp_var->add_domain( - static_cast(lower ? std::ceil(bound - kWantedPrecision) - : std::floor(bound + kWantedPrecision))); + static_cast(lower ? std::ceil(bound - kWantedPrecision) + : std::floor(bound + kWantedPrecision))); } if (cp_var->domain(0) > cp_var->domain(1)) { @@ -730,7 +734,8 @@ bool ConvertMPModelProtoToCpModelProto(const SatParameters& params, << kSmallDomainSize << " values."; ConstraintScaler scaler; - const int64 kScalingTarget = int64{1} << params.mip_max_activity_exponent(); + const int64_t kScalingTarget = int64_t{1} + << params.mip_max_activity_exponent(); scaler.wanted_precision = kWantedPrecision; scaler.scaling_target = kScalingTarget; @@ -828,8 +833,8 @@ bool ConvertMPModelProtoToCpModelProto(const SatParameters& params, if (mp_var.objective_coefficient() == 0.0) continue; const auto& var_proto = cp_model->variables(i); - const int64 lb = var_proto.domain(0); - const int64 ub = var_proto.domain(var_proto.domain_size() - 1); + const int64_t lb = var_proto.domain(0); + const int64_t ub = var_proto.domain(var_proto.domain_size() - 1); if (lb == 0 && ub == 0) continue; var_indices.push_back(i); @@ -877,7 +882,8 @@ bool ConvertMPModelProtoToCpModelProto(const SatParameters& params, } } - const int64 gcd = ComputeGcdOfRoundedDoubles(coefficients, scaling_factor); + const int64_t gcd = + ComputeGcdOfRoundedDoubles(coefficients, scaling_factor); // Display the objective error/scaling. LOG_IF(INFO, log_info) @@ -898,8 +904,8 @@ bool ConvertMPModelProtoToCpModelProto(const SatParameters& params, mult); objective->set_scaling_factor(1.0 / scaling_factor * gcd * mult); for (int i = 0; i < coefficients.size(); ++i) { - const int64 value = - static_cast(std::round(coefficients[i] * scaling_factor)) / + const int64_t value = + static_cast(std::round(coefficients[i] * scaling_factor)) / gcd; if (value != 0) { objective->add_vars(var_indices[i]); @@ -968,7 +974,7 @@ bool ConvertBinaryMPModelProtoToBooleanProblem(const MPModelProto& mp_model, } // Variables needed to scale the double coefficients into int64. - const int64 kInt64Max = std::numeric_limits::max(); + const int64_t kInt64Max = std::numeric_limits::max(); double max_relative_error = 0.0; double max_bound_error = 0.0; double max_scaling_factor = 0.0; @@ -989,7 +995,8 @@ bool ConvertBinaryMPModelProtoToBooleanProblem(const MPModelProto& mp_model, } GetBestScalingOfDoublesToInt64(coefficients, kInt64Max, &scaling_factor, &relative_error); - const int64 gcd = ComputeGcdOfRoundedDoubles(coefficients, scaling_factor); + const int64_t gcd = + ComputeGcdOfRoundedDoubles(coefficients, scaling_factor); max_relative_error = std::max(relative_error, max_relative_error); max_scaling_factor = std::max(scaling_factor / gcd, max_scaling_factor); @@ -997,7 +1004,7 @@ bool ConvertBinaryMPModelProtoToBooleanProblem(const MPModelProto& mp_model, for (int i = 0; i < num_coeffs; ++i) { const double scaled_value = mp_constraint.coefficient(i) * scaling_factor; bound_error += std::abs(round(scaled_value) - scaled_value); - const int64 value = static_cast(round(scaled_value)) / gcd; + const int64_t value = static_cast(round(scaled_value)) / gcd; if (value != 0) { constraint->add_literals(mp_constraint.var_index(i) + 1); constraint->add_coefficients(value); @@ -1019,7 +1026,8 @@ bool ConvertBinaryMPModelProtoToBooleanProblem(const MPModelProto& mp_model, if (lb * scaling_factor > -static_cast(kInt64Max)) { // Otherwise, the constraint is not needed. constraint->set_lower_bound( - static_cast(round(lb * scaling_factor - bound_error)) / gcd); + static_cast(round(lb * scaling_factor - bound_error)) / + gcd); } } const Fractional ub = mp_constraint.upper_bound(); @@ -1031,7 +1039,8 @@ bool ConvertBinaryMPModelProtoToBooleanProblem(const MPModelProto& mp_model, if (ub * scaling_factor < static_cast(kInt64Max)) { // Otherwise, the constraint is not needed. constraint->set_upper_bound( - static_cast(round(ub * scaling_factor + bound_error)) / gcd); + static_cast(round(ub * scaling_factor + bound_error)) / + gcd); } } } @@ -1049,7 +1058,7 @@ bool ConvertBinaryMPModelProtoToBooleanProblem(const MPModelProto& mp_model, } GetBestScalingOfDoublesToInt64(coefficients, kInt64Max, &scaling_factor, &relative_error); - const int64 gcd = ComputeGcdOfRoundedDoubles(coefficients, scaling_factor); + const int64_t gcd = ComputeGcdOfRoundedDoubles(coefficients, scaling_factor); max_relative_error = std::max(relative_error, max_relative_error); // Display the objective error/scaling. @@ -1064,9 +1073,10 @@ bool ConvertBinaryMPModelProtoToBooleanProblem(const MPModelProto& mp_model, objective->set_scaling_factor(1.0 / scaling_factor * gcd); for (int var_id = 0; var_id < num_variables; ++var_id) { const MPVariableProto& mp_var = mp_model.variable(var_id); - const int64 value = static_cast(round( - mp_var.objective_coefficient() * scaling_factor)) / - gcd; + const int64_t value = + static_cast( + round(mp_var.objective_coefficient() * scaling_factor)) / + gcd; if (value != 0) { objective->add_literals(var_id + 1); objective->add_coefficients(value); diff --git a/ortools/sat/optimization.cc b/ortools/sat/optimization.cc index 5be4dafd2c..8082c23237 100644 --- a/ortools/sat/optimization.cc +++ b/ortools/sat/optimization.cc @@ -14,6 +14,7 @@ #include "ortools/sat/optimization.h" #include +#include #include #include #include @@ -76,7 +77,7 @@ std::string CnfObjectiveLine(const LinearBooleanProblem& problem, Coefficient objective) { const double scaled_objective = AddOffsetAndScaleObjectiveValue(problem, objective); - return absl::StrFormat("o %d", static_cast(scaled_objective)); + return absl::StrFormat("o %d", static_cast(scaled_objective)); } struct LiteralWithCoreIndex { @@ -471,8 +472,8 @@ SatSolver::Status SolveWithWPM1(LogBehavior log, // The current lower_bound on the cost. // It will be correct after the initialization. - Coefficient lower_bound(static_cast(problem.objective().offset())); - Coefficient upper_bound(kint64max); + Coefficient lower_bound(static_cast(problem.objective().offset())); + Coefficient upper_bound(std::numeric_limits::max()); // The assumption literals and their associated cost. std::vector assumptions; @@ -572,7 +573,7 @@ SatSolver::Status SolveWithWPM1(LogBehavior log, ExtractAssignment(problem, *solver, solution); DCHECK(IsAssignmentValid(problem, *solution)); const Coefficient objective_offset( - static_cast(problem.objective().offset())); + static_cast(problem.objective().offset())); const Coefficient objective = ComputeObjectiveValue(problem, *solution); if (objective + objective_offset < upper_bound) { logger.Log(CnfObjectiveLine(problem, objective)); @@ -775,8 +776,8 @@ SatSolver::Status SolveWithRandomParameters(LogBehavior log, int max_number_of_conflicts = 5; parameters.set_log_search_progress(false); - Coefficient min_seen(std::numeric_limits::max()); - Coefficient max_seen(std::numeric_limits::min()); + Coefficient min_seen(std::numeric_limits::max()); + Coefficient max_seen(std::numeric_limits::min()); Coefficient best(min_seen); for (int i = 0; i < num_times; ++i) { solver->Backtrack(0); @@ -968,7 +969,7 @@ SatSolver::Status SolveWithCardinalityEncodingAndCore( // Initialize the bounds. // This is in term of number of variables not at their minimal value. Coefficient lower_bound(0); - Coefficient upper_bound(kint64max); + Coefficient upper_bound(std::numeric_limits::max()); if (!solution->empty()) { CHECK(IsAssignmentValid(problem, *solution)); upper_bound = ComputeObjectiveValue(problem, *solution) + offset; @@ -1006,7 +1007,7 @@ SatSolver::Status SolveWithCardinalityEncodingAndCore( absl::StrFormat("c iter:%d [%s] lb:%d%s assumptions:%u depth:%d", iter, previous_core_info, lower_bound.value() - offset.value() + - static_cast(problem.objective().offset()), + static_cast(problem.objective().offset()), gap_string, nodes.size(), max_depth)); // Solve under the assumptions. @@ -1606,7 +1607,7 @@ SatSolver::Status CoreBasedOptimizer::Optimize() { if (!already_switched_to_linear_scan_) { already_switched_to_linear_scan_ = true; std::vector constraint_vars; - std::vector constraint_coeffs; + std::vector constraint_coeffs; for (const int index : term_indices) { constraint_vars.push_back(terms_[index].var); constraint_coeffs.push_back(terms_[index].weight.value()); @@ -1627,8 +1628,8 @@ SatSolver::Status CoreBasedOptimizer::Optimize() { for (const ObjectiveTerm& term : terms_) { max_depth = std::max(max_depth, term.depth); } - const int64 lb = integer_trail_->LowerBound(objective_var_).value(); - const int64 ub = integer_trail_->UpperBound(objective_var_).value(); + const int64_t lb = integer_trail_->LowerBound(objective_var_).value(); + const int64_t ub = integer_trail_->UpperBound(objective_var_).value(); const int gap = lb == ub ? 0 @@ -1730,7 +1731,7 @@ SatSolver::Status CoreBasedOptimizer::Optimize() { // Sum variables in the core <= new_var. { std::vector constraint_vars; - std::vector constraint_coeffs; + std::vector constraint_coeffs; for (const Literal lit : core) { const int index = gtl::FindOrDie(literal_to_term_index, lit.Index()); terms_[index].weight -= min_weight; @@ -1843,7 +1844,7 @@ SatSolver::Status MinimizeWithHittingSetAndLazyEncoding( CHECK_EQ(response.status(), MPSolverResponseStatus::MPSOLVER_OPTIMAL); const IntegerValue mip_objective( - static_cast(std::round(response.objective_value()))); + static_cast(std::round(response.objective_value()))); VLOG(1) << "constraints: " << hs_model.constraint_size() << " variables: " << hs_model.variable_size() << " hs_lower_bound: " << objective_definition.ScaleIntegerObjective(mip_objective) @@ -1867,7 +1868,7 @@ SatSolver::Status MinimizeWithHittingSetAndLazyEncoding( IntegerValue next_stratified_threshold(0); for (int i = 0; i < num_variables_in_objective; ++i) { const IntegerValue hs_value( - static_cast(response.variable_value(i))); + static_cast(response.variable_value(i))); if (hs_value == integer_trail->UpperBound(variables[i])) continue; // Only consider the terms above the threshold. diff --git a/ortools/sat/pb_constraint.h b/ortools/sat/pb_constraint.h index d63b074801..27990a4ef6 100644 --- a/ortools/sat/pb_constraint.h +++ b/ortools/sat/pb_constraint.h @@ -15,6 +15,7 @@ #define OR_TOOLS_SAT_PB_CONSTRAINT_H_ #include +#include #include #include #include @@ -38,7 +39,7 @@ namespace sat { // The type of the integer coefficients in a pseudo-Boolean constraint. // This is also used for the current value of a constraint or its bounds. -DEFINE_INT_TYPE(Coefficient, int64); +DEFINE_INT_TYPE(Coefficient, int64_t); // IMPORTANT: We can't use numeric_limits::max() which will compile // but just returns zero!! @@ -49,7 +50,7 @@ const Coefficient kCoefficientMax( struct LiteralWithCoeff { LiteralWithCoeff() {} LiteralWithCoeff(Literal l, Coefficient c) : literal(l), coefficient(c) {} - LiteralWithCoeff(Literal l, int64 c) : literal(l), coefficient(c) {} + LiteralWithCoeff(Literal l, int64_t c) : literal(l), coefficient(c) {} Literal literal; Coefficient coefficient; bool operator==(const LiteralWithCoeff& other) const { @@ -469,7 +470,7 @@ class UpperBoundedLinearConstraint { // Returns a fingerprint of the constraint linear expression (without rhs). // This is used for duplicate detection. - int64 hash() const { return hash_; } + int64_t hash() const { return hash_; } // This is used to get statistics of the number of literals inspected by // a Propagate() call. @@ -507,7 +508,7 @@ class UpperBoundedLinearConstraint { std::vector literals_; Coefficient rhs_; - int64 hash_; + int64_t hash_; }; // Class responsible for managing a set of pseudo-Boolean constraints and their @@ -599,11 +600,11 @@ class PbConstraints : public SatPropagator { } // Some statistics. - int64 num_constraint_lookups() const { return num_constraint_lookups_; } - int64 num_inspected_constraint_literals() const { + int64_t num_constraint_lookups() const { return num_constraint_lookups_; } + int64_t num_inspected_constraint_literals() const { return num_inspected_constraint_literals_; } - int64 num_threshold_updates() const { return num_threshold_updates_; } + int64_t num_threshold_updates() const { return num_threshold_updates_; } private: bool PropagateNext(Trail* trail); @@ -625,7 +626,7 @@ class PbConstraints : public SatPropagator { // about two times faster with this implementation than one with direct // pointer to an UpperBoundedLinearConstraint. The main reason for this is // probably that the thresholds_ vector is a lot more efficient cache-wise. - DEFINE_INT_TYPE(ConstraintIndex, int32); + DEFINE_INT_TYPE(ConstraintIndex, int32_t); struct ConstraintIndexWithCoeff { ConstraintIndexWithCoeff() {} // Needed for vector.resize() ConstraintIndexWithCoeff(bool n, ConstraintIndex i, Coefficient c) @@ -651,7 +652,7 @@ class PbConstraints : public SatPropagator { // Pointers to the constraints grouped by their hash. // This is used to find duplicate constraints by AddConstraint(). - absl::flat_hash_map> + absl::flat_hash_map> possible_duplicates_; // Helper to enqueue propagated literals on the trail and store their reasons. @@ -671,9 +672,9 @@ class PbConstraints : public SatPropagator { // Some statistics. mutable StatsGroup stats_; - int64 num_constraint_lookups_; - int64 num_inspected_constraint_literals_; - int64 num_threshold_updates_; + int64_t num_constraint_lookups_; + int64_t num_inspected_constraint_literals_; + int64_t num_threshold_updates_; DISALLOW_COPY_AND_ASSIGN(PbConstraints); }; diff --git a/ortools/sat/precedences.h b/ortools/sat/precedences.h index f87c82289d..a78db1856d 100644 --- a/ortools/sat/precedences.h +++ b/ortools/sat/precedences.h @@ -14,6 +14,7 @@ #ifndef OR_TOOLS_SAT_PRECEDENCES_H_ #define OR_TOOLS_SAT_PRECEDENCES_H_ +#include #include #include #include @@ -341,7 +342,7 @@ inline std::function LowerOrEqual(IntegerVariable a, // a + offset <= b. inline std::function LowerOrEqualWithOffset(IntegerVariable a, IntegerVariable b, - int64 offset) { + int64_t offset) { return [=](Model* model) { return model->GetOrCreate()->AddPrecedenceWithOffset( a, b, IntegerValue(offset)); @@ -351,13 +352,13 @@ inline std::function LowerOrEqualWithOffset(IntegerVariable a, // a + b <= ub. inline std::function Sum2LowerOrEqual(IntegerVariable a, IntegerVariable b, - int64 ub) { + int64_t ub) { return LowerOrEqualWithOffset(a, NegationOf(b), -ub); } // l => (a + b <= ub). inline std::function ConditionalSum2LowerOrEqual( - IntegerVariable a, IntegerVariable b, int64 ub, + IntegerVariable a, IntegerVariable b, int64_t ub, const std::vector& enforcement_literals) { return [=](Model* model) { PrecedencesPropagator* p = model->GetOrCreate(); @@ -370,7 +371,7 @@ inline std::function ConditionalSum2LowerOrEqual( inline std::function Sum3LowerOrEqual(IntegerVariable a, IntegerVariable b, IntegerVariable c, - int64 ub) { + int64_t ub) { return [=](Model* model) { PrecedencesPropagator* p = model->GetOrCreate(); p->AddPrecedenceWithAllOptions(a, NegationOf(c), IntegerValue(-ub), b, {}); @@ -379,7 +380,7 @@ inline std::function Sum3LowerOrEqual(IntegerVariable a, // l => (a + b + c <= ub). inline std::function ConditionalSum3LowerOrEqual( - IntegerVariable a, IntegerVariable b, IntegerVariable c, int64 ub, + IntegerVariable a, IntegerVariable b, IntegerVariable c, int64_t ub, const std::vector& enforcement_literals) { return [=](Model* model) { PrecedencesPropagator* p = model->GetOrCreate(); @@ -408,7 +409,7 @@ inline std::function Equality(IntegerVariable a, // a + offset == b. inline std::function EqualityWithOffset(IntegerVariable a, IntegerVariable b, - int64 offset) { + int64_t offset) { return [=](Model* model) { model->Add(LowerOrEqualWithOffset(a, b, offset)); model->Add(LowerOrEqualWithOffset(b, a, -offset)); @@ -417,7 +418,7 @@ inline std::function EqualityWithOffset(IntegerVariable a, // is_le => (a + offset <= b). inline std::function ConditionalLowerOrEqualWithOffset( - IntegerVariable a, IntegerVariable b, int64 offset, Literal is_le) { + IntegerVariable a, IntegerVariable b, int64_t offset, Literal is_le) { return [=](Model* model) { PrecedencesPropagator* p = model->GetOrCreate(); p->AddConditionalPrecedenceWithOffset(a, b, IntegerValue(offset), is_le); @@ -443,7 +444,7 @@ inline std::function ConditionalLowerOrEqual( // is_le <=> (a + offset <= b). inline std::function ReifiedLowerOrEqualWithOffset( - IntegerVariable a, IntegerVariable b, int64 offset, Literal is_le) { + IntegerVariable a, IntegerVariable b, int64_t offset, Literal is_le) { return [=](Model* model) { PrecedencesPropagator* p = model->GetOrCreate(); p->AddConditionalPrecedenceWithOffset(a, b, IntegerValue(offset), is_le); @@ -476,7 +477,7 @@ inline std::function ReifiedEquality(IntegerVariable a, // is_eq <=> (a + offset == b). inline std::function ReifiedEqualityWithOffset(IntegerVariable a, IntegerVariable b, - int64 offset, + int64_t offset, Literal is_eq) { return [=](Model* model) { // We creates two extra Boolean variables in this case. diff --git a/ortools/sat/presolve_context.cc b/ortools/sat/presolve_context.cc index 3d453c2725..253d6335e1 100644 --- a/ortools/sat/presolve_context.cc +++ b/ortools/sat/presolve_context.cc @@ -13,6 +13,9 @@ #include "ortools/sat/presolve_context.h" +#include +#include + #include "ortools/base/map_util.h" #include "ortools/base/mathutil.h" #include "ortools/port/proto_utils.h" @@ -40,7 +43,7 @@ int PresolveContext::NewIntVar(const Domain& domain) { int PresolveContext::NewBoolVar() { return NewIntVar(Domain(0, 1)); } -int PresolveContext::GetOrCreateConstantVar(int64 cst) { +int PresolveContext::GetOrCreateConstantVar(int64_t cst) { if (!gtl::ContainsKey(constant_to_ref_, cst)) { constant_to_ref_[cst] = SavedVariable(working_model->variables_size()); IntegerVariableProto* const var_proto = working_model->add_variables(); @@ -104,22 +107,22 @@ bool PresolveContext::LiteralIsFalse(int lit) const { } } -int64 PresolveContext::MinOf(int ref) const { +int64_t PresolveContext::MinOf(int ref) const { DCHECK(!DomainIsEmpty(ref)); return RefIsPositive(ref) ? domains[PositiveRef(ref)].Min() : -domains[PositiveRef(ref)].Max(); } -int64 PresolveContext::MaxOf(int ref) const { +int64_t PresolveContext::MaxOf(int ref) const { DCHECK(!DomainIsEmpty(ref)); return RefIsPositive(ref) ? domains[PositiveRef(ref)].Max() : -domains[PositiveRef(ref)].Min(); } -int64 PresolveContext::MinOf(const LinearExpressionProto& expr) const { - int64 result = expr.offset(); +int64_t PresolveContext::MinOf(const LinearExpressionProto& expr) const { + int64_t result = expr.offset(); for (int i = 0; i < expr.vars_size(); ++i) { - const int64 coeff = expr.coeffs(i); + const int64_t coeff = expr.coeffs(i); if (coeff > 0) { result += coeff * MinOf(expr.vars(i)); } else { @@ -129,10 +132,10 @@ int64 PresolveContext::MinOf(const LinearExpressionProto& expr) const { return result; } -int64 PresolveContext::MaxOf(const LinearExpressionProto& expr) const { - int64 result = expr.offset(); +int64_t PresolveContext::MaxOf(const LinearExpressionProto& expr) const { + int64_t result = expr.offset(); for (int i = 0; i < expr.vars_size(); ++i) { - const int64 coeff = expr.coeffs(i); + const int64_t coeff = expr.coeffs(i); if (coeff > 0) { result += coeff * MaxOf(expr.vars(i)); } else { @@ -228,7 +231,7 @@ Domain PresolveContext::DomainOf(int ref) const { return result; } -bool PresolveContext::DomainContains(int ref, int64 value) const { +bool PresolveContext::DomainContains(int ref, int64_t value) const { if (!RefIsPositive(ref)) { return domains[PositiveRef(ref)].Contains(-value); } @@ -274,7 +277,7 @@ ABSL_MUST_USE_RESULT bool PresolveContext::IntersectDomainWith( ABSL_MUST_USE_RESULT bool PresolveContext::SetLiteralToFalse(int lit) { const int var = PositiveRef(lit); - const int64 value = RefIsPositive(lit) ? 0 : 1; + const int64_t value = RefIsPositive(lit) ? 0 : 1; return IntersectDomainWith(var, Domain(value)); } @@ -412,7 +415,7 @@ bool PresolveContext::ConstraintVariableUsageIsConsistent() { // Note(user): When both domain contains [0,1] and later the wrong variable // become usable as boolean, then we have a bug. Because of that, the code // for GetLiteralRepresentative() is not as simple as it should be. -bool PresolveContext::AddRelation(int x, int y, int64 c, int64 o, +bool PresolveContext::AddRelation(int x, int y, int64_t c, int64_t o, AffineRelation* repo) { // When the coefficient is larger than one, then if later one variable becomes // Boolean, it must be the representative. @@ -431,8 +434,8 @@ bool PresolveContext::AddRelation(int x, int y, int64 c, int64 o, // also be the variable with the smallest domain magnitude (1 or 0 if fixed). const int rep_x = repo->Get(x).representative; const int rep_y = repo->Get(y).representative; - const int64 m_x = std::max(std::abs(MinOf(rep_x)), std::abs(MaxOf(rep_x))); - const int64 m_y = std::max(std::abs(MinOf(rep_y)), std::abs(MaxOf(rep_y))); + const int64_t m_x = std::max(std::abs(MinOf(rep_x)), std::abs(MaxOf(rep_x))); + const int64_t m_y = std::max(std::abs(MinOf(rep_y)), std::abs(MaxOf(rep_y))); bool allow_rep_x = m_x < m_y; bool allow_rep_y = m_y < m_x; if (m_x == m_y) { @@ -447,7 +450,7 @@ bool PresolveContext::AddRelation(int x, int y, int64 c, int64 o, void PresolveContext::ExploitFixedDomain(int var) { CHECK(RefIsPositive(var)); CHECK(IsFixed(var)); - const int64 min = MinOf(var); + const int64_t min = MinOf(var); if (gtl::ContainsKey(constant_to_ref_, min)) { const int rep = constant_to_ref_[min].Get(this); if (RefIsPositive(rep)) { @@ -527,8 +530,8 @@ void PresolveContext::RemoveVariableFromAffineRelation(int var) { } } -bool PresolveContext::StoreAffineRelation(int ref_x, int ref_y, int64 coeff, - int64 offset) { +bool PresolveContext::StoreAffineRelation(int ref_x, int ref_y, int64_t coeff, + int64_t offset) { CHECK_NE(coeff, 0); if (is_unsat) return false; @@ -538,7 +541,7 @@ bool PresolveContext::StoreAffineRelation(int ref_x, int ref_y, int64 coeff, if (!PropagateAffineRelation(ref_y)) return true; if (IsFixed(ref_x)) { - const int64 lhs = DomainOf(ref_x).Min() - offset; + const int64_t lhs = DomainOf(ref_x).Min() - offset; if (lhs % std::abs(coeff) != 0) { is_unsat = true; return true; @@ -549,7 +552,7 @@ bool PresolveContext::StoreAffineRelation(int ref_x, int ref_y, int64 coeff, } if (IsFixed(ref_y)) { - const int64 value_x = DomainOf(ref_y).Min() * coeff + offset; + const int64_t value_x = DomainOf(ref_y).Min() * coeff + offset; static_cast(IntersectDomainWith(ref_x, Domain(value_x))); UpdateRuleStats("affine: fixed"); return true; @@ -565,8 +568,8 @@ bool PresolveContext::StoreAffineRelation(int ref_x, int ref_y, int64 coeff, // And x == coeff * ry.coeff * rep + (coeff * ry.offset + offset). // // So we get the relation a * rep == b with a and b defined here: - const int64 a = coeff * ry.coeff - rx.coeff; - const int64 b = coeff * ry.offset + offset - rx.offset; + const int64_t a = coeff * ry.coeff - rx.coeff; + const int64_t b = coeff * ry.offset + offset - rx.offset; if (a == 0) { if (b != 0) is_unsat = true; return true; @@ -576,7 +579,7 @@ bool PresolveContext::StoreAffineRelation(int ref_x, int ref_y, int64 coeff, return true; } UpdateRuleStats("affine: unique solution"); - const int64 unique_value = -b / a; + const int64_t unique_value = -b / a; if (!IntersectDomainWith(rx.representative, Domain(unique_value))) { return true; } @@ -593,8 +596,9 @@ bool PresolveContext::StoreAffineRelation(int ref_x, int ref_y, int64 coeff, const int x = PositiveRef(ref_x); const int y = PositiveRef(ref_y); - const int64 c = RefIsPositive(ref_x) == RefIsPositive(ref_y) ? coeff : -coeff; - const int64 o = RefIsPositive(ref_x) ? offset : -offset; + const int64_t c = + RefIsPositive(ref_x) == RefIsPositive(ref_y) ? coeff : -coeff; + const int64_t o = RefIsPositive(ref_x) ? offset : -offset; // TODO(user): can we force the rep and remove GetAffineRelation()? bool added = AddRelation(x, y, c, o, &affine_relations_); @@ -803,12 +807,13 @@ bool PresolveContext::RemapEncodingMaps() { // Encoding. { - const absl::flat_hash_map& var_map = encoding_[var]; + const absl::flat_hash_map& var_map = + encoding_[var]; for (const auto& entry : var_map) { const int lit = entry.second.Get(this); if (removed_variables_.contains(PositiveRef(lit))) continue; if ((entry.first - r.offset) % r.coeff != 0) continue; - const int64 rep_value = (entry.first - r.offset) / r.coeff; + const int64_t rep_value = (entry.first - r.offset) / r.coeff; ++num_remapping; InsertVarValueEncodingInternal(lit, r.representative, rep_value, /*add_constraints=*/false); @@ -819,11 +824,11 @@ bool PresolveContext::RemapEncodingMaps() { // Eq half encoding. { - const absl::flat_hash_map>& var_map = + const absl::flat_hash_map>& var_map = eq_half_encoding_[var]; for (const auto& entry : var_map) { if ((entry.first - r.offset) % r.coeff != 0) continue; - const int64 rep_value = (entry.first - r.offset) / r.coeff; + const int64_t rep_value = (entry.first - r.offset) / r.coeff; for (int literal : entry.second) { ++num_remapping; InsertHalfVarValueEncoding(GetLiteralRepresentative(literal), @@ -837,11 +842,11 @@ bool PresolveContext::RemapEncodingMaps() { // Neq half encoding. { - const absl::flat_hash_map>& var_map = + const absl::flat_hash_map>& var_map = neq_half_encoding_[var]; for (const auto& entry : var_map) { if ((entry.first - r.offset) % r.coeff != 0) continue; - const int64 rep_value = (entry.first - r.offset) / r.coeff; + const int64_t rep_value = (entry.first - r.offset) / r.coeff; for (int literal : entry.second) { ++num_remapping; InsertHalfVarValueEncoding(GetLiteralRepresentative(literal), @@ -865,12 +870,12 @@ bool PresolveContext::RemapEncodingMaps() { void PresolveContext::CanonicalizeDomainOfSizeTwo(int var) { CHECK(RefIsPositive(var)); CHECK_EQ(DomainOf(var).Size(), 2); - const int64 var_min = MinOf(var); - const int64 var_max = MaxOf(var); + const int64_t var_min = MinOf(var); + const int64_t var_max = MaxOf(var); if (is_unsat) return; - absl::flat_hash_map& var_map = encoding_[var]; + absl::flat_hash_map& var_map = encoding_[var]; // Find encoding for min if present. auto min_it = var_map.find(var_min); @@ -949,11 +954,11 @@ void PresolveContext::CanonicalizeDomainOfSizeTwo(int var) { } void PresolveContext::InsertVarValueEncodingInternal(int literal, int var, - int64 value, + int64_t value, bool add_constraints) { CHECK(!VariableWasRemoved(literal)); CHECK(!VariableWasRemoved(var)); - absl::flat_hash_map& var_map = encoding_[var]; + absl::flat_hash_map& var_map = encoding_[var]; // Ticky and rare: I have only observed this on the LNS of // radiation_m18_12_05_sat.fzn. The value was encoded, but maybe we never @@ -998,7 +1003,7 @@ void PresolveContext::InsertVarValueEncodingInternal(int literal, int var, } bool PresolveContext::InsertHalfVarValueEncoding(int literal, int var, - int64 value, bool imply_eq) { + int64_t value, bool imply_eq) { if (is_unsat) return false; CHECK(RefIsPositive(var)); @@ -1029,7 +1034,7 @@ bool PresolveContext::InsertHalfVarValueEncoding(int literal, int var, return true; } -bool PresolveContext::CanonicalizeEncoding(int* ref, int64* value) { +bool PresolveContext::CanonicalizeEncoding(int* ref, int64_t* value) { const AffineRelation::Relation r = GetAffineRelation(*ref); if ((*value - r.offset) % r.coeff != 0) return false; *ref = r.representative; @@ -1038,7 +1043,7 @@ bool PresolveContext::CanonicalizeEncoding(int* ref, int64* value) { } void PresolveContext::InsertVarValueEncoding(int literal, int ref, - int64 value) { + int64_t value) { if (!RemapEncodingMaps()) return; if (!CanonicalizeEncoding(&ref, &value)) return; literal = GetLiteralRepresentative(literal); @@ -1046,7 +1051,7 @@ void PresolveContext::InsertVarValueEncoding(int literal, int ref, } bool PresolveContext::StoreLiteralImpliesVarEqValue(int literal, int var, - int64 value) { + int64_t value) { if (!RemapEncodingMaps()) return false; if (!CanonicalizeEncoding(&var, &value)) return false; literal = GetLiteralRepresentative(literal); @@ -1054,17 +1059,18 @@ bool PresolveContext::StoreLiteralImpliesVarEqValue(int literal, int var, } bool PresolveContext::StoreLiteralImpliesVarNEqValue(int literal, int var, - int64 value) { + int64_t value) { if (!RemapEncodingMaps()) return false; if (!CanonicalizeEncoding(&var, &value)) return false; literal = GetLiteralRepresentative(literal); return InsertHalfVarValueEncoding(literal, var, value, /*imply_eq=*/false); } -bool PresolveContext::HasVarValueEncoding(int ref, int64 value, int* literal) { +bool PresolveContext::HasVarValueEncoding(int ref, int64_t value, + int* literal) { if (!RemapEncodingMaps()) return false; if (!CanonicalizeEncoding(&ref, &value)) return false; - const absl::flat_hash_map& var_map = encoding_[ref]; + const absl::flat_hash_map& var_map = encoding_[ref]; const auto it = var_map.find(value); if (it != var_map.end()) { if (literal != nullptr) { @@ -1075,7 +1081,7 @@ bool PresolveContext::HasVarValueEncoding(int ref, int64 value, int* literal) { return false; } -int PresolveContext::GetOrCreateVarValueEncoding(int ref, int64 value) { +int PresolveContext::GetOrCreateVarValueEncoding(int ref, int64_t value) { if (!RemapEncodingMaps()) return GetOrCreateConstantVar(0); if (!CanonicalizeEncoding(&ref, &value)) return GetOrCreateConstantVar(0); @@ -1088,7 +1094,7 @@ int PresolveContext::GetOrCreateVarValueEncoding(int ref, int64 value) { } // Returns the associated literal if already present. - absl::flat_hash_map& var_map = encoding_[var]; + absl::flat_hash_map& var_map = encoding_[var]; auto it = var_map.find(value); if (it != var_map.end()) { return it->second.Get(this); @@ -1102,11 +1108,11 @@ int PresolveContext::GetOrCreateVarValueEncoding(int ref, int64 value) { } // Special case for domains of size 2. - const int64 var_min = MinOf(var); - const int64 var_max = MaxOf(var); + const int64_t var_min = MinOf(var); + const int64_t var_max = MaxOf(var); if (domains[var].Size() == 2) { // Checks if the other value is already encoded. - const int64 other_value = value == var_min ? var_max : var_min; + const int64_t other_value = value == var_min ? var_max : var_min; auto other_it = var_map.find(other_value); if (other_it != var_map.end()) { // Update the encoding map. The domain could have been reduced to size @@ -1160,7 +1166,7 @@ void PresolveContext::ReadObjectiveFromProto() { objective_map_.clear(); for (int i = 0; i < obj.vars_size(); ++i) { const int ref = obj.vars(i); - int64 coeff = obj.coeffs(i); + int64_t coeff = obj.coeffs(i); if (!RefIsPositive(ref)) coeff = -coeff; int var = PositiveRef(ref); @@ -1178,7 +1184,7 @@ void PresolveContext::ReadObjectiveFromProto() { } bool PresolveContext::CanonicalizeObjective() { - int64 offset_change = 0; + int64_t offset_change = 0; // We replace each entry by its affine representative. // Note that the non-deterministic loop is fine, but because we iterate @@ -1196,7 +1202,7 @@ bool PresolveContext::CanonicalizeObjective() { const int var = entry.first; const auto it = objective_map_.find(var); if (it == objective_map_.end()) continue; - const int64 coeff = it->second; + const int64_t coeff = it->second; // If a variable only appear in objective, we can fix it! // Note that we don't care if it was in affine relation, because if none @@ -1232,7 +1238,8 @@ bool PresolveContext::CanonicalizeObjective() { // Do the substitution. offset_change += coeff * r.offset; - const int64 new_coeff = objective_map_[r.representative] += coeff * r.coeff; + const int64_t new_coeff = objective_map_[r.representative] += + coeff * r.coeff; // Process new term. if (new_coeff == 0) { @@ -1249,7 +1256,7 @@ bool PresolveContext::CanonicalizeObjective() { } Domain implied_domain(0); - int64 gcd(0); + int64_t gcd(0); // We need to sort the entries to be deterministic. tmp_entries_.clear(); @@ -1259,7 +1266,7 @@ bool PresolveContext::CanonicalizeObjective() { std::sort(tmp_entries_.begin(), tmp_entries_.end()); for (const auto& entry : tmp_entries_) { const int var = entry.first; - const int64 coeff = entry.second; + const int64_t coeff = entry.second; gcd = MathUtil::GCD64(gcd, std::abs(coeff)); implied_domain = implied_domain.AdditionWith(DomainOf(var).MultiplicationBy(coeff)) @@ -1293,13 +1300,14 @@ bool PresolveContext::CanonicalizeObjective() { // value without any issues. objective_domain_is_constraining_ = !implied_domain - .IntersectionWith(Domain(kint64min, objective_domain_.Max())) + .IntersectionWith(Domain(std::numeric_limits::min(), + objective_domain_.Max())) .IsIncludedIn(objective_domain_); return true; } bool PresolveContext::SubstituteVariableInObjective( - int var_in_equality, int64 coeff_in_equality, + int var_in_equality, int64_t coeff_in_equality, const ConstraintProto& equality, std::vector* new_vars_in_objective) { CHECK(equality.enforcement_literal().empty()); CHECK(RefIsPositive(var_in_equality)); @@ -1308,40 +1316,40 @@ bool PresolveContext::SubstituteVariableInObjective( // We can only "easily" substitute if the objective coefficient is a multiple // of the one in the constraint. - const int64 coeff_in_objective = + const int64_t coeff_in_objective = gtl::FindOrDie(objective_map_, var_in_equality); CHECK_NE(coeff_in_equality, 0); CHECK_EQ(coeff_in_objective % coeff_in_equality, 0); - const int64 multiplier = coeff_in_objective / coeff_in_equality; + const int64_t multiplier = coeff_in_objective / coeff_in_equality; // Abort if the new objective seems to violate our overflow preconditions. - int64 change = 0; + int64_t change = 0; for (int i = 0; i < equality.linear().vars().size(); ++i) { int var = equality.linear().vars(i); if (PositiveRef(var) == var_in_equality) continue; - int64 coeff = equality.linear().coeffs(i); + int64_t coeff = equality.linear().coeffs(i); change += std::abs(coeff) * std::max(std::abs(MinOf(var)), std::abs(MaxOf(var))); } - const int64 new_value = + const int64_t new_value = CapAdd(CapProd(std::abs(multiplier), change), objective_overflow_detection_ - std::abs(coeff_in_equality) * std::max(std::abs(MinOf(var_in_equality)), std::abs(MaxOf(var_in_equality)))); - if (new_value == kint64max) return false; + if (new_value == std::numeric_limits::max()) return false; objective_overflow_detection_ = new_value; for (int i = 0; i < equality.linear().vars().size(); ++i) { int var = equality.linear().vars(i); - int64 coeff = equality.linear().coeffs(i); + int64_t coeff = equality.linear().coeffs(i); if (!RefIsPositive(var)) { var = NegatedRef(var); coeff = -coeff; } if (var == var_in_equality) continue; - int64& map_ref = objective_map_[var]; + int64_t& map_ref = objective_map_[var]; if (map_ref == 0 && new_vars_in_objective != nullptr) { new_vars_in_objective->push_back(var); } @@ -1383,7 +1391,7 @@ bool PresolveContext::SubstituteVariableInObjective( void PresolveContext::WriteObjectiveToProto() const { // We need to sort the entries to be deterministic. - std::vector> entries; + std::vector> entries; for (const auto& entry : objective_map_) { entries.push_back(entry); } @@ -1423,7 +1431,7 @@ int PresolveContext::GetOrCreateReifiedPrecedenceLiteral(int time_i, int time_j, lesseq->mutable_linear()->add_coeffs(-1); lesseq->mutable_linear()->add_coeffs(1); lesseq->mutable_linear()->add_domain(0); - lesseq->mutable_linear()->add_domain(kint64max); + lesseq->mutable_linear()->add_domain(std::numeric_limits::max()); if (!LiteralIsTrue(active_i)) { AddImplication(result, active_i); } @@ -1437,7 +1445,7 @@ int PresolveContext::GetOrCreateReifiedPrecedenceLiteral(int time_i, int time_j, greater->mutable_linear()->add_vars(time_j); greater->mutable_linear()->add_coeffs(-1); greater->mutable_linear()->add_coeffs(1); - greater->mutable_linear()->add_domain(kint64min); + greater->mutable_linear()->add_domain(std::numeric_limits::min()); greater->mutable_linear()->add_domain(-1); // Manages enforcement literal. diff --git a/ortools/sat/presolve_context.h b/ortools/sat/presolve_context.h index fef5851f49..58e4712fb6 100644 --- a/ortools/sat/presolve_context.h +++ b/ortools/sat/presolve_context.h @@ -14,6 +14,7 @@ #ifndef OR_TOOLS_SAT_PRESOLVE_CONTEXT_H_ #define OR_TOOLS_SAT_PRESOLVE_CONTEXT_H_ +#include #include #include @@ -79,7 +80,7 @@ class PresolveContext { // Helpers to adds new variables to the presolved model. int NewIntVar(const Domain& domain); int NewBoolVar(); - int GetOrCreateConstantVar(int64 cst); + int GetOrCreateConstantVar(int64_t cst); // a => b. void AddImplication(int a, int b); @@ -93,16 +94,16 @@ class PresolveContext { bool CanBeUsedAsLiteral(int ref) const; bool LiteralIsTrue(int lit) const; bool LiteralIsFalse(int lit) const; - int64 MinOf(int ref) const; - int64 MaxOf(int ref) const; - bool DomainContains(int ref, int64 value) const; + int64_t MinOf(int ref) const; + int64_t MaxOf(int ref) const; + bool DomainContains(int ref, int64_t value) const; Domain DomainOf(int ref) const; // Helpers to query the current domain of a linear expression. // This doesn't check for integer overflow, but our linear expression // should be such that this cannot happen (tested at validation). - int64 MinOf(const LinearExpressionProto& expr) const; - int64 MaxOf(const LinearExpressionProto& expr) const; + int64_t MinOf(const LinearExpressionProto& expr) const; + int64_t MaxOf(const LinearExpressionProto& expr) const; // This function takes a positive variable reference. bool DomainOfVarIsIncludedIn(int var, const Domain& domain) { @@ -191,7 +192,7 @@ class PresolveContext { // special kAffineRelationConstraint. This will allow to identify when a // variable is no longer needed (only appear there and is not a // representative). - bool StoreAffineRelation(int ref_x, int ref_y, int64 coeff, int64 offset); + bool StoreAffineRelation(int ref_x, int ref_y, int64_t coeff, int64_t offset); // Adds the fact that ref_a == ref_b using StoreAffineRelation() above. // This should never fail, so the relation will always be added. @@ -237,7 +238,7 @@ class PresolveContext { // Important: This does not update the constraint<->variable graph, so // ConstraintVariableGraphIsUpToDate() will be false until // UpdateNewConstraintsVariableUsage() is called. - void InsertVarValueEncoding(int literal, int ref, int64 value); + void InsertVarValueEncoding(int literal, int ref, int64_t value); // Gets the associated literal if it is already created. Otherwise // create it, add the corresponding constraints and returns it. @@ -245,7 +246,7 @@ class PresolveContext { // Important: This does not update the constraint<->variable graph, so // ConstraintVariableGraphIsUpToDate() will be false until // UpdateNewConstraintsVariableUsage() is called. - int GetOrCreateVarValueEncoding(int ref, int64 value); + int GetOrCreateVarValueEncoding(int ref, int64_t value); // If not already done, adds a Boolean to represent any integer variables that // take only two values. Make sure all the relevant affine and encoding @@ -256,15 +257,15 @@ class PresolveContext { // Returns true if a literal attached to ref == var exists. // It assigns the corresponding to `literal` if non null. - bool HasVarValueEncoding(int ref, int64 value, int* literal = nullptr); + bool HasVarValueEncoding(int ref, int64_t value, int* literal = nullptr); // Stores the fact that literal implies var == value. // It returns true if that information is new. - bool StoreLiteralImpliesVarEqValue(int literal, int var, int64 value); + bool StoreLiteralImpliesVarEqValue(int literal, int var, int64_t value); // Stores the fact that literal implies var != value. // It returns true if that information is new. - bool StoreLiteralImpliesVarNEqValue(int literal, int var, int64 value); + bool StoreLiteralImpliesVarNEqValue(int literal, int var, int64_t value); // Objective handling functions. We load it at the beginning so that during // presolve we can work on the more efficient hash_map representation. @@ -297,13 +298,13 @@ class PresolveContext { // substitued variable is not implied free (i.e. if its domain is smaller than // the implied domain from the equality). bool SubstituteVariableInObjective( - int var_in_equality, int64 coeff_in_equality, + int var_in_equality, int64_t coeff_in_equality, const ConstraintProto& equality, std::vector* new_vars_in_objective = nullptr); // Objective getters. const Domain& ObjectiveDomain() const { return objective_domain_; } - const absl::flat_hash_map& ObjectiveMap() const { + const absl::flat_hash_map& ObjectiveMap() const { return objective_map_; } bool ObjectiveDomainIsConstraining() const { @@ -393,7 +394,7 @@ class PresolveContext { // of the presolve or not. Note that depending on the presolve transformation, // a rule can correspond to a tiny change or a big change. Because of that, // this isn't a perfect proxy for the efficacy of the presolve. - int64 num_presolve_operations = 0; + int64_t num_presolve_operations = 0; // Temporary storage. std::vector tmp_literals; @@ -402,14 +403,14 @@ class PresolveContext { absl::flat_hash_set tmp_literal_set; // Each time a domain is modified this is set to true. - SparseBitset modified_domains; + SparseBitset modified_domains; // Advanced presolve. See this class comment. DomainDeductions deductions; private: // Helper to add an affine relation x = c.y + o to the given repository. - bool AddRelation(int x, int y, int64 c, int64 o, AffineRelation* repo); + bool AddRelation(int x, int y, int64_t c, int64_t o, AffineRelation* repo); void AddVariableUsage(int c); void UpdateLinear1Usage(const ConstraintProto& ct, int c); @@ -426,7 +427,7 @@ class PresolveContext { // // Returns false if ref cannot take the given value (it might not have been // propagated yed). - bool CanonicalizeEncoding(int* ref, int64* value); + bool CanonicalizeEncoding(int* ref, int64_t* value); // Inserts an half reified var value encoding (literal => var ==/!= value). // It returns true if the new state is different from the old state. @@ -436,11 +437,11 @@ class PresolveContext { // Thus, if you detect literal <=> var == value, then two calls must be made: // InsertHalfVarValueEncoding(literal, var, value, true); // InsertHalfVarValueEncoding(NegatedRef(literal), var, value, false); - bool InsertHalfVarValueEncoding(int literal, int var, int64 value, + bool InsertHalfVarValueEncoding(int literal, int var, int64_t value, bool imply_eq); // Insert fully reified var-value encoding. - void InsertVarValueEncodingInternal(int literal, int var, int64 value, + void InsertVarValueEncodingInternal(int literal, int var, int64_t value, bool add_constraints); const bool log_info_; @@ -458,9 +459,9 @@ class PresolveContext { // the objective in this format in order to have more efficient substitution // on large problems (also because the objective is often dense). At the end // we re-convert it to its proto form. - absl::flat_hash_map objective_map_; - int64 objective_overflow_detection_; - std::vector> tmp_entries_; + absl::flat_hash_map objective_map_; + int64_t objective_overflow_detection_; + std::vector> tmp_entries_; bool objective_domain_is_constraining_ = false; Domain objective_domain_; double objective_offset_; @@ -485,7 +486,7 @@ class PresolveContext { // variable with the same constant value. If two variables end up having the // same fixed value, then we can detect it using this and add a new // equivalence relation. See ExploitFixedDomain(). - absl::flat_hash_map constant_to_ref_; + absl::flat_hash_map constant_to_ref_; // When a "representative" gets a new representative, it should be enqueued // here so that we can lazily update the *encoding_ maps below. @@ -493,15 +494,18 @@ class PresolveContext { // Contains variables with some encoded value: encoding_[i][v] points // to the literal attached to the value v of the variable i. - absl::flat_hash_map> encoding_; + absl::flat_hash_map> + encoding_; // Contains the currently collected half value encodings: // i.e.: literal => var ==/!= value // The state is accumulated (adding x => var == value then !x => var != value) // will deduce that x equivalent to var == value. - absl::flat_hash_map>> + absl::flat_hash_map>> eq_half_encoding_; - absl::flat_hash_map>> + absl::flat_hash_map>> neq_half_encoding_; // This regroups all the affine relations between variables. Note that the diff --git a/ortools/sat/presolve_util.cc b/ortools/sat/presolve_util.cc index 3be0bd6c69..5b5705fd96 100644 --- a/ortools/sat/presolve_util.cc +++ b/ortools/sat/presolve_util.cc @@ -13,6 +13,8 @@ #include "ortools/sat/presolve_util.h" +#include + #include "ortools/base/map_util.h" #include "ortools/sat/cp_model_utils.h" @@ -100,15 +102,15 @@ namespace { // Helper method for variable substitution. Returns the coefficient of 'var' in // 'proto' and copies other terms in 'terms'. template -int64 GetVarCoeffAndCopyOtherTerms(const int var, - const ProtoWithVarsAndCoeffs& proto, - std::vector>* terms) { +int64_t GetVarCoeffAndCopyOtherTerms( + const int var, const ProtoWithVarsAndCoeffs& proto, + std::vector>* terms) { bool found = false; - int64 var_coeff = 0; + int64_t var_coeff = 0; const int size = proto.vars().size(); for (int i = 0; i < size; ++i) { int ref = proto.vars(i); - int64 coeff = proto.coeffs(i); + int64_t coeff = proto.coeffs(i); if (!RefIsPositive(ref)) { ref = NegatedRef(ref); coeff = -coeff; @@ -136,7 +138,7 @@ void SortAndMergeTerms(std::vector>* terms, proto->clear_coeffs(); std::sort(terms->begin(), terms->end()); int current_var = 0; - int64 current_coeff = 0; + int64_t current_coeff = 0; for (const auto entry : *terms) { CHECK(RefIsPositive(entry.first)); if (entry.first == current_var) { @@ -158,13 +160,13 @@ void SortAndMergeTerms(std::vector>* terms, // Adds all the terms from the var definition constraint with given var // coefficient. -void AddTermsFromVarDefinition(const int var, const int64 var_coeff, +void AddTermsFromVarDefinition(const int var, const int64_t var_coeff, const ConstraintProto& definition, - std::vector>* terms) { + std::vector>* terms) { const int definition_size = definition.linear().vars().size(); for (int i = 0; i < definition_size; ++i) { int ref = definition.linear().vars(i); - int64 coeff = definition.linear().coeffs(i); + int64_t coeff = definition.linear().coeffs(i); if (!RefIsPositive(ref)) { ref = NegatedRef(ref); coeff = -coeff; @@ -179,15 +181,15 @@ void AddTermsFromVarDefinition(const int var, const int64 var_coeff, } } // namespace -void SubstituteVariable(int var, int64 var_coeff_in_definition, +void SubstituteVariable(int var, int64_t var_coeff_in_definition, const ConstraintProto& definition, ConstraintProto* ct) { CHECK(RefIsPositive(var)); CHECK_EQ(std::abs(var_coeff_in_definition), 1); // Copy all the terms (except the one refering to var). - std::vector> terms; - int64 var_coeff = GetVarCoeffAndCopyOtherTerms(var, ct->linear(), &terms); + std::vector> terms; + int64_t var_coeff = GetVarCoeffAndCopyOtherTerms(var, ct->linear(), &terms); if (var_coeff_in_definition < 0) var_coeff *= -1; diff --git a/ortools/sat/presolve_util.h b/ortools/sat/presolve_util.h index c60a5cfd2f..8f18cf75e1 100644 --- a/ortools/sat/presolve_util.h +++ b/ortools/sat/presolve_util.h @@ -15,6 +15,7 @@ #define OR_TOOLS_SAT_PRESOLVE_UTIL_H_ #include +#include #include #include "absl/container/flat_hash_map.h" @@ -85,7 +86,7 @@ class DomainDeductions { // Replaces the variable var in ct using the definition constraint. // Currently the coefficient in the definition must be 1 or -1. -void SubstituteVariable(int var, int64 var_coeff_in_definition, +void SubstituteVariable(int var, int64_t var_coeff_in_definition, const ConstraintProto& definition, ConstraintProto* ct); } // namespace sat diff --git a/ortools/sat/probing.cc b/ortools/sat/probing.cc index a1ddbb8733..d53123ae51 100644 --- a/ortools/sat/probing.cc +++ b/ortools/sat/probing.cc @@ -13,6 +13,7 @@ #include "ortools/sat/probing.h" +#include #include #include "ortools/base/iterator_adaptors.h" @@ -373,11 +374,11 @@ bool FailedLiteralProbingRound(ProbingOptions options, Model* model) { const int num_variables = sat_solver->NumVariables(); SparseBitset processed(LiteralIndex(2 * num_variables)); - int64 num_probed = 0; - int64 num_explicit_fix = 0; - int64 num_conflicts = 0; - int64 num_new_binary = 0; - int64 num_subsumed = 0; + int64_t num_probed = 0; + int64_t num_explicit_fix = 0; + int64_t num_conflicts = 0; + int64_t num_new_binary = 0; + int64_t num_subsumed = 0; const auto& trail = *(model->Get()); const auto& assignment = trail.Assignment(); diff --git a/ortools/sat/python/visualization.py b/ortools/sat/python/visualization.py index 75a1933d55..a4287a7134 100644 --- a/ortools/sat/python/visualization.py +++ b/ortools/sat/python/visualization.py @@ -18,7 +18,6 @@ try: from IPython.display import display from IPython.display import SVG import plotly.figure_factory as ff - import plotly.offline as pyo import svgwrite correct_imports = True except ImportError: @@ -78,8 +77,6 @@ def DisplayJobshop(starts, durations, machines, name): sorted_df = sorted(df, key=lambda k: k['Task']) - pyo.init_notebook_mode() - colors = {} cm = ColorManager() cm.SeedRandomColor(0) @@ -94,7 +91,7 @@ def DisplayJobshop(starts, durations, machines, name): showgrid_x=True, showgrid_y=True, group_tasks=True) - pyo.iplot(fig) + fig.show() class SvgWrapper(object): diff --git a/ortools/sat/rins.cc b/ortools/sat/rins.cc index 5194e38a6b..4d8a15bee3 100644 --- a/ortools/sat/rins.cc +++ b/ortools/sat/rins.cc @@ -13,6 +13,7 @@ #include "ortools/sat/rins.h" +#include #include #include "ortools/sat/cp_model_loader.h" @@ -73,7 +74,7 @@ std::vector GetGeneralRelaxationValues( relaxation_solutions->NumSolutions() == 0) { return relaxation_values; } - const SharedSolutionRepository::Solution relaxation_solution = + const SharedSolutionRepository::Solution relaxation_solution = relaxation_solutions->GetRandomBiasedSolution(random); for (int model_var = 0; @@ -130,9 +131,9 @@ RINSNeighborhood GetRINSNeighborhood( if (relaxation_values.empty()) return rins_neighborhood; const double tolerance = 1e-6; - const SharedSolutionRepository::Solution solution = + const SharedSolutionRepository::Solution solution = use_only_relaxation_values - ? SharedSolutionRepository::Solution() + ? SharedSolutionRepository::Solution() : response_manager->SolutionsRepository().GetRandomBiasedSolution( random); for (int model_var = 0; model_var < relaxation_values.size(); ++model_var) { @@ -149,10 +150,10 @@ RINSNeighborhood GetRINSNeighborhood( // Important: the LP relaxation doesn't know about holes in the variable // domains, so the intersection of [domain_lb, domain_ub] with the // initial variable domain might be empty. - const int64 domain_lb = - static_cast(std::floor(relaxation_value + tolerance)); - const int64 domain_ub = - static_cast(std::ceil(relaxation_value - tolerance)); + const int64_t domain_lb = + static_cast(std::floor(relaxation_value + tolerance)); + const int64_t domain_ub = + static_cast(std::ceil(relaxation_value - tolerance)); if (domain_lb == domain_ub) { rins_neighborhood.fixed_vars.push_back({model_var, domain_lb}); } else { diff --git a/ortools/sat/rins.h b/ortools/sat/rins.h index 6534531b23..e8c9c91ad9 100644 --- a/ortools/sat/rins.h +++ b/ortools/sat/rins.h @@ -14,6 +14,7 @@ #ifndef OR_TOOLS_SAT_RINS_H_ #define OR_TOOLS_SAT_RINS_H_ +#include #include #include "absl/container/flat_hash_map.h" @@ -55,8 +56,9 @@ struct LPVariables { // relaxation ignore those. struct RINSNeighborhood { // A variable will appear only once and not in both vectors. - std::vector> fixed_vars; - std::vector>> + std::vector> fixed_vars; + std::vector< + std::pair>> reduced_domain_vars; }; diff --git a/ortools/sat/samples/cp_is_fun_sat.cc b/ortools/sat/samples/cp_is_fun_sat.cc index b7d4b3a676..f2e1b96d71 100644 --- a/ortools/sat/samples/cp_is_fun_sat.cc +++ b/ortools/sat/samples/cp_is_fun_sat.cc @@ -19,6 +19,7 @@ // // This problem has 72 different solutions in base 10. +#include #include #include "ortools/sat/cp_model.h" @@ -33,7 +34,7 @@ void CPIsFunSat() { CpModelBuilder cp_model; // [START variables] - const int64 kBase = 10; + const int64_t kBase = 10; // Define decision variables. Domain digit(0, kBase - 1); diff --git a/ortools/sat/samples/earliness_tardiness_cost_sample_sat.cc b/ortools/sat/samples/earliness_tardiness_cost_sample_sat.cc index 5845b1d64f..a3b4488aa8 100644 --- a/ortools/sat/samples/earliness_tardiness_cost_sample_sat.cc +++ b/ortools/sat/samples/earliness_tardiness_cost_sample_sat.cc @@ -11,6 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include + #include "ortools/sat/cp_model.h" #include "ortools/sat/model.h" #include "ortools/sat/sat_parameters.pb.h" @@ -19,10 +21,10 @@ namespace operations_research { namespace sat { void EarlinessTardinessCostSampleSat() { - const int64 kEarlinessDate = 5; - const int64 kEarlinessCost = 8; - const int64 kLatenessDate = 15; - const int64 kLatenessCost = 12; + const int64_t kEarlinessDate = 5; + const int64_t kEarlinessCost = 8; + const int64_t kLatenessDate = 15; + const int64_t kLatenessCost = 12; // Create the CP-SAT model. CpModelBuilder cp_model; @@ -36,7 +38,7 @@ void EarlinessTardinessCostSampleSat() { // \______/ // ed ld // - const int64 kLargeConstant = 1000; + const int64_t kLargeConstant = 1000; const IntVar expr = cp_model.NewIntVar({0, kLargeConstant}); // First segment. diff --git a/ortools/sat/samples/no_overlap_sample_sat.cc b/ortools/sat/samples/no_overlap_sample_sat.cc index 9b7dc78754..84be4f4eb9 100644 --- a/ortools/sat/samples/no_overlap_sample_sat.cc +++ b/ortools/sat/samples/no_overlap_sample_sat.cc @@ -11,6 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include + #include "ortools/sat/cp_model.h" namespace operations_research { @@ -18,7 +20,7 @@ namespace sat { void NoOverlapSampleSat() { CpModelBuilder cp_model; - const int64 kHorizon = 21; // 3 weeks. + const int64_t kHorizon = 21; // 3 weeks. const Domain horizon(0, kHorizon); // Task 0, duration 2. diff --git a/ortools/sat/sat_base.h b/ortools/sat/sat_base.h index 6d254a5a6b..2bd06f3443 100644 --- a/ortools/sat/sat_base.h +++ b/ortools/sat/sat_base.h @@ -17,6 +17,7 @@ #define OR_TOOLS_SAT_SAT_BASE_H_ #include +#include #include #include #include @@ -196,16 +197,16 @@ struct AssignmentInfo { // TODO(user): We currently don't support more than 2^28 decision levels. That // should be enough for most practical problem, but we should fail properly if // this limit is reached. - uint32 level : 28; + uint32_t level : 28; // The type of assignment (see AssignmentType below). // // Note(user): We currently don't support more than 16 types of assignment. // This is checked in RegisterPropagator(). - mutable uint32 type : 4; + mutable uint32_t type : 4; // The index of this assignment in the trail. - int32 trail_index; + int32_t trail_index; std::string DebugString() const { return absl::StrFormat("level:%d type:%d trail_index:%d", level, type, @@ -374,7 +375,7 @@ class Trail { // Getters. int NumVariables() const { return trail_.size(); } - int64 NumberOfEnqueues() const { return num_untrailed_enqueues_ + Index(); } + int64_t NumberOfEnqueues() const { return num_untrailed_enqueues_ + Index(); } int Index() const { return current_info_.trail_index; } const Literal& operator[](int index) const { return trail_[index]; } const VariablesAssignment& Assignment() const { return assignment_; } @@ -395,7 +396,7 @@ class Trail { } private: - int64 num_untrailed_enqueues_ = 0; + int64_t num_untrailed_enqueues_ = 0; AssignmentInfo current_info_; VariablesAssignment assignment_; std::vector trail_; diff --git a/ortools/sat/sat_decision.cc b/ortools/sat/sat_decision.cc index 3d7864e34c..2a8b1b82d8 100644 --- a/ortools/sat/sat_decision.cc +++ b/ortools/sat/sat_decision.cc @@ -13,6 +13,8 @@ #include "ortools/sat/sat_decision.h" +#include + #include "ortools/sat/util.h" namespace operations_research { @@ -428,7 +430,7 @@ void SatDecisionPolicy::Untrail(int target_trail_index) { // TODO(user): This heuristic can make this code quite slow because // all the untrailed variable will cause a priority queue update. - const int64 num_bumps = num_bumps_[var]; + const int64_t num_bumps = num_bumps_[var]; double new_rate = 0.0; if (num_bumps > 0) { DCHECK_GT(num_conflicts, 0); diff --git a/ortools/sat/sat_decision.h b/ortools/sat/sat_decision.h index 7168413bb5..7a1668a482 100644 --- a/ortools/sat/sat_decision.h +++ b/ortools/sat/sat_decision.h @@ -14,6 +14,7 @@ #ifndef OR_TOOLS_SAT_SAT_DECISION_H_ #define OR_TOOLS_SAT_SAT_DECISION_H_ +#include #include #include "ortools/base/integral_types.h" @@ -182,9 +183,9 @@ class SatDecisionPolicy { // summing the entry.count for all entries with a trail index greater than i. struct NumConflictsStackEntry { int trail_index; - int64 count; + int64_t count; }; - int64 num_conflicts_ = 0; + int64_t num_conflicts_ = 0; std::vector num_conflicts_stack_; // Whether the priority of the given variable needs to be updated in @@ -202,7 +203,7 @@ class SatDecisionPolicy { // The later is only used with the ERWA heuristic. absl::StrongVector activities_; absl::StrongVector tie_breakers_; - absl::StrongVector num_bumps_; + absl::StrongVector num_bumps_; // If the polarity if forced (externally) we alway use this first. absl::StrongVector has_forced_polarity_; @@ -219,8 +220,8 @@ class SatDecisionPolicy { // Each phase last for an arithmetically increasing number of conflicts. absl::StrongVector var_polarity_; bool maybe_enable_phase_saving_ = true; - int64 polarity_phase_ = 0; - int64 num_conflicts_until_rephase_ = 1000; + int64_t polarity_phase_ = 0; + int64_t num_conflicts_until_rephase_ = 1000; // The longest partial assignment since the last reset. std::vector best_partial_assignment_; diff --git a/ortools/sat/sat_inprocessing.cc b/ortools/sat/sat_inprocessing.cc index a3498e5c5e..0c1726729b 100644 --- a/ortools/sat/sat_inprocessing.cc +++ b/ortools/sat/sat_inprocessing.cc @@ -13,6 +13,9 @@ #include "ortools/sat/sat_inprocessing.h" +#include +#include + #include "absl/container/inlined_vector.h" #include "ortools/base/stl_util.h" #include "ortools/base/strong_vector.h" @@ -207,12 +210,12 @@ bool Inprocessing::InprocessingRound() { #undef RETURN_IF_FALSE bool Inprocessing::MoreFixedVariableToClean() const { - const int64 new_num_fixed_variables = trail_->Index(); + const int64_t new_num_fixed_variables = trail_->Index(); return last_num_fixed_variables_ < new_num_fixed_variables; } bool Inprocessing::MoreRedundantVariableToClean() const { - const int64 new_num_redundant_literals = + const int64_t new_num_redundant_literals = implication_graph_->num_redundant_literals(); return last_num_redundant_literals_ < new_num_redundant_literals; } @@ -262,9 +265,9 @@ bool Inprocessing::RemoveFixedAndEquivalentVariables(bool log_info) { // function. We should also merge the code with the deletion code in // sat_solver_.cc, but that require some refactoring of the dependence between // files. - const int64 new_num_redundant_literals = + const int64_t new_num_redundant_literals = implication_graph_->num_redundant_literals(); - const int64 new_num_fixed_variables = trail_->Index(); + const int64_t new_num_fixed_variables = trail_->Index(); if (last_num_redundant_literals_ == new_num_redundant_literals && last_num_fixed_variables_ == new_num_fixed_variables) { return true; @@ -276,8 +279,8 @@ bool Inprocessing::RemoveFixedAndEquivalentVariables(bool log_info) { WallTimer wall_timer; wall_timer.Start(); - int64 num_removed_literals = 0; - int64 num_inspected_literals = 0; + int64_t num_removed_literals = 0; + int64_t num_inspected_literals = 0; // We need this temporary vector for the DRAT proof settings, otherwise // we could just have done an in-place transformation. @@ -360,10 +363,10 @@ bool Inprocessing::SubsumeAndStrenghtenRound(bool log_info) { WallTimer wall_timer; wall_timer.Start(); - int64 num_subsumed_clauses = 0; - int64 num_removed_literals = 0; - int64 num_inspected_signatures = 0; - int64 num_inspected_literals = 0; + int64_t num_subsumed_clauses = 0; + int64_t num_removed_literals = 0; + int64_t num_inspected_signatures = 0; + int64_t num_inspected_literals = 0; // We need this temporary vector for the DRAT proof settings, otherwise // we could just have done an in-place transformation. @@ -394,7 +397,7 @@ bool Inprocessing::SubsumeAndStrenghtenRound(bool log_info) { num_literals.value()); // Clause signatures in the same order as clauses. - std::vector signatures(clauses.size()); + std::vector signatures(clauses.size()); std::vector candidates_for_removal; for (int clause_index = 0; clause_index < clauses.size(); ++clause_index) { @@ -419,11 +422,11 @@ bool Inprocessing::SubsumeAndStrenghtenRound(bool log_info) { // subsumption. // Compute hash and mark literals. - uint64 signature = 0; + uint64_t signature = 0; marked.SparseClearAll(); for (const Literal l : clause->AsSpan()) { marked.Set(l.Index()); - signature |= (uint64{1} << (l.Variable().value() % 64)); + signature |= (uint64_t{1} << (l.Variable().value() % 64)); } // Look for clause that subsumes this one. Note that because we inspect @@ -431,7 +434,7 @@ bool Inprocessing::SubsumeAndStrenghtenRound(bool log_info) { // included inside this one, it must appear in one of these lists. bool removed = false; candidates_for_removal.clear(); - const uint64 mask = ~signature; + const uint64_t mask = ~signature; for (const Literal l : clause->AsSpan()) { num_inspected_signatures += one_watcher[l.Index()].size(); for (const int i : one_watcher[l.Index()]) { @@ -518,7 +521,7 @@ bool Inprocessing::SubsumeAndStrenghtenRound(bool log_info) { // Recompute signature. signature = 0; for (const Literal l : clause->AsSpan()) { - signature |= (uint64{1} << (l.Variable().value() % 64)); + signature |= (uint64_t{1} << (l.Variable().value() % 64)); } } @@ -536,7 +539,7 @@ bool Inprocessing::SubsumeAndStrenghtenRound(bool log_info) { // Important: we can only use this clause to subsume/strenghten others if // it cannot be deleted later. if (!clause_manager_->IsRemovable(clause)) { - int min_size = kint32max; + int min_size = std::numeric_limits::max(); LiteralIndex min_literal = kNoLiteralIndex; for (const Literal l : clause->AsSpan()) { if (one_watcher[l.Index()].size() < min_size) { @@ -703,7 +706,7 @@ bool StampingSimplifier::ComputeStamps() { } // Perform a DFS from each root to compute the stamps. - int64 stamp = 0; + int64_t stamp = 0; first_stamps_.resize(size); last_stamps_.resize(size); marked_.assign(size, false); @@ -1330,7 +1333,7 @@ bool BoundedVariableElimination::ResolveAllClauseContaining(Literal lit) { // If this is true, then "clause" is subsumed by one of its resolvant and we // can just remove lit from it. Then it doesn't need to be acounted at all. bool clause_can_be_simplified = false; - const int64 saved_score = new_score_; + const int64_t saved_score = new_score_; // Resolution with binary clauses. for (const Literal l : implications) { @@ -1511,7 +1514,7 @@ bool BoundedVariableElimination::CrossProduct(BooleanVariable var) { // Compute the current score. // TODO(user): cleanup the list lazily at the same time? - int64 score = 0; + int64_t score = 0; const int clause_weight = parameters_.presolve_bve_clause_weight(); score += implication_graph_->DirectImplications(lit).size() * (clause_weight + 2); diff --git a/ortools/sat/sat_inprocessing.h b/ortools/sat/sat_inprocessing.h index 81a31537a5..fef9a3f7af 100644 --- a/ortools/sat/sat_inprocessing.h +++ b/ortools/sat/sat_inprocessing.h @@ -21,6 +21,8 @@ #ifndef OR_TOOLS_SAT_SAT_INPROCESSING_H_ #define OR_TOOLS_SAT_SAT_INPROCESSING_H_ +#include + #include "ortools/base/strong_vector.h" #include "ortools/sat/clause.h" #include "ortools/sat/model.h" @@ -152,8 +154,8 @@ class Inprocessing { Model* model_; // Last since clause database was cleaned up. - int64 last_num_redundant_literals_ = 0; - int64 last_num_fixed_variables_ = 0; + int64_t last_num_redundant_literals_ = 0; + int64_t last_num_fixed_variables_ = 0; }; // Implements "stamping" as described in "Efficient CNF Simplification based on @@ -214,9 +216,9 @@ class StampingSimplifier { // Reset at each round. double dtime_ = 0.0; - int64 num_subsumed_clauses_ = 0; - int64 num_removed_literals_ = 0; - int64 num_fixed_ = 0; + int64_t num_subsumed_clauses_ = 0; + int64_t num_removed_literals_ = 0; + int64_t num_fixed_ = 0; // Encode a spanning tree of the implication graph. absl::StrongVector parents_; @@ -270,8 +272,8 @@ class BlockedClauseSimplifier { TimeLimit* time_limit_; double dtime_ = 0.0; - int32 num_blocked_clauses_ = 0; - int64 num_inspected_literals_ = 0; + int32_t num_blocked_clauses_ = 0; + int64_t num_inspected_literals_ = 0; // Temporary vector to mark literal of a clause. absl::StrongVector marked_; @@ -283,7 +285,7 @@ class BlockedClauseSimplifier { // We compute the occurrence graph just once at the beginning of each round // and we do not shrink it as we remove blocked clauses. - DEFINE_INT_TYPE(ClauseIndex, int32); + DEFINE_INT_TYPE(ClauseIndex, int32_t); absl::StrongVector clauses_; absl::StrongVector> literal_to_clauses_; @@ -331,15 +333,15 @@ class BoundedVariableElimination { int propagation_index_; double dtime_ = 0.0; - int64 num_inspected_literals_ = 0; - int64 num_simplifications_ = 0; - int64 num_blocked_clauses_ = 0; - int64 num_eliminated_variables_ = 0; - int64 num_literals_diff_ = 0; - int64 num_clauses_diff_ = 0; + int64_t num_inspected_literals_ = 0; + int64_t num_simplifications_ = 0; + int64_t num_blocked_clauses_ = 0; + int64_t num_eliminated_variables_ = 0; + int64_t num_literals_diff_ = 0; + int64_t num_clauses_diff_ = 0; - int64 new_score_; - int64 score_threshold_; + int64_t new_score_; + int64_t score_threshold_; // Temporary vector to mark literal of a clause and compute its resolvant. absl::StrongVector marked_; @@ -349,7 +351,7 @@ class BoundedVariableElimination { // We will process highest priority first. struct VariableWithPriority { BooleanVariable var; - int32 priority; + int32_t priority; // Interface for the IntegerPriorityQueue. int Index() const { return var.value(); } @@ -366,7 +368,7 @@ class BoundedVariableElimination { // We compute the occurrence graph just once at the beginning of each round. // We maintains the sizes at all time and lazily shrink the graph with deleted // clauses. - DEFINE_INT_TYPE(ClauseIndex, int32); + DEFINE_INT_TYPE(ClauseIndex, int32_t); absl::StrongVector clauses_; absl::StrongVector> literal_to_clauses_; diff --git a/ortools/sat/sat_solver.cc b/ortools/sat/sat_solver.cc index c6602d1c96..05ca8ab011 100644 --- a/ortools/sat/sat_solver.cc +++ b/ortools/sat/sat_solver.cc @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -79,15 +80,15 @@ void SatSolver::SetNumVariables(int num_variables) { decisions_.resize(num_variables + 1); } -int64 SatSolver::num_branches() const { return counters_.num_branches; } +int64_t SatSolver::num_branches() const { return counters_.num_branches; } -int64 SatSolver::num_failures() const { return counters_.num_failures; } +int64_t SatSolver::num_failures() const { return counters_.num_failures; } -int64 SatSolver::num_propagations() const { +int64_t SatSolver::num_propagations() const { return trail_->NumberOfEnqueues() - counters_.num_branches; } -int64 SatSolver::num_restarts() const { return counters_.num_restarts; } +int64_t SatSolver::num_restarts() const { return counters_.num_restarts; } double SatSolver::deterministic_time() const { // Each of these counters mesure really basic operations. The weight are just @@ -120,9 +121,9 @@ void SatSolver::SetParameters(const SatParameters& parameters) { } bool SatSolver::IsMemoryLimitReached() const { - const int64 memory_usage = + const int64_t memory_usage = ::operations_research::sysinfo::MemoryUsageProcess(); - const int64 kMegaByte = 1024 * 1024; + const int64_t kMegaByte = 1024 * 1024; return memory_usage > kMegaByte * parameters_->max_memory_in_mb(); } @@ -556,7 +557,7 @@ bool SatSolver::ReapplyAssumptionsIfNeeded() { if (CurrentDecisionLevel() >= assumption_level_) return true; int unused = 0; - const int64 old_num_branches = counters_.num_branches; + const int64_t old_num_branches = counters_.num_branches; const SatSolver::Status status = ReapplyDecisionsUpTo(assumption_level_ - 1, &unused); counters_.num_branches = old_num_branches; @@ -939,7 +940,7 @@ void SatSolver::ClearNewlyAddedBinaryClauses() { namespace { // Return the next value that is a multiple of interval. -int64 NextMultipleOf(int64 value, int64 interval) { +int64_t NextMultipleOf(int64_t value, int64_t interval) { return interval * (1 + value / interval); } } // namespace @@ -1141,27 +1142,27 @@ SatSolver::Status SatSolver::SolveInternal(TimeLimit* time_limit) { } // Used to trigger clause minimization via propagation. - int64 next_minimization_num_restart = + int64_t next_minimization_num_restart = restart_->NumRestarts() + parameters_->minimize_with_propagation_restart_period(); // Variables used to show the search progress. - const int64 kDisplayFrequency = 10000; - int64 next_display = parameters_->log_search_progress() - ? NextMultipleOf(num_failures(), kDisplayFrequency) - : std::numeric_limits::max(); + const int64_t kDisplayFrequency = 10000; + int64_t next_display = parameters_->log_search_progress() + ? NextMultipleOf(num_failures(), kDisplayFrequency) + : std::numeric_limits::max(); // Variables used to check the memory limit every kMemoryCheckFrequency. - const int64 kMemoryCheckFrequency = 10000; - int64 next_memory_check = + const int64_t kMemoryCheckFrequency = 10000; + int64_t next_memory_check = NextMultipleOf(num_failures(), kMemoryCheckFrequency); // The max_number_of_conflicts is per solve but the counter is for the whole // solver. - const int64 kFailureLimit = + const int64_t kFailureLimit = parameters_->max_number_of_conflicts() == - std::numeric_limits::max() - ? std::numeric_limits::max() + std::numeric_limits::max() + ? std::numeric_limits::max() : counters_.num_failures + parameters_->max_number_of_conflicts(); // Starts search. @@ -1249,7 +1250,7 @@ void SatSolver::MinimizeSomeClauses(int decisions_budget) { // while we are processing it. block_clause_deletion_ = true; - const int64 target_num_branches = counters_.num_branches + decisions_budget; + const int64_t target_num_branches = counters_.num_branches + decisions_budget; while (counters_.num_branches < target_num_branches && (time_limit_ == nullptr || !time_limit_->LimitReached())) { SatClause* to_minimize = clauses_propagator_->NextClauseToMinimize(); diff --git a/ortools/sat/sat_solver.h b/ortools/sat/sat_solver.h index 71cae074da..5107c61883 100644 --- a/ortools/sat/sat_solver.h +++ b/ortools/sat/sat_solver.h @@ -19,6 +19,7 @@ #ifndef OR_TOOLS_SAT_SAT_SOLVER_H_ #define OR_TOOLS_SAT_SAT_SOLVER_H_ +#include #include #include #include @@ -84,7 +85,7 @@ class SatSolver { const int num_vars = NumVariables(); // We need to be able to encode the variable as a literal. - CHECK_LT(2 * num_vars, std::numeric_limits::max()); + CHECK_LT(2 * num_vars, std::numeric_limits::max()); SetNumVariables(num_vars + 1); return BooleanVariable(num_vars); } @@ -362,14 +363,14 @@ class SatSolver { const VariablesAssignment& Assignment() const { return trail_->Assignment(); } // Some statistics since the creation of the solver. - int64 num_branches() const; - int64 num_failures() const; - int64 num_propagations() const; + int64_t num_branches() const; + int64_t num_failures() const; + int64_t num_propagations() const; // Note that we count the number of backtrack to level zero from a positive // level. Those can corresponds to actual restarts, or conflicts that learn // unit clauses or any other reason that trigger such backtrack. - int64 num_restarts() const; + int64_t num_restarts() const; // A deterministic number that should be correlated with the time spent in // the Solve() function. The order of magnitude should be close to the time @@ -429,7 +430,7 @@ class SatSolver { // Simplifies the problem when new variables are assigned at level 0. void ProcessNewlyFixedVariables(); - int64 NumFixedVariables() const { + int64_t NumFixedVariables() const { if (!decisions_.empty()) return decisions_[0].trail_index; CHECK_EQ(CurrentDecisionLevel(), 0); return trail_->Index(); @@ -738,28 +739,28 @@ class SatSolver { // Tracks various information about the solver progress. struct Counters { - int64 num_branches = 0; - int64 num_failures = 0; - int64 num_restarts = 0; + int64_t num_branches = 0; + int64_t num_failures = 0; + int64_t num_restarts = 0; // Minimization stats. - int64 num_minimizations = 0; - int64 num_literals_removed = 0; + int64_t num_minimizations = 0; + int64_t num_literals_removed = 0; // PB constraints. - int64 num_learned_pb_literals = 0; + int64_t num_learned_pb_literals = 0; // Clause learning /deletion stats. - int64 num_literals_learned = 0; - int64 num_literals_forgotten = 0; - int64 num_subsumed_clauses = 0; + int64_t num_literals_learned = 0; + int64_t num_literals_forgotten = 0; + int64_t num_subsumed_clauses = 0; // TryToMinimizeClause() stats. - int64 minimization_num_clauses = 0; - int64 minimization_num_decisions = 0; - int64 minimization_num_true = 0; - int64 minimization_num_subsumed = 0; - int64 minimization_num_removed_literals = 0; + int64_t minimization_num_clauses = 0; + int64_t minimization_num_decisions = 0; + int64_t minimization_num_true = 0; + int64_t minimization_num_subsumed = 0; + int64_t minimization_num_removed_literals = 0; }; Counters counters_; @@ -850,7 +851,8 @@ void MinimizeCore(SatSolver* solver, std::vector* core); // ============================================================================ inline std::function BooleanLinearConstraint( - int64 lower_bound, int64 upper_bound, std::vector* cst) { + int64_t lower_bound, int64_t upper_bound, + std::vector* cst) { return [=](Model* model) { model->GetOrCreate()->AddLinearConstraint( /*use_lower_bound=*/true, Coefficient(lower_bound), @@ -859,7 +861,7 @@ inline std::function BooleanLinearConstraint( } inline std::function CardinalityConstraint( - int64 lower_bound, int64 upper_bound, + int64_t lower_bound, int64_t upper_bound, const std::vector& literals) { return [=](Model* model) { std::vector cst; @@ -991,7 +993,7 @@ inline std::function ReifiedBoolLe(Literal a, Literal b, } // This checks that the variable is fixed. -inline std::function Value(Literal l) { +inline std::function Value(Literal l) { return [=](const Model& model) { const Trail* trail = model.Get(); CHECK(trail->Assignment().VariableIsAssigned(l.Variable())); @@ -1000,7 +1002,7 @@ inline std::function Value(Literal l) { } // This checks that the variable is fixed. -inline std::function Value(BooleanVariable b) { +inline std::function Value(BooleanVariable b) { return [=](const Model& model) { const Trail* trail = model.Get(); CHECK(trail->Assignment().VariableIsAssigned(b)); diff --git a/ortools/sat/simplification.cc b/ortools/sat/simplification.cc index 6bd23fa27b..5df84531db 100644 --- a/ortools/sat/simplification.cc +++ b/ortools/sat/simplification.cc @@ -14,6 +14,7 @@ #include "ortools/sat/simplification.h" #include +#include #include #include #include @@ -330,7 +331,7 @@ bool SatPresolver::Presolve(const std::vector& can_be_removed, WallTimer timer; timer.Start(); if (log_info) { - int64 num_removable = 0; + int64_t num_removable = 0; for (const bool b : can_be_removed) { if (b) ++num_removable; } @@ -536,10 +537,10 @@ void SatPresolver::SimpleBva(LiteralIndex l) { AddToBvaPriorityQueue(l); } -uint64 SatPresolver::ComputeSignatureOfClauseVariables(ClauseIndex ci) { - uint64 signature = 0; +uint64_t SatPresolver::ComputeSignatureOfClauseVariables(ClauseIndex ci) { + uint64_t signature = 0; for (const Literal l : clauses_[ci]) { - signature |= (uint64{1} << (l.Variable().value() % 64)); + signature |= (uint64_t{1} << (l.Variable().value() % 64)); } DCHECK_EQ(signature == 0, clauses_[ci].empty()); return signature; @@ -551,7 +552,7 @@ uint64 SatPresolver::ComputeSignatureOfClauseVariables(ClauseIndex ci) { bool SatPresolver::ProcessClauseToSimplifyOthersUsingLiteral( ClauseIndex clause_index, Literal lit) { const std::vector& clause = clauses_[clause_index]; - const uint64 clause_signature = signatures_[clause_index]; + const uint64_t clause_signature = signatures_[clause_index]; LiteralIndex opposite_literal; // Try to simplify the clauses containing 'lit'. We take advantage of this @@ -560,7 +561,7 @@ bool SatPresolver::ProcessClauseToSimplifyOthersUsingLiteral( bool need_cleaning = false; num_inspected_signatures_ += literal_to_clauses_[lit.Index()].size(); for (const ClauseIndex ci : literal_to_clauses_[lit.Index()]) { - const uint64 ci_signature = signatures_[ci]; + const uint64_t ci_signature = signatures_[ci]; // This allows to check for empty clause without fetching the memory at // clause_[ci]. It can have a huge time impact on large problems. @@ -648,9 +649,9 @@ bool SatPresolver::ProcessClauseToSimplifyOthers(ClauseIndex clause_index) { int new_index = 0; bool something_removed = false; auto& occurrence_list_ref = literal_to_clauses_[lit.NegatedIndex()]; - const uint64 clause_signature = signatures_[clause_index]; + const uint64_t clause_signature = signatures_[clause_index]; for (const ClauseIndex ci : occurrence_list_ref) { - const uint64 ci_signature = signatures_[ci]; + const uint64_t ci_signature = signatures_[ci]; DCHECK_EQ(ci_signature, ComputeSignatureOfClauseVariables(ci)); if (ci_signature == 0) continue; @@ -930,7 +931,7 @@ void SatPresolver::DisplayStats(double elapsed_seconds) { bool SimplifyClause(const std::vector& a, std::vector* b, LiteralIndex* opposite_literal, - int64* num_inspected_literals) { + int64_t* num_inspected_literals) { if (b->size() < a.size()) return false; DCHECK(std::is_sorted(a.begin(), a.end())); DCHECK(std::is_sorted(b->begin(), b->end())); @@ -1090,7 +1091,7 @@ class PropagationGraph { // Returns the set of node adjacent to the given one. // Interface needed by FindStronglyConnectedComponents(), note that it needs // to be const. - const std::vector& operator[](int32 index) const { + const std::vector& operator[](int32_t index) const { scratchpad_.clear(); solver_->Backtrack(0); @@ -1119,7 +1120,7 @@ class PropagationGraph { } private: - mutable std::vector scratchpad_; + mutable std::vector scratchpad_; SatSolver* const solver_; const double deterministic_time_limit; @@ -1139,8 +1140,8 @@ void ProbeAndFindEquivalentLiteral( PropagationGraph graph( solver->parameters().presolve_probing_deterministic_time_limit(), solver); - const int32 size = solver->NumVariables() * 2; - std::vector> scc; + const int32_t size = solver->NumVariables() * 2; + std::vector> scc; FindStronglyConnectedComponents(size, graph, &scc); // We have no guarantee that the cycle of x and not(x) touch the same @@ -1153,7 +1154,7 @@ void ProbeAndFindEquivalentLiteral( // // Because of this, we "merge" the cycles. MergingPartition partition(size); - for (const std::vector& component : scc) { + for (const std::vector& component : scc) { if (component.size() > 1) { if (mapping->empty()) mapping->resize(size, LiteralIndex(-1)); const Literal representative((LiteralIndex(component[0]))); diff --git a/ortools/sat/simplification.h b/ortools/sat/simplification.h index a8d0681c62..f7daf554ee 100644 --- a/ortools/sat/simplification.h +++ b/ortools/sat/simplification.h @@ -19,6 +19,7 @@ #ifndef OR_TOOLS_SAT_SIMPLIFICATION_H_ #define OR_TOOLS_SAT_SIMPLIFICATION_H_ +#include #include #include #include @@ -143,7 +144,7 @@ class SatPostsolver { class SatPresolver { public: // TODO(user): use IntType! - typedef int32 ClauseIndex; + typedef int32_t ClauseIndex; explicit SatPresolver(SatPostsolver* postsolver) : postsolver_(postsolver), @@ -269,7 +270,7 @@ class SatPresolver { // Returns a hash of the given clause variables (not literal) in such a way // that hash1 & not(hash2) == 0 iff the set of variable of clause 1 is a // subset of the one of clause2. - uint64 ComputeSignatureOfClauseVariables(ClauseIndex ci); + uint64_t ComputeSignatureOfClauseVariables(ClauseIndex ci); // The "active" variables on which we want to call CrossProduct() are kept // in a priority queue so that we process first the ones that occur the least @@ -338,9 +339,9 @@ class SatPresolver { std::vector> clauses_; // Indexed by ClauseIndex // The cached value of ComputeSignatureOfClauseVariables() for each clause. - std::vector signatures_; // Indexed by ClauseIndex - int64 num_inspected_signatures_ = 0; - int64 num_inspected_literals_ = 0; + std::vector signatures_; // Indexed by ClauseIndex + int64_t num_inspected_signatures_ = 0; + int64_t num_inspected_literals_ = 0; // Occurrence list. For each literal, contains the ClauseIndex of the clause // that contains it (ordered by clause index). @@ -380,7 +381,7 @@ class SatPresolver { // of scanning b linearly. bool SimplifyClause(const std::vector& a, std::vector* b, LiteralIndex* opposite_literal, - int64* num_inspected_literals = nullptr); + int64_t* num_inspected_literals = nullptr); // Visible for testing. Returns kNoLiteralIndex except if: // - a and b differ in only one literal. diff --git a/ortools/sat/subsolver.cc b/ortools/sat/subsolver.cc index 5172f8e65f..8844a293c8 100644 --- a/ortools/sat/subsolver.cc +++ b/ortools/sat/subsolver.cc @@ -13,6 +13,8 @@ #include "ortools/sat/subsolver.h" +#include + #include "ortools/base/logging.h" #if !defined(__PORTABLE_PLATFORM__) @@ -32,7 +34,7 @@ namespace { // For now we use a really basic logic: call the least frequently called. int NextSubsolverToSchedule( const std::vector>& subsolvers, - const std::vector& num_generated_tasks) { + const std::vector& num_generated_tasks) { int best = -1; for (int i = 0; i < subsolvers.size(); ++i) { if (subsolvers[i]->TaskIsAvailable()) { @@ -52,8 +54,8 @@ void SynchronizeAll(const std::vector>& subsolvers) { } // namespace void SequentialLoop(const std::vector>& subsolvers) { - int64 task_id = 0; - std::vector num_generated_tasks(subsolvers.size(), 0); + int64_t task_id = 0; + std::vector num_generated_tasks(subsolvers.size(), 0); while (true) { SynchronizeAll(subsolvers); const int best = NextSubsolverToSchedule(subsolvers, num_generated_tasks); @@ -90,8 +92,8 @@ void DeterministicLoop( return SequentialLoop(subsolvers); } - int64 task_id = 0; - std::vector num_generated_tasks(subsolvers.size(), 0); + int64_t task_id = 0; + std::vector num_generated_tasks(subsolvers.size(), 0); while (true) { SynchronizeAll(subsolvers); @@ -133,8 +135,8 @@ void NonDeterministicLoop( // The lambda below are using little space, but there is no reason // to create millions of them, so we use the blocking nature of // pool.Schedule() when the queue capacity is set. - int64 task_id = 0; - std::vector num_generated_tasks(subsolvers.size(), 0); + int64_t task_id = 0; + std::vector num_generated_tasks(subsolvers.size(), 0); while (true) { bool all_done = false; { diff --git a/ortools/sat/subsolver.h b/ortools/sat/subsolver.h index 8f4e9c783e..4f3276302a 100644 --- a/ortools/sat/subsolver.h +++ b/ortools/sat/subsolver.h @@ -58,7 +58,7 @@ class SubSolver { // TODO(user): We could use a more complex selection logic and pass in the // deterministic time limit this subtask should run for. Unclear at this // stage. - virtual std::function GenerateTask(int64 task_id) = 0; + virtual std::function GenerateTask(int64_t task_id) = 0; // Synchronizes with the external world from this SubSolver point of view. // Also incorporate the results of the latest completed tasks if any. @@ -95,7 +95,7 @@ class SynchronizationPoint : public SubSolver { explicit SynchronizationPoint(std::function f) : SubSolver(""), f_(std::move(f)) {} bool TaskIsAvailable() final { return false; } - std::function GenerateTask(int64 task_id) final { return nullptr; } + std::function GenerateTask(int64_t task_id) final { return nullptr; } void Synchronize() final { f_(); } private: diff --git a/ortools/sat/symmetry_util.cc b/ortools/sat/symmetry_util.cc index 34b9f8e38c..2d3a369342 100644 --- a/ortools/sat/symmetry_util.cc +++ b/ortools/sat/symmetry_util.cc @@ -13,6 +13,8 @@ #include "ortools/sat/symmetry_util.h" +#include + #include "ortools/algorithms/dynamic_partition.h" namespace operations_research { @@ -50,7 +52,7 @@ std::vector> BasicOrbitopeExtraction( if (num_cycles_to_2cyclers[i].size() > 1) { const int num_perms = num_cycles_to_2cyclers[i].size() + 1; VLOG(1) << "Potential orbitope: " << i << " x " << num_perms; - const int64 score = std::min(i, num_perms); + const int64_t score = std::min(i, num_perms); if (score > best_score) { best = i; best_score = score; diff --git a/ortools/sat/synchronization.cc b/ortools/sat/synchronization.cc index 54fdc86dc5..2eb244be5a 100644 --- a/ortools/sat/synchronization.cc +++ b/ortools/sat/synchronization.cc @@ -13,6 +13,9 @@ #include "ortools/sat/synchronization.h" +#include +#include + #if !defined(__PORTABLE_PLATFORM__) #include "ortools/base/file.h" #include "ortools/sat/cp_model_loader.h" @@ -50,7 +53,7 @@ void SharedRelaxationSolutionRepository::NewRelaxationSolution( if (response.solution().empty()) return; // Add this solution to the pool. - SharedSolutionRepository::Solution solution; + SharedSolutionRepository::Solution solution; solution.variable_values.assign(response.solution().begin(), response.solution().end()); // For now we use the negated lower bound as the "internal objective" to @@ -393,12 +396,12 @@ void SharedResponseManager::NewSolution(const CpSolverResponse& response, absl::MutexLock mutex_lock(&mutex_); if (model_proto_.has_objective()) { - const int64 objective_value = + const int64_t objective_value = ComputeInnerObjective(model_proto_.objective(), response); // Add this solution to the pool, even if it is not improving. if (!response.solution().empty()) { - SharedSolutionRepository::Solution solution; + SharedSolutionRepository::Solution solution; solution.variable_values.assign(response.solution().begin(), response.solution().end()); solution.rank = objective_value; @@ -447,8 +450,8 @@ void SharedResponseManager::NewSolution(const CpSolverResponse& response, if (log_updates_) { std::string solution_info = response.solution_info(); if (model != nullptr) { - const int64 num_bool = model->Get()->NumVariables(); - const int64 num_fixed = model->Get()->NumFixedVariables(); + const int64_t num_bool = model->Get()->NumVariables(); + const int64_t num_fixed = model->Get()->NumFixedVariables(); absl::StrAppend(&solution_info, " fixed_bools:", num_fixed, "/", num_bool); } @@ -522,7 +525,7 @@ void SharedResponseManager::LoadDebugSolution(Model* model) { if (objective_def == nullptr) return; const IntegerVariable objective_var = objective_def->objective_var; - const int64 objective_value = + const int64_t objective_value = ComputeInnerObjective(model_proto_.objective(), response); debug_solution[objective_var] = objective_value; debug_solution[NegationOf(objective_var)] = -objective_value; @@ -550,7 +553,7 @@ void SharedResponseManager::SetStatsFromModelInternal(Model* model) { best_response_.set_deterministic_time( time_limit->GetElapsedDeterministicTime()); - int64 num_lp_iters = 0; + int64_t num_lp_iters = 0; for (const LinearProgrammingConstraint* lp : *model->GetOrCreate()) { num_lp_iters += lp->total_num_simplex_iterations(); @@ -621,10 +624,12 @@ void SharedResponseManager::DisplayImprovementStatistics() { SharedBoundsManager::SharedBoundsManager(const CpModelProto& model_proto) : num_variables_(model_proto.variables_size()), model_proto_(model_proto), - lower_bounds_(num_variables_, kint64min), - upper_bounds_(num_variables_, kint64max), - synchronized_lower_bounds_(num_variables_, kint64min), - synchronized_upper_bounds_(num_variables_, kint64max) { + lower_bounds_(num_variables_, std::numeric_limits::min()), + upper_bounds_(num_variables_, std::numeric_limits::max()), + synchronized_lower_bounds_(num_variables_, + std::numeric_limits::min()), + synchronized_upper_bounds_(num_variables_, + std::numeric_limits::max()) { changed_variables_since_last_synchronize_.ClearAndResize(num_variables_); for (int i = 0; i < num_variables_; ++i) { lower_bounds_[i] = model_proto.variables(i).domain(0); @@ -638,8 +643,8 @@ SharedBoundsManager::SharedBoundsManager(const CpModelProto& model_proto) void SharedBoundsManager::ReportPotentialNewBounds( const CpModelProto& model_proto, const std::string& worker_name, const std::vector& variables, - const std::vector& new_lower_bounds, - const std::vector& new_upper_bounds) { + const std::vector& new_lower_bounds, + const std::vector& new_upper_bounds) { CHECK_EQ(variables.size(), new_lower_bounds.size()); CHECK_EQ(variables.size(), new_upper_bounds.size()); int num_improvements = 0; @@ -648,10 +653,10 @@ void SharedBoundsManager::ReportPotentialNewBounds( for (int i = 0; i < variables.size(); ++i) { const int var = variables[i]; if (var >= num_variables_) continue; - const int64 old_lb = lower_bounds_[var]; - const int64 old_ub = upper_bounds_[var]; - const int64 new_lb = new_lower_bounds[i]; - const int64 new_ub = new_upper_bounds[i]; + const int64_t old_lb = lower_bounds_[var]; + const int64_t old_ub = upper_bounds_[var]; + const int64_t new_lb = new_lower_bounds[i]; + const int64_t new_ub = new_upper_bounds[i]; const bool changed_lb = new_lb > old_lb; const bool changed_ub = new_ub < old_ub; CHECK_GE(var, 0); @@ -693,9 +698,9 @@ int SharedBoundsManager::RegisterNewId() { id_to_changed_variables_.resize(id + 1); id_to_changed_variables_[id].ClearAndResize(num_variables_); for (int var = 0; var < num_variables_; ++var) { - const int64 lb = model_proto_.variables(var).domain(0); + const int64_t lb = model_proto_.variables(var).domain(0); const int domain_size = model_proto_.variables(var).domain_size(); - const int64 ub = model_proto_.variables(var).domain(domain_size - 1); + const int64_t ub = model_proto_.variables(var).domain(domain_size - 1); if (lb != synchronized_lower_bounds_[var] || ub != synchronized_upper_bounds_[var]) { id_to_changed_variables_[id].Set(var); @@ -705,8 +710,8 @@ int SharedBoundsManager::RegisterNewId() { } void SharedBoundsManager::GetChangedBounds( - int id, std::vector* variables, std::vector* new_lower_bounds, - std::vector* new_upper_bounds) { + int id, std::vector* variables, std::vector* new_lower_bounds, + std::vector* new_upper_bounds) { variables->clear(); new_lower_bounds->clear(); new_upper_bounds->clear(); diff --git a/ortools/sat/synchronization.h b/ortools/sat/synchronization.h index ac8c8bf40c..77faa8e2fd 100644 --- a/ortools/sat/synchronization.h +++ b/ortools/sat/synchronization.h @@ -14,7 +14,9 @@ #ifndef OR_TOOLS_SAT_SYNCHRONIZATION_H_ #define OR_TOOLS_SAT_SYNCHRONIZATION_H_ +#include #include +#include #include #include @@ -55,7 +57,7 @@ class SharedSolutionRepository { // this rank is actually the unscaled internal minimization objective. // Remove this assumptions by simply recomputing this value since it is not // too costly to do so. - int64 rank; + int64_t rank; std::vector variable_values; @@ -112,7 +114,7 @@ class SharedSolutionRepository { const int num_solutions_to_keep_; mutable absl::Mutex mutex_; - int64 num_synchronization_ ABSL_GUARDED_BY(mutex_) = 0; + int64_t num_synchronization_ ABSL_GUARDED_BY(mutex_) = 0; // Our two solutions pools, the current one and the new one that will be // merged into the current one on each Synchronize() calls. @@ -124,10 +126,10 @@ class SharedSolutionRepository { // This is currently only used to store feasible solution from our 'relaxation' // LNS generators which in turn are used to generate some RINS neighborhood. class SharedRelaxationSolutionRepository - : public SharedSolutionRepository { + : public SharedSolutionRepository { public: explicit SharedRelaxationSolutionRepository(int num_solutions_to_keep) - : SharedSolutionRepository(num_solutions_to_keep) {} + : SharedSolutionRepository(num_solutions_to_keep) {} void NewRelaxationSolution(const CpSolverResponse& response); }; @@ -273,10 +275,10 @@ class SharedResponseManager { // Returns the underlying solution repository where we keep a set of best // solutions. - const SharedSolutionRepository& SolutionsRepository() const { + const SharedSolutionRepository& SolutionsRepository() const { return solutions_; } - SharedSolutionRepository* MutableSolutionsRepository() { + SharedSolutionRepository* MutableSolutionsRepository() { return &solutions_; } @@ -322,17 +324,20 @@ class SharedResponseManager { double relative_gap_limit_ ABSL_GUARDED_BY(mutex_) = 0.0; CpSolverResponse best_response_ ABSL_GUARDED_BY(mutex_); - SharedSolutionRepository solutions_ ABSL_GUARDED_BY(mutex_); + SharedSolutionRepository solutions_ ABSL_GUARDED_BY(mutex_); int num_solutions_ ABSL_GUARDED_BY(mutex_) = 0; - int64 inner_objective_lower_bound_ ABSL_GUARDED_BY(mutex_) = kint64min; - int64 inner_objective_upper_bound_ ABSL_GUARDED_BY(mutex_) = kint64max; - int64 best_solution_objective_value_ ABSL_GUARDED_BY(mutex_) = kint64max; + int64_t inner_objective_lower_bound_ ABSL_GUARDED_BY(mutex_) = + std::numeric_limits::min(); + int64_t inner_objective_upper_bound_ ABSL_GUARDED_BY(mutex_) = + std::numeric_limits::max(); + int64_t best_solution_objective_value_ ABSL_GUARDED_BY(mutex_) = + std::numeric_limits::max(); - IntegerValue synchronized_inner_objective_lower_bound_ - ABSL_GUARDED_BY(mutex_) = IntegerValue(kint64min); - IntegerValue synchronized_inner_objective_upper_bound_ - ABSL_GUARDED_BY(mutex_) = IntegerValue(kint64max); + IntegerValue synchronized_inner_objective_lower_bound_ ABSL_GUARDED_BY( + mutex_) = IntegerValue(std::numeric_limits::min()); + IntegerValue synchronized_inner_objective_upper_bound_ ABSL_GUARDED_BY( + mutex_) = IntegerValue(std::numeric_limits::max()); bool update_integral_on_each_change_ ABSL_GUARDED_BY(mutex_) = false; double primal_integral_ ABSL_GUARDED_BY(mutex_) = 0.0; @@ -363,8 +368,8 @@ class SharedBoundsManager { void ReportPotentialNewBounds(const CpModelProto& model_proto, const std::string& worker_name, const std::vector& variables, - const std::vector& new_lower_bounds, - const std::vector& new_upper_bounds); + const std::vector& new_lower_bounds, + const std::vector& new_upper_bounds); // Returns a new id to be used in GetChangedBounds(). This is just an ever // increasing sequence starting from zero. Note that the class is not designed @@ -374,8 +379,8 @@ class SharedBoundsManager { // When called, returns the set of bounds improvements since // the last time this method was called with the same id. void GetChangedBounds(int id, std::vector* variables, - std::vector* new_lower_bounds, - std::vector* new_upper_bounds); + std::vector* new_lower_bounds, + std::vector* new_upper_bounds); // Publishes any new bounds so that GetChangedBounds() will reflect the latest // state. @@ -388,15 +393,15 @@ class SharedBoundsManager { absl::Mutex mutex_; // These are always up to date. - std::vector lower_bounds_ ABSL_GUARDED_BY(mutex_); - std::vector upper_bounds_ ABSL_GUARDED_BY(mutex_); - SparseBitset changed_variables_since_last_synchronize_ + std::vector lower_bounds_ ABSL_GUARDED_BY(mutex_); + std::vector upper_bounds_ ABSL_GUARDED_BY(mutex_); + SparseBitset changed_variables_since_last_synchronize_ ABSL_GUARDED_BY(mutex_); // These are only updated on Synchronize(). - std::vector synchronized_lower_bounds_ ABSL_GUARDED_BY(mutex_); - std::vector synchronized_upper_bounds_ ABSL_GUARDED_BY(mutex_); - std::deque> id_to_changed_variables_ + std::vector synchronized_lower_bounds_ ABSL_GUARDED_BY(mutex_); + std::vector synchronized_upper_bounds_ ABSL_GUARDED_BY(mutex_); + std::deque> id_to_changed_variables_ ABSL_GUARDED_BY(mutex_); }; @@ -426,7 +431,7 @@ typename SharedSolutionRepository::Solution SharedSolutionRepository::GetRandomBiasedSolution( absl::BitGenRef random) const { absl::MutexLock mutex_lock(&mutex_); - const int64 best_rank = solutions_[0].rank; + const int64_t best_rank = solutions_[0].rank; // As long as we have solution with the best objective that haven't been // explored too much, we select one uniformly. Otherwise, we select a solution diff --git a/ortools/sat/table.cc b/ortools/sat/table.cc index 0135599fa9..b685b84526 100644 --- a/ortools/sat/table.cc +++ b/ortools/sat/table.cc @@ -14,6 +14,8 @@ #include "ortools/sat/table.h" #include +#include +#include #include #include #include @@ -95,8 +97,8 @@ void ProcessOneColumn( // Simpler encoding for table constraints with 2 variables. void AddSizeTwoTable( absl::Span vars, - const std::vector>& tuples, - const std::vector>& values_per_var, + const std::vector>& tuples, + const std::vector>& values_per_var, Model* model) { const int n = vars.size(); CHECK_EQ(n, 2); @@ -104,8 +106,8 @@ void AddSizeTwoTable( std::vector> encodings(n); for (int i = 0; i < n; ++i) { - const std::vector reached_values(values_per_var[i].begin(), - values_per_var[i].end()); + const std::vector reached_values(values_per_var[i].begin(), + values_per_var[i].end()); integer_trail->UpdateInitialDomain(vars[i], Domain::FromValues(reached_values)); if (values_per_var.size() > 1) { @@ -175,8 +177,8 @@ void AddSizeTwoTable( // In that case, it creates the complement of the projected tuples and add that // as a forbidden assignment constraint. void ExploreSubsetOfVariablesAndAddNegatedTables( - const std::vector>& tuples, - const std::vector>& var_domains, + const std::vector>& tuples, + const std::vector>& var_domains, absl::Span vars, Model* model) { const int num_vars = var_domains.size(); for (int start = 0; start < num_vars; ++start) { @@ -189,7 +191,7 @@ void ExploreSubsetOfVariablesAndAddNegatedTables( // (x=2, y=3, z=*). // Compute the maximum number of such prefix tuples. - int64 max_num_prefix_tuples = 1; + int64_t max_num_prefix_tuples = 1; for (int i = start; i <= end; ++i) { max_num_prefix_tuples = CapProd(max_num_prefix_tuples, var_domains[i].size()); @@ -198,9 +200,9 @@ void ExploreSubsetOfVariablesAndAddNegatedTables( // Abort early. if (max_num_prefix_tuples > 2 * tuples.size()) break; - absl::flat_hash_set> prefixes; + absl::flat_hash_set> prefixes; bool skip = false; - for (const std::vector& tuple : tuples) { + for (const std::vector& tuple : tuples) { prefixes.insert(absl::MakeSpan(&tuple[start], end - start + 1)); if (prefixes.size() == max_num_prefix_tuples) { // Nothing to add with this range [start..end]. @@ -211,12 +213,12 @@ void ExploreSubsetOfVariablesAndAddNegatedTables( if (skip) continue; const int num_prefix_tuples = prefixes.size(); - std::vector> negated_tuples; + std::vector> negated_tuples; int created = 0; if (num_prefix_tuples < max_num_prefix_tuples && max_num_prefix_tuples < num_prefix_tuples * 2) { - std::vector tmp_tuple; + std::vector tmp_tuple; for (int i = 0; i < max_num_prefix_tuples; ++i) { tmp_tuple.clear(); int index = i; @@ -246,19 +248,20 @@ void ExploreSubsetOfVariablesAndAddNegatedTables( // the decomposition uses clauses corresponding to the equivalence: // (\/_{row | tuples[row][col] = val} tuple_literals[row]) <=> (vars[col] = val) void AddTableConstraint(absl::Span vars, - std::vector> tuples, Model* model) { + std::vector> tuples, + Model* model) { const int n = vars.size(); IntegerTrail* integer_trail = model->GetOrCreate(); const int num_original_tuples = tuples.size(); // Compute the set of possible values for each variable (from the table). // Remove invalid tuples along the way. - std::vector> values_per_var(n); + std::vector> values_per_var(n); int index = 0; for (int tuple_index = 0; tuple_index < num_original_tuples; ++tuple_index) { bool keep = true; for (int i = 0; i < n; ++i) { - const int64 value = tuples[tuple_index][i]; + const int64_t value = tuples[tuple_index][i]; if (!values_per_var[i].contains(value) /* cached */ && !integer_trail->InitialVariableDomain(vars[i]).Contains(value)) { keep = false; @@ -290,14 +293,14 @@ void AddTableConstraint(absl::Span vars, // tuples. int num_prefix_tuples = 0; { - absl::flat_hash_set> prefixes; - for (const std::vector& tuple : tuples) { + absl::flat_hash_set> prefixes; + for (const std::vector& tuple : tuples) { prefixes.insert(absl::MakeSpan(tuple.data(), n - 1)); } num_prefix_tuples = prefixes.size(); } - std::vector> var_domains(n); + std::vector> var_domains(n); for (int j = 0; j < n; ++j) { var_domains[j].assign(values_per_var[j].begin(), values_per_var[j].end()); std::sort(var_domains[j].begin(), var_domains[j].end()); @@ -312,8 +315,8 @@ void AddTableConstraint(absl::Span vars, // point here. std::vector> encodings(n); for (int i = 0; i < n; ++i) { - const std::vector reached_values(values_per_var[i].begin(), - values_per_var[i].end()); + const std::vector reached_values(values_per_var[i].begin(), + values_per_var[i].end()); integer_trail->UpdateInitialDomain(vars[i], Domain::FromValues(reached_values)); if (values_per_var.size() > 1) { @@ -323,8 +326,8 @@ void AddTableConstraint(absl::Span vars, } // Compress tuples. - const int64 any_value = kint64min; - std::vector domain_sizes; + const int64_t any_value = std::numeric_limits::min(); + std::vector domain_sizes; for (int i = 0; i < n; ++i) { domain_sizes.push_back(values_per_var[i].size()); } @@ -335,7 +338,7 @@ void AddTableConstraint(absl::Span vars, const bool prefixes_are_all_different = num_prefix_tuples == num_valid_tuples; if (VLOG_IS_ON(2)) { // Compute the maximum number of prefix tuples. - int64 max_num_prefix_tuples = 1; + int64_t max_num_prefix_tuples = 1; for (int i = 0; i + 1 < n; ++i) { max_num_prefix_tuples = CapProd(max_num_prefix_tuples, values_per_var[i].size()); @@ -401,7 +404,7 @@ void AddTableConstraint(absl::Span vars, active_values.clear(); any_tuple_literals.clear(); for (int j = 0; j < tuple_literals.size(); ++j) { - const int64 v = tuples[j][i]; + const int64_t v = tuples[j][i]; if (v == any_value) { any_tuple_literals.push_back(tuple_literals[j]); @@ -430,7 +433,7 @@ void AddTableConstraint(absl::Span vars, // Ignore fixed variables. if (values_per_var[i].size() == 1) continue; - const int64 v = tuples[j][i]; + const int64_t v = tuples[j][i]; // Ignored 'any' created during compression. if (v == any_value) continue; @@ -455,7 +458,7 @@ void AddTableConstraint(absl::Span vars, } void AddNegatedTableConstraint(absl::Span vars, - std::vector> tuples, + std::vector> tuples, Model* model) { const int n = vars.size(); auto* integer_trail = model->GetOrCreate(); @@ -485,8 +488,8 @@ void AddNegatedTableConstraint(absl::Span vars, } // Compress tuples. - const int64 any_value = kint64min; - std::vector domain_sizes; + const int64_t any_value = std::numeric_limits::min(); + std::vector domain_sizes; for (int i = 0; i < n; ++i) { domain_sizes.push_back( integer_trail->InitialVariableDomain(vars[i]).Size()); @@ -494,7 +497,7 @@ void AddNegatedTableConstraint(absl::Span vars, CompressTuples(domain_sizes, any_value, &tuples); // Collect all relevant var == value literal. - std::vector> mapping(n); + std::vector> mapping(n); for (int i = 0; i < n; ++i) { for (const auto pair : integer_encoder->PartialDomainEncoding(vars[i])) { mapping[i][pair.value.value()] = pair.literal; @@ -503,11 +506,11 @@ void AddNegatedTableConstraint(absl::Span vars, // For each tuple, forbid the variables values to be this tuple. std::vector clause; - for (const std::vector& tuple : tuples) { + for (const std::vector& tuple : tuples) { bool add_tuple = true; clause.clear(); for (int i = 0; i < n; ++i) { - const int64 value = tuple[i]; + const int64_t value = tuple[i]; if (value == any_value) continue; // If a literal associated to var == value exist, use it, otherwise @@ -516,8 +519,8 @@ void AddNegatedTableConstraint(absl::Span vars, if (mapping[i].contains(value)) { clause.push_back(gtl::FindOrDie(mapping[i], value).Negated()); } else { - const int64 lb = model->Get(LowerBound(vars[i])); - const int64 ub = model->Get(UpperBound(vars[i])); + const int64_t lb = model->Get(LowerBound(vars[i])); + const int64_t ub = model->Get(UpperBound(vars[i])); // TODO(user): test the full initial domain instead of just checking // the bounds. That shouldn't change too much since the literals added @@ -590,8 +593,8 @@ std::function LiteralTableConstraint( std::function TransitionConstraint( const std::vector& vars, - const std::vector>& automaton, int64 initial_state, - const std::vector& final_states) { + const std::vector>& automaton, int64_t initial_state, + const std::vector& final_states) { return [=](Model* model) { IntegerTrail* integer_trail = model->GetOrCreate(); const int n = vars.size(); diff --git a/ortools/sat/table.h b/ortools/sat/table.h index 3b8d07c8f5..d7f62c611e 100644 --- a/ortools/sat/table.h +++ b/ortools/sat/table.h @@ -14,6 +14,7 @@ #ifndef OR_TOOLS_SAT_TABLE_H_ #define OR_TOOLS_SAT_TABLE_H_ +#include #include #include @@ -30,14 +31,14 @@ namespace sat { // tuples. All the tuples must have the same size as var.size(), this is // Checked. void AddTableConstraint(absl::Span vars, - std::vector> tuples, Model* model); + std::vector> tuples, Model* model); // Enforces that none of the given tuple appear. // // TODO(user): we could propagate more than what we currently do which is simply // adding one clause per tuples. void AddNegatedTableConstraint(absl::Span vars, - std::vector> tuples, + std::vector> tuples, Model* model); // Enforces that exactly one literal in line_literals is true, and that @@ -62,8 +63,8 @@ std::function LiteralTableConstraint( // See the test for some examples. std::function TransitionConstraint( const std::vector& vars, - const std::vector>& automaton, int64 initial_state, - const std::vector& final_states); + const std::vector>& automaton, int64_t initial_state, + const std::vector& final_states); } // namespace sat } // namespace operations_research diff --git a/ortools/sat/theta_tree.cc b/ortools/sat/theta_tree.cc index 2b0a5300ad..707b02eb30 100644 --- a/ortools/sat/theta_tree.cc +++ b/ortools/sat/theta_tree.cc @@ -14,6 +14,7 @@ #include "ortools/sat/theta_tree.h" #include +#include #include #include "ortools/base/int_type.h" @@ -298,7 +299,7 @@ void ThetaLambdaTree::GetLeavesWithOptionalEnvelopeGreaterThan( } template class ThetaLambdaTree; -template class ThetaLambdaTree; +template class ThetaLambdaTree; } // namespace sat } // namespace operations_research diff --git a/ortools/sat/theta_tree.h b/ortools/sat/theta_tree.h index 1f945b7024..d792e39620 100644 --- a/ortools/sat/theta_tree.h +++ b/ortools/sat/theta_tree.h @@ -14,6 +14,7 @@ #ifndef OR_TOOLS_SAT_THETA_TREE_H_ #define OR_TOOLS_SAT_THETA_TREE_H_ +#include #include #include "ortools/base/logging.h" @@ -245,7 +246,7 @@ class ThetaLambdaTree { // Explicit instantiations in theta_Tree.cc. extern template class ThetaLambdaTree; -extern template class ThetaLambdaTree; +extern template class ThetaLambdaTree; } // namespace sat } // namespace operations_research diff --git a/ortools/sat/timetable.cc b/ortools/sat/timetable.cc index 54fc158c30..64f82e2a32 100644 --- a/ortools/sat/timetable.cc +++ b/ortools/sat/timetable.cc @@ -14,6 +14,7 @@ #include "ortools/sat/timetable.h" #include +#include #include #include @@ -26,8 +27,8 @@ namespace sat { void AddReservoirConstraint(std::vector times, std::vector deltas, - std::vector presences, int64 min_level, - int64 max_level, Model* model) { + std::vector presences, int64_t min_level, + int64_t max_level, Model* model) { // We only create a side if it can fail. IntegerValue min_possible(0); IntegerValue max_possible(0); diff --git a/ortools/sat/timetable.h b/ortools/sat/timetable.h index 5809611b9c..0163f09e4c 100644 --- a/ortools/sat/timetable.h +++ b/ortools/sat/timetable.h @@ -14,6 +14,7 @@ #ifndef OR_TOOLS_SAT_TIMETABLE_H_ #define OR_TOOLS_SAT_TIMETABLE_H_ +#include #include #include "ortools/base/macros.h" @@ -32,8 +33,8 @@ namespace sat { // propagation. void AddReservoirConstraint(std::vector times, std::vector deltas, - std::vector presences, int64 min_level, - int64 max_level, Model* model); + std::vector presences, int64_t min_level, + int64_t max_level, Model* model); // The piecewise constant function must be below the given capacity. The initial // function value is zero. Note that a negative capacity will thus be trivially diff --git a/ortools/sat/timetable_edgefinding.cc b/ortools/sat/timetable_edgefinding.cc index b7031bca84..3bd6167871 100644 --- a/ortools/sat/timetable_edgefinding.cc +++ b/ortools/sat/timetable_edgefinding.cc @@ -14,6 +14,7 @@ #include "ortools/sat/timetable_edgefinding.h" #include +#include #include #include #include @@ -55,7 +56,7 @@ void TimeTableEdgeFinding::RegisterWith(GenericLiteralWatcher* watcher) { bool TimeTableEdgeFinding::Propagate() { while (true) { - const int64 old_timestamp = integer_trail_->num_enqueues(); + const int64_t old_timestamp = integer_trail_->num_enqueues(); helper_->SynchronizeAndSetTimeDirection(true); if (!TimeTableEdgeFindingPass()) return false; diff --git a/ortools/sat/util.cc b/ortools/sat/util.cc index 07d2c0ba48..5f2883f131 100644 --- a/ortools/sat/util.cc +++ b/ortools/sat/util.cc @@ -15,6 +15,7 @@ #include #include +#include #include "ortools/base/stl_util.h" @@ -109,8 +110,8 @@ double Percentile::GetPercentile(double percent) { (sorted_records[lower_rank + 1] - sorted_records[lower_rank]); } -void CompressTuples(absl::Span domain_sizes, int64 any_value, - std::vector>* tuples) { +void CompressTuples(absl::Span domain_sizes, int64_t any_value, + std::vector>* tuples) { if (tuples->empty()) return; // Remove duplicates if any. @@ -119,11 +120,11 @@ void CompressTuples(absl::Span domain_sizes, int64 any_value, const int num_vars = (*tuples)[0].size(); std::vector to_remove; - std::vector tuple_minus_var_i(num_vars - 1); + std::vector tuple_minus_var_i(num_vars - 1); for (int i = 0; i < num_vars; ++i) { const int domain_size = domain_sizes[i]; if (domain_size == 1) continue; - absl::flat_hash_map, std::vector> + absl::flat_hash_map, std::vector> masked_tuples_to_indices; for (int t = 0; t < tuples->size(); ++t) { int out = 0; diff --git a/ortools/sat/util.h b/ortools/sat/util.h index a162ba6148..de1688cc8a 100644 --- a/ortools/sat/util.h +++ b/ortools/sat/util.h @@ -14,6 +14,7 @@ #ifndef OR_TOOLS_SAT_UTIL_H_ #define OR_TOOLS_SAT_UTIL_H_ +#include #include #include "absl/random/bit_gen_ref.h" @@ -135,13 +136,13 @@ class IncrementalAverage { void Reset(double reset_value); double CurrentAverage() const { return average_; } - int64 NumRecords() const { return num_records_; } + int64_t NumRecords() const { return num_records_; } void AddData(double new_record); private: double average_ = 0.0; - int64 num_records_ = 0; + int64_t num_records_ = 0; }; // Manages exponential moving averages defined as @@ -160,13 +161,13 @@ class ExponentialMovingAverage { double CurrentAverage() const { return average_; } // Returns the total number of added records so far. - int64 NumRecords() const { return num_records_; } + int64_t NumRecords() const { return num_records_; } void AddData(double new_record); private: double average_ = 0.0; - int64 num_records_ = 0; + int64_t num_records_ = 0; const double decaying_factor_; }; @@ -185,7 +186,7 @@ class Percentile { void AddRecord(double record); // Returns number of stored records. - int64 NumRecords() const { return records_.size(); } + int64_t NumRecords() const { return records_.size(); } // Note that this is not fast and runs in O(n log n) for n records. double GetPercentile(double percent); @@ -202,8 +203,8 @@ class Percentile { // regexps. // // This method is exposed for testing purposes. -void CompressTuples(absl::Span domain_sizes, int64 any_value, - std::vector>* tuples); +void CompressTuples(absl::Span domain_sizes, int64_t any_value, + std::vector>* tuples); } // namespace sat } // namespace operations_research diff --git a/ortools/sat/var_domination.cc b/ortools/sat/var_domination.cc index 131579e3c4..5f4cd89688 100644 --- a/ortools/sat/var_domination.cc +++ b/ortools/sat/var_domination.cc @@ -13,6 +13,9 @@ #include "ortools/sat/var_domination.h" +#include +#include + #include "ortools/base/stl_util.h" #include "ortools/base/strong_vector.h" @@ -59,7 +62,7 @@ void VarDomination::CanOnlyDominateEachOther(absl::Span refs) { } void VarDomination::ActivityShouldNotChange(absl::Span refs, - absl::Span coeffs) { + absl::Span coeffs) { if (phase_ != 0) return; FillTempRanks(/*reverse_references=*/false, /*enforcements=*/{}, refs, coeffs); @@ -83,7 +86,7 @@ void VarDomination::ProcessTempRanks() { ++ct_index_for_signature_; for (IntegerVariableWithRank& entry : tmp_ranks_) { can_freely_decrease_[entry.var] = false; - block_down_signatures_[entry.var] |= uint64{1} + block_down_signatures_[entry.var] |= uint64_t{1} << (ct_index_for_signature_ % 64); entry.part = partition_->PartOf(entry.var.value()); } @@ -112,14 +115,14 @@ void VarDomination::ProcessTempRanks() { void VarDomination::ActivityShouldNotDecrease( absl::Span enforcements, absl::Span refs, - absl::Span coeffs) { + absl::Span coeffs) { FillTempRanks(/*reverse_references=*/false, enforcements, refs, coeffs); ProcessTempRanks(); } void VarDomination::ActivityShouldNotIncrease( absl::Span enforcements, absl::Span refs, - absl::Span coeffs) { + absl::Span coeffs) { FillTempRanks(/*reverse_references=*/true, enforcements, refs, coeffs); ProcessTempRanks(); } @@ -130,7 +133,7 @@ void VarDomination::MakeRankEqualToStartOfPart( int start = 0; int previous_value = 0; for (int i = 0; i < size; ++i) { - const int64 value = span[i].rank; + const int64_t value = span[i].rank; if (value != previous_value) { previous_value = value; start = i; @@ -211,8 +214,8 @@ void VarDomination::EndFirstPhase() { const int start = buffer_.size(); int new_size = 0; - const uint64 var_sig = block_down_signatures_[var]; - const uint64 not_var_sig = block_down_signatures_[NegationOf(var)]; + const uint64_t var_sig = block_down_signatures_[var]; + const uint64_t not_var_sig = block_down_signatures_[NegationOf(var)]; const int stored_size = initial_candidates_[var].size; if (stored_size == 0 || part_size < stored_size) { // We start with the partition part. @@ -378,7 +381,7 @@ void VarDomination::EndSecondPhase() { void VarDomination::FillTempRanks(bool reverse_references, absl::Span enforcements, absl::Span refs, - absl::Span coeffs) { + absl::Span coeffs) { tmp_ranks_.clear(); if (coeffs.empty()) { // Simple case: all coefficients are assumed to be the same. @@ -548,21 +551,21 @@ void DualBoundStrengthening::CannotMove(absl::Span refs) { template void DualBoundStrengthening::ProcessLinearConstraint( bool is_objective, const PresolveContext& context, - const LinearProto& linear, int64 min_activity, int64 max_activity) { - const int64 lb_limit = linear.domain(linear.domain_size() - 2); - const int64 ub_limit = linear.domain(1); + const LinearProto& linear, int64_t min_activity, int64_t max_activity) { + const int64_t lb_limit = linear.domain(linear.domain_size() - 2); + const int64_t ub_limit = linear.domain(1); const int num_terms = linear.vars_size(); for (int i = 0; i < num_terms; ++i) { int ref = linear.vars(i); - int64 coeff = linear.coeffs(i); + int64_t coeff = linear.coeffs(i); if (coeff < 0) { ref = NegatedRef(ref); coeff = -coeff; } - const int64 min_term = coeff * context.MinOf(ref); - const int64 max_term = coeff * context.MaxOf(ref); - const int64 term_diff = max_term - min_term; + const int64_t min_term = coeff * context.MinOf(ref); + const int64_t max_term = coeff * context.MaxOf(ref); + const int64_t term_diff = max_term - min_term; const IntegerVariable var = RefToIntegerVariable(ref); // lb side. @@ -611,8 +614,8 @@ bool DualBoundStrengthening::Strengthen(PresolveContext* context) { if (context->IsFixed(var)) continue; // Fix to lb? - const int64 lb = context->MinOf(var); - const int64 ub_limit = std::max(lb, CanFreelyDecreaseUntil(var)); + const int64_t lb = context->MinOf(var); + const int64_t ub_limit = std::max(lb, CanFreelyDecreaseUntil(var)); if (ub_limit == lb) { context->UpdateRuleStats("dual: fix variable"); CHECK(context->IntersectDomainWith(var, Domain(lb))); @@ -620,8 +623,8 @@ bool DualBoundStrengthening::Strengthen(PresolveContext* context) { } // Fix to ub? - const int64 ub = context->MaxOf(var); - const int64 lb_limit = + const int64_t ub = context->MaxOf(var); + const int64_t lb_limit = std::min(ub, -CanFreelyDecreaseUntil(NegatedRef(var))); if (lb_limit == ub) { context->UpdateRuleStats("dual: fix variable"); @@ -635,9 +638,9 @@ bool DualBoundStrengthening::Strengthen(PresolveContext* context) { const Domain domain = context->DomainOf(var).IntersectionWith(Domain(ub_limit, lb_limit)); if (!domain.IsEmpty()) { - int64 value = domain.Contains(0) ? 0 : domain.Min(); + int64_t value = domain.Contains(0) ? 0 : domain.Min(); if (value != 0) { - for (const int64 bound : domain.FlattenedIntervals()) { + for (const int64_t bound : domain.FlattenedIntervals()) { if (std::abs(bound) < std::abs(value)) value = bound; } } @@ -650,16 +653,20 @@ bool DualBoundStrengthening::Strengthen(PresolveContext* context) { // Here we can reduce the domain, but we must be careful when the domain // has holes. if (lb_limit > lb || ub_limit < ub) { - const int64 new_ub = - ub_limit < ub ? context->DomainOf(var) - .IntersectionWith(Domain(ub_limit, kint64max)) - .Min() - : ub; - const int64 new_lb = - lb_limit > lb ? context->DomainOf(var) - .IntersectionWith(Domain(kint64min, lb_limit)) - .Max() - : lb; + const int64_t new_ub = + ub_limit < ub + ? context->DomainOf(var) + .IntersectionWith( + Domain(ub_limit, std::numeric_limits::max())) + .Min() + : ub; + const int64_t new_lb = + lb_limit > lb + ? context->DomainOf(var) + .IntersectionWith( + Domain(std::numeric_limits::min(), lb_limit)) + .Max() + : lb; context->UpdateRuleStats("dual: reduced domain"); CHECK(context->IntersectDomainWith(var, Domain(new_lb, new_ub))); } @@ -733,14 +740,14 @@ namespace { // TODO(user): Maybe we should avoid recomputing that here. template void FillMinMaxActivity(const PresolveContext& context, - const LinearExprProto& proto, int64* min_activity, - int64* max_activity) { + const LinearExprProto& proto, int64_t* min_activity, + int64_t* max_activity) { *min_activity = 0; *max_activity = 0; const int num_vars = proto.vars().size(); for (int i = 0; i < num_vars; ++i) { - const int64 a = proto.coeffs(i) * context.MinOf(proto.vars(i)); - const int64 b = proto.coeffs(i) * context.MaxOf(proto.vars(i)); + const int64_t a = proto.coeffs(i) * context.MinOf(proto.vars(i)); + const int64_t b = proto.coeffs(i) * context.MaxOf(proto.vars(i)); *min_activity += std::min(a, b); *max_activity += std::max(a, b); } @@ -756,8 +763,8 @@ void DetectDominanceRelations( var_domination->Reset(num_vars); dual_bound_strengthening->Reset(num_vars); - int64 min_activity = kint64min; - int64 max_activity = kint64max; + int64_t min_activity = std::numeric_limits::min(); + int64_t max_activity = std::numeric_limits::max(); for (int var = 0; var < num_vars; ++var) { // Deal with the affine relations that are not part of the proto. @@ -920,9 +927,9 @@ void DetectDominanceRelations( } // Some statistics. - int64 num_unconstrained_refs = 0; - int64 num_dominated_refs = 0; - int64 num_dominance_relations = 0; + int64_t num_unconstrained_refs = 0; + int64_t num_dominated_refs = 0; + int64_t num_dominance_relations = 0; for (int var = 0; var < num_vars; ++var) { if (context.IsFixed(var)) continue; @@ -960,7 +967,8 @@ bool ExploitDominanceRelations(const VarDomination& var_domination, } if (!work_to_do) return true; - absl::StrongVector var_lb_to_ub_diff(num_vars * 2, 0); + absl::StrongVector var_lb_to_ub_diff(num_vars * 2, + 0); absl::StrongVector in_constraints(num_vars * 2, false); const int num_constraints = cp_model.constraints_size(); @@ -1045,26 +1053,26 @@ bool ExploitDominanceRelations(const VarDomination& var_domination, if (num_dominated == 0) continue; // Precompute. - int64 min_activity = 0; - int64 max_activity = 0; + int64_t min_activity = 0; + int64_t max_activity = 0; const int num_terms = ct.linear().vars_size(); for (int i = 0; i < num_terms; ++i) { int ref = ct.linear().vars(i); - int64 coeff = ct.linear().coeffs(i); + int64_t coeff = ct.linear().coeffs(i); if (coeff < 0) { ref = NegatedRef(ref); coeff = -coeff; } - const int64 min_term = coeff * context->MinOf(ref); - const int64 max_term = coeff * context->MaxOf(ref); + const int64_t min_term = coeff * context->MinOf(ref); + const int64_t max_term = coeff * context->MaxOf(ref); min_activity += min_term; max_activity += max_term; const IntegerVariable ivar = VarDomination::RefToIntegerVariable(ref); var_lb_to_ub_diff[ivar] = max_term - min_term; var_lb_to_ub_diff[NegationOf(ivar)] = min_term - max_term; } - const int64 rhs_lb = ct.linear().domain(0); - const int64 rhs_ub = ct.linear().domain(ct.linear().domain_size() - 1); + const int64_t rhs_lb = ct.linear().domain(0); + const int64_t rhs_ub = ct.linear().domain(ct.linear().domain_size() - 1); if (max_activity < rhs_lb || min_activity > rhs_ub) { return context->NotifyThatModelIsUnsat("linear equation unsat."); } @@ -1072,8 +1080,8 @@ bool ExploitDominanceRelations(const VarDomination& var_domination, // Look for dominated var. for (int i = 0; i < num_terms; ++i) { const int ref = ct.linear().vars(i); - const int64 coeff = ct.linear().coeffs(i); - const int64 coeff_magnitude = std::abs(coeff); + const int64_t coeff = ct.linear().coeffs(i); + const int64_t coeff_magnitude = std::abs(coeff); if (context->IsFixed(ref)) continue; for (const int current_ref : {ref, NegatedRef(ref)}) { @@ -1087,21 +1095,21 @@ bool ExploitDominanceRelations(const VarDomination& var_domination, } else { if (min_activity >= rhs_lb) continue; } - const int64 slack = + const int64_t slack = ub_side ? rhs_ub - min_activity : max_activity - rhs_lb; // Compute the delta in activity if all dominating var moves to their // other bound. - int64 delta = 0; + int64_t delta = 0; for (const IntegerVariable ivar : dominated_by) { if (ub_side) { - delta += std::max(int64{0}, var_lb_to_ub_diff[ivar]); + delta += std::max(int64_t{0}, var_lb_to_ub_diff[ivar]); } else { - delta += std::max(int64{0}, -var_lb_to_ub_diff[ivar]); + delta += std::max(int64_t{0}, -var_lb_to_ub_diff[ivar]); } } - const int64 lb = context->MinOf(current_ref); + const int64_t lb = context->MinOf(current_ref); if (delta + coeff_magnitude > slack) { context->UpdateRuleStats("domination: fixed to lb."); if (!context->IntersectDomainWith(current_ref, Domain(lb))) { @@ -1126,7 +1134,7 @@ bool ExploitDominanceRelations(const VarDomination& var_domination, const IntegerValue diff = FloorRatio(IntegerValue(slack - delta), IntegerValue(coeff_magnitude)); - const int64 new_ub = lb + diff.value(); + const int64_t new_ub = lb + diff.value(); if (new_ub < context->MaxOf(current_ref)) { context->UpdateRuleStats("domination: reduced ub."); if (!context->IntersectDomainWith(current_ref, Domain(lb, new_ub))) { @@ -1143,7 +1151,7 @@ bool ExploitDominanceRelations(const VarDomination& var_domination, CHECK_LE(var_lb_to_ub_diff[current_var], 0); min_activity -= var_lb_to_ub_diff[current_var]; } - const int64 new_diff = std::abs(coeff_magnitude * (new_ub - lb)); + const int64_t new_diff = std::abs(coeff_magnitude * (new_ub - lb)); if (ub_side) { var_lb_to_ub_diff[current_var] = new_diff; var_lb_to_ub_diff[NegationOf(current_var)] = -new_diff; diff --git a/ortools/sat/var_domination.h b/ortools/sat/var_domination.h index d32b805439..00b8c95c8a 100644 --- a/ortools/sat/var_domination.h +++ b/ortools/sat/var_domination.h @@ -14,6 +14,8 @@ #ifndef OR_TOOLS_SAT_VAR_DOMINATION_H_ #define OR_TOOLS_SAT_VAR_DOMINATION_H_ +#include + #include "ortools/algorithms/dynamic_partition.h" #include "ortools/base/strong_vector.h" #include "ortools/sat/cp_model_utils.h" @@ -87,13 +89,13 @@ class VarDomination { // increase / decrease functions also refine the partition. void CanOnlyDominateEachOther(absl::Span refs); void ActivityShouldNotChange(absl::Span refs, - absl::Span coeffs); + absl::Span coeffs); void ActivityShouldNotDecrease(absl::Span enforcements, absl::Span refs, - absl::Span coeffs); + absl::Span coeffs); void ActivityShouldNotIncrease(absl::Span enforcements, absl::Span refs, - absl::Span coeffs); + absl::Span coeffs); // EndFirstPhase() must be called once all constraints have been processed // once. One then needs to redo the calls to ActivityShouldNotIncrease() and @@ -124,7 +126,7 @@ class VarDomination { struct IntegerVariableWithRank { IntegerVariable var; int part; - int64 rank; + int64_t rank; bool operator<(const IntegerVariableWithRank& o) const { return rank < o.rank; @@ -139,7 +141,7 @@ class VarDomination { void FillTempRanks(bool reverse_references, absl::Span enforcements, absl::Span refs, - absl::Span coeffs); + absl::Span coeffs); // First phase functions. We will keep for each variable a list of possible // candidates which is as short as possible. @@ -177,8 +179,8 @@ class VarDomination { // For all one sided constraints, we keep the bitmap of constraint indices // modulo 64 that block on the lower side each variable. - int64 ct_index_for_signature_ = 0; - absl::StrongVector block_down_signatures_; + int64_t ct_index_for_signature_ = 0; + absl::StrongVector block_down_signatures_; // Used by FilterUsingTempRanks(). int num_vars_with_negation_; @@ -226,8 +228,8 @@ class DualBoundStrengthening { template void ProcessLinearConstraint(bool is_objective, const PresolveContext& context, - const LinearProto& linear, int64 min_activity, - int64 max_activity); + const LinearProto& linear, int64_t min_activity, + int64_t max_activity); // Once ALL constraints have been processed, call this to fix variables or // reduce their domain if possible. @@ -240,7 +242,7 @@ class DualBoundStrengthening { // The given ref can always freely decrease until the returned value. // Note that this does not take into account the domain of the variable. - int64 CanFreelyDecreaseUntil(int ref) const { + int64_t CanFreelyDecreaseUntil(int ref) const { return can_freely_decrease_until_[RefToIntegerVariable(ref)].value(); } @@ -256,11 +258,11 @@ class DualBoundStrengthening { // How many times can_freely_decrease_until_[var] was set by a constraints. // If only one constraint is blocking, we can do more presolve. - absl::StrongVector num_locks_; + absl::StrongVector num_locks_; // If num_locks_[var] == 1, this will be the unique constraint that block var // in this direction. Note that it can be set to -1 if this wasn't recorded. - absl::StrongVector locking_ct_index_; + absl::StrongVector locking_ct_index_; }; // Detect the variable dominance relations within the given model. Note that