21#include "absl/container/flat_hash_map.h"
22#include "absl/strings/str_format.h"
23#include "absl/strings/str_join.h"
30#include "ortools/constraint_solver/assignment.pb.h"
56 SetRange(element.min_, element.max_);
66 const IntVarAssignment& int_var_assignment_proto) {
67 min_ = int_var_assignment_proto.min();
68 max_ = int_var_assignment_proto.max();
69 if (int_var_assignment_proto.active()) {
77 if (var_ != element.var_) {
88 return min_ == element.min_ && max_ == element.max_;
92 IntVarAssignment* int_var_assignment_proto)
const {
93 int_var_assignment_proto->set_var_id(var_->
name());
94 int_var_assignment_proto->set_min(min_);
95 int_var_assignment_proto->set_max(max_);
96 int_var_assignment_proto->set_active(
Activated());
102 return absl::StrFormat(
"(%d)", min_);
104 return absl::StrFormat(
"(%d..%d)", min_, max_);
131 element->
Copy(*
this);
151 if (performed_max_ != 0LL) {
156 end_min_ = var_->
EndMin();
157 end_max_ = var_->
EndMax();
162 if (performed_max_ == performed_min_) {
165 if (performed_max_ != 0LL) {
173 const IntervalVarAssignment& interval_var_assignment_proto) {
174 start_min_ = interval_var_assignment_proto.start_min();
175 start_max_ = interval_var_assignment_proto.start_max();
176 duration_min_ = interval_var_assignment_proto.duration_min();
177 duration_max_ = interval_var_assignment_proto.duration_max();
178 end_min_ = interval_var_assignment_proto.end_min();
179 end_max_ = interval_var_assignment_proto.end_max();
180 performed_min_ = interval_var_assignment_proto.performed_min();
181 performed_max_ = interval_var_assignment_proto.performed_max();
182 if (interval_var_assignment_proto.active()) {
190 IntervalVarAssignment* interval_var_assignment_proto)
const {
191 interval_var_assignment_proto->set_var_id(var_->
name());
192 interval_var_assignment_proto->set_start_min(start_min_);
193 interval_var_assignment_proto->set_start_max(start_max_);
194 interval_var_assignment_proto->set_duration_min(duration_min_);
195 interval_var_assignment_proto->set_duration_max(duration_max_);
196 interval_var_assignment_proto->set_end_min(end_min_);
197 interval_var_assignment_proto->set_end_max(end_max_);
198 interval_var_assignment_proto->set_performed_min(performed_min_);
199 interval_var_assignment_proto->set_performed_max(performed_max_);
200 interval_var_assignment_proto->set_active(
Activated());
206 absl::StrAppendFormat(&out,
"(start = %d", start_min_);
207 if (start_max_ != start_min_) {
208 absl::StrAppendFormat(&out,
"..%d", start_max_);
210 absl::StrAppendFormat(&out,
", duration = %d", duration_min_);
211 if (duration_max_ != duration_min_) {
212 absl::StrAppendFormat(&out,
"..%d", duration_max_);
214 absl::StrAppendFormat(&out,
", status = %d", performed_min_);
215 if (performed_max_ != performed_min_) {
216 absl::StrAppendFormat(&out,
"..%d", performed_max_);
226 if (var_ != element.var_) {
237 return start_min_ == element.start_min_ && start_max_ == element.start_max_ &&
238 duration_min_ == element.duration_min_ &&
239 duration_max_ == element.duration_max_ &&
240 end_min_ == element.end_min_ && end_max_ == element.end_max_ &&
241 performed_min_ == element.performed_min_ &&
242 performed_max_ == element.performed_max_ && var_ == element.var_;
253 forward_sequence_.clear();
254 backward_sequence_.clear();
255 unperformed_.clear();
260 element->
Copy(*
this);
265 forward_sequence_ = element.forward_sequence_;
266 backward_sequence_ = element.backward_sequence_;
267 unperformed_ = element.unperformed_;
277 var_->
FillSequence(&forward_sequence_, &backward_sequence_, &unperformed_);
281 var_->
RankSequence(forward_sequence_, backward_sequence_, unperformed_);
285 const SequenceVarAssignment& sequence_var_assignment_proto) {
286 for (
const int32_t forward_sequence :
287 sequence_var_assignment_proto.forward_sequence()) {
288 forward_sequence_.push_back(forward_sequence);
290 for (
const int32_t backward_sequence :
291 sequence_var_assignment_proto.backward_sequence()) {
292 backward_sequence_.push_back(backward_sequence);
294 for (
const int32_t unperformed :
295 sequence_var_assignment_proto.unperformed()) {
296 unperformed_.push_back(unperformed);
298 if (sequence_var_assignment_proto.active()) {
303 DCHECK(CheckClassInvariants());
307 SequenceVarAssignment* sequence_var_assignment_proto)
const {
308 sequence_var_assignment_proto->set_var_id(var_->
name());
309 sequence_var_assignment_proto->set_active(
Activated());
310 for (
const int forward_sequence : forward_sequence_) {
311 sequence_var_assignment_proto->add_forward_sequence(forward_sequence);
313 for (
const int backward_sequence : backward_sequence_) {
314 sequence_var_assignment_proto->add_backward_sequence(backward_sequence);
316 for (
const int unperformed : unperformed_) {
317 sequence_var_assignment_proto->add_unperformed(unperformed);
323 return absl::StrFormat(
"[forward %s, backward %s, unperformed [%s]]",
324 absl::StrJoin(forward_sequence_,
" -> "),
325 absl::StrJoin(backward_sequence_,
" -> "),
326 absl::StrJoin(unperformed_,
", "));
333 if (var_ != element.var_) {
344 return forward_sequence_ == element.forward_sequence_ &&
345 backward_sequence_ == element.backward_sequence_ &&
346 unperformed_ == element.unperformed_;
350 return forward_sequence_;
354 return backward_sequence_;
362 const std::vector<int>& backward_sequence,
363 const std::vector<int>& unperformed) {
364 forward_sequence_ = forward_sequence;
365 backward_sequence_ = backward_sequence;
366 unperformed_ = unperformed;
367 DCHECK(CheckClassInvariants());
371 const std::vector<int>& forward_sequence) {
372 forward_sequence_ = forward_sequence;
376 const std::vector<int>& backward_sequence) {
377 backward_sequence_ = backward_sequence;
381 unperformed_ = unperformed;
384bool SequenceVarElement::CheckClassInvariants() {
385 absl::flat_hash_set<int> visited;
386 for (
const int forward_sequence : forward_sequence_) {
387 if (visited.contains(forward_sequence)) {
390 visited.insert(forward_sequence);
392 for (
const int backward_sequence : backward_sequence_) {
393 if (visited.contains(backward_sequence)) {
396 visited.insert(backward_sequence);
398 for (
const int unperformed : unperformed_) {
399 if (visited.contains(unperformed)) {
402 visited.insert(unperformed);
411 int_var_container_(copy->int_var_container_),
412 interval_var_container_(copy->interval_var_container_),
413 sequence_var_container_(copy->sequence_var_container_),
414 objective_element_(copy->objective_element_) {}
422 objective_element_.
Reset(
nullptr);
423 int_var_container_.
Clear();
424 interval_var_container_.
Clear();
425 sequence_var_container_.
Clear();
429 int_var_container_.
Store();
430 interval_var_container_.
Store();
431 sequence_var_container_.
Store();
433 objective_element_.
Store();
440 interval_var_container_.
Restore();
441 sequence_var_container_.
Restore();
447template <
class V,
class E>
449 absl::flat_hash_map<std::string, E*>* id_to_element_map) {
450 CHECK(id_to_element_map !=
nullptr);
451 id_to_element_map->clear();
452 for (
int i = 0; i < container->
Size(); ++i) {
454 const V*
const var = element->
Var();
457 LOG(
INFO) <<
"Cannot save/load variables with empty name"
458 <<
"; variable will be ignored";
459 }
else if (id_to_element_map->contains(
name)) {
460 LOG(
INFO) <<
"Cannot save/load variables with duplicate names: " <<
name
461 <<
"; variable will be ignored";
463 (*id_to_element_map)[
name] = element;
468template <
class E,
class P>
469void LoadElement(
const absl::flat_hash_map<std::string, E*>& id_to_element_map,
471 const std::string& var_id =
proto.var_id();
472 CHECK(!var_id.empty());
473 E* element =
nullptr;
475 element->LoadFromProto(
proto);
477 LOG(
INFO) <<
"Variable " << var_id
478 <<
" not in assignment; skipping variable";
487 LOG(
INFO) <<
"Cannot open " << filename;
495 AssignmentProto assignment_proto;
498 LOG(
INFO) <<
"No assignment found in " <<
file->filename();
501 Load(assignment_proto);
502 return reader.
Close();
505template <
class Var,
class Element,
class Proto,
class Container>
506void RealLoad(
const AssignmentProto& assignment_proto,
507 Container*
const container,
508 int (AssignmentProto::*GetSize)()
const,
509 const Proto& (AssignmentProto::*GetElem)(
int)
const) {
510 bool fast_load = (container->Size() == (assignment_proto.*GetSize)());
511 for (
int i = 0; fast_load && i < (assignment_proto.*GetSize)(); ++i) {
512 Element*
const element = container->MutableElement(i);
513 const Proto&
proto = (assignment_proto.*GetElem)(i);
514 if (element->Var()->name() ==
proto.var_id()) {
515 element->LoadFromProto(
proto);
521 absl::flat_hash_map<std::string, Element*> id_to_element_map;
522 IdToElementMap<Var, Element>(container, &id_to_element_map);
523 for (
int i = 0; i < (assignment_proto.*GetSize)(); ++i) {
524 LoadElement<Element, Proto>(id_to_element_map,
525 (assignment_proto.*GetElem)(i));
531 RealLoad<IntVar, IntVarElement, IntVarAssignment, IntContainer>(
532 assignment_proto, &int_var_container_,
533 &AssignmentProto::int_var_assignment_size,
534 &AssignmentProto::int_var_assignment);
537 &AssignmentProto::interval_var_assignment_size,
538 &AssignmentProto::interval_var_assignment);
541 &AssignmentProto::sequence_var_assignment_size,
542 &AssignmentProto::sequence_var_assignment);
543 if (assignment_proto.has_objective()) {
544 const IntVarAssignment& objective = assignment_proto.objective();
545 const std::string& objective_id = objective.var_id();
546 CHECK(!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;
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();
592 RealSave<IntVar, IntVarElement, IntVarAssignment, IntContainer>(
593 assignment_proto, int_var_container_,
594 &AssignmentProto::add_int_var_assignment);
597 &AssignmentProto::add_interval_var_assignment);
600 &AssignmentProto::add_sequence_var_assignment);
603 const std::string&
name = objective->
name();
605 IntVarAssignment* objective = assignment_proto->mutable_objective();
606 objective->set_var_id(
name);
609 objective->set_min(obj_min);
610 objective->set_max(obj_max);
616template <
class Container,
class Element>
618 for (
const Element& element : container.elements()) {
619 if (element.Var() !=
nullptr) {
620 absl::StrAppendFormat(out,
"%s %s | ", element.Var()->name(),
621 element.DebugString());
627 std::string out =
"Assignment(";
628 RealDebugString<IntContainer, IntVarElement>(int_var_container_, &out);
629 RealDebugString<IntervalContainer, IntervalVarElement>(
630 interval_var_container_, &out);
631 RealDebugString<SequenceContainer, SequenceVarElement>(
632 sequence_var_container_, &out);
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) {
880 objective_element_.
Reset(v);
887 return objective_element_.
Min();
894 return objective_element_.
Max();
901 return objective_element_.
Value();
908 return objective_element_.
Bound();
915 objective_element_.
SetMin(m);
921 objective_element_.
SetMax(m);
1006 interval_var_container_.
CopyIntersection(assignment->interval_var_container_);
1007 sequence_var_container_.
CopyIntersection(assignment->sequence_var_container_);
1008 if (objective_element_.
Var() == assignment->objective_element_.
Var()) {
1009 objective_element_ = assignment->objective_element_;
1015 int_var_container_.
Copy(assignment->int_var_container_);
1016 interval_var_container_.
Copy(assignment->interval_var_container_);
1017 sequence_var_container_.
Copy(assignment->sequence_var_container_);
1018 objective_element_ = assignment->objective_element_;
1022 const std::vector<IntVar*>& target_vars,
1024 const std::vector<IntVar*>& source_vars) {
1025 const int vars_size = target_vars.size();
1026 CHECK_EQ(source_vars.size(), vars_size);
1027 CHECK(target_assignment !=
nullptr);
1029 target_assignment->
Clear();
1030 const Solver*
const target_solver = target_assignment->
solver();
1031 const Solver*
const source_solver = source_assignment->
solver();
1037 target_assignment->
Add(target_var)
1052 explicit RestoreAssignment(
Assignment* assignment)
1053 : assignment_(assignment) {}
1055 ~RestoreAssignment()
override {}
1057 Decision* Next(Solver*
const solver)
override {
1058 assignment_->Restore();
1062 std::string DebugString()
const override {
return "RestoreAssignment"; }
1065 Assignment*
const assignment_;
1070 explicit StoreAssignment(Assignment* assignment) : assignment_(assignment) {}
1072 ~StoreAssignment()
override {}
1074 Decision* Next(Solver*
const solver)
override {
1075 assignment_->Store();
1079 std::string DebugString()
const override {
return "StoreAssignment"; }
1082 Assignment*
const assignment_;
1087 return RevAlloc(
new RestoreAssignment(assignment));
#define CHECK_EQ(val1, val2)
#define DCHECK(condition)
bool Contains(const V *const var) const
const E & Element(const V *const var) const
void Copy(const AssignmentContainer< V, E > &container)
Copies all the elements of 'container' to this container, clearing its previous content.
E * MutableElement(const V *const var)
void CopyIntersection(const AssignmentContainer< V, E > &container)
Copies the elements of 'container' which are already in the calling container.
E * FastAdd(V *var)
Adds element without checking its presence in the container.
An Assignment is a variable -> domains mapping, used to report solutions to the user.
bool ActivatedObjective() const
const std::vector< int > & Unperformed(const SequenceVar *const var) const
void SetForwardSequence(const SequenceVar *const var, const std::vector< int > &forward_sequence)
void SetStartRange(const IntervalVar *const var, int64_t mi, int64_t ma)
void Deactivate(const IntVar *const var)
int64_t EndMin(const IntervalVar *const var) const
int64_t PerformedMin(const IntervalVar *const var) const
int64_t EndMax(const IntervalVar *const var) const
void SetBackwardSequence(const SequenceVar *const var, const std::vector< int > &backward_sequence)
int64_t StartMax(const IntervalVar *const var) const
const std::vector< int > & BackwardSequence(const SequenceVar *const var) const
void SetStartMin(const IntervalVar *const var, int64_t m)
int64_t DurationMin(const IntervalVar *const var) const
int64_t EndValue(const IntervalVar *const var) const
int64_t ObjectiveMax() const
Assignment(Solver *const s)
void SetRange(const IntVar *const var, int64_t l, int64_t u)
int64_t StartValue(const IntervalVar *const var) const
void SetObjectiveValue(int64_t value)
IntVar * Objective() const
void SetObjectiveMax(int64_t m)
bool Load(const std::string &filename)
Loads an assignment from a file; does not add variables to the assignment (only the variables contain...
void SetMax(const IntVar *const var, int64_t m)
void SetDurationMin(const IntervalVar *const var, int64_t m)
int64_t PerformedValue(const IntervalVar *const var) const
int64_t DurationMax(const IntervalVar *const var) const
bool Contains(const IntVar *const var) const
void SetEndRange(const IntervalVar *const var, int64_t mi, int64_t ma)
int64_t ObjectiveValue() const
bool Activated(const IntVar *const var) const
bool Save(const std::string &filename) const
Saves the assignment to a file.
void SetPerformedRange(const IntervalVar *const var, int64_t mi, int64_t ma)
int64_t DurationValue(const IntervalVar *const var) const
const std::vector< int > & ForwardSequence(const SequenceVar *const var) const
bool HasObjective() const
void SetDurationRange(const IntervalVar *const var, int64_t mi, int64_t ma)
void AddObjective(IntVar *const v)
void SetEndMin(const IntervalVar *const var, int64_t m)
void SetValue(const IntVar *const var, int64_t value)
void Activate(const IntVar *const var)
void DeactivateObjective()
int64_t ObjectiveMin() const
void SetDurationMax(const IntervalVar *const var, int64_t m)
int64_t Max(const IntVar *const var) const
int64_t Value(const IntVar *const var) const
void SetStartMax(const IntervalVar *const var, int64_t m)
void SetPerformedMax(const IntervalVar *const var, int64_t m)
void SetUnperformed(const SequenceVar *const var, const std::vector< int > &unperformed)
void SetObjectiveRange(int64_t l, int64_t u)
void SetMin(const IntVar *const var, int64_t m)
int64_t PerformedMax(const IntervalVar *const var) const
void SetObjectiveMin(int64_t m)
void SetDurationValue(const IntervalVar *const var, int64_t value)
void CopyIntersection(const Assignment *assignment)
Copies the intersection of the two assignments to the current assignment.
void SetEndValue(const IntervalVar *const var, int64_t value)
bool ObjectiveBound() const
void SetStartValue(const IntervalVar *const var, int64_t value)
void SetEndMax(const IntervalVar *const var, int64_t m)
void SetPerformedValue(const IntervalVar *const var, int64_t value)
void SetPerformedMin(const IntervalVar *const var, int64_t m)
void Copy(const Assignment *assignment)
Copies 'assignment' to the current assignment, clearing its previous content.
void SetSequence(const SequenceVar *const var, const std::vector< int > &forward_sequence, const std::vector< int > &backward_sequence, const std::vector< int > &unperformed)
IntVarElement * Add(IntVar *const var)
bool Bound(const IntVar *const var) const
std::string DebugString() const override
int64_t Min(const IntVar *const var) const
IntVarElement * FastAdd(IntVar *const var)
Adds without checking if variable has been previously added.
int64_t StartMin(const IntervalVar *const var) const
A DecisionBuilder is responsible for creating the search tree.
void Copy(const IntVarElement &element)
void Reset(IntVar *const var)
bool operator==(const IntVarElement &element) const
std::string DebugString() const
void WriteToProto(IntVarAssignment *int_var_assignment_proto) const
void LoadFromProto(const IntVarAssignment &int_var_assignment_proto)
void SetRange(int64_t l, int64_t u)
The class IntVar is a subset of IntExpr.
IntVar * Var() override
Creates a variable from the expression.
IntervalVarElement * Clone()
void LoadFromProto(const IntervalVarAssignment &interval_var_assignment_proto)
int64_t StartValue() const
void SetDurationRange(int64_t mi, int64_t ma)
void Reset(IntervalVar *const var)
int64_t PerformedMax() const
int64_t DurationMax() const
void SetPerformedRange(int64_t mi, int64_t ma)
int64_t DurationMin() const
void SetEndRange(int64_t mi, int64_t ma)
void SetEndValue(int64_t v)
void SetEndMin(int64_t m)
void SetDurationValue(int64_t v)
void SetPerformedMin(int64_t m)
void SetStartRange(int64_t mi, int64_t ma)
void SetDurationMin(int64_t m)
void SetEndMax(int64_t m)
std::string DebugString() const
void SetStartMin(int64_t m)
void SetStartMax(int64_t m)
int64_t PerformedMin() const
void SetPerformedValue(int64_t v)
int64_t PerformedValue() const
bool operator==(const IntervalVarElement &element) const
void Copy(const IntervalVarElement &element)
void WriteToProto(IntervalVarAssignment *interval_var_assignment_proto) const
void SetPerformedMax(int64_t m)
void SetDurationMax(int64_t m)
void SetStartValue(int64_t v)
int64_t DurationValue() const
Interval variables are often used in scheduling.
virtual int64_t DurationMax() const =0
virtual int64_t DurationMin() const =0
These methods query, set, and watch the duration of the interval var.
virtual void SetPerformed(bool val)=0
virtual void SetStartRange(int64_t mi, int64_t ma)=0
virtual bool MustBePerformed() const =0
These methods query, set, and watch the performed status of the interval var.
virtual int64_t EndMin() const =0
These methods query, set, and watch the end position of the interval var.
virtual int64_t StartMin() const =0
These methods query, set, and watch the start position of the interval var.
virtual void SetDurationRange(int64_t mi, int64_t ma)=0
virtual int64_t EndMax() const =0
virtual bool MayBePerformed() const =0
virtual void SetEndRange(int64_t mi, int64_t ma)=0
virtual int64_t StartMax() const =0
virtual std::string name() const
Object naming.
void FreezeQueue()
This method freezes the propagation queue.
void UnfreezeQueue()
This method unfreezes the propagation queue.
The SequenceVarElement stores a partial representation of ranked interval variables in the underlying...
void SetSequence(const std::vector< int > &forward_sequence, const std::vector< int > &backward_sequence, const std::vector< int > &unperformed)
void Reset(SequenceVar *const var)
bool operator==(const SequenceVarElement &element) const
const std::vector< int > & BackwardSequence() const
void SetBackwardSequence(const std::vector< int > &backward_sequence)
const std::vector< int > & Unperformed() const
void SetUnperformed(const std::vector< int > &unperformed)
std::string DebugString() const
SequenceVarElement * Clone()
const std::vector< int > & ForwardSequence() const
void Copy(const SequenceVarElement &element)
void LoadFromProto(const SequenceVarAssignment &sequence_var_assignment_proto)
void WriteToProto(SequenceVarAssignment *sequence_var_assignment_proto) const
void SetForwardSequence(const std::vector< int > &forward_sequence)
A sequence variable is a variable whose domain is a set of possible orderings of the interval variabl...
void FillSequence(std::vector< int > *const rank_first, std::vector< int > *const rank_last, std::vector< int > *const unperformed) const
Clears 'rank_first' and 'rank_last', and fills them with the intervals in the order of the ranks.
void RankSequence(const std::vector< int > &rank_first, const std::vector< int > &rank_last, const std::vector< int > &unperformed)
Applies the following sequence of ranks, ranks first, then rank last.
Assignment * MakeAssignment()
This method creates an empty assignment.
DecisionBuilder * MakeStoreAssignment(Assignment *assignment)
Returns a DecisionBuilder which stores an Assignment (calls void Assignment::Store())
DecisionBuilder * MakeRestoreAssignment(Assignment *assignment)
Returns a DecisionBuilder which restores an Assignment (calls void Assignment::Restore())
T * RevAlloc(T *object)
Registers the given object as being reversible.
bool ReadProtocolMessage(P *const proto)
bool WriteProtocolMessage(const P &proto)
absl::Status Open(const absl::string_view &filename, const absl::string_view &mode, File **f, int flags)
bool FindCopy(const Collection &collection, const Key &key, Value *const value)
void StoreAssignment(const VariablesAssignment &assignment, BooleanAssignment *output)
Collection of objects used to extend the Constraint Solver library.
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 SetAssignmentFromAssignment(Assignment *target_assignment, const std::vector< IntVar * > &target_vars, const Assignment *source_assignment, const std::vector< IntVar * > &source_vars)
NOLINT.
void RealDebugString(const Container &container, std::string *const out)
void RealSave(AssignmentProto *const assignment_proto, const Container &container, Proto *(AssignmentProto::*Add)())