OR-Tools  9.3
constraint_solver/assignment.cc
Go to the documentation of this file.
1// Copyright 2010-2021 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14#include <stddef.h>
15
16#include <cstdint>
17#include <limits>
18#include <string>
19#include <vector>
20
21#include "absl/container/flat_hash_map.h"
22#include "absl/strings/str_format.h"
23#include "absl/strings/str_join.h"
24#include "ortools/base/file.h"
25#include "ortools/base/hash.h"
30#include "ortools/constraint_solver/assignment.pb.h"
32
33namespace operations_research {
34
35// ----------------- Solutions ------------------------
36
37// ----- IntVarElement -----
38
40
42
44 var_ = var;
47}
48
50 IntVarElement* element = new IntVarElement;
51 element->Copy(*this);
52 return element;
53}
54
55void IntVarElement::Copy(const IntVarElement& element) {
56 SetRange(element.min_, element.max_);
57 var_ = element.var_;
58 if (element.Activated()) {
59 Activate();
60 } else {
61 Deactivate();
62 }
63}
64
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()) {
70 Activate();
71 } else {
72 Deactivate();
73 }
74}
75
76bool IntVarElement::operator==(const IntVarElement& element) const {
77 if (var_ != element.var_) {
78 return false;
79 }
80 if (Activated() != element.Activated()) {
81 return false;
82 }
83 if (!Activated() && !element.Activated()) {
84 // If both elements are deactivated, then they are equal, regardless of
85 // their min and max.
86 return true;
87 }
88 return min_ == element.min_ && max_ == element.max_;
89}
90
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());
97}
98
99std::string IntVarElement::DebugString() const {
100 if (Activated()) {
101 if (min_ == max_) {
102 return absl::StrFormat("(%d)", min_);
103 } else {
104 return absl::StrFormat("(%d..%d)", min_, max_);
105 }
106 } else {
107 return "(...)";
108 }
109}
110
111// ----- IntervalVarElement -----
112
114
116
118 var_ = var;
121 duration_min_ = std::numeric_limits<int64_t>::min();
122 duration_max_ = std::numeric_limits<int64_t>::max();
125 performed_min_ = 0;
126 performed_max_ = 1;
127}
128
131 element->Copy(*this);
132 return element;
133}
134
136 SetStartRange(element.start_min_, element.start_max_);
137 SetDurationRange(element.duration_min_, element.duration_max_);
138 SetEndRange(element.end_min_, element.end_max_);
139 SetPerformedRange(element.performed_min_, element.performed_max_);
140 var_ = element.var_;
141 if (element.Activated()) {
142 Activate();
143 } else {
144 Deactivate();
145 }
146}
147
149 performed_min_ = static_cast<int64_t>(var_->MustBePerformed());
150 performed_max_ = static_cast<int64_t>(var_->MayBePerformed());
151 if (performed_max_ != 0LL) {
152 start_min_ = var_->StartMin();
153 start_max_ = var_->StartMax();
154 duration_min_ = var_->DurationMin();
155 duration_max_ = var_->DurationMax();
156 end_min_ = var_->EndMin();
157 end_max_ = var_->EndMax();
158 }
159}
160
162 if (performed_max_ == performed_min_) {
163 var_->SetPerformed(performed_min_);
164 }
165 if (performed_max_ != 0LL) {
166 var_->SetStartRange(start_min_, start_max_);
167 var_->SetDurationRange(duration_min_, duration_max_);
168 var_->SetEndRange(end_min_, end_max_);
169 }
170}
171
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()) {
183 Activate();
184 } else {
185 Deactivate();
186 }
187}
188
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());
201}
202
204 if (Activated()) {
205 std::string out;
206 absl::StrAppendFormat(&out, "(start = %d", start_min_);
207 if (start_max_ != start_min_) {
208 absl::StrAppendFormat(&out, "..%d", start_max_);
209 }
210 absl::StrAppendFormat(&out, ", duration = %d", duration_min_);
211 if (duration_max_ != duration_min_) {
212 absl::StrAppendFormat(&out, "..%d", duration_max_);
213 }
214 absl::StrAppendFormat(&out, ", status = %d", performed_min_);
215 if (performed_max_ != performed_min_) {
216 absl::StrAppendFormat(&out, "..%d", performed_max_);
217 }
218 out.append(")");
219 return out;
220 } else {
221 return "(...)";
222 }
223}
224
226 if (var_ != element.var_) {
227 return false;
228 }
229 if (Activated() != element.Activated()) {
230 return false;
231 }
232 if (!Activated() && !element.Activated()) {
233 // If both elements are deactivated, then they are equal, regardless of
234 // their other fields.
235 return true;
236 }
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_;
243}
244
245// ----- SequenceVarElement -----
246
248
250
252 var_ = var;
253 forward_sequence_.clear();
254 backward_sequence_.clear();
255 unperformed_.clear();
256}
257
259 SequenceVarElement* const element = new SequenceVarElement;
260 element->Copy(*this);
261 return element;
262}
263
265 forward_sequence_ = element.forward_sequence_;
266 backward_sequence_ = element.backward_sequence_;
267 unperformed_ = element.unperformed_;
268 var_ = element.var_;
269 if (element.Activated()) {
270 Activate();
271 } else {
272 Deactivate();
273 }
274}
275
277 var_->FillSequence(&forward_sequence_, &backward_sequence_, &unperformed_);
278}
279
281 var_->RankSequence(forward_sequence_, backward_sequence_, unperformed_);
282}
283
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);
289 }
290 for (const int32_t backward_sequence :
291 sequence_var_assignment_proto.backward_sequence()) {
292 backward_sequence_.push_back(backward_sequence);
293 }
294 for (const int32_t unperformed :
295 sequence_var_assignment_proto.unperformed()) {
296 unperformed_.push_back(unperformed);
297 }
298 if (sequence_var_assignment_proto.active()) {
299 Activate();
300 } else {
301 Deactivate();
302 }
303 DCHECK(CheckClassInvariants());
304}
305
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);
312 }
313 for (const int backward_sequence : backward_sequence_) {
314 sequence_var_assignment_proto->add_backward_sequence(backward_sequence);
315 }
316 for (const int unperformed : unperformed_) {
317 sequence_var_assignment_proto->add_unperformed(unperformed);
318 }
319}
320
322 if (Activated()) {
323 return absl::StrFormat("[forward %s, backward %s, unperformed [%s]]",
324 absl::StrJoin(forward_sequence_, " -> "),
325 absl::StrJoin(backward_sequence_, " -> "),
326 absl::StrJoin(unperformed_, ", "));
327 } else {
328 return "(...)";
329 }
330}
331
333 if (var_ != element.var_) {
334 return false;
335 }
336 if (Activated() != element.Activated()) {
337 return false;
338 }
339 if (!Activated() && !element.Activated()) {
340 // If both elements are deactivated, then they are equal, regardless of
341 // their other fields.
342 return true;
343 }
344 return forward_sequence_ == element.forward_sequence_ &&
345 backward_sequence_ == element.backward_sequence_ &&
346 unperformed_ == element.unperformed_;
347}
348
349const std::vector<int>& SequenceVarElement::ForwardSequence() const {
350 return forward_sequence_;
351}
352
353const std::vector<int>& SequenceVarElement::BackwardSequence() const {
354 return backward_sequence_;
355}
356
357const std::vector<int>& SequenceVarElement::Unperformed() const {
358 return unperformed_;
359}
360
361void SequenceVarElement::SetSequence(const std::vector<int>& forward_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());
368}
369
371 const std::vector<int>& forward_sequence) {
372 forward_sequence_ = forward_sequence;
373}
374
376 const std::vector<int>& backward_sequence) {
377 backward_sequence_ = backward_sequence;
378}
379
380void SequenceVarElement::SetUnperformed(const std::vector<int>& unperformed) {
381 unperformed_ = unperformed;
382}
383
384bool SequenceVarElement::CheckClassInvariants() {
385 absl::flat_hash_set<int> visited;
386 for (const int forward_sequence : forward_sequence_) {
387 if (visited.contains(forward_sequence)) {
388 return false;
389 }
390 visited.insert(forward_sequence);
391 }
392 for (const int backward_sequence : backward_sequence_) {
393 if (visited.contains(backward_sequence)) {
394 return false;
395 }
396 visited.insert(backward_sequence);
397 }
398 for (const int unperformed : unperformed_) {
399 if (visited.contains(unperformed)) {
400 return false;
401 }
402 visited.insert(unperformed);
403 }
404 return true;
405}
406
407// ----- Assignment -----
408
410 : PropagationBaseObject(copy->solver()),
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_) {}
415
417 : PropagationBaseObject(s), objective_element_(nullptr) {}
418
420
422 objective_element_.Reset(nullptr);
423 int_var_container_.Clear();
424 interval_var_container_.Clear();
425 sequence_var_container_.Clear();
426}
427
429 int_var_container_.Store();
430 interval_var_container_.Store();
431 sequence_var_container_.Store();
432 if (HasObjective()) {
433 objective_element_.Store();
434 }
435}
436
438 FreezeQueue();
439 int_var_container_.Restore();
440 interval_var_container_.Restore();
441 sequence_var_container_.Restore();
443}
444
445namespace {
446
447template <class V, class E>
448void IdToElementMap(AssignmentContainer<V, E>* container,
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) {
453 E* const element = container->MutableElement(i);
454 const V* const var = element->Var();
455 const std::string& name = var->name();
456 if (name.empty()) {
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";
462 } else {
463 (*id_to_element_map)[name] = element;
464 }
465 }
466}
467
468template <class E, class P>
469void LoadElement(const absl::flat_hash_map<std::string, E*>& id_to_element_map,
470 const P& proto) {
471 const std::string& var_id = proto.var_id();
472 CHECK(!var_id.empty());
473 E* element = nullptr;
474 if (gtl::FindCopy(id_to_element_map, var_id, &element)) {
475 element->LoadFromProto(proto);
476 } else {
477 LOG(INFO) << "Variable " << var_id
478 << " not in assignment; skipping variable";
479 }
480}
481
482} // namespace
483
484bool Assignment::Load(const std::string& filename) {
485 File* file;
486 if (!file::Open(filename, "r", &file, file::Defaults()).ok()) {
487 LOG(INFO) << "Cannot open " << filename;
488 return false;
489 }
490 return Load(file);
491}
492
494 CHECK(file != nullptr);
495 AssignmentProto assignment_proto;
497 if (!reader.ReadProtocolMessage(&assignment_proto)) {
498 LOG(INFO) << "No assignment found in " << file->filename();
499 return false;
500 }
501 Load(assignment_proto);
502 return reader.Close();
503}
504
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);
516 } else {
517 fast_load = false;
518 }
519 }
520 if (!fast_load) {
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));
526 }
527 }
528}
529
530void Assignment::Load(const AssignmentProto& assignment_proto) {
531 RealLoad<IntVar, IntVarElement, IntVarAssignment, IntContainer>(
532 assignment_proto, &int_var_container_,
533 &AssignmentProto::int_var_assignment_size,
534 &AssignmentProto::int_var_assignment);
535 RealLoad<IntervalVar, IntervalVarElement, IntervalVarAssignment,
536 IntervalContainer>(assignment_proto, &interval_var_container_,
537 &AssignmentProto::interval_var_assignment_size,
538 &AssignmentProto::interval_var_assignment);
539 RealLoad<SequenceVar, SequenceVarElement, SequenceVarAssignment,
540 SequenceContainer>(assignment_proto, &sequence_var_container_,
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());
547 if (HasObjective() && objective_id == Objective()->name()) {
548 const int64_t obj_min = objective.min();
549 const int64_t obj_max = objective.max();
550 SetObjectiveRange(obj_min, obj_max);
551 if (objective.active()) {
553 } else {
555 }
556 }
557 }
558}
559
560bool Assignment::Save(const std::string& filename) const {
561 File* file;
562 if (!file::Open(filename, "w", &file, file::Defaults()).ok()) {
563 LOG(INFO) << "Cannot open " << filename;
564 return false;
565 }
566 return Save(file);
567}
568
570 CHECK(file != nullptr);
571 AssignmentProto assignment_proto;
572 Save(&assignment_proto);
574 return writer.WriteProtocolMessage(assignment_proto) && writer.Close();
575}
576
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();
582 const std::string& name = var->name();
583 if (!name.empty()) {
584 Proto* const var_assignment_proto = (assignment_proto->*Add)();
585 element.WriteToProto(var_assignment_proto);
586 }
587 }
588}
589
590void Assignment::Save(AssignmentProto* const assignment_proto) const {
591 assignment_proto->Clear();
592 RealSave<IntVar, IntVarElement, IntVarAssignment, IntContainer>(
593 assignment_proto, int_var_container_,
594 &AssignmentProto::add_int_var_assignment);
595 RealSave<IntervalVar, IntervalVarElement, IntervalVarAssignment,
596 IntervalContainer>(assignment_proto, interval_var_container_,
597 &AssignmentProto::add_interval_var_assignment);
598 RealSave<SequenceVar, SequenceVarElement, SequenceVarAssignment,
599 SequenceContainer>(assignment_proto, sequence_var_container_,
600 &AssignmentProto::add_sequence_var_assignment);
601 if (HasObjective()) {
602 const IntVar* objective = Objective();
603 const std::string& name = objective->name();
604 if (!name.empty()) {
605 IntVarAssignment* objective = assignment_proto->mutable_objective();
606 objective->set_var_id(name);
607 const int64_t obj_min = ObjectiveMin();
608 const int64_t obj_max = ObjectiveMax();
609 objective->set_min(obj_min);
610 objective->set_max(obj_max);
611 objective->set_active(ActivatedObjective());
612 }
613 }
614}
615
616template <class Container, class Element>
617void RealDebugString(const Container& container, std::string* const out) {
618 for (const Element& element : container.elements()) {
619 if (element.Var() != nullptr) {
620 absl::StrAppendFormat(out, "%s %s | ", element.Var()->name(),
621 element.DebugString());
622 }
623 }
624}
625
626std::string Assignment::DebugString() const {
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);
633 if (HasObjective() && objective_element_.Activated()) {
634 out += objective_element_.DebugString();
635 }
636 out += ")";
637 return out;
638}
639
641 return int_var_container_.Add(var);
642}
643
644void Assignment::Add(const std::vector<IntVar*>& vars) {
645 for (IntVar* const var : vars) {
646 Add(var);
647 }
648}
649
651 return int_var_container_.FastAdd(var);
652}
653
654int64_t Assignment::Min(const IntVar* const var) const {
655 return int_var_container_.Element(var).Min();
656}
657
658int64_t Assignment::Max(const IntVar* const var) const {
659 return int_var_container_.Element(var).Max();
660}
661
662int64_t Assignment::Value(const IntVar* const var) const {
663 return int_var_container_.Element(var).Value();
664}
665
666bool Assignment::Bound(const IntVar* const var) const {
667 return int_var_container_.Element(var).Bound();
668}
669
670void Assignment::SetMin(const IntVar* const var, int64_t m) {
671 int_var_container_.MutableElement(var)->SetMin(m);
672}
673
674void Assignment::SetMax(const IntVar* const var, int64_t m) {
675 int_var_container_.MutableElement(var)->SetMax(m);
676}
677
678void Assignment::SetRange(const IntVar* const var, int64_t l, int64_t u) {
679 int_var_container_.MutableElement(var)->SetRange(l, u);
680}
681
682void Assignment::SetValue(const IntVar* const var, int64_t value) {
683 int_var_container_.MutableElement(var)->SetValue(value);
684}
685
686// ----- Interval Var -----
687
689 return interval_var_container_.Add(var);
690}
691
692void Assignment::Add(const std::vector<IntervalVar*>& vars) {
693 for (IntervalVar* const var : vars) {
694 Add(var);
695 }
696}
697
699 return interval_var_container_.FastAdd(var);
700}
701
702int64_t Assignment::StartMin(const IntervalVar* const var) const {
703 return interval_var_container_.Element(var).StartMin();
704}
705
706int64_t Assignment::StartMax(const IntervalVar* const var) const {
707 return interval_var_container_.Element(var).StartMax();
708}
709
710int64_t Assignment::StartValue(const IntervalVar* const var) const {
711 return interval_var_container_.Element(var).StartValue();
712}
713
714int64_t Assignment::DurationMin(const IntervalVar* const var) const {
715 return interval_var_container_.Element(var).DurationMin();
716}
717
718int64_t Assignment::DurationMax(const IntervalVar* const var) const {
719 return interval_var_container_.Element(var).DurationMax();
720}
721
722int64_t Assignment::DurationValue(const IntervalVar* const var) const {
723 return interval_var_container_.Element(var).DurationValue();
724}
725
726int64_t Assignment::EndMin(const IntervalVar* const var) const {
727 return interval_var_container_.Element(var).EndMin();
728}
729
730int64_t Assignment::EndMax(const IntervalVar* const var) const {
731 return interval_var_container_.Element(var).EndMax();
732}
733
734int64_t Assignment::EndValue(const IntervalVar* const var) const {
735 return interval_var_container_.Element(var).EndValue();
736}
737
738int64_t Assignment::PerformedMin(const IntervalVar* const var) const {
739 return interval_var_container_.Element(var).PerformedMin();
740}
741
742int64_t Assignment::PerformedMax(const IntervalVar* const var) const {
743 return interval_var_container_.Element(var).PerformedMax();
744}
745
746int64_t Assignment::PerformedValue(const IntervalVar* const var) const {
747 return interval_var_container_.Element(var).PerformedValue();
748}
749
750void Assignment::SetStartMin(const IntervalVar* const var, int64_t m) {
751 interval_var_container_.MutableElement(var)->SetStartMin(m);
752}
753
754void Assignment::SetStartMax(const IntervalVar* const var, int64_t m) {
755 interval_var_container_.MutableElement(var)->SetStartMax(m);
756}
757
758void Assignment::SetStartRange(const IntervalVar* const var, int64_t mi,
759 int64_t ma) {
760 interval_var_container_.MutableElement(var)->SetStartRange(mi, ma);
761}
762
763void Assignment::SetStartValue(const IntervalVar* const var, int64_t value) {
764 interval_var_container_.MutableElement(var)->SetStartValue(value);
765}
766
767void Assignment::SetDurationMin(const IntervalVar* const var, int64_t m) {
768 interval_var_container_.MutableElement(var)->SetDurationMin(m);
769}
770
771void Assignment::SetDurationMax(const IntervalVar* const var, int64_t m) {
772 interval_var_container_.MutableElement(var)->SetDurationMax(m);
773}
774
775void Assignment::SetDurationRange(const IntervalVar* const var, int64_t mi,
776 int64_t ma) {
777 interval_var_container_.MutableElement(var)->SetDurationRange(mi, ma);
778}
779
781 interval_var_container_.MutableElement(var)->SetDurationValue(value);
782}
783
784void Assignment::SetEndMin(const IntervalVar* const var, int64_t m) {
785 interval_var_container_.MutableElement(var)->SetEndMin(m);
786}
787
788void Assignment::SetEndMax(const IntervalVar* const var, int64_t m) {
789 interval_var_container_.MutableElement(var)->SetEndMax(m);
790}
791
792void Assignment::SetEndRange(const IntervalVar* const var, int64_t mi,
793 int64_t ma) {
794 interval_var_container_.MutableElement(var)->SetEndRange(mi, ma);
795}
796
797void Assignment::SetEndValue(const IntervalVar* const var, int64_t value) {
798 interval_var_container_.MutableElement(var)->SetEndValue(value);
799}
800
801void Assignment::SetPerformedMin(const IntervalVar* const var, int64_t m) {
802 interval_var_container_.MutableElement(var)->SetPerformedMin(m);
803}
804
805void Assignment::SetPerformedMax(const IntervalVar* const var, int64_t m) {
806 interval_var_container_.MutableElement(var)->SetPerformedMax(m);
807}
808
809void Assignment::SetPerformedRange(const IntervalVar* const var, int64_t mi,
810 int64_t ma) {
811 interval_var_container_.MutableElement(var)->SetPerformedRange(mi, ma);
812}
813
815 int64_t value) {
816 interval_var_container_.MutableElement(var)->SetPerformedValue(value);
817}
818
819// ----- Sequence Var -----
820
822 return sequence_var_container_.Add(var);
823}
824
825void Assignment::Add(const std::vector<SequenceVar*>& vars) {
826 for (SequenceVar* const var : vars) {
827 Add(var);
828 }
829}
830
832 return sequence_var_container_.FastAdd(var);
833}
834
835const std::vector<int>& Assignment::ForwardSequence(
836 const SequenceVar* const var) const {
837 return sequence_var_container_.Element(var).ForwardSequence();
838}
839
840const std::vector<int>& Assignment::BackwardSequence(
841 const SequenceVar* const var) const {
842 return sequence_var_container_.Element(var).BackwardSequence();
843}
844
845const std::vector<int>& Assignment::Unperformed(
846 const SequenceVar* const var) const {
847 return sequence_var_container_.Element(var).Unperformed();
848}
849
851 const std::vector<int>& forward_sequence,
852 const std::vector<int>& backward_sequence,
853 const std::vector<int>& unperformed) {
854 sequence_var_container_.MutableElement(var)->SetSequence(
855 forward_sequence, backward_sequence, unperformed);
856}
857
859 const std::vector<int>& forward_sequence) {
860 sequence_var_container_.MutableElement(var)->SetForwardSequence(
861 forward_sequence);
862}
863
865 const SequenceVar* const var, const std::vector<int>& backward_sequence) {
866 sequence_var_container_.MutableElement(var)->SetBackwardSequence(
867 backward_sequence);
868}
869
871 const std::vector<int>& unperformed) {
872 sequence_var_container_.MutableElement(var)->SetUnperformed(unperformed);
873}
874
875// ----- Objective -----
876
878 // Check if adding twice an objective to the solution.
880 objective_element_.Reset(v);
881}
882
883IntVar* Assignment::Objective() const { return objective_element_.Var(); }
884
886 if (HasObjective()) {
887 return objective_element_.Min();
888 }
889 return 0;
890}
891
893 if (HasObjective()) {
894 return objective_element_.Max();
895 }
896 return 0;
897}
898
900 if (HasObjective()) {
901 return objective_element_.Value();
902 }
903 return 0;
904}
905
907 if (HasObjective()) {
908 return objective_element_.Bound();
909 }
910 return true;
911}
912
914 if (HasObjective()) {
915 objective_element_.SetMin(m);
916 }
917}
918
920 if (HasObjective()) {
921 objective_element_.SetMax(m);
922 }
923}
924
925void Assignment::SetObjectiveRange(int64_t l, int64_t u) {
926 if (HasObjective()) {
927 objective_element_.SetRange(l, u);
928 }
929}
930
932 if (HasObjective()) {
933 objective_element_.SetValue(value);
934 }
935}
936
937void Assignment::Activate(const IntVar* const var) {
938 int_var_container_.MutableElement(var)->Activate();
939}
940
942 int_var_container_.MutableElement(var)->Deactivate();
943}
944
945bool Assignment::Activated(const IntVar* const var) const {
946 return int_var_container_.Element(var).Activated();
947}
948
950 interval_var_container_.MutableElement(var)->Activate();
951}
952
954 interval_var_container_.MutableElement(var)->Deactivate();
955}
956
957bool Assignment::Activated(const IntervalVar* const var) const {
958 return interval_var_container_.Element(var).Activated();
959}
960
962 sequence_var_container_.MutableElement(var)->Activate();
963}
964
966 sequence_var_container_.MutableElement(var)->Deactivate();
967}
968
969bool Assignment::Activated(const SequenceVar* const var) const {
970 return sequence_var_container_.Element(var).Activated();
971}
972
974 if (HasObjective()) {
975 objective_element_.Activate();
976 }
977}
978
980 if (HasObjective()) {
981 objective_element_.Deactivate();
982 }
983}
984
986 if (HasObjective()) {
987 return objective_element_.Activated();
988 }
989 return true;
990}
991
992bool Assignment::Contains(const IntVar* const var) const {
993 return int_var_container_.Contains(var);
994}
995
996bool Assignment::Contains(const IntervalVar* const var) const {
997 return interval_var_container_.Contains(var);
998}
999
1000bool Assignment::Contains(const SequenceVar* const var) const {
1001 return sequence_var_container_.Contains(var);
1002}
1003
1005 int_var_container_.CopyIntersection(assignment->int_var_container_);
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_;
1010 }
1011}
1012
1013void Assignment::Copy(const Assignment* assignment) {
1014 Clear();
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_;
1019}
1020
1022 const std::vector<IntVar*>& target_vars,
1023 const Assignment* source_assignment,
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);
1028
1029 target_assignment->Clear();
1030 const Solver* const target_solver = target_assignment->solver();
1031 const Solver* const source_solver = source_assignment->solver();
1032 for (int index = 0; index < vars_size; index++) {
1033 IntVar* target_var = target_vars[index];
1034 CHECK_EQ(target_var->solver(), target_solver);
1035 IntVar* source_var = source_vars[index];
1036 CHECK_EQ(source_var->solver(), source_solver);
1037 target_assignment->Add(target_var)
1038 ->SetValue(source_assignment->Value(source_var));
1039 }
1040}
1041
1043
1045 return RevAlloc(new Assignment(a));
1046}
1047
1048// ----- Storing and Restoring assignments -----
1049namespace {
1050class RestoreAssignment : public DecisionBuilder {
1051 public:
1052 explicit RestoreAssignment(Assignment* assignment)
1053 : assignment_(assignment) {}
1054
1055 ~RestoreAssignment() override {}
1056
1057 Decision* Next(Solver* const solver) override {
1058 assignment_->Restore();
1059 return nullptr;
1060 }
1061
1062 std::string DebugString() const override { return "RestoreAssignment"; }
1063
1064 private:
1065 Assignment* const assignment_;
1066};
1067
1068class StoreAssignment : public DecisionBuilder {
1069 public:
1070 explicit StoreAssignment(Assignment* assignment) : assignment_(assignment) {}
1071
1072 ~StoreAssignment() override {}
1073
1074 Decision* Next(Solver* const solver) override {
1075 assignment_->Store();
1076 return nullptr;
1077 }
1078
1079 std::string DebugString() const override { return "StoreAssignment"; }
1080
1081 private:
1082 Assignment* const assignment_;
1083};
1084} // namespace
1085
1087 return RevAlloc(new RestoreAssignment(assignment));
1088}
1089
1091 return RevAlloc(new StoreAssignment(assignment));
1092}
1093
1094std::ostream& operator<<(std::ostream& out, const Assignment& assignment) {
1095 return out << assignment.DebugString();
1096}
1097
1098} // namespace operations_research
int64_t max
Definition: alldiff_cst.cc:140
int64_t min
Definition: alldiff_cst.cc:139
#define CHECK(condition)
Definition: base/logging.h:495
#define CHECK_EQ(val1, val2)
Definition: base/logging.h:703
#define LOG(severity)
Definition: base/logging.h:420
#define DCHECK(condition)
Definition: base/logging.h:890
Definition: base/file.h:33
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.
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.
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
void SetRange(const IntVar *const var, int64_t l, int64_t u)
int64_t StartValue(const IntervalVar *const var) const
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)
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
void SetDurationRange(const IntervalVar *const var, int64_t mi, int64_t ma)
void SetEndMin(const IntervalVar *const var, int64_t m)
void SetValue(const IntVar *const var, int64_t value)
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 SetMin(const IntVar *const var, int64_t m)
int64_t PerformedMax(const IntervalVar *const var) const
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)
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
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)
bool operator==(const IntVarElement &element) 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.
void LoadFromProto(const IntervalVarAssignment &interval_var_assignment_proto)
void SetDurationRange(int64_t mi, int64_t ma)
void SetPerformedRange(int64_t mi, int64_t ma)
void SetEndRange(int64_t mi, int64_t ma)
void SetStartRange(int64_t mi, int64_t ma)
bool operator==(const IntervalVarElement &element) const
void Copy(const IntervalVarElement &element)
void WriteToProto(IntervalVarAssignment *interval_var_assignment_proto) 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)
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)
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)
Definition: recordio.h:91
bool WriteProtocolMessage(const P &proto)
Definition: recordio.h:41
int64_t a
CpModelProto proto
const std::string name
int64_t value
IntVar * var
Definition: expr_array.cc:1874
int index
const int INFO
Definition: log_severity.h:31
int Defaults()
Definition: base/file.h:120
absl::Status Open(const absl::string_view &filename, const absl::string_view &mode, File **f, int flags)
Definition: base/file.cc:142
bool FindCopy(const Collection &collection, const Key &key, Value *const value)
Definition: map_util.h:185
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)())