28#if !defined(__PORTABLE_PLATFORM__)
29#include "google/protobuf/descriptor.h"
31#include "absl/container/btree_set.h"
32#include "absl/container/flat_hash_map.h"
33#include "absl/numeric/int128.h"
34#include "absl/random/bit_gen_ref.h"
35#include "absl/random/distributions.h"
36#include "absl/types/span.h"
41#include "ortools/sat/sat_parameters.pb.h"
53void QuotientAndRemainder(int64_t
a, int64_t
b, int64_t& q, int64_t& r) {
61#if !defined(__PORTABLE_PLATFORM__)
63 const google::protobuf::EnumDescriptor* order_d =
64 SatParameters::VariableOrder_descriptor();
66 static_cast<SatParameters::VariableOrder
>(
67 order_d->value(absl::Uniform(random, 0, order_d->value_count()))
71 const google::protobuf::EnumDescriptor* polarity_d =
72 SatParameters::Polarity_descriptor();
73 parameters->set_initial_polarity(
static_cast<SatParameters::Polarity
>(
74 polarity_d->value(absl::Uniform(random, 0, polarity_d->value_count()))
78 parameters->set_use_phase_saving(absl::Bernoulli(random, 0.5));
79 parameters->set_random_polarity_ratio(absl::Bernoulli(random, 0.5) ? 0.01
81 parameters->set_random_branches_ratio(absl::Bernoulli(random, 0.5) ? 0.01
91 int64_t r[2] = {m, x};
92 int64_t t[2] = {0, 1};
105 for (; r[i ^ 1] != 0; i ^= 1) {
106 QuotientAndRemainder(r[i], r[i ^ 1], q, r[i]);
107 t[i] -= t[i ^ 1] * q;
111 if (r[i] != 1)
return 0;
115 if (t[i] < 0) t[i] += m;
121 const int64_t r = x % m;
122 return r < 0 ? r + m : r;
130 if (rhs == 0 || mod == 1)
return 0;
143 const absl::int128 p = absl::int128{inverse} * absl::int128{rhs};
144 return static_cast<int64_t
>(p % absl::int128{mod});
148 int64_t& x0, int64_t& y0) {
154 const int64_t gcd = std::gcd(std::abs(
a), std::abs(
b));
155 if (cte % gcd != 0)
return false;
171 if (cte < 0 && x0 != 0) x0 -= std::abs(
b);
177 const absl::int128 t = absl::int128{cte} - absl::int128{
a} * absl::int128{x0};
178 DCHECK_EQ(t % absl::int128{
b}, absl::int128{0});
183 const absl::int128 r = t / absl::int128{
b};
187 y0 =
static_cast<int64_t
>(r);
196 static_cast<int64_t
>(std::floor(std::sqrt(
static_cast<double>(
a))));
197 while (
CapProd(result, result) >
a) --result;
198 while (
CapProd(result + 1, result + 1) <=
a) ++result;
205 static_cast<int64_t
>(std::ceil(std::sqrt(
static_cast<double>(
a))));
206 while (
CapProd(result, result) <
a) ++result;
207 while ((result - 1) * (result - 1) >=
a) --result;
213 int64_t result =
value / base * base;
214 if (
value - result > base / 2) result += base;
219 int64_t base,
const std::vector<int64_t>& coeffs,
220 const std::vector<int64_t>& lbs,
const std::vector<int64_t>& ubs,
221 int64_t rhs, int64_t* new_rhs) {
223 int64_t max_activity = 0;
225 int64_t min_error = 0;
226 const int num_terms = coeffs.size();
227 if (num_terms == 0)
return false;
228 for (
int i = 0; i < num_terms; ++i) {
229 const int64_t
coeff = coeffs[i];
232 max_activity +=
coeff * ubs[i];
233 max_x += closest / base * ubs[i];
235 const int64_t error =
coeff - closest;
237 min_error += error * lbs[i];
239 min_error += error * ubs[i];
243 if (max_activity <= rhs) {
250 int64_t max_error_if_invalid = 0;
251 const int64_t slack = max_activity - rhs - 1;
252 for (
int i = 0; i < num_terms; ++i) {
253 const int64_t
coeff = coeffs[i];
255 const int64_t error =
coeff - closest;
257 max_error_if_invalid += error * ubs[i];
260 max_error_if_invalid += error * lb;
275 const int64_t infeasibility_bound =
279 return *new_rhs < infeasibility_bound;
283 const absl::btree_set<LiteralIndex>& processed,
int relevant_prefix_size,
284 std::vector<Literal>* literals) {
285 if (literals->empty())
return -1;
287 return std::min<int>(relevant_prefix_size, literals->size());
297 int num_processed = 0;
298 int num_not_processed = 0;
299 int target_prefix_size = literals->size() - 1;
300 for (
int i = literals->size() - 1; i >= 0; i--) {
305 target_prefix_size = i;
307 if (num_not_processed >= num_processed)
break;
309 if (num_not_processed == 0)
return -1;
310 target_prefix_size =
std::min(target_prefix_size, relevant_prefix_size);
314 std::stable_partition(literals->begin() + target_prefix_size, literals->end(),
316 return gtl::ContainsKey(processed, l.Index());
318 return target_prefix_size;
323 average_ = reset_value;
328 average_ += (new_record - average_) / num_records_;
333 average_ = (num_records_ == 1)
335 : (new_record + decaying_factor_ * (average_ - new_record));
339 records_.push_front(record);
340 if (records_.size() > record_limit_) {
349 std::vector<double> sorted_records(records_.begin(), records_.end());
350 std::sort(sorted_records.begin(), sorted_records.end());
351 const int num_records = sorted_records.size();
353 const double percentile_rank =
354 static_cast<double>(num_records) * percent / 100.0 - 0.5;
355 if (percentile_rank <= 0) {
356 return sorted_records.front();
357 }
else if (percentile_rank >= num_records - 1) {
358 return sorted_records.back();
362 DCHECK_LT(percentile_rank, num_records - 1);
363 const int lower_rank =
static_cast<int>(std::floor(percentile_rank));
365 return sorted_records[lower_rank] +
366 (percentile_rank - lower_rank) *
367 (sorted_records[lower_rank + 1] - sorted_records[lower_rank]);
371 std::vector<std::vector<int64_t>>* tuples) {
372 if (tuples->empty())
return;
377 const int num_vars = (*tuples)[0].size();
379 std::vector<int> to_remove;
380 std::vector<int64_t> tuple_minus_var_i(num_vars - 1);
381 for (
int i = 0; i < num_vars; ++i) {
382 const int domain_size = domain_sizes[i];
383 if (domain_size == 1)
continue;
384 absl::flat_hash_map<const std::vector<int64_t>, std::vector<int>>
385 masked_tuples_to_indices;
386 for (
int t = 0; t < tuples->size(); ++t) {
388 for (
int j = 0; j < num_vars; ++j) {
389 if (i == j)
continue;
390 tuple_minus_var_i[out++] = (*tuples)[t][j];
392 masked_tuples_to_indices[tuple_minus_var_i].push_back(t);
395 for (
const auto& it : masked_tuples_to_indices) {
396 if (it.second.size() != domain_size)
continue;
397 (*tuples)[it.second.front()][i] = any_value;
398 to_remove.insert(to_remove.end(), it.second.begin() + 1, it.second.end());
400 std::sort(to_remove.begin(), to_remove.end(), std::greater<int>());
401 for (
const int t : to_remove) {
402 (*tuples)[t] = tuples->back();
#define DCHECK_LE(val1, val2)
#define DCHECK_NE(val1, val2)
#define CHECK_GE(val1, val2)
#define CHECK_GT(val1, val2)
#define DCHECK_GE(val1, val2)
#define CHECK_NE(val1, val2)
#define DCHECK_LT(val1, val2)
#define CHECK_LE(val1, val2)
#define DCHECK_EQ(val1, val2)
static IntegralType CeilOfRatio(IntegralType numerator, IntegralType denominator)
static IntegralType FloorOfRatio(IntegralType numerator, IntegralType denominator)
void AddData(double new_record)
void AddData(double new_record)
void Reset(double reset_value)
double GetPercentile(double percent)
void AddRecord(double record)
void STLSortAndRemoveDuplicates(T *v, const LessFunc &less_func)
bool ContainsKey(const Collection &collection, const Key &key)
void RandomizeDecisionHeuristic(absl::BitGenRef random, SatParameters *parameters)
int64_t ClosestMultiple(int64_t value, int64_t base)
void CompressTuples(absl::Span< const int64_t > domain_sizes, int64_t any_value, std::vector< std::vector< int64_t > > *tuples)
int64_t PositiveMod(int64_t x, int64_t m)
int64_t CeilSquareRoot(int64_t a)
bool SolveDiophantineEquationOfSizeTwo(int64_t &a, int64_t &b, int64_t &cte, int64_t &x0, int64_t &y0)
int64_t FloorSquareRoot(int64_t a)
int64_t ModularInverse(int64_t x, int64_t m)
int64_t ProductWithModularInverse(int64_t coeff, int64_t mod, int64_t rhs)
int MoveOneUnprocessedLiteralLast(const absl::btree_set< LiteralIndex > &processed, int relevant_prefix_size, std::vector< Literal > *literals)
bool LinearInequalityCanBeReducedWithClosestMultiple(int64_t base, const std::vector< int64_t > &coeffs, const std::vector< int64_t > &lbs, const std::vector< int64_t > &ubs, int64_t rhs, int64_t *new_rhs)
Collection of objects used to extend the Constraint Solver library.
int64_t CapProd(int64_t x, int64_t y)