Google OR-Tools v9.14
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
assignment.cc
Go to the documentation of this file.
1// Copyright 2010-2025 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 <ostream>
19#include <string>
20#include <vector>
21
22#include "absl/container/flat_hash_map.h"
23#include "absl/strings/str_format.h"
24#include "absl/strings/str_join.h"
25#include "absl/strings/string_view.h"
26#include "ortools/base/file.h"
32
33namespace operations_research {
34
35// ----------------- Solutions ------------------------
36
37// ----- IntVarElement -----
38
40
42
43void IntVarElement::Reset(IntVar* const var) {
44 var_ = var;
45 min_ = std::numeric_limits<int64_t>::min();
46 max_ = std::numeric_limits<int64_t>::max();
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;
119 start_min_ = std::numeric_limits<int64_t>::min();
120 start_max_ = std::numeric_limits<int64_t>::max();
121 duration_min_ = std::numeric_limits<int64_t>::min();
122 duration_max_ = std::numeric_limits<int64_t>::max();
123 end_min_ = std::numeric_limits<int64_t>::min();
124 end_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_elements_(copy->objective_elements_) {}
415
418
420 objective_elements_.clear();
421 int_var_container_.Clear();
422 interval_var_container_.Clear();
423 sequence_var_container_.Clear();
424}
425
427 int_var_container_.Store();
428 interval_var_container_.Store();
429 sequence_var_container_.Store();
430 for (IntVarElement& objective_element : objective_elements_) {
431 objective_element.Store();
432 }
433}
434
436 FreezeQueue();
437 int_var_container_.Restore();
438 interval_var_container_.Restore();
439 sequence_var_container_.Restore();
441}
442
443namespace {
444
445template <class V, class E>
446void IdToElementMap(AssignmentContainer<V, E>* container,
447 absl::flat_hash_map<std::string, E*>* id_to_element_map) {
448 CHECK(id_to_element_map != nullptr);
449 id_to_element_map->clear();
450 for (int i = 0; i < container->Size(); ++i) {
451 E* const element = container->MutableElement(i);
452 const V* const var = element->Var();
453 const std::string& name = var->name();
454 if (name.empty()) {
455 LOG(INFO) << "Cannot save/load variables with empty name"
456 << "; variable will be ignored";
457 } else if (id_to_element_map->contains(name)) {
458 LOG(INFO) << "Cannot save/load variables with duplicate names: " << name
459 << "; variable will be ignored";
460 } else {
461 (*id_to_element_map)[name] = element;
462 }
463 }
464}
465
466template <class E, class P>
467void LoadElement(const absl::flat_hash_map<std::string, E*>& id_to_element_map,
468 const P& proto) {
469 absl::string_view var_id = proto.var_id();
470 CHECK(!var_id.empty());
471 E* element = nullptr;
472 if (gtl::FindCopy(id_to_element_map, var_id, &element)) {
473 element->LoadFromProto(proto);
474 } else {
475 LOG(INFO) << "Variable " << var_id
476 << " not in assignment; skipping variable";
477 }
478}
479
480} // namespace
481
482bool Assignment::Load(const std::string& filename) {
483 File* file;
484 if (!file::Open(filename, "r", &file, file::Defaults()).ok()) {
485 LOG(INFO) << "Cannot open " << filename;
486 return false;
487 }
488 return Load(file);
489}
490
492 CHECK(file != nullptr);
493 AssignmentProto assignment_proto;
495 if (!reader.ReadProtocolMessage(&assignment_proto)) {
496 LOG(INFO) << "No assignment found in " << file->filename();
497 return false;
498 }
499 Load(assignment_proto);
500 return reader.Close();
501}
502
503template <class Var, class Element, class Proto, class Container>
504void RealLoad(const AssignmentProto& assignment_proto,
505 Container* const container,
506 int (AssignmentProto::*GetSize)() const,
507 const Proto& (AssignmentProto::*GetElem)(int) const) {
508 bool fast_load = (container->Size() == (assignment_proto.*GetSize)());
509 for (int i = 0; fast_load && i < (assignment_proto.*GetSize)(); ++i) {
510 Element* const element = container->MutableElement(i);
511 const Proto& proto = (assignment_proto.*GetElem)(i);
512 if (element->Var()->name() == proto.var_id()) {
513 element->LoadFromProto(proto);
514 } else {
515 fast_load = false;
516 }
517 }
518 if (!fast_load) {
519 absl::flat_hash_map<std::string, Element*> id_to_element_map;
520 IdToElementMap<Var, Element>(container, &id_to_element_map);
521 for (int i = 0; i < (assignment_proto.*GetSize)(); ++i) {
522 LoadElement<Element, Proto>(id_to_element_map,
523 (assignment_proto.*GetElem)(i));
524 }
525 }
526}
527
528void Assignment::Load(const AssignmentProto& assignment_proto) {
530 assignment_proto, &int_var_container_,
534 IntervalContainer>(assignment_proto, &interval_var_container_,
538 SequenceContainer>(assignment_proto, &sequence_var_container_,
541 for (int i = 0; i < assignment_proto.objective_size(); ++i) {
542 const IntVarAssignment& objective = assignment_proto.objective(i);
543 absl::string_view objective_id = objective.var_id();
544 DCHECK(!objective_id.empty());
545 if (HasObjectiveFromIndex(i) &&
546 objective_id == ObjectiveFromIndex(i)->name()) {
547 const int64_t obj_min = objective.min();
548 const int64_t obj_max = objective.max();
549 SetObjectiveRangeFromIndex(i, obj_min, obj_max);
550 if (objective.active()) {
552 } else {
554 }
555 }
556 }
557}
558
559bool Assignment::Save(const std::string& filename) const {
560 File* file;
561 if (!file::Open(filename, "w", &file, file::Defaults()).ok()) {
562 LOG(INFO) << "Cannot open " << filename;
563 return false;
564 }
565 return Save(file);
566}
567
569 CHECK(file != nullptr);
570 AssignmentProto assignment_proto;
571 Save(&assignment_proto);
573 return writer.WriteProtocolMessage(assignment_proto) && writer.Close();
574}
575
576template <class Var, class Element, class Proto, class Container>
577void RealSave(AssignmentProto* const assignment_proto,
578 const Container& container, Proto* (AssignmentProto::*Add)()) {
579 for (const Element& element : container.elements()) {
580 const Var* const var = element.Var();
581 const std::string& name = var->name();
582 if (!name.empty()) {
583 Proto* const var_assignment_proto = (assignment_proto->*Add)();
584 element.WriteToProto(var_assignment_proto);
585 }
586 }
587}
588
589void Assignment::Save(AssignmentProto* const assignment_proto) const {
590 assignment_proto->Clear();
592 assignment_proto, int_var_container_,
595 IntervalContainer>(assignment_proto, interval_var_container_,
598 SequenceContainer>(assignment_proto, sequence_var_container_,
600 for (int i = 0; i < objective_elements_.size(); ++i) {
601 const std::string& name = ObjectiveFromIndex(i)->name();
602 if (!name.empty()) {
603 IntVarAssignment* objective = assignment_proto->add_objective();
604 objective->set_var_id(name);
605 objective->set_min(ObjectiveMinFromIndex(i));
606 objective->set_max(ObjectiveMaxFromIndex(i));
608 }
609 }
610}
611
612template <class Container, class Element>
613void RealDebugString(const Container& container, std::string* const out) {
614 for (const Element& element : container.elements()) {
615 if (element.Var() != nullptr) {
616 absl::StrAppendFormat(out, "%s %s | ", element.Var()->name(),
617 element.DebugString());
618 }
619 }
620}
621
622std::string Assignment::DebugString() const {
623 std::string out = "Assignment(";
624 RealDebugString<IntContainer, IntVarElement>(int_var_container_, &out);
626 interval_var_container_, &out);
628 sequence_var_container_, &out);
629 std::vector<std::string> objective_str;
630 for (const IntVarElement& objective_element : objective_elements_) {
631 if (objective_element.Activated()) {
632 objective_str.push_back(objective_element.DebugString());
633 }
634 }
635 absl::StrAppendFormat(&out, "%s)", absl::StrJoin(objective_str, ", "));
636 return out;
637}
638
640 return int_var_container_.Add(var);
641}
642
643void Assignment::Add(const std::vector<IntVar*>& vars) {
644 for (IntVar* const var : vars) {
645 Add(var);
646 }
647}
648
650 return int_var_container_.FastAdd(var);
651}
652
653int64_t Assignment::Min(const IntVar* const var) const {
654 return int_var_container_.Element(var).Min();
655}
656
657int64_t Assignment::Max(const IntVar* const var) const {
658 return int_var_container_.Element(var).Max();
659}
660
661int64_t Assignment::Value(const IntVar* const var) const {
662 return int_var_container_.Element(var).Value();
663}
664
665bool Assignment::Bound(const IntVar* const var) const {
666 return int_var_container_.Element(var).Bound();
667}
668
669void Assignment::SetMin(const IntVar* const var, int64_t m) {
670 int_var_container_.MutableElement(var)->SetMin(m);
671}
672
673void Assignment::SetMax(const IntVar* const var, int64_t m) {
674 int_var_container_.MutableElement(var)->SetMax(m);
675}
676
677void Assignment::SetRange(const IntVar* const var, int64_t l, int64_t u) {
678 int_var_container_.MutableElement(var)->SetRange(l, u);
679}
680
681void Assignment::SetValue(const IntVar* const var, int64_t value) {
682 int_var_container_.MutableElement(var)->SetValue(value);
683}
684
685// ----- Interval Var -----
686
688 return interval_var_container_.Add(var);
689}
690
691void Assignment::Add(const std::vector<IntervalVar*>& vars) {
692 for (IntervalVar* const var : vars) {
693 Add(var);
694 }
695}
696
698 return interval_var_container_.FastAdd(var);
699}
700
701int64_t Assignment::StartMin(const IntervalVar* const var) const {
702 return interval_var_container_.Element(var).StartMin();
703}
704
705int64_t Assignment::StartMax(const IntervalVar* const var) const {
706 return interval_var_container_.Element(var).StartMax();
707}
708
709int64_t Assignment::StartValue(const IntervalVar* const var) const {
710 return interval_var_container_.Element(var).StartValue();
711}
712
713int64_t Assignment::DurationMin(const IntervalVar* const var) const {
714 return interval_var_container_.Element(var).DurationMin();
715}
716
717int64_t Assignment::DurationMax(const IntervalVar* const var) const {
718 return interval_var_container_.Element(var).DurationMax();
719}
720
721int64_t Assignment::DurationValue(const IntervalVar* const var) const {
722 return interval_var_container_.Element(var).DurationValue();
723}
724
725int64_t Assignment::EndMin(const IntervalVar* const var) const {
726 return interval_var_container_.Element(var).EndMin();
727}
728
729int64_t Assignment::EndMax(const IntervalVar* const var) const {
730 return interval_var_container_.Element(var).EndMax();
731}
732
733int64_t Assignment::EndValue(const IntervalVar* const var) const {
734 return interval_var_container_.Element(var).EndValue();
735}
736
737int64_t Assignment::PerformedMin(const IntervalVar* const var) const {
738 return interval_var_container_.Element(var).PerformedMin();
739}
740
741int64_t Assignment::PerformedMax(const IntervalVar* const var) const {
742 return interval_var_container_.Element(var).PerformedMax();
743}
744
745int64_t Assignment::PerformedValue(const IntervalVar* const var) const {
746 return interval_var_container_.Element(var).PerformedValue();
747}
748
749void Assignment::SetStartMin(const IntervalVar* const var, int64_t m) {
750 interval_var_container_.MutableElement(var)->SetStartMin(m);
751}
752
753void Assignment::SetStartMax(const IntervalVar* const var, int64_t m) {
754 interval_var_container_.MutableElement(var)->SetStartMax(m);
755}
756
757void Assignment::SetStartRange(const IntervalVar* const var, int64_t mi,
758 int64_t ma) {
759 interval_var_container_.MutableElement(var)->SetStartRange(mi, ma);
760}
761
762void Assignment::SetStartValue(const IntervalVar* const var, int64_t value) {
763 interval_var_container_.MutableElement(var)->SetStartValue(value);
764}
765
766void Assignment::SetDurationMin(const IntervalVar* const var, int64_t m) {
767 interval_var_container_.MutableElement(var)->SetDurationMin(m);
768}
769
770void Assignment::SetDurationMax(const IntervalVar* const var, int64_t m) {
771 interval_var_container_.MutableElement(var)->SetDurationMax(m);
772}
773
774void Assignment::SetDurationRange(const IntervalVar* const var, int64_t mi,
775 int64_t ma) {
776 interval_var_container_.MutableElement(var)->SetDurationRange(mi, ma);
777}
778
779void Assignment::SetDurationValue(const IntervalVar* const var, int64_t value) {
780 interval_var_container_.MutableElement(var)->SetDurationValue(value);
781}
782
783void Assignment::SetEndMin(const IntervalVar* const var, int64_t m) {
784 interval_var_container_.MutableElement(var)->SetEndMin(m);
785}
786
787void Assignment::SetEndMax(const IntervalVar* const var, int64_t m) {
788 interval_var_container_.MutableElement(var)->SetEndMax(m);
789}
790
791void Assignment::SetEndRange(const IntervalVar* const var, int64_t mi,
792 int64_t ma) {
793 interval_var_container_.MutableElement(var)->SetEndRange(mi, ma);
794}
795
796void Assignment::SetEndValue(const IntervalVar* const var, int64_t value) {
797 interval_var_container_.MutableElement(var)->SetEndValue(value);
798}
799
800void Assignment::SetPerformedMin(const IntervalVar* const var, int64_t m) {
801 interval_var_container_.MutableElement(var)->SetPerformedMin(m);
802}
803
804void Assignment::SetPerformedMax(const IntervalVar* const var, int64_t m) {
805 interval_var_container_.MutableElement(var)->SetPerformedMax(m);
806}
807
808void Assignment::SetPerformedRange(const IntervalVar* const var, int64_t mi,
809 int64_t ma) {
810 interval_var_container_.MutableElement(var)->SetPerformedRange(mi, ma);
811}
812
814 int64_t value) {
815 interval_var_container_.MutableElement(var)->SetPerformedValue(value);
816}
817
818// ----- Sequence Var -----
819
821 return sequence_var_container_.Add(var);
822}
823
824void Assignment::Add(const std::vector<SequenceVar*>& vars) {
825 for (SequenceVar* const var : vars) {
826 Add(var);
827 }
828}
829
831 return sequence_var_container_.FastAdd(var);
832}
833
834const std::vector<int>& Assignment::ForwardSequence(
835 const SequenceVar* const var) const {
836 return sequence_var_container_.Element(var).ForwardSequence();
837}
838
839const std::vector<int>& Assignment::BackwardSequence(
840 const SequenceVar* const var) const {
841 return sequence_var_container_.Element(var).BackwardSequence();
842}
843
844const std::vector<int>& Assignment::Unperformed(
845 const SequenceVar* const var) const {
846 return sequence_var_container_.Element(var).Unperformed();
847}
848
850 const std::vector<int>& forward_sequence,
851 const std::vector<int>& backward_sequence,
852 const std::vector<int>& unperformed) {
853 sequence_var_container_.MutableElement(var)->SetSequence(
854 forward_sequence, backward_sequence, unperformed);
855}
856
858 const std::vector<int>& forward_sequence) {
859 sequence_var_container_.MutableElement(var)->SetForwardSequence(
860 forward_sequence);
861}
862
864 const SequenceVar* const var, const std::vector<int>& backward_sequence) {
865 sequence_var_container_.MutableElement(var)->SetBackwardSequence(
866 backward_sequence);
867}
868
870 const std::vector<int>& unperformed) {
871 sequence_var_container_.MutableElement(var)->SetUnperformed(unperformed);
872}
873
874void Assignment::Activate(const IntVar* const var) {
875 int_var_container_.MutableElement(var)->Activate();
876}
877
878void Assignment::Deactivate(const IntVar* const var) {
879 int_var_container_.MutableElement(var)->Deactivate();
880}
881
882bool Assignment::Activated(const IntVar* const var) const {
883 return int_var_container_.Element(var).Activated();
884}
885
886void Assignment::Activate(const IntervalVar* const var) {
887 interval_var_container_.MutableElement(var)->Activate();
888}
889
890void Assignment::Deactivate(const IntervalVar* const var) {
891 interval_var_container_.MutableElement(var)->Deactivate();
892}
893
894bool Assignment::Activated(const IntervalVar* const var) const {
895 return interval_var_container_.Element(var).Activated();
896}
897
898void Assignment::Activate(const SequenceVar* const var) {
899 sequence_var_container_.MutableElement(var)->Activate();
900}
901
902void Assignment::Deactivate(const SequenceVar* const var) {
903 sequence_var_container_.MutableElement(var)->Deactivate();
904}
905
906bool Assignment::Activated(const SequenceVar* const var) const {
907 return sequence_var_container_.Element(var).Activated();
908}
909
910bool Assignment::Contains(const IntVar* const var) const {
911 return int_var_container_.Contains(var);
912}
913
914bool Assignment::Contains(const IntervalVar* const var) const {
915 return interval_var_container_.Contains(var);
916}
917
918bool Assignment::Contains(const SequenceVar* const var) const {
919 return sequence_var_container_.Contains(var);
920}
921
923 int_var_container_.CopyIntersection(assignment->int_var_container_);
924 interval_var_container_.CopyIntersection(assignment->interval_var_container_);
925 sequence_var_container_.CopyIntersection(assignment->sequence_var_container_);
926 for (int i = 0; i < objective_elements_.size(); i++) {
927 if (i >= assignment->objective_elements_.size() ||
928 // TODO(user): The current behavior is to copy the objective "prefix"
929 // which fits the notion of lexicographic objectives well. Reconsider if
930 // multiple objectives are used in another context.
931 objective_elements_[i].Var() !=
932 assignment->objective_elements_[i].Var()) {
933 break;
934 }
935 objective_elements_[i] = assignment->objective_elements_[i];
936 }
937}
938
939void Assignment::Copy(const Assignment* assignment) {
940 Clear();
941 int_var_container_.Copy(assignment->int_var_container_);
942 interval_var_container_.Copy(assignment->interval_var_container_);
943 sequence_var_container_.Copy(assignment->sequence_var_container_);
944 objective_elements_ = assignment->objective_elements_;
945}
946
948 const std::vector<IntVar*>& target_vars,
949 const Assignment* source_assignment,
950 const std::vector<IntVar*>& source_vars) {
951 const int vars_size = target_vars.size();
952 CHECK_EQ(source_vars.size(), vars_size);
953 CHECK(target_assignment != nullptr);
954 CHECK(source_assignment != nullptr);
955
956 target_assignment->Clear();
957 const Solver* const target_solver = target_assignment->solver();
958 const Solver* const source_solver = source_assignment->solver();
959 for (int index = 0; index < vars_size; index++) {
960 IntVar* target_var = target_vars[index];
961 CHECK_EQ(target_var->solver(), target_solver);
962 IntVar* source_var = source_vars[index];
963 CHECK_EQ(source_var->solver(), source_solver);
964 target_assignment->Add(target_var)
965 ->SetValue(source_assignment->Value(source_var));
966 }
967}
968
970
972 return RevAlloc(new Assignment(a));
973}
974
975// ----- Storing and Restoring assignments -----
976namespace {
977class RestoreAssignment : public DecisionBuilder {
978 public:
979 explicit RestoreAssignment(Assignment* assignment)
980 : assignment_(assignment) {}
981
982 ~RestoreAssignment() override {}
983
984 Decision* Next(Solver* const /*solver*/) override {
985 assignment_->Restore();
986 return nullptr;
987 }
988
989 std::string DebugString() const override { return "RestoreAssignment"; }
990
991 private:
992 Assignment* const assignment_;
993};
994
995class StoreAssignment : public DecisionBuilder {
996 public:
997 explicit StoreAssignment(Assignment* assignment) : assignment_(assignment) {}
998
999 ~StoreAssignment() override {}
1000
1001 Decision* Next(Solver* const /*solver*/) override {
1002 assignment_->Store();
1003 return nullptr;
1004 }
1005
1006 std::string DebugString() const override { return "StoreAssignment"; }
1007
1008 private:
1009 Assignment* const assignment_;
1010};
1011} // namespace
1012
1014 return RevAlloc(new RestoreAssignment(assignment));
1015}
1016
1018 return RevAlloc(new StoreAssignment(assignment));
1019}
1020
1021std::ostream& operator<<(std::ostream& out, const Assignment& assignment) {
1022 return out << assignment.DebugString();
1023}
1024
1025} // namespace operations_research
Definition file.h:29
int objective_size() const
repeated .operations_research.IntVarAssignment objective = 3;
::operations_research::SequenceVarAssignment *PROTOBUF_NONNULL add_sequence_var_assignment()
const ::operations_research::SequenceVarAssignment & sequence_var_assignment(int index) const
ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL
int interval_var_assignment_size() const
repeated .operations_research.IntervalVarAssignment interval_var_assignment = 2;
const ::operations_research::IntVarAssignment & objective(int index) const
::operations_research::IntervalVarAssignment *PROTOBUF_NONNULL add_interval_var_assignment()
const ::operations_research::IntervalVarAssignment & interval_var_assignment(int index) const
int int_var_assignment_size() const
repeated .operations_research.IntVarAssignment int_var_assignment = 1;
::operations_research::IntVarAssignment *PROTOBUF_NONNULL add_int_var_assignment()
int sequence_var_assignment_size() const
repeated .operations_research.SequenceVarAssignment sequence_var_assignment = 6;
::operations_research::IntVarAssignment *PROTOBUF_NONNULL add_objective()
const ::operations_research::IntVarAssignment & int_var_assignment(int index) const
void Activate(const IntVar *var)
void SetPerformedRange(const IntervalVar *var, int64_t mi, int64_t ma)
AssignmentContainer< SequenceVar, SequenceVarElement > SequenceContainer
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)
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)
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
AssignmentContainer< IntervalVar, IntervalVarElement > IntervalContainer
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
const ::std::string & var_id() const
void set_var_id(Arg_ &&arg, Args_... args)
bool operator==(const IntVarElement &element) const
Definition assignment.cc:76
void SetRange(int64_t l, int64_t u)
IntVarElement()
--------------— Solutions ---------------------—
Definition assignment.cc:39
std::string DebugString() const
Definition assignment.cc:99
void Copy(const IntVarElement &element)
Definition assignment.cc:55
void WriteToProto(IntVarAssignment *int_var_assignment_proto) const
Definition assignment.cc:91
void LoadFromProto(const IntVarAssignment &int_var_assignment_proto)
Definition assignment.cc:65
void set_var_id(Arg_ &&arg, Args_... args)
void SetDurationRange(int64_t mi, int64_t ma)
void WriteToProto(IntervalVarAssignment *interval_var_assignment_proto) const
void Copy(const IntervalVarElement &element)
void SetEndRange(int64_t mi, int64_t ma)
IntervalVarElement()
--— IntervalVarElement --—
bool operator==(const IntervalVarElement &element) const
void SetStartRange(int64_t mi, int64_t ma)
void SetPerformedRange(int64_t mi, int64_t ma)
void LoadFromProto(const IntervalVarAssignment &interval_var_assignment_proto)
virtual std::string name() const
Object naming.
::int32_t forward_sequence(int index) const
::int32_t backward_sequence(int index) const
void set_var_id(Arg_ &&arg, Args_... args)
void WriteToProto(SequenceVarAssignment *sequence_var_assignment_proto) const
bool operator==(const SequenceVarElement &element) const
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 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.
Definition recordio.cc:55
bool ReadProtocolMessage(P *const proto)
Definition recordio.h:91
bool Close()
Closes the underlying file.
Definition recordio.cc:30
bool WriteProtocolMessage(const P &proto)
Definition recordio.h:41
Definition file.cc:326
Options Defaults()
Definition file.h:85
absl::Status Open(absl::string_view file_name, absl::string_view mode, File **f, Options options)
As of 2016-01, these methods can only be used with flags = file::Defaults().
Definition file.cc:327
bool FindCopy(const Collection &collection, const Key &key, Value *const value)
Definition map_util.h:190
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)())
bool Next()