24 #include "absl/container/flat_hash_set.h"
25 #include "absl/strings/str_cat.h"
26 #include "absl/strings/str_format.h"
27 #include "absl/strings/str_join.h"
28 #include "absl/strings/string_view.h"
58 result.
values.push_back(included_min);
59 result.
values.push_back(included_max);
66 result.
values.push_back(0);
67 result.
values.push_back(1);
130 if (!domain.
values.empty()) {
140 const int64_t imin =
values[0];
141 const int64_t imax =
values[1];
156 if (interval_min > interval_max) {
162 values.push_back(interval_min);
163 values.push_back(interval_max);
166 if (
values[0] >= interval_min &&
values[1] <= interval_max)
return false;
181 std::vector<int64_t> new_values;
182 new_values.reserve(
values.size());
183 bool changed =
false;
184 for (
const int64_t val :
values) {
185 if (val > interval_max) {
189 if (val >= interval_min &&
190 (new_values.empty() || val != new_values.back())) {
191 new_values.push_back(val);
210 for (
const int64_t v : integers) {
211 if (v >= dmin && v <= dmax)
values.push_back(v);
219 const int64_t last =
values.back();
232 absl::flat_hash_set<int64_t> other_values(integers.begin(), integers.end());
233 std::vector<int64_t> new_values;
235 bool changed =
false;
236 for (
const int64_t val :
values) {
237 if (other_values.contains(val)) {
238 if (new_values.empty() || val != new_values.back()) {
239 new_values.push_back(val);
275 bool changed =
false;
372 bool IntervalOverlapValues(int64_t lb, int64_t ub,
373 const std::vector<int64_t>& values) {
374 for (int64_t
value : values) {
389 return IntervalOverlapValues(
values[0],
values[1], vec);
392 const std::vector<int64_t>& to_scan =
394 const absl::flat_hash_set<int64_t> container =
395 values.size() <= vec.size()
396 ? absl::flat_hash_set<int64_t>(vec.begin(), vec.end())
397 : absl::flat_hash_set<int64_t>(
values.begin(),
values.end());
398 for (int64_t
value : to_scan) {
399 if (container.contains(
value)) {
413 const int64_t dlb =
values[0];
414 const int64_t dub =
values[1];
415 return !(dub < lb || dlb > ub);
417 return IntervalOverlapValues(lb, ub,
values);
423 if (other.
values.empty()) {
445 const int64_t vmax =
values[1];
448 for (int64_t v =
values[0] + 1; v <= vmax; ++v) {
474 LOG(DFATAL) <<
"Error with float domain";
475 return "error_float";
482 return absl::StrFormat(
"[%d..%d]",
values[0],
values[1]);
484 }
else if (
values.size() == 1) {
485 return absl::StrCat(
values.back());
487 return absl::StrFormat(
"[%s]", absl::StrJoin(
values,
", "));
503 result.
values.push_back(imin);
504 result.
values.push_back(imax);
544 if (domain.
values.empty()) {
565 result.
floats.push_back(lb);
566 result.
floats.push_back(ub);
580 return absl::StrFormat(
"%d",
values[0]);
582 return absl::StrFormat(
"[%d..%d]",
values[0],
values[1]);
584 return absl::StrFormat(
"[%s]", absl::StrJoin(
values,
", "));
590 std::string result =
"[";
591 for (
int i = 0; i <
variables.size(); ++i) {
593 result.append(i !=
variables.size() - 1 ?
", " :
"]");
598 return "VoidArgument";
600 return absl::StrCat(
floats[0]);
602 return absl::StrCat(
"[",
floats[0],
"..",
floats[1],
"]");
604 return absl::StrFormat(
"[%s]", absl::StrJoin(
floats,
", "));
606 LOG(FATAL) <<
"Unhandled case in DebugString " <<
static_cast<int>(
type);
619 DCHECK(
HasOneValue()) <<
"Value() called on unbound Argument: "
630 LOG(FATAL) <<
"Should not be here";
646 if (!domain.HasOneValue()) {
656 if (!
var->domain.HasOneValue()) {
685 LOG(FATAL) <<
"Cannot call Contains() on " <<
DebugString();
695 CHECK_LT(pos,
values.size());
708 LOG(FATAL) <<
"Should not be here";
718 CHECK_LT(pos,
values.size());
723 return domains[pos].HasOneValue();
728 return variables[pos]->domain.HasOneValue();
731 LOG(FATAL) <<
"Should not be here";
759 LOG(FATAL) <<
"Should not be here";
767 Variable::Variable(absl::string_view name_,
const Domain& domain_,
769 :
name(name_), domain(domain_), temporary(temporary_), active(true) {
770 if (!domain.is_interval) {
776 bool other_temporary) {
791 active ?
"" :
" [removed during presolve]");
799 const std::string presolve_status_str =
802 :
"[removed during presolve]");
804 strong, presolve_status_str);
817 type =
"false_constraint";
850 std::vector<Annotation> args) {
885 LOG(INFO) <<
"Create INT_LIST";
921 ann.AppendAllVariables(vars);
946 return absl::StrFormat(
"[%s]", absl::StrJoin(
values,
", "));
952 std::string result =
"[";
953 for (
int i = 0; i <
variables.size(); ++i) {
955 result.append(i !=
variables.size() - 1 ?
", " :
"]");
963 LOG(FATAL) <<
"Unhandled case in DebugString " <<
static_cast<int>(
type);
983 absl::string_view
name, std::vector<Bounds>
bounds,
1003 return absl::StrFormat(
"output_var(%s)",
variable->
name);
1005 return absl::StrFormat(
"output_array([%s] [%s])",
1021 variables_.push_back(
var);
1029 variables_.push_back(
var);
1036 variables_.push_back(
var);
1043 new Constraint(
id, std::move(arguments), is_domain);
1044 constraints_.push_back(constraint);
1048 std::vector<Argument> arguments) {
1049 AddConstraint(
id, std::move(arguments),
false);
1053 output_.push_back(std::move(output));
1058 search_annotations_ = std::move(search_annotations);
1062 std::vector<Annotation> search_annotations) {
1065 search_annotations_ = std::move(search_annotations);
1069 std::vector<Annotation> search_annotations) {
1072 search_annotations_ = std::move(search_annotations);
1076 std::string output = absl::StrFormat(
"Model %s\nVariables\n", name_);
1077 for (
int i = 0; i < variables_.size(); ++i) {
1078 absl::StrAppendFormat(&output,
" %s\n", variables_[i]->
DebugString());
1080 output.append(
"Constraints\n");
1081 for (
int i = 0; i < constraints_.size(); ++i) {
1082 if (constraints_[i] !=
nullptr) {
1083 absl::StrAppendFormat(&output,
" %s\n", constraints_[i]->
DebugString());
1087 absl::StrAppendFormat(&output,
"%s %s\n %s\n",
1091 absl::StrAppendFormat(&output,
"Satisfy\n %s\n",
1094 output.append(
"Output\n");
1095 for (
int i = 0; i < output_.size(); ++i) {
1096 absl::StrAppendFormat(&output,
" %s\n", output_[i].
DebugString());
1104 if (
var->domain.empty()) {
1109 if (
ct->type ==
"false_constraint") {
1120 SOLVER_LOG(logger_,
"Model ", model_.name());
1121 for (
const auto& it : constraints_per_type_) {
1122 SOLVER_LOG(logger_,
" - ", it.first,
": ", it.second.size());
1124 if (model_.objective() ==
nullptr) {
1125 SOLVER_LOG(logger_,
" - Satisfaction problem");
1128 (model_.maximize() ?
"Maximization" :
"Minimization"),
1135 constraints_per_type_.clear();
1136 constraints_per_variables_.clear();
1138 if (
ct !=
nullptr &&
ct->active) {
1139 constraints_per_type_[
ct->type].push_back(
ct);
1140 absl::flat_hash_set<const Variable*> marked;
1147 constraints_per_variables_[
var].push_back(
ct);
1161 out->push_back(ann);
void AddConstraint(absl::string_view id, std::vector< Argument > arguments, bool is_domain)
Variable * AddConstant(int64_t value)
void Satisfy(std::vector< Annotation > search_annotations)
std::string DebugString() const
void AddOutput(SolutionOutputSpecs output)
Variable * AddVariable(absl::string_view name, const Domain &domain, bool defined)
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
static Annotation String(absl::string_view str)
static Annotation FunctionCallWithArguments(absl::string_view id, std::vector< Annotation > args)
bool IsFunctionCallWithIdentifier(absl::string_view identifier) const
std::string DebugString() const
static Annotation FunctionCall(absl::string_view id)
static Annotation AnnotationList(std::vector< Annotation > list)
std::vector< Variable * > variables
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()
std::vector< int64_t > values
static Annotation Identifier(absl::string_view id)
static Annotation IntegerList(const std::vector< int64_t > &values)
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
bool HasOneValueAt(int pos) const
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 MultiDimensionalArray(absl::string_view name, std::vector< Bounds > bounds, std::vector< Variable * > flat_variables, bool display_as_boolean)
static SolutionOutputSpecs VoidOutput()
std::string DebugString() const
std::vector< Variable * > flat_variables
std::vector< Bounds > bounds
static SolutionOutputSpecs SingleVariable(absl::string_view name, Variable *variable, bool display_as_boolean)
std::string DebugString() const
bool Merge(absl::string_view other_name, const Domain &other_domain, bool other_temporary)
#define SOLVER_LOG(logger,...)