22#include "absl/container/flat_hash_map.h"
23#include "absl/strings/str_format.h"
24#include "absl/strings/str_join.h"
31#include "ortools/constraint_solver/assignment.pb.h"
46 min_ = std::numeric_limits<int64_t>::min();
47 max_ = std::numeric_limits<int64_t>::max();
57 SetRange(element.min_, element.max_);
67 const IntVarAssignment& int_var_assignment_proto) {
68 min_ = int_var_assignment_proto.min();
69 max_ = int_var_assignment_proto.max();
70 if (int_var_assignment_proto.active()) {
78 if (var_ != element.var_) {
89 return min_ == element.min_ && max_ == element.max_;
93 IntVarAssignment* int_var_assignment_proto)
const {
94 int_var_assignment_proto->set_var_id(var_->
name());
95 int_var_assignment_proto->set_min(min_);
96 int_var_assignment_proto->set_max(max_);
97 int_var_assignment_proto->set_active(
Activated());
103 return absl::StrFormat(
"(%d)", min_);
105 return absl::StrFormat(
"(%d..%d)", min_, max_);
120 start_min_ = std::numeric_limits<int64_t>::min();
121 start_max_ = std::numeric_limits<int64_t>::max();
122 duration_min_ = std::numeric_limits<int64_t>::min();
123 duration_max_ = std::numeric_limits<int64_t>::max();
124 end_min_ = std::numeric_limits<int64_t>::min();
125 end_max_ = std::numeric_limits<int64_t>::max();
132 element->
Copy(*
this);
152 if (performed_max_ != 0LL) {
157 end_min_ = var_->
EndMin();
158 end_max_ = var_->
EndMax();
163 if (performed_max_ == performed_min_) {
166 if (performed_max_ != 0LL) {
174 const IntervalVarAssignment& interval_var_assignment_proto) {
175 start_min_ = interval_var_assignment_proto.start_min();
176 start_max_ = interval_var_assignment_proto.start_max();
177 duration_min_ = interval_var_assignment_proto.duration_min();
178 duration_max_ = interval_var_assignment_proto.duration_max();
179 end_min_ = interval_var_assignment_proto.end_min();
180 end_max_ = interval_var_assignment_proto.end_max();
181 performed_min_ = interval_var_assignment_proto.performed_min();
182 performed_max_ = interval_var_assignment_proto.performed_max();
183 if (interval_var_assignment_proto.active()) {
191 IntervalVarAssignment* interval_var_assignment_proto)
const {
192 interval_var_assignment_proto->set_var_id(var_->
name());
193 interval_var_assignment_proto->set_start_min(start_min_);
194 interval_var_assignment_proto->set_start_max(start_max_);
195 interval_var_assignment_proto->set_duration_min(duration_min_);
196 interval_var_assignment_proto->set_duration_max(duration_max_);
197 interval_var_assignment_proto->set_end_min(end_min_);
198 interval_var_assignment_proto->set_end_max(end_max_);
199 interval_var_assignment_proto->set_performed_min(performed_min_);
200 interval_var_assignment_proto->set_performed_max(performed_max_);
201 interval_var_assignment_proto->set_active(
Activated());
207 absl::StrAppendFormat(&out,
"(start = %d", start_min_);
208 if (start_max_ != start_min_) {
209 absl::StrAppendFormat(&out,
"..%d", start_max_);
211 absl::StrAppendFormat(&out,
", duration = %d", duration_min_);
212 if (duration_max_ != duration_min_) {
213 absl::StrAppendFormat(&out,
"..%d", duration_max_);
215 absl::StrAppendFormat(&out,
", status = %d", performed_min_);
216 if (performed_max_ != performed_min_) {
217 absl::StrAppendFormat(&out,
"..%d", performed_max_);
227 if (var_ != element.var_) {
238 return start_min_ == element.start_min_ && start_max_ == element.start_max_ &&
239 duration_min_ == element.duration_min_ &&
240 duration_max_ == element.duration_max_ &&
241 end_min_ == element.end_min_ && end_max_ == element.end_max_ &&
242 performed_min_ == element.performed_min_ &&
243 performed_max_ == element.performed_max_ && var_ == element.var_;
254 forward_sequence_.clear();
255 backward_sequence_.clear();
256 unperformed_.clear();
261 element->
Copy(*
this);
266 forward_sequence_ = element.forward_sequence_;
267 backward_sequence_ = element.backward_sequence_;
268 unperformed_ = element.unperformed_;
278 var_->
FillSequence(&forward_sequence_, &backward_sequence_, &unperformed_);
282 var_->
RankSequence(forward_sequence_, backward_sequence_, unperformed_);
286 const SequenceVarAssignment& sequence_var_assignment_proto) {
287 for (
const int32_t forward_sequence :
288 sequence_var_assignment_proto.forward_sequence()) {
289 forward_sequence_.push_back(forward_sequence);
291 for (
const int32_t backward_sequence :
292 sequence_var_assignment_proto.backward_sequence()) {
293 backward_sequence_.push_back(backward_sequence);
295 for (
const int32_t unperformed :
296 sequence_var_assignment_proto.unperformed()) {
297 unperformed_.push_back(unperformed);
299 if (sequence_var_assignment_proto.active()) {
304 DCHECK(CheckClassInvariants());
308 SequenceVarAssignment* sequence_var_assignment_proto)
const {
309 sequence_var_assignment_proto->set_var_id(var_->
name());
310 sequence_var_assignment_proto->set_active(
Activated());
311 for (
const int forward_sequence : forward_sequence_) {
312 sequence_var_assignment_proto->add_forward_sequence(forward_sequence);
314 for (
const int backward_sequence : backward_sequence_) {
315 sequence_var_assignment_proto->add_backward_sequence(backward_sequence);
317 for (
const int unperformed : unperformed_) {
318 sequence_var_assignment_proto->add_unperformed(unperformed);
324 return absl::StrFormat(
"[forward %s, backward %s, unperformed [%s]]",
325 absl::StrJoin(forward_sequence_,
" -> "),
326 absl::StrJoin(backward_sequence_,
" -> "),
327 absl::StrJoin(unperformed_,
", "));
334 if (var_ != element.var_) {
345 return forward_sequence_ == element.forward_sequence_ &&
346 backward_sequence_ == element.backward_sequence_ &&
347 unperformed_ == element.unperformed_;
351 return forward_sequence_;
355 return backward_sequence_;
363 const std::vector<int>& backward_sequence,
364 const std::vector<int>& unperformed) {
365 forward_sequence_ = forward_sequence;
366 backward_sequence_ = backward_sequence;
367 unperformed_ = unperformed;
368 DCHECK(CheckClassInvariants());
372 const std::vector<int>& forward_sequence) {
373 forward_sequence_ = forward_sequence;
377 const std::vector<int>& backward_sequence) {
378 backward_sequence_ = backward_sequence;
382 unperformed_ = unperformed;
385bool SequenceVarElement::CheckClassInvariants() {
386 absl::flat_hash_set<int> visited;
387 for (
const int forward_sequence : forward_sequence_) {
388 if (visited.contains(forward_sequence)) {
391 visited.insert(forward_sequence);
393 for (
const int backward_sequence : backward_sequence_) {
394 if (visited.contains(backward_sequence)) {
397 visited.insert(backward_sequence);
399 for (
const int unperformed : unperformed_) {
400 if (visited.contains(unperformed)) {
403 visited.insert(unperformed);
412 int_var_container_(copy->int_var_container_),
413 interval_var_container_(copy->interval_var_container_),
414 sequence_var_container_(copy->sequence_var_container_),
415 objective_elements_(copy->objective_elements_) {}
421 objective_elements_.clear();
422 int_var_container_.
Clear();
423 interval_var_container_.
Clear();
424 sequence_var_container_.
Clear();
428 int_var_container_.
Store();
429 interval_var_container_.
Store();
430 sequence_var_container_.
Store();
431 for (
IntVarElement& objective_element : objective_elements_) {
432 objective_element.Store();
439 interval_var_container_.
Restore();
440 sequence_var_container_.
Restore();
446template <
class V,
class E>
448 absl::flat_hash_map<std::string, E*>* id_to_element_map) {
449 CHECK(id_to_element_map !=
nullptr);
450 id_to_element_map->clear();
451 for (
int i = 0; i < container->
Size(); ++i) {
453 const V*
const var = element->
Var();
456 LOG(INFO) <<
"Cannot save/load variables with empty name"
457 <<
"; variable will be ignored";
458 }
else if (id_to_element_map->contains(
name)) {
459 LOG(INFO) <<
"Cannot save/load variables with duplicate names: " <<
name
460 <<
"; variable will be ignored";
462 (*id_to_element_map)[
name] = element;
467template <
class E,
class P>
468void LoadElement(
const absl::flat_hash_map<std::string, E*>& id_to_element_map,
470 const std::string& var_id =
proto.var_id();
471 CHECK(!var_id.empty());
472 E* element =
nullptr;
474 element->LoadFromProto(
proto);
476 LOG(INFO) <<
"Variable " << var_id
477 <<
" not in assignment; skipping variable";
486 LOG(INFO) <<
"Cannot open " << filename;
493 CHECK(
file !=
nullptr);
494 AssignmentProto assignment_proto;
497 LOG(INFO) <<
"No assignment found in " <<
file->filename();
500 Load(assignment_proto);
501 return reader.
Close();
504template <
class Var,
class Element,
class Proto,
class Container>
505void RealLoad(
const AssignmentProto& assignment_proto,
506 Container*
const container,
507 int (AssignmentProto::*GetSize)()
const,
508 const Proto& (AssignmentProto::*GetElem)(
int)
const) {
509 bool fast_load = (container->Size() == (assignment_proto.*GetSize)());
510 for (
int i = 0; fast_load && i < (assignment_proto.*GetSize)(); ++i) {
511 Element*
const element = container->MutableElement(i);
512 const Proto&
proto = (assignment_proto.*GetElem)(i);
513 if (element->Var()->name() ==
proto.var_id()) {
514 element->LoadFromProto(
proto);
520 absl::flat_hash_map<std::string, Element*> id_to_element_map;
521 IdToElementMap<Var, Element>(container, &id_to_element_map);
522 for (
int i = 0; i < (assignment_proto.*GetSize)(); ++i) {
523 LoadElement<Element, Proto>(id_to_element_map,
524 (assignment_proto.*GetElem)(i));
531 assignment_proto, &int_var_container_,
532 &AssignmentProto::int_var_assignment_size,
533 &AssignmentProto::int_var_assignment);
536 &AssignmentProto::interval_var_assignment_size,
537 &AssignmentProto::interval_var_assignment);
540 &AssignmentProto::sequence_var_assignment_size,
541 &AssignmentProto::sequence_var_assignment);
542 for (
int i = 0; i < assignment_proto.objective_size(); ++i) {
543 const IntVarAssignment& objective = assignment_proto.objective(i);
544 const std::string& objective_id = objective.var_id();
545 DCHECK(!objective_id.empty());
548 const int64_t obj_min = objective.min();
549 const int64_t obj_max = objective.max();
551 if (objective.active()) {
563 LOG(INFO) <<
"Cannot open " << filename;
570 CHECK(
file !=
nullptr);
571 AssignmentProto assignment_proto;
572 Save(&assignment_proto);
577template <
class Var,
class Element,
class Proto,
class Container>
578void RealSave(AssignmentProto*
const assignment_proto,
579 const Container& container, Proto* (AssignmentProto::*Add)()) {
580 for (
const Element& element : container.elements()) {
581 const Var*
const var = element.
Var();
584 Proto*
const var_assignment_proto = (assignment_proto->*Add)();
585 element.WriteToProto(var_assignment_proto);
591 assignment_proto->Clear();
593 assignment_proto, int_var_container_,
594 &AssignmentProto::add_int_var_assignment);
597 &AssignmentProto::add_interval_var_assignment);
600 &AssignmentProto::add_sequence_var_assignment);
601 for (
int i = 0; i < objective_elements_.size(); ++i) {
604 IntVarAssignment* objective = assignment_proto->add_objective();
605 objective->set_var_id(
name);
613template <
class Container,
class Element>
615 for (
const Element& element : container.elements()) {
616 if (element.Var() !=
nullptr) {
617 absl::StrAppendFormat(out,
"%s %s | ", element.Var()->name(),
618 element.DebugString());
624 std::string out =
"Assignment(";
627 interval_var_container_, &out);
629 sequence_var_container_, &out);
630 std::vector<std::string> objective_str;
631 for (
const IntVarElement& objective_element : objective_elements_) {
632 if (objective_element.Activated()) {
633 objective_str.push_back(objective_element.DebugString());
636 absl::StrAppendFormat(&out,
"%s)", absl::StrJoin(objective_str,
", "));
641 return int_var_container_.
Add(
var);
689 return interval_var_container_.
Add(
var);
822 return sequence_var_container_.
Add(
var);
851 const std::vector<int>& forward_sequence,
852 const std::vector<int>& backward_sequence,
853 const std::vector<int>& unperformed) {
855 forward_sequence, backward_sequence, unperformed);
859 const std::vector<int>& forward_sequence) {
865 const SequenceVar*
const var,
const std::vector<int>& backward_sequence) {
871 const std::vector<int>& unperformed) {
925 interval_var_container_.
CopyIntersection(assignment->interval_var_container_);
926 sequence_var_container_.
CopyIntersection(assignment->sequence_var_container_);
927 for (
int i = 0; i < objective_elements_.size(); i++) {
928 if (i >= assignment->objective_elements_.size() ||
932 objective_elements_[i].Var() !=
933 assignment->objective_elements_[i].Var()) {
936 objective_elements_[i] = assignment->objective_elements_[i];
942 int_var_container_.
Copy(assignment->int_var_container_);
943 interval_var_container_.
Copy(assignment->interval_var_container_);
944 sequence_var_container_.
Copy(assignment->sequence_var_container_);
945 objective_elements_ = assignment->objective_elements_;
949 const std::vector<IntVar*>& target_vars,
951 const std::vector<IntVar*>& source_vars) {
952 const int vars_size = target_vars.size();
953 CHECK_EQ(source_vars.size(), vars_size);
954 CHECK(target_assignment !=
nullptr);
956 target_assignment->
Clear();
957 const Solver*
const target_solver = target_assignment->
solver();
958 const Solver*
const source_solver = source_assignment->
solver();
961 CHECK_EQ(target_var->
solver(), target_solver);
963 CHECK_EQ(source_var->
solver(), source_solver);
964 target_assignment->
Add(target_var)
979 explicit RestoreAssignment(
Assignment* assignment)
980 : assignment_(assignment) {}
982 ~RestoreAssignment()
override {}
984 Decision*
Next(Solver*
const )
override {
985 assignment_->Restore();
989 std::string DebugString()
const override {
return "RestoreAssignment"; }
992 Assignment*
const assignment_;
997 explicit StoreAssignment(Assignment* assignment) : assignment_(assignment) {}
999 ~StoreAssignment()
override {}
1001 Decision*
Next(Solver*
const )
override {
1002 assignment_->Store();
1006 std::string DebugString()
const override {
return "StoreAssignment"; }
1009 Assignment*
const assignment_;
1014 return RevAlloc(
new RestoreAssignment(assignment));
1018 return RevAlloc(
new StoreAssignment(assignment));
const E & Element(const V *const var) const
E * FastAdd(V *var)
Adds element without checking its presence in the container.
void Copy(const AssignmentContainer< V, E > &container)
E * MutableElement(const V *const var)
void CopyIntersection(const AssignmentContainer< V, E > &container)
bool Contains(const V *const var) const
void Activate(const IntVar *var)
Assignment(Solver *solver)
void SetPerformedRange(const IntervalVar *var, int64_t mi, int64_t ma)
int64_t Value(const IntVar *var) const
void SetStartMax(const IntervalVar *var, int64_t m)
void SetMax(const IntVar *var, int64_t m)
void SetForwardSequence(const SequenceVar *var, const std::vector< int > &forward_sequence)
int64_t EndMin(const IntervalVar *var) const
bool Activated(const IntVar *var) const
int64_t DurationMax(const IntervalVar *var) const
int64_t PerformedMin(const IntervalVar *var) const
int64_t Max(const IntVar *var) const
void SetBackwardSequence(const SequenceVar *var, const std::vector< int > &backward_sequence)
int64_t Min(const IntVar *var) const
void SetEndValue(const IntervalVar *var, int64_t value)
bool Contains(const IntVar *var) const
void SetValue(const IntVar *var, int64_t value)
void SetEndMin(const IntervalVar *var, int64_t m)
bool Load(const std::string &filename)
int64_t EndValue(const IntervalVar *var) const
void SetMin(const IntVar *var, int64_t m)
void DeactivateObjectiveFromIndex(int index)
const std::vector< int > & Unperformed(const SequenceVar *var) const
void SetPerformedValue(const IntervalVar *var, int64_t value)
int64_t PerformedValue(const IntervalVar *var) const
int64_t StartValue(const IntervalVar *var) const
IntVarElement * Add(IntVar *var)
void SetPerformedMax(const IntervalVar *var, int64_t m)
void ActivateObjectiveFromIndex(int index)
int64_t ObjectiveMinFromIndex(int index) const
std::string DebugString() const override
int64_t EndMax(const IntervalVar *var) const
int64_t StartMin(const IntervalVar *var) const
IntVarElement * FastAdd(IntVar *var)
Adds without checking if variable has been previously added.
void Deactivate(const IntVar *var)
void Copy(const Assignment *assignment)
const std::vector< int > & ForwardSequence(const SequenceVar *var) const
void SetRange(const IntVar *var, int64_t l, int64_t u)
int64_t ObjectiveMaxFromIndex(int index) const
bool ActivatedObjectiveFromIndex(int index) const
int64_t DurationMin(const IntervalVar *var) const
bool Bound(const IntVar *var) const
int64_t DurationValue(const IntervalVar *var) const
void SetSequence(const SequenceVar *var, const std::vector< int > &forward_sequence, const std::vector< int > &backward_sequence, const std::vector< int > &unperformed)
void SetStartMin(const IntervalVar *var, int64_t m)
void SetDurationMin(const IntervalVar *var, int64_t m)
void SetStartValue(const IntervalVar *var, int64_t value)
void SetDurationMax(const IntervalVar *var, int64_t m)
void SetEndMax(const IntervalVar *var, int64_t m)
void SetStartRange(const IntervalVar *var, int64_t mi, int64_t ma)
void SetDurationValue(const IntervalVar *var, int64_t value)
void CopyIntersection(const Assignment *assignment)
void SetEndRange(const IntervalVar *var, int64_t mi, int64_t ma)
void SetDurationRange(const IntervalVar *var, int64_t mi, int64_t ma)
bool HasObjectiveFromIndex(int index) const
int64_t StartMax(const IntervalVar *var) const
IntVar * ObjectiveFromIndex(int index) const
bool Save(const std::string &filename) const
Saves the assignment to a file.
const std::vector< int > & BackwardSequence(const SequenceVar *var) const
void SetPerformedMin(const IntervalVar *var, int64_t m)
void SetObjectiveRangeFromIndex(int index, int64_t l, int64_t u)
void SetUnperformed(const SequenceVar *var, const std::vector< int > &unperformed)
int64_t PerformedMax(const IntervalVar *var) const
bool operator==(const IntVarElement &element) const
void SetRange(int64_t l, int64_t u)
IntVarElement()
--------------— Solutions ---------------------—
std::string DebugString() const
void Copy(const IntVarElement &element)
void WriteToProto(IntVarAssignment *int_var_assignment_proto) const
void LoadFromProto(const IntVarAssignment &int_var_assignment_proto)
IntVar * Var() override
Creates a variable from the expression.
void SetStartValue(int64_t v)
void SetDurationValue(int64_t v)
int64_t PerformedValue() const
void SetEndMin(int64_t m)
void SetDurationRange(int64_t mi, int64_t ma)
void SetStartMax(int64_t m)
void SetPerformedMin(int64_t m)
IntervalVarElement * Clone()
void SetStartMin(int64_t m)
std::string DebugString() const
void WriteToProto(IntervalVarAssignment *interval_var_assignment_proto) const
void SetPerformedMax(int64_t m)
void SetPerformedValue(int64_t v)
void SetEndMax(int64_t m)
void Reset(IntervalVar *var)
void Copy(const IntervalVarElement &element)
int64_t DurationMax() const
void SetEndRange(int64_t mi, int64_t ma)
void SetDurationMax(int64_t m)
IntervalVarElement()
--— IntervalVarElement --—
int64_t PerformedMin() const
bool operator==(const IntervalVarElement &element) const
void SetStartRange(int64_t mi, int64_t ma)
int64_t DurationMin() const
void SetPerformedRange(int64_t mi, int64_t ma)
void LoadFromProto(const IntervalVarAssignment &interval_var_assignment_proto)
int64_t PerformedMax() const
int64_t DurationValue() const
void SetEndValue(int64_t v)
void SetDurationMin(int64_t m)
int64_t StartValue() const
virtual int64_t DurationMax() const =0
virtual void SetEndRange(int64_t mi, int64_t ma)=0
virtual int64_t EndMax() const =0
virtual int64_t EndMin() const =0
These methods query, set, and watch the end position of the interval var.
virtual void SetPerformed(bool val)=0
virtual void SetStartRange(int64_t mi, int64_t ma)=0
virtual int64_t StartMax() const =0
virtual bool MayBePerformed() const =0
virtual int64_t DurationMin() const =0
These methods query, set, and watch the duration of the interval var.
virtual void SetDurationRange(int64_t mi, int64_t ma)=0
virtual int64_t StartMin() const =0
virtual bool MustBePerformed() const =0
virtual std::string name() const
Object naming.
void Reset(SequenceVar *var)
void WriteToProto(SequenceVarAssignment *sequence_var_assignment_proto) const
bool operator==(const SequenceVarElement &element) const
std::string DebugString() const
SequenceVarElement * Clone()
SequenceVarElement()
--— SequenceVarElement --—
void SetUnperformed(const std::vector< int > &unperformed)
const std::vector< int > & ForwardSequence() const
void Copy(const SequenceVarElement &element)
void SetBackwardSequence(const std::vector< int > &backward_sequence)
const std::vector< int > & BackwardSequence() const
void SetSequence(const std::vector< int > &forward_sequence, const std::vector< int > &backward_sequence, const std::vector< int > &unperformed)
void SetForwardSequence(const std::vector< int > &forward_sequence)
void LoadFromProto(const SequenceVarAssignment &sequence_var_assignment_proto)
const std::vector< int > & Unperformed() const
void RankSequence(const std::vector< int > &rank_first, const std::vector< int > &rank_last, const std::vector< int > &unperformed)
void FillSequence(std::vector< int > *rank_first, std::vector< int > *rank_last, std::vector< int > *unperformed) const
For the time being, Solver is neither MT_SAFE nor MT_HOT.
DecisionBuilder * MakeRestoreAssignment(Assignment *assignment)
DecisionBuilder * MakeStoreAssignment(Assignment *assignment)
Assignment * MakeAssignment()
This method creates an empty assignment.
bool Close()
Closes the underlying file.
bool ReadProtocolMessage(P *const proto)
bool Close()
Closes the underlying file.
bool WriteProtocolMessage(const P &proto)
CpModelProto proto
The output proto.
const std::string name
A name for logging purposes.
absl::Status Open(absl::string_view filename, absl::string_view mode, File **f, Options options)
As of 2016-01, these methods can only be used with flags = file::Defaults().
bool FindCopy(const Collection &collection, const Key &key, Value *const value)
void StoreAssignment(const VariablesAssignment &assignment, BooleanAssignment *output)
In SWIG mode, we don't want anything besides these top-level includes.
void RealLoad(const AssignmentProto &assignment_proto, Container *const container, int(AssignmentProto::*GetSize)() const, const Proto &(AssignmentProto::*GetElem)(int) const)
std::ostream & operator<<(std::ostream &out, const Assignment &assignment)
void RealDebugString(const Container &container, std::string *const out)
void SetAssignmentFromAssignment(Assignment *target_assignment, const std::vector< IntVar * > &target_vars, const Assignment *source_assignment, const std::vector< IntVar * > &source_vars)
NOLINT.
void RealSave(AssignmentProto *const assignment_proto, const Container &container, Proto *(AssignmentProto::*Add)())