21#include "absl/container/flat_hash_set.h"
22#include "absl/strings/str_cat.h"
23#include "absl/strings/str_format.h"
24#include "absl/strings/str_join.h"
55 result.
values.push_back(included_min);
56 result.
values.push_back(included_max);
63 result.
values.push_back(0);
64 result.
values.push_back(1);
127 if (!domain.
values.empty()) {
137 const int64_t imin =
values[0];
138 const int64_t imax =
values[1];
153 if (interval_min > interval_max) {
159 values.push_back(interval_min);
160 values.push_back(interval_max);
163 if (
values[0] >= interval_min &&
values[1] <= interval_max)
return false;
178 std::vector<int64_t> new_values;
179 new_values.reserve(
values.size());
180 bool changed =
false;
181 for (
const int64_t val :
values) {
182 if (val > interval_max) {
186 if (val >= interval_min &&
187 (new_values.empty() || val != new_values.back())) {
188 new_values.push_back(val);
207 for (
const int64_t v : integers) {
208 if (v >= dmin && v <= dmax)
values.push_back(v);
216 const int64_t last =
values.back();
229 absl::flat_hash_set<int64_t> other_values(integers.begin(), integers.end());
230 std::vector<int64_t> new_values;
232 bool changed =
false;
233 for (
const int64_t val :
values) {
234 if (other_values.contains(val)) {
235 if (new_values.empty() || val != new_values.back()) {
236 new_values.push_back(val);
272 bool changed =
false;
369bool IntervalOverlapValues(int64_t lb, int64_t ub,
370 const std::vector<int64_t>& values) {
371 for (int64_t
value : values) {
386 return IntervalOverlapValues(
values[0],
values[1], vec);
389 const std::vector<int64_t>& to_scan =
391 const absl::flat_hash_set<int64_t> container =
392 values.size() <= vec.size()
393 ? absl::flat_hash_set<int64_t>(vec.begin(), vec.end())
394 : absl::flat_hash_set<int64_t>(
values.begin(),
values.end());
395 for (int64_t
value : to_scan) {
396 if (container.contains(
value)) {
410 const int64_t dlb =
values[0];
411 const int64_t dub =
values[1];
412 return !(dub < lb || dlb > ub);
414 return IntervalOverlapValues(lb, ub,
values);
420 if (other.
values.empty()) {
442 const int64_t vmax =
values[1];
445 for (int64_t v =
values[0] + 1; v <= vmax; ++v) {
471 LOG(DFATAL) <<
"Error with float domain";
472 return "error_float";
479 return absl::StrFormat(
"[%d..%d]",
values[0],
values[1]);
481 }
else if (
values.size() == 1) {
482 return absl::StrCat(
values.back());
484 return absl::StrFormat(
"[%s]", absl::StrJoin(
values,
", "));
500 result.
values.push_back(imin);
501 result.
values.push_back(imax);
541 if (domain.
values.empty()) {
562 result.
floats.push_back(lb);
563 result.
floats.push_back(ub);
577 return absl::StrFormat(
"%d",
values[0]);
579 return absl::StrFormat(
"[%d..%d]",
values[0],
values[1]);
581 return absl::StrFormat(
"[%s]", absl::StrJoin(
values,
", "));
587 std::string result =
"[";
588 for (
int i = 0; i <
variables.size(); ++i) {
590 result.append(i !=
variables.size() - 1 ?
", " :
"]");
595 return "VoidArgument";
597 return absl::StrCat(
floats[0]);
599 return absl::StrCat(
"[",
floats[0],
"..",
floats[1],
"]");
601 return absl::StrFormat(
"[%s]", absl::StrJoin(
floats,
", "));
603 LOG(
FATAL) <<
"Unhandled case in DebugString " <<
static_cast<int>(
type);
643 if (!domain.HasOneValue()) {
653 if (!
var->domain.HasOneValue()) {
723Variable::Variable(
const std::string& name_,
const Domain& domain_,
725 :
name(name_), domain(domain_), temporary(temporary_), active(true) {
726 if (!domain.is_interval) {
732 bool other_temporary) {
747 active ?
"" :
" [removed during presolve]");
755 const std::string presolve_status_str =
758 :
"[removed during presolve]");
760 strong, presolve_status_str);
773 type =
"false_constraint";
806 std::vector<Annotation> args) {
869 ann.AppendAllVariables(vars);
897 std::string result =
"[";
898 for (
int i = 0; i <
variables.size(); ++i) {
900 result.append(i !=
variables.size() - 1 ?
", " :
"]");
908 LOG(
FATAL) <<
"Unhandled case in DebugString " <<
static_cast<int>(
type);
928 const std::string&
name, std::vector<Bounds>
bounds,
948 return absl::StrFormat(
"output_var(%s)",
variable->
name);
950 return absl::StrFormat(
"output_array([%s] [%s])",
966 variables_.push_back(
var);
974 variables_.push_back(
var);
981 variables_.push_back(
var);
986 std::vector<Argument> arguments,
bool is_domain) {
988 new Constraint(
id, std::move(arguments), is_domain);
989 constraints_.push_back(constraint);
993 std::vector<Argument> arguments) {
994 AddConstraint(
id, std::move(arguments),
false);
998 output_.push_back(std::move(output));
1003 search_annotations_ = std::move(search_annotations);
1007 std::vector<Annotation> search_annotations) {
1010 search_annotations_ = std::move(search_annotations);
1014 std::vector<Annotation> search_annotations) {
1017 search_annotations_ = std::move(search_annotations);
1021 std::string output = absl::StrFormat(
"Model %s\nVariables\n", name_);
1022 for (
int i = 0; i < variables_.size(); ++i) {
1023 absl::StrAppendFormat(&output,
" %s\n", variables_[i]->
DebugString());
1025 output.append(
"Constraints\n");
1026 for (
int i = 0; i < constraints_.size(); ++i) {
1027 if (constraints_[i] !=
nullptr) {
1028 absl::StrAppendFormat(&output,
" %s\n", constraints_[i]->
DebugString());
1032 absl::StrAppendFormat(&output,
"%s %s\n %s\n",
1036 absl::StrAppendFormat(&output,
"Satisfy\n %s\n",
1039 output.append(
"Output\n");
1040 for (
int i = 0; i < output_.size(); ++i) {
1041 absl::StrAppendFormat(&output,
" %s\n", output_[i].
DebugString());
1049 if (
var->domain.empty()) {
1054 if (
ct->type ==
"false_constraint") {
1065 SOLVER_LOG(logger_,
"Model ", model_.name());
1066 for (
const auto& it : constraints_per_type_) {
1067 SOLVER_LOG(logger_,
" - ", it.first,
": ", it.second.size());
1069 if (model_.objective() ==
nullptr) {
1070 SOLVER_LOG(logger_,
" - Satisfaction problem");
1073 (model_.maximize() ?
"Maximization" :
"Minimization"),
1080 constraints_per_type_.clear();
1081 constraints_per_variables_.clear();
1083 if (
ct !=
nullptr &&
ct->active) {
1084 constraints_per_type_[
ct->type].push_back(
ct);
1085 absl::flat_hash_set<const Variable*> marked;
1092 constraints_per_variables_[
var].push_back(
ct);
1106 out->push_back(ann);
#define CHECK_LT(val1, val2)
#define CHECK_EQ(val1, val2)
#define CHECK_GE(val1, val2)
#define DCHECK(condition)
Variable * AddVariable(const std::string &name, const Domain &domain, bool defined)
Variable * AddConstant(int64_t value)
void Satisfy(std::vector< Annotation > search_annotations)
std::string DebugString() const
void AddOutput(SolutionOutputSpecs output)
void AddConstraint(const std::string &id, std::vector< Argument > arguments, bool is_domain)
void Maximize(Variable *obj, std::vector< Annotation > search_annotations)
bool IsInconsistent() const
void Minimize(Variable *obj, std::vector< Annotation > search_annotations)
Variable * AddFloatConstant(double value)
void PrintStatistics() const
void STLSortAndRemoveDuplicates(T *v, const LessFunc &less_func)
void STLDeleteElements(T *container)
void FlattenAnnotations(const Annotation &ann, std::vector< Annotation > *out)
Collection of objects used to extend the Constraint Solver library.
std::string JoinNameFieldPtr(const std::vector< T > &v, const std::string &separator)
std::string JoinDebugString(const std::vector< T > &v, const std::string &separator)
static Annotation IntegerValue(int64_t value)
void AppendAllVariables(std::vector< Variable * > *vars) const
std::string DebugString() const
static Annotation FunctionCall(const std::string &id)
static Annotation AnnotationList(std::vector< Annotation > list)
std::vector< Variable * > variables
static Annotation String(const std::string &str)
static Annotation Identifier(const std::string &id)
bool IsFunctionCallWithIdentifier(const std::string &identifier) const
std::vector< Annotation > annotations
static Annotation Interval(int64_t interval_min, int64_t interval_max)
static Annotation VarRefArray(std::vector< Variable * > variables)
static Annotation VarRef(Variable *const var)
static Annotation Empty()
static Annotation FunctionCallWithArguments(const std::string &id, std::vector< Annotation > args)
static Argument FloatInterval(double lb, double ub)
static Argument DomainList(std::vector< Domain > domains)
Variable * VarAt(int pos) const
static Argument VarRef(Variable *const var)
std::vector< double > floats
bool Contains(int64_t value) const
static Argument IntegerList(std::vector< int64_t > values)
static Argument VoidArgument()
static Argument VarRefArray(std::vector< Variable * > vars)
static Argument IntegerValue(int64_t value)
static Argument Interval(int64_t imin, int64_t imax)
std::string DebugString() const
std::vector< Variable * > variables
static Argument FloatValue(double value)
std::vector< Domain > domains
std::vector< int64_t > values
int64_t ValueAt(int pos) const
static Argument FloatList(std::vector< double > floats)
bool IsArrayOfValues() const
static Argument FromDomain(const Domain &domain)
bool presolve_propagation_done
void RemoveArg(int arg_pos)
std::string DebugString() const
std::vector< Argument > arguments
static Domain IntegerValue(int64_t value)
static Domain EmptyDomain()
bool Contains(int64_t value) const
bool SetEmptyFloatDomain()
bool OverlapsDomain(const Domain &other) const
static Domain SetOfAllInt64()
bool IntersectWithSingleton(int64_t value)
static Domain SetOfInterval(int64_t included_min, int64_t included_max)
static Domain IntegerList(std::vector< int64_t > values)
std::string DebugString() const
bool IntersectWithInterval(int64_t interval_min, int64_t interval_max)
bool IntersectWithFloatDomain(const Domain &domain)
bool IntersectWithDomain(const Domain &domain)
std::vector< double > float_values
static Domain FloatInterval(double lb, double ub)
bool OverlapsIntInterval(int64_t lb, int64_t ub) const
static Domain SetOfIntegerValue(int64_t value)
bool OverlapsIntList(const std::vector< int64_t > &vec) const
static Domain Interval(int64_t included_min, int64_t included_max)
std::vector< int64_t > values
static Domain SetOfBoolean()
static Domain SetOfIntegerList(std::vector< int64_t > values)
static Domain FloatValue(double value)
bool IntersectWithListOfIntegers(const std::vector< int64_t > &integers)
static Domain AllFloats()
bool RemoveValue(int64_t value)
std::string DebugString() const
static SolutionOutputSpecs VoidOutput()
std::string DebugString() const
static SolutionOutputSpecs SingleVariable(const std::string &name, Variable *variable, bool display_as_boolean)
std::vector< Variable * > flat_variables
std::vector< Bounds > bounds
static SolutionOutputSpecs MultiDimensionalArray(const std::string &name, std::vector< Bounds > bounds, std::vector< Variable * > flat_variables, bool display_as_boolean)
std::string DebugString() const
bool Merge(const std::string &other_name, const Domain &other_domain, bool other_temporary)
#define SOLVER_LOG(logger,...)