Google OR-Tools: ortools/flatzinc/model.cc Source File
23#include "absl/base/optimization.h"
24#include "absl/container/flat_hash_set.h"
27#include "absl/strings/str_cat.h"
28#include "absl/strings/str_format.h"
29#include "absl/strings/str_join.h"
30#include "absl/strings/string_view.h"
31#include "absl/types/span.h"
37namespace fz {
134 if (!domain.values.empty()) {
140 is_interval = false;
141 if (values.empty()) {
144 const int64_t imin = values[0];
145 const int64_t imax = values[1];
160 if (interval_min > interval_max) {
165 if (values.empty()) {
166 values.push_back(interval_min);
167 values.push_back(interval_max);
170 if (values[0] >= interval_min && values[1] <= interval_max) return false;
171 values[0] = std::max(values[0], interval_min);
172 values[1] = std::min(values[1], interval_max);
183 if (!values.empty()) {
185 std::vector<int64_t> new_values;
186 new_values.reserve(values.size());
188 for (const int64_t val : values) {
193 if (val >= interval_min &&
194 (new_values.empty() || val != new_values.back())) {
195 new_values.push_back(val);
200 values.swap(new_values);
210 values.empty() ? std::numeric_limits<int64_t>::min() : values[0];
212 values.empty() ? std::numeric_limits<int64_t>::max() : values[1];
214 for (const int64_t v : integers) {
215 if (v >= dmin && v <= dmax) values.push_back(v);
218 if (!values.empty() &&
220 values.size() >= 2) {
221 if (values.size() > 2) {
223 const int64_t last = values.back();
227 return values[0] != dmin || values[1] != dmax;
236 absl::flat_hash_set<int64_t> other_values(integers.begin(), integers.end());
237 std::vector<int64_t> new_values;
238 new_values.reserve(std::min(values.size(), integers.size()));
240 for (const int64_t val : values) {
241 if (other_values.contains(val)) {
242 if (new_values.empty() || val != new_values.back()) {
243 new_values.push_back(val);
249 values.swap(new_values);
354 return values.front();
359 (values.empty() || (values[0] == std::numeric_limits<int64_t>::min() &&
360 values[1] == std::numeric_limits<int64_t>::max()));
365 if (values.empty()) {
368 return value >= values[0] && value <= values[1];
371 return std::find(values.begin(), values.end(), value) != values.end();
376bool IntervalOverlapValues(int64_t lb, int64_t ub,
377 absl::Span<const int64_t> values) {
378 for (int64_t value : values) {
379 if (lb <= value && value <= ub) {
392 CHECK(!values.empty());
393 return IntervalOverlapValues(values[0], values[1], vec);
396 const std::vector<int64_t>& to_scan =
398 const absl::flat_hash_set<int64_t> container =
399 values.size() <= vec.size()
400 ? absl::flat_hash_set<int64_t>(vec.begin(), vec.end())
401 : absl::flat_hash_set<int64_t>(values.begin(), values.end());
402 for (int64_t value : to_scan) {
416 CHECK(!values.empty());
417 const int64_t dlb = values[0];
418 const int64_t dub = values[1];
419 return !(dub < lb || dlb > ub);
421 return IntervalOverlapValues(lb, ub, values);
439 if (values.empty()) {
441 } else if (value == values[0] && value != values[1]) {
444 } else if (value == values[1] && value != values[0]) {
448 value < values[1]) {
449 const int64_t vmax = values[1];
452 for (int64_t v = values[0] + 1; v <= vmax; ++v) {
481 return absl::StrCat(prefix, float_values[0]);
486 LOG(DFATAL) << "Error with float domain";
491 if (values.empty()) {
492 return absl::StrCat(prefix, "int");
494 return absl::StrCat(prefix, "[", values[0], "..", values[1], "]");
496 } else if (values.size() == 1) {
497 return absl::StrCat(prefix, values.back());
499 return absl::StrFormat("%s[%s]", prefix, absl::StrJoin(values, ", "));
556 if (domain.values.empty()) {
590 switch (type) {
592 return absl::StrFormat("%d", values[0]);
594 return absl::StrFormat("[%d..%d]", values[0], values[1]);
596 return absl::StrFormat("[%s]", absl::StrJoin(values, ", "));
603 for (int i = 0; i < variables.size(); ++i) {
604 result.append(variables[i]->name);
605 result.append(i != variables.size() - 1 ? ", " : "]");
612 return absl::StrCat(floats[0]);
614 return absl::StrCat("[", floats[0], "..", floats[1], "]");
616 return absl::StrFormat("[%s]", absl::StrJoin(floats, ", "));
618 LOG(FATAL) << "Unhandled case in DebugString " << static_cast<int>(type);
631 DCHECK(HasOneValue()) << "Value() called on unbound Argument: "
633 switch (type) {
639 return variables[0]->domain.values[0];
685 switch (type) {
687 return std::find(values.begin(), values.end(), value) != values.end();
689 return value >= values.front() && value <= values.back();
691 return value == values.front();
700 switch (type) {
703 CHECK_LT(pos, values.size());
707 CHECK_LT(pos, domains.size());
708 return domains[pos].Value();
713 return variables[pos]->domain.Value();
722 switch (type) {
725 CHECK_LT(pos, values.size());
729 CHECK_LT(pos, domains.size());
730 return domains[pos].HasOneValue();
735 return variables[pos]->domain.HasOneValue();
775Variable::Variable(absl::string_view name_, const Domain& domain_,
777 : name(name_), domain(domain_), temporary(temporary_), active(true) {
778 if (!domain.is_interval) {
779 gtl::STLSortAndRemoveDuplicates(&domain.values);
785 if (temporary && !other_temporary) {
787 name = other_name;
789 domain.IntersectWithDomain(other_domain);
794 if (!domain.is_interval && domain.values.size() == 1) {
795 return absl::StrFormat("% d", domain.values.back());
797 return absl::StrFormat("%s(%s%s)%s", name, domain.DebugString(),
799 active ? "" : " [removed during presolve]");
806 const std::string strong = strong_propagation ? " strong propagation" : "";
807 const std::string presolve_status_str =
808 active ? "" : " [removed during presolve]";
809 const std::string symmetric_breaking_str =
811 const std::string redundant_str = is_redundant ? " redundant" : "";
827 type = "false_constraint";
939 switch (type) {
943 return id;
951 return absl::StrFormat("[%s]", absl::StrJoin(values, ", "));
956 for (int i = 0; i < variables.size(); ++i) {
958 result.append(i != variables.size() - 1 ? ", " : "]");
963 return absl::StrFormat("\"%s\"", string_value);
965 LOG(FATAL) << "Unhandled case in DebugString " << static_cast<int>(type);
1005 return absl::StrFormat("output_var(%s)", variable->name);
1047 bool is_domain, bool symmetry, bool redundant) {
1049 new Constraint(id, std::move(arguments), is_domain, symmetry, redundant);
1054 std::vector<Argument> arguments) {
1055 AddConstraint(id, std::move(arguments), false, false, false);
1059 output_.push_back(std::move(output));
1082 std::string output = absl::StrFormat("Model %s\nVariables\n", name_);
1083 for (int i = 0; i < variables_.size(); ++i) {
1084 absl::StrAppendFormat(&output, " %s\n", variables_[i]->DebugString());
1086 output.append("Constraints\n");
1087 for (int i = 0; i < constraints_.size(); ++i) {
1088 if (constraints_[i] != nullptr) {
1089 absl::StrAppendFormat(&output, " %s\n", constraints_[i]->DebugString());
1092 if (objective_ != nullptr) {
1093 absl::StrAppendFormat(&output, "%s %s\n %s\n",
1094 maximize_ ? "Maximize" : "Minimize", objective_->name,
1096 } else if (!float_objective_variables_.empty()) {
1097 absl::StrAppendFormat(&output, "%s [%s] * [%s] + %f\n %s\n",
1098 maximize_ ? "Maximize" : "Minimize",
1100 absl::StrJoin(float_objective_coefficients_, ", "),
1105 absl::StrAppendFormat(&output, "Satisfy\n %s\n",
1108 output.append("Output\n");
1109 for (int i = 0; i < output_.size(); ++i) {
1110 absl::StrAppendFormat(&output, " %s\n", output_[i].DebugString());
1117 for (Variable* var : variables_) {
1118 if (var->domain.empty()) {
1122 for (Constraint* ct : constraints_) {
1134 SOLVER_LOG(logger_, "Model ", model_.name());
1141 for (Variable* var : model_.variables()) {
1142 if (var->domain.is_float) {
1144 } else if (var->domain.is_a_set) {
1146 } else if (var->domain.display_as_boolean) {
1153 SOLVER_LOG(logger_, " - boolean variables:", num_bool_vars);
1156 SOLVER_LOG(logger_, " - integer variables:", num_int_vars);
1158 if (num_float_vars > 0) {
1159 SOLVER_LOG(logger_, " - float variables:", num_float_vars);
1162 SOLVER_LOG(logger_, " - set variables:", num_set_vars);
1167 int num_redundant_constraints = 0;
1168 int num_symmetry_breaking_constraints = 0;
1169 for (Constraint* const ct : model_.constraints()) {
1170 if (ct != nullptr && ct->active) {
1172 ++num_redundant_constraints;
1174 if (ct->is_symmetric_breaking) {
1175 ++num_symmetry_breaking_constraints;
1179 for (const auto& it : constraints_per_type_) {
1180 SOLVER_LOG(logger_, " - ", it.first, ": ", it.second.size());
1183 if (num_redundant_constraints > 0) {
1185 " - redundant constraints: ", num_redundant_constraints);
1187 if (num_symmetry_breaking_constraints > 0) {
1188 SOLVER_LOG(logger_, " - symmetry breaking constraints: ",
1189 num_symmetry_breaking_constraints);
1191 if (model_.objective() == nullptr) {
1192 SOLVER_LOG(logger_, " - Satisfaction problem");
1202 constraints_per_type_.clear();
1203 constraints_per_variables_.clear();
1204 for (Constraint* const ct : model_.constraints()) {
1205 if (ct != nullptr && ct->active) {
1206 constraints_per_type_[ct->type].push_back(ct);
1207 absl::flat_hash_set<const Variable*> marked;
1208 for (const Argument& arg : ct->arguments) {
1213 for (const Variable* const var : marked) {
void BuildStatistics()
Definition model.cc:1201
void PrintStatistics() const
Definition model.cc:1133
void AddConstraint(absl::string_view id, std::vector< Argument > arguments, bool is_domain, bool symmetry, bool redundant)
Definition model.cc:1046
~Model()
Definition model.cc:1015
const std::vector< SolutionOutputSpecs > & output() const
Variable * AddVariable(absl::string_view name, const Domain &domain, bool defined, bool set_is_fixed=false)
Definition model.cc:1020
Variable * AddFloatConstant(double value)
Definition model.cc:1039
std::string DebugString() const
Definition model.cc:1081
void AddOutput(SolutionOutputSpecs output)
Definition model.cc:1058
void Maximize(Variable *obj, std::vector< Annotation > search_annotations)
Definition model.cc:1074
void Satisfy(std::vector< Annotation > search_annotations)
Definition model.cc:1062
const std::string & name() const
const std::vector< Annotation > & search_annotations() const
bool IsInconsistent() const
Definition model.cc:1116
void Minimize(Variable *obj, std::vector< Annotation > search_annotations)
Definition model.cc:1067
Variable * AddConstant(int64_t value)
Definition model.cc:1032
void STLSortAndRemoveDuplicates(T *v, const LessFunc &less_func)
void STLDeleteElements(T *container)
void FlattenAnnotations(const Annotation &ann, std::vector< Annotation > *out)
Definition model.cc:1221
std::string JoinDebugStringPtr(const std::vector< T > &v, absl::string_view separator)
std::string JoinNameFieldPtr(const std::vector< T > &v, absl::string_view separator)
std::string JoinDebugString(const std::vector< T > &v, absl::string_view separator)
static Annotation String(absl::string_view str)
Definition model.cc:920
static Annotation FunctionCall(absl::string_view id)
Definition model.cc:870
void AppendAllVariables(std::vector< Variable * > *vars) const
Definition model.cc:929
static Annotation FunctionCallWithArguments(absl::string_view id, std::vector< Annotation > args)
Definition model.cc:859
static Annotation Empty()
Definition model.cc:833
static Annotation AnnotationList(std::vector< Annotation > list)
Definition model.cc:841
static Annotation IntegerList(const std::vector< int64_t > &values)
Definition model.cc:894
static Annotation VarRefArray(std::vector< Variable * > variables)
Definition model.cc:911
static Annotation Identifier(absl::string_view id)
Definition model.cc:850
std::vector< Variable * > variables
std::vector< int64_t > values
bool IsFunctionCallWithIdentifier(absl::string_view identifier) const
static Annotation VarRef(Variable *var)
Definition model.cc:902
static Annotation IntegerValue(int64_t value)
Definition model.cc:887
static Annotation Interval(int64_t interval_min, int64_t interval_max)
Definition model.cc:879
std::vector< Annotation > annotations
std::string DebugString() const
Definition model.cc:938
std::vector< Variable * > variables
static Argument FloatList(std::vector< double > floats)
Definition model.cc:582
int Size() const
Definition model.cc:751
Variable * Var() const
Definition model.cc:743
static Argument FloatValue(double value)
Definition model.cc:567
bool IsVariable() const
Definition model.cc:622
std::vector< Domain > domains
bool HasOneValueAt(int pos) const
Definition model.cc:721
Variable * VarAt(int pos) const
Definition model.cc:747
std::string DebugString() const
Definition model.cc:589
bool IsArrayOfValues() const
Definition model.cc:646
static Argument VoidArgument()
Definition model.cc:548
bool HasOneValue() const
Definition model.cc:624
static Argument IntegerValue(int64_t value)
Definition model.cc:505
int64_t ValueAt(int pos) const
Definition model.cc:699
static Argument Interval(int64_t imin, int64_t imax)
Definition model.cc:512
static Argument FromDomain(const Domain &domain)
Definition model.cc:554
int64_t Value() const
Definition model.cc:630
static Argument IntegerList(std::vector< int64_t > values)
Definition model.cc:520
static Argument VarRef(Variable *var)
Definition model.cc:534
static Argument FloatInterval(double lb, double ub)
Definition model.cc:574
std::vector< double > floats
bool Contains(int64_t value) const
Definition model.cc:684
static Argument DomainList(std::vector< Domain > domains)
Definition model.cc:527
static Argument VarRefArray(std::vector< Variable * > vars)
Definition model.cc:541
std::vector< int64_t > values
bool is_symmetric_breaking
std::string DebugString() const
Definition model.cc:805
void MarkAsInactive()
Definition model.cc:821
void RemoveArg(int arg_pos)
Definition model.cc:817
void SetAsFalse()
Definition model.cc:826
std::vector< Argument > arguments
static Domain Boolean()
Definition model.cc:67
static Domain AllFloats()
Definition model.cc:107
bool IntersectWithSingleton(int64_t value)
Definition model.cc:155
static Domain IntegerList(std::vector< int64_t > values)
Definition model.cc:40
bool OverlapsDomain(const Domain &other) const
Definition model.cc:425
static Domain IntegerValue(int64_t value)
Definition model.cc:53
int64_t Max() const
Definition model.cc:346
std::string DebugString() const
Definition model.cc:468
static Domain FloatValue(double value)
Definition model.cc:122
bool IntersectWithInterval(int64_t interval_min, int64_t interval_max)
Definition model.cc:159
bool IntersectWithDomain(const Domain &domain)
Definition model.cc:129
bool SetEmptyFloatDomain()
Definition model.cc:324
bool empty() const
Definition model.cc:335
static Domain EmptyDomain()
Definition model.cc:105
bool IntersectWithFloatDomain(const Domain &domain)
Definition model.cc:254
bool RemoveValue(int64_t value)
Definition model.cc:437
static Domain FloatInterval(double lb, double ub)
Definition model.cc:114
int64_t Min() const
Definition model.cc:340
std::vector< int64_t > values
static Domain SetOfBoolean()
Definition model.cc:99
static Domain Interval(int64_t included_min, int64_t included_max)
Definition model.cc:59
static Domain SetOfAllInt64()
Definition model.cc:81
static Domain SetOfInterval(int64_t included_min, int64_t included_max)
Definition model.cc:93
bool Contains(int64_t value) const
Definition model.cc:363
bool OverlapsIntInterval(int64_t lb, int64_t ub) const
Definition model.cc:411
std::vector< double > float_values
static Domain SetOfIntegerList(std::vector< int64_t > values)
Definition model.cc:75
static Domain SetOfIntegerValue(int64_t value)
Definition model.cc:87
bool HasOneValue() const
Definition model.cc:331
int64_t Value() const
Definition model.cc:352
static Domain AllInt64()
Definition model.cc:47
bool IntersectWithListOfIntegers(absl::Span< const int64_t > integers)
Definition model.cc:207
bool IsAllInt64() const
Definition model.cc:357
bool OverlapsIntList(const std::vector< int64_t > &vec) const
Definition model.cc:387
std::string DebugString() const
Definition model.cc:971
std::vector< Variable * > flat_variables
static SolutionOutputSpecs MultiDimensionalArray(absl::string_view name, std::vector< Bounds > bounds, std::vector< Variable * > flat_variables, bool display_as_boolean)
Definition model.cc:984
std::string DebugString() const
Definition model.cc:1003
static SolutionOutputSpecs VoidOutput()
Definition model.cc:996
static SolutionOutputSpecs SingleVariable(absl::string_view name, Variable *variable, bool display_as_boolean)
Definition model.cc:975
std::vector< Bounds > bounds
bool Merge(absl::string_view other_name, const Domain &other_domain, bool other_temporary)
Definition model.cc:783
std::string DebugString() const
Definition model.cc:793
#define SOLVER_LOG(logger,...)