2013-06-11 14:49:19 +00:00
|
|
|
// Copyright 2010-2013 Google
|
2010-09-15 12:42:33 +00:00
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
|
//
|
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
//
|
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
|
// limitations under the License.
|
|
|
|
|
|
2013-12-16 10:24:42 +00:00
|
|
|
#include <cstring>
|
2011-09-21 15:16:48 +00:00
|
|
|
#include <string>
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
#include "base/integral_types.h"
|
|
|
|
|
#include "base/logging.h"
|
|
|
|
|
#include "base/scoped_ptr.h"
|
|
|
|
|
#include "base/stringprintf.h"
|
|
|
|
|
#include "constraint_solver/constraint_solver.h"
|
2012-07-21 01:19:32 +00:00
|
|
|
#include "constraint_solver/constraint_solveri.h"
|
2011-11-03 10:27:53 +00:00
|
|
|
#include "util/string_array.h"
|
2010-09-15 12:42:33 +00:00
|
|
|
|
|
|
|
|
namespace operations_research {
|
2013-01-10 17:01:34 +00:00
|
|
|
namespace {
|
2013-10-10 15:23:20 +00:00
|
|
|
int64 ValueToIndex(int64 value) { return value - 1; }
|
2013-01-10 17:01:34 +00:00
|
|
|
|
2013-10-10 15:23:20 +00:00
|
|
|
int64 IndexToValue(int64 index) { return index + 1; }
|
2013-01-10 17:01:34 +00:00
|
|
|
} // namespace
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2012-07-21 01:19:32 +00:00
|
|
|
// ----- SequenceVar -----
|
|
|
|
|
|
|
|
|
|
// TODO(user): Add better class invariants, in particular checks
|
|
|
|
|
// that ranked_first, ranked_last, and unperformed are truly disjoint.
|
|
|
|
|
|
2013-10-10 15:23:20 +00:00
|
|
|
SequenceVar::SequenceVar(Solver* const s, const std::vector<IntervalVar*>& intervals,
|
2013-12-16 10:24:42 +00:00
|
|
|
const std::vector<IntVar*>& nexts, const std::string& name)
|
2013-10-10 15:23:20 +00:00
|
|
|
: PropagationBaseObject(s),
|
|
|
|
|
intervals_(intervals),
|
|
|
|
|
nexts_(nexts),
|
|
|
|
|
previous_(nexts.size() + 1, -1) {
|
2012-07-21 01:19:32 +00:00
|
|
|
set_name(name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SequenceVar::~SequenceVar() {}
|
|
|
|
|
|
|
|
|
|
IntervalVar* SequenceVar::Interval(int index) const {
|
|
|
|
|
return intervals_[index];
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-10 15:23:20 +00:00
|
|
|
IntVar* SequenceVar::Next(int index) const { return nexts_[index]; }
|
2012-07-21 01:19:32 +00:00
|
|
|
|
2013-12-16 10:24:42 +00:00
|
|
|
std::string SequenceVar::DebugString() const {
|
2012-07-21 01:19:32 +00:00
|
|
|
int64 hmin, hmax, dmin, dmax;
|
|
|
|
|
HorizonRange(&hmin, &hmax);
|
|
|
|
|
DurationRange(&dmin, &dmax);
|
|
|
|
|
int unperformed = 0;
|
|
|
|
|
int ranked = 0;
|
|
|
|
|
int not_ranked = 0;
|
|
|
|
|
ComputeStatistics(&ranked, ¬_ranked, &unperformed);
|
2013-10-10 15:23:20 +00:00
|
|
|
return StringPrintf("%s(horizon = %" GG_LL_FORMAT "d..%" GG_LL_FORMAT
|
|
|
|
|
"d, duration = %" GG_LL_FORMAT "d..%" GG_LL_FORMAT
|
2013-07-30 21:41:29 +00:00
|
|
|
"d, not ranked = %d, ranked = %d, nexts = [%s])",
|
2013-10-10 15:23:20 +00:00
|
|
|
name().c_str(), hmin, hmax, dmin, dmax, not_ranked,
|
2013-10-17 08:58:26 +00:00
|
|
|
ranked, JoinDebugStringPtr(nexts_, ", ").c_str());
|
2012-07-21 01:19:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SequenceVar::Accept(ModelVisitor* const visitor) const {
|
|
|
|
|
visitor->VisitSequenceVariable(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SequenceVar::DurationRange(int64* const dmin, int64* const dmax) const {
|
|
|
|
|
int64 dur_min = 0;
|
|
|
|
|
int64 dur_max = 0;
|
2013-10-10 15:23:20 +00:00
|
|
|
for (int i = 0; i < intervals_.size(); ++i) {
|
2012-07-21 01:19:32 +00:00
|
|
|
IntervalVar* const t = intervals_[i];
|
|
|
|
|
if (t->MayBePerformed()) {
|
|
|
|
|
if (t->MustBePerformed()) {
|
|
|
|
|
dur_min += t->DurationMin();
|
|
|
|
|
}
|
|
|
|
|
dur_max += t->DurationMax();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
*dmin = dur_min;
|
|
|
|
|
*dmax = dur_max;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SequenceVar::HorizonRange(int64* const hmin, int64* const hmax) const {
|
|
|
|
|
int64 hor_min = kint64max;
|
|
|
|
|
int64 hor_max = kint64min;
|
2013-10-10 15:23:20 +00:00
|
|
|
for (int i = 0; i < intervals_.size(); ++i) {
|
2012-07-21 01:19:32 +00:00
|
|
|
IntervalVar* const t = intervals_[i];
|
|
|
|
|
if (t->MayBePerformed()) {
|
|
|
|
|
IntervalVar* const t = intervals_[i];
|
|
|
|
|
hor_min = std::min(hor_min, t->StartMin());
|
2012-07-24 00:22:05 +00:00
|
|
|
hor_max = std::max(hor_max, t->EndMax());
|
2012-07-21 01:19:32 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
*hmin = hor_min;
|
|
|
|
|
*hmax = hor_max;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SequenceVar::ActiveHorizonRange(int64* const hmin,
|
|
|
|
|
int64* const hmax) const {
|
|
|
|
|
hash_set<int> decided;
|
2013-10-10 15:23:20 +00:00
|
|
|
for (int i = 0; i < intervals_.size(); ++i) {
|
2012-07-21 01:19:32 +00:00
|
|
|
if (intervals_[i]->CannotBePerformed()) {
|
|
|
|
|
decided.insert(i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
int first = 0;
|
|
|
|
|
while (nexts_[first]->Bound()) {
|
|
|
|
|
first = nexts_[first]->Min();
|
2013-10-10 15:23:20 +00:00
|
|
|
if (first < nexts_.size()) {
|
2013-01-10 17:01:34 +00:00
|
|
|
decided.insert(ValueToIndex(first));
|
2012-07-21 01:19:32 +00:00
|
|
|
} else {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-10-10 15:23:20 +00:00
|
|
|
if (first != nexts_.size()) {
|
2012-07-21 01:19:32 +00:00
|
|
|
UpdatePrevious();
|
2013-10-10 15:23:20 +00:00
|
|
|
int last = nexts_.size();
|
2012-07-21 01:19:32 +00:00
|
|
|
while (previous_[last] != -1) {
|
|
|
|
|
last = previous_[last];
|
2013-01-10 17:01:34 +00:00
|
|
|
decided.insert(ValueToIndex(last));
|
2012-07-21 01:19:32 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
int64 hor_min = kint64max;
|
|
|
|
|
int64 hor_max = kint64min;
|
2013-10-10 15:23:20 +00:00
|
|
|
for (int i = 0; i < intervals_.size(); ++i) {
|
2012-07-21 01:19:32 +00:00
|
|
|
if (!ContainsKey(decided, i)) {
|
|
|
|
|
IntervalVar* const t = intervals_[i];
|
|
|
|
|
hor_min = std::min(hor_min, t->StartMin());
|
2012-07-24 00:22:05 +00:00
|
|
|
hor_max = std::max(hor_max, t->EndMax());
|
2012-07-21 01:19:32 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
*hmin = hor_min;
|
|
|
|
|
*hmax = hor_max;
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-10 15:23:20 +00:00
|
|
|
void SequenceVar::ComputeStatistics(int* const ranked, int* const not_ranked,
|
2012-07-21 01:19:32 +00:00
|
|
|
int* const unperformed) const {
|
|
|
|
|
*unperformed = 0;
|
2013-10-10 15:23:20 +00:00
|
|
|
for (int i = 0; i < intervals_.size(); ++i) {
|
2012-07-21 01:19:32 +00:00
|
|
|
if (intervals_[i]->CannotBePerformed()) {
|
|
|
|
|
(*unperformed)++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
*ranked = 0;
|
|
|
|
|
int first = 0;
|
2013-10-10 15:23:20 +00:00
|
|
|
while (first < nexts_.size() && nexts_[first]->Bound()) {
|
2012-07-21 01:19:32 +00:00
|
|
|
first = nexts_[first]->Min();
|
|
|
|
|
(*ranked)++;
|
|
|
|
|
}
|
2013-10-10 15:23:20 +00:00
|
|
|
if (first != nexts_.size()) {
|
2012-07-21 01:19:32 +00:00
|
|
|
UpdatePrevious();
|
2013-10-10 15:23:20 +00:00
|
|
|
int last = nexts_.size();
|
2012-07-21 01:19:32 +00:00
|
|
|
while (previous_[last] != -1) {
|
|
|
|
|
last = previous_[last];
|
|
|
|
|
(*ranked)++;
|
|
|
|
|
}
|
2013-07-30 21:41:29 +00:00
|
|
|
} else { // We counted the sentinel.
|
|
|
|
|
(*ranked)--;
|
2012-07-21 01:19:32 +00:00
|
|
|
}
|
2013-10-10 15:23:20 +00:00
|
|
|
*not_ranked = intervals_.size() - *ranked - *unperformed;
|
2012-07-21 01:19:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int SequenceVar::ComputeForwardFrontier() {
|
|
|
|
|
int first = 0;
|
2013-10-10 15:23:20 +00:00
|
|
|
while (first != nexts_.size() && nexts_[first]->Bound()) {
|
2012-07-21 01:19:32 +00:00
|
|
|
first = nexts_[first]->Min();
|
|
|
|
|
}
|
|
|
|
|
return first;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int SequenceVar::ComputeBackwardFrontier() {
|
|
|
|
|
UpdatePrevious();
|
2013-10-10 15:23:20 +00:00
|
|
|
int last = nexts_.size();
|
2012-07-21 01:19:32 +00:00
|
|
|
while (previous_[last] != -1) {
|
|
|
|
|
last = previous_[last];
|
|
|
|
|
}
|
|
|
|
|
return last;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SequenceVar::ComputePossibleFirstsAndLasts(
|
2013-10-10 15:23:20 +00:00
|
|
|
std::vector<int>* const possible_firsts, std::vector<int>* const possible_lasts) {
|
2013-07-30 21:41:29 +00:00
|
|
|
possible_firsts->clear();
|
|
|
|
|
possible_lasts->clear();
|
2012-07-25 00:37:43 +00:00
|
|
|
hash_set<int> to_check;
|
2013-10-10 15:23:20 +00:00
|
|
|
for (int i = 0; i < intervals_.size(); ++i) {
|
2012-07-25 00:37:43 +00:00
|
|
|
if (intervals_[i]->MayBePerformed()) {
|
|
|
|
|
to_check.insert(i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
int first = 0;
|
|
|
|
|
while (nexts_[first]->Bound()) {
|
|
|
|
|
first = nexts_[first]->Min();
|
2013-10-10 15:23:20 +00:00
|
|
|
if (first == nexts_.size()) {
|
2012-07-25 00:37:43 +00:00
|
|
|
return;
|
|
|
|
|
}
|
2013-07-30 21:41:29 +00:00
|
|
|
to_check.erase(ValueToIndex(first));
|
2012-07-25 00:37:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IntVar* const forward_var = nexts_[first];
|
2012-07-24 00:22:05 +00:00
|
|
|
std::vector<int> candidates;
|
|
|
|
|
int64 smallest_start_max = kint64max;
|
|
|
|
|
int ssm_support = -1;
|
2012-07-21 01:19:32 +00:00
|
|
|
for (int64 i = forward_var->Min(); i <= forward_var->Max(); ++i) {
|
2012-09-11 15:57:55 +00:00
|
|
|
// TODO(user): use domain iterator.
|
2013-10-10 15:23:20 +00:00
|
|
|
if (i != 0 && i < IndexToValue(intervals_.size()) &&
|
2013-01-10 17:01:34 +00:00
|
|
|
intervals_[ValueToIndex(i)]->MayBePerformed() &&
|
2012-08-31 08:16:45 +00:00
|
|
|
forward_var->Contains(i)) {
|
2013-01-10 17:01:34 +00:00
|
|
|
const int candidate = ValueToIndex(i);
|
2012-07-24 00:22:05 +00:00
|
|
|
candidates.push_back(candidate);
|
|
|
|
|
if (intervals_[candidate]->MustBePerformed()) {
|
|
|
|
|
if (smallest_start_max > intervals_[candidate]->StartMax()) {
|
|
|
|
|
smallest_start_max = intervals_[candidate]->StartMax();
|
|
|
|
|
ssm_support = candidate;
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-07-21 01:19:32 +00:00
|
|
|
}
|
|
|
|
|
}
|
2012-07-24 00:22:05 +00:00
|
|
|
for (int i = 0; i < candidates.size(); ++i) {
|
|
|
|
|
const int candidate = candidates[i];
|
|
|
|
|
if (candidate == ssm_support ||
|
|
|
|
|
intervals_[candidate]->EndMin() <= smallest_start_max) {
|
|
|
|
|
possible_firsts->push_back(candidate);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-25 00:37:43 +00:00
|
|
|
UpdatePrevious();
|
2013-10-10 15:23:20 +00:00
|
|
|
int last = nexts_.size();
|
2012-07-25 00:37:43 +00:00
|
|
|
while (previous_[last] != -1) {
|
|
|
|
|
last = previous_[last];
|
2013-01-10 17:01:34 +00:00
|
|
|
to_check.erase(ValueToIndex(last));
|
2012-07-25 00:37:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
candidates.clear();
|
|
|
|
|
int64 biggest_end_min = kint64min;
|
|
|
|
|
int bem_support = -1;
|
2013-10-10 15:23:20 +00:00
|
|
|
for (ConstIter<hash_set<int>> it(to_check); !it.at_end(); ++it) {
|
2012-07-25 00:37:43 +00:00
|
|
|
const int candidate = *it;
|
2013-01-10 17:01:34 +00:00
|
|
|
if (nexts_[IndexToValue(candidate)]->Contains(last)) {
|
2012-07-25 00:37:43 +00:00
|
|
|
candidates.push_back(candidate);
|
|
|
|
|
if (intervals_[candidate]->MustBePerformed()) {
|
|
|
|
|
if (biggest_end_min < intervals_[candidate]->EndMin()) {
|
|
|
|
|
biggest_end_min = intervals_[candidate]->EndMin();
|
|
|
|
|
bem_support = candidate;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < candidates.size(); ++i) {
|
|
|
|
|
const int candidate = candidates[i];
|
|
|
|
|
if (candidate == bem_support ||
|
|
|
|
|
intervals_[candidate]->StartMax() >= biggest_end_min) {
|
|
|
|
|
possible_lasts->push_back(candidate);
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-07-21 01:19:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SequenceVar::RankSequence(const std::vector<int>& rank_first,
|
|
|
|
|
const std::vector<int>& rank_last,
|
|
|
|
|
const std::vector<int>& unperformed) {
|
2013-10-10 15:23:20 +00:00
|
|
|
solver()->GetPropagationMonitor()->RankSequence(this, rank_first, rank_last,
|
2012-07-21 01:19:32 +00:00
|
|
|
unperformed);
|
|
|
|
|
// Mark unperformed.
|
2013-10-10 15:23:20 +00:00
|
|
|
for (ConstIter<std::vector<int>> it(unperformed); !it.at_end(); ++it) {
|
2012-07-21 01:19:32 +00:00
|
|
|
intervals_[*it]->SetPerformed(false);
|
|
|
|
|
}
|
|
|
|
|
// Forward.
|
|
|
|
|
int forward = 0;
|
|
|
|
|
for (int i = 0; i < rank_first.size(); ++i) {
|
|
|
|
|
const int next = 1 + rank_first[i];
|
|
|
|
|
nexts_[forward]->SetValue(next);
|
|
|
|
|
forward = next;
|
|
|
|
|
}
|
2012-07-24 23:06:40 +00:00
|
|
|
// Backward.
|
2013-10-10 15:23:20 +00:00
|
|
|
int backward = IndexToValue(intervals_.size());
|
2012-07-24 23:06:40 +00:00
|
|
|
for (int i = 0; i < rank_last.size(); ++i) {
|
|
|
|
|
const int next = 1 + rank_last[i];
|
|
|
|
|
nexts_[next]->SetValue(backward);
|
|
|
|
|
backward = next;
|
|
|
|
|
}
|
2012-07-21 01:19:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SequenceVar::RankFirst(int index) {
|
|
|
|
|
solver()->GetPropagationMonitor()->RankFirst(this, index);
|
2012-07-24 22:32:50 +00:00
|
|
|
intervals_[index]->SetPerformed(true);
|
2013-07-30 21:41:29 +00:00
|
|
|
int forward_frontier = 0;
|
2013-10-10 15:23:20 +00:00
|
|
|
while (forward_frontier != nexts_.size() &&
|
|
|
|
|
nexts_[forward_frontier]->Bound()) {
|
2013-07-30 21:41:29 +00:00
|
|
|
forward_frontier = nexts_[forward_frontier]->Min();
|
|
|
|
|
if (forward_frontier == IndexToValue(index)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-10-10 15:23:20 +00:00
|
|
|
DCHECK_LT(forward_frontier, nexts_.size());
|
2013-01-10 17:01:34 +00:00
|
|
|
nexts_[forward_frontier]->SetValue(IndexToValue(index));
|
2012-07-21 01:19:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SequenceVar::RankNotFirst(int index) {
|
|
|
|
|
solver()->GetPropagationMonitor()->RankNotFirst(this, index);
|
|
|
|
|
const int forward_frontier = ComputeForwardFrontier();
|
2013-10-10 15:23:20 +00:00
|
|
|
if (forward_frontier < nexts_.size()) {
|
2013-01-10 17:01:34 +00:00
|
|
|
nexts_[forward_frontier]->RemoveValue(IndexToValue(index));
|
2012-07-24 00:22:05 +00:00
|
|
|
}
|
2012-07-21 01:19:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SequenceVar::RankLast(int index) {
|
|
|
|
|
solver()->GetPropagationMonitor()->RankLast(this, index);
|
2012-07-24 22:32:50 +00:00
|
|
|
intervals_[index]->SetPerformed(true);
|
2013-07-30 21:41:29 +00:00
|
|
|
UpdatePrevious();
|
2013-10-10 15:23:20 +00:00
|
|
|
int backward_frontier = nexts_.size();
|
2013-07-30 21:41:29 +00:00
|
|
|
while (previous_[backward_frontier] != -1) {
|
|
|
|
|
backward_frontier = previous_[backward_frontier];
|
|
|
|
|
if (backward_frontier == IndexToValue(index)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
DCHECK_NE(backward_frontier, 0);
|
2013-01-10 17:01:34 +00:00
|
|
|
nexts_[IndexToValue(index)]->SetValue(backward_frontier);
|
2012-07-21 01:19:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SequenceVar::RankNotLast(int index) {
|
|
|
|
|
solver()->GetPropagationMonitor()->RankNotLast(this, index);
|
|
|
|
|
const int backward_frontier = ComputeBackwardFrontier();
|
2013-01-10 17:01:34 +00:00
|
|
|
nexts_[IndexToValue(index)]->RemoveValue(backward_frontier);
|
2012-07-21 01:19:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SequenceVar::UpdatePrevious() const {
|
2013-10-10 15:23:20 +00:00
|
|
|
for (int i = 0; i < intervals_.size() + 2; ++i) {
|
2012-07-21 01:19:32 +00:00
|
|
|
previous_[i] = -1;
|
|
|
|
|
}
|
2013-10-10 15:23:20 +00:00
|
|
|
for (int i = 0; i < nexts_.size(); ++i) {
|
2012-07-21 01:19:32 +00:00
|
|
|
if (nexts_[i]->Bound()) {
|
|
|
|
|
previous_[nexts_[i]->Min()] = i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SequenceVar::FillSequence(std::vector<int>* const rank_first,
|
|
|
|
|
std::vector<int>* const rank_last,
|
|
|
|
|
std::vector<int>* const unperformed) const {
|
2013-10-10 15:23:20 +00:00
|
|
|
CHECK(rank_first != nullptr);
|
|
|
|
|
CHECK(rank_last != nullptr);
|
|
|
|
|
CHECK(unperformed != nullptr);
|
2012-07-21 01:19:32 +00:00
|
|
|
rank_first->clear();
|
|
|
|
|
rank_last->clear();
|
|
|
|
|
unperformed->clear();
|
2013-10-10 15:23:20 +00:00
|
|
|
for (int i = 0; i < intervals_.size(); ++i) {
|
2012-07-21 01:19:32 +00:00
|
|
|
if (intervals_[i]->CannotBePerformed()) {
|
|
|
|
|
unperformed->push_back(i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
int first = 0;
|
|
|
|
|
while (nexts_[first]->Bound()) {
|
|
|
|
|
first = nexts_[first]->Min();
|
2013-10-10 15:23:20 +00:00
|
|
|
if (first < nexts_.size()) {
|
2013-01-10 17:01:34 +00:00
|
|
|
rank_first->push_back(ValueToIndex(first));
|
2012-07-21 01:19:32 +00:00
|
|
|
} else {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-10-10 15:23:20 +00:00
|
|
|
if (first != nexts_.size()) {
|
2012-07-21 01:19:32 +00:00
|
|
|
UpdatePrevious();
|
2013-10-10 15:23:20 +00:00
|
|
|
int last = nexts_.size();
|
2012-07-21 01:19:32 +00:00
|
|
|
while (previous_[last] != -1) {
|
|
|
|
|
last = previous_[last];
|
2013-01-10 17:01:34 +00:00
|
|
|
rank_last->push_back(ValueToIndex(last));
|
2012-07-21 01:19:32 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
// ----- Decisions and DecisionBuilders on interval vars -----
|
|
|
|
|
|
|
|
|
|
// TODO(user) : treat optional intervals
|
2011-01-06 17:40:30 +00:00
|
|
|
// TODO(user) : Call DecisionVisitor and pass name of variable
|
2011-08-11 05:15:18 +00:00
|
|
|
namespace {
|
2010-09-15 12:42:33 +00:00
|
|
|
class ScheduleOrPostpone : public Decision {
|
|
|
|
|
public:
|
|
|
|
|
ScheduleOrPostpone(IntervalVar* const var, int64 est, int64* const marker)
|
|
|
|
|
: var_(var), est_(est), marker_(marker) {}
|
|
|
|
|
virtual ~ScheduleOrPostpone() {}
|
|
|
|
|
|
|
|
|
|
virtual void Apply(Solver* const s) {
|
|
|
|
|
var_->SetPerformed(true);
|
2013-06-11 14:49:19 +00:00
|
|
|
if (est_.Value() < var_->StartMin()) {
|
|
|
|
|
est_.SetValue(s, var_->StartMin());
|
|
|
|
|
}
|
|
|
|
|
var_->SetStartRange(est_.Value(), est_.Value());
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void Refute(Solver* const s) {
|
2013-06-11 14:49:19 +00:00
|
|
|
s->SaveAndSetValue(marker_, est_.Value() + 1);
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2011-01-06 17:40:30 +00:00
|
|
|
virtual void Accept(DecisionVisitor* const visitor) const {
|
2013-10-10 15:23:20 +00:00
|
|
|
CHECK(visitor != nullptr);
|
2013-06-11 14:49:19 +00:00
|
|
|
visitor->VisitScheduleOrPostpone(var_, est_.Value());
|
2011-01-06 17:40:30 +00:00
|
|
|
}
|
|
|
|
|
|
2013-12-16 10:24:42 +00:00
|
|
|
virtual std::string DebugString() const {
|
2010-09-15 12:42:33 +00:00
|
|
|
return StringPrintf("ScheduleOrPostpone(%s at %" GG_LL_FORMAT "d)",
|
2013-06-11 14:49:19 +00:00
|
|
|
var_->DebugString().c_str(), est_.Value());
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
2011-08-11 05:15:18 +00:00
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
private:
|
|
|
|
|
IntervalVar* const var_;
|
2013-06-11 14:49:19 +00:00
|
|
|
NumericalRev<int64> est_;
|
2010-09-15 12:42:33 +00:00
|
|
|
int64* const marker_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class SetTimesForward : public DecisionBuilder {
|
|
|
|
|
public:
|
2013-10-10 15:23:20 +00:00
|
|
|
explicit SetTimesForward(const std::vector<IntervalVar*>& vars)
|
|
|
|
|
: vars_(vars), markers_(vars.size(), kint64min) {}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
|
|
|
|
virtual ~SetTimesForward() {}
|
|
|
|
|
|
|
|
|
|
virtual Decision* Next(Solver* const s) {
|
|
|
|
|
int64 best_est = kint64max;
|
|
|
|
|
int64 best_lct = kint64max;
|
|
|
|
|
int support = -1;
|
|
|
|
|
int refuted = 0;
|
2013-10-10 15:23:20 +00:00
|
|
|
for (int i = 0; i < vars_.size(); ++i) {
|
2010-09-15 12:42:33 +00:00
|
|
|
IntervalVar* const v = vars_[i];
|
2010-11-02 19:02:53 +00:00
|
|
|
if (v->MayBePerformed() && v->StartMax() > v->StartMin()) {
|
2010-09-15 12:42:33 +00:00
|
|
|
if (v->StartMin() >= markers_[i] &&
|
2013-10-10 15:23:20 +00:00
|
|
|
(v->StartMin() < best_est ||
|
|
|
|
|
(v->StartMin() == best_est && v->EndMax() < best_lct))) {
|
2010-09-15 12:42:33 +00:00
|
|
|
best_est = v->StartMin();
|
|
|
|
|
best_lct = v->EndMax();
|
|
|
|
|
support = i;
|
|
|
|
|
} else {
|
|
|
|
|
refuted++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// TODO(user) : remove this crude quadratic loop with
|
|
|
|
|
// reversibles range reduction.
|
|
|
|
|
if (support == -1) {
|
|
|
|
|
if (refuted == 0) {
|
2013-10-10 15:23:20 +00:00
|
|
|
return nullptr;
|
2010-09-15 12:42:33 +00:00
|
|
|
} else {
|
|
|
|
|
s->Fail();
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-10-10 15:23:20 +00:00
|
|
|
return s->RevAlloc(new ScheduleOrPostpone(
|
|
|
|
|
vars_[support], vars_[support]->StartMin(), &markers_[support]));
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2013-12-16 10:24:42 +00:00
|
|
|
virtual std::string DebugString() const { return "SetTimesForward()"; }
|
2011-08-11 05:15:18 +00:00
|
|
|
|
|
|
|
|
virtual void Accept(ModelVisitor* const visitor) const {
|
|
|
|
|
visitor->BeginVisitExtension(ModelVisitor::kVariableGroupExtension);
|
|
|
|
|
visitor->VisitIntervalArrayArgument(ModelVisitor::kIntervalsArgument,
|
2013-10-10 15:23:20 +00:00
|
|
|
vars_);
|
2011-08-11 05:15:18 +00:00
|
|
|
visitor->EndVisitExtension(ModelVisitor::kVariableGroupExtension);
|
|
|
|
|
}
|
|
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
private:
|
2013-10-10 15:23:20 +00:00
|
|
|
const std::vector<IntervalVar*> vars_;
|
|
|
|
|
std::vector<int64> markers_;
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// ----- Decisions and DecisionBuilders on sequences -----
|
|
|
|
|
|
2011-12-16 21:02:59 +00:00
|
|
|
class RankFirst : public Decision {
|
2010-09-15 12:42:33 +00:00
|
|
|
public:
|
2011-12-16 21:02:59 +00:00
|
|
|
RankFirst(SequenceVar* const seq, int index)
|
2010-09-15 12:42:33 +00:00
|
|
|
: sequence_(seq), index_(index) {}
|
2011-12-16 21:02:59 +00:00
|
|
|
virtual ~RankFirst() {}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2013-10-10 15:23:20 +00:00
|
|
|
virtual void Apply(Solver* const s) { sequence_->RankFirst(index_); }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2013-10-10 15:23:20 +00:00
|
|
|
virtual void Refute(Solver* const s) { sequence_->RankNotFirst(index_); }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2011-01-06 17:40:30 +00:00
|
|
|
void Accept(DecisionVisitor* const visitor) const {
|
2013-10-10 15:23:20 +00:00
|
|
|
CHECK(visitor != nullptr);
|
2011-12-16 21:02:59 +00:00
|
|
|
visitor->VisitRankFirstInterval(sequence_, index_);
|
2011-01-06 17:40:30 +00:00
|
|
|
}
|
|
|
|
|
|
2013-12-16 10:24:42 +00:00
|
|
|
virtual std::string DebugString() const {
|
2013-10-10 15:23:20 +00:00
|
|
|
return StringPrintf("RankFirst(%s, %d)", sequence_->DebugString().c_str(),
|
|
|
|
|
index_);
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
2011-08-11 05:15:18 +00:00
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
private:
|
2011-11-03 10:27:53 +00:00
|
|
|
SequenceVar* const sequence_;
|
2010-09-15 12:42:33 +00:00
|
|
|
const int index_;
|
|
|
|
|
};
|
|
|
|
|
|
2011-12-16 21:02:59 +00:00
|
|
|
class RankLast : public Decision {
|
|
|
|
|
public:
|
2013-10-10 15:23:20 +00:00
|
|
|
RankLast(SequenceVar* const seq, int index) : sequence_(seq), index_(index) {}
|
2011-12-16 21:02:59 +00:00
|
|
|
virtual ~RankLast() {}
|
2011-01-06 17:40:30 +00:00
|
|
|
|
2013-10-10 15:23:20 +00:00
|
|
|
virtual void Apply(Solver* const s) { sequence_->RankLast(index_); }
|
2011-12-16 21:02:59 +00:00
|
|
|
|
2013-10-10 15:23:20 +00:00
|
|
|
virtual void Refute(Solver* const s) { sequence_->RankNotLast(index_); }
|
2011-12-16 21:02:59 +00:00
|
|
|
|
|
|
|
|
void Accept(DecisionVisitor* const visitor) const {
|
2013-10-10 15:23:20 +00:00
|
|
|
CHECK(visitor != nullptr);
|
2011-12-16 21:02:59 +00:00
|
|
|
visitor->VisitRankLastInterval(sequence_, index_);
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-16 10:24:42 +00:00
|
|
|
virtual std::string DebugString() const {
|
2013-10-10 15:23:20 +00:00
|
|
|
return StringPrintf("RankLast(%s, %d)", sequence_->DebugString().c_str(),
|
|
|
|
|
index_);
|
2011-12-16 21:02:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
SequenceVar* const sequence_;
|
|
|
|
|
const int index_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class RankFirstIntervalVars : public DecisionBuilder {
|
2010-09-15 12:42:33 +00:00
|
|
|
public:
|
2013-10-10 15:23:20 +00:00
|
|
|
RankFirstIntervalVars(const std::vector<SequenceVar*>& sequences,
|
2011-12-16 21:02:59 +00:00
|
|
|
Solver::SequenceStrategy str)
|
2013-10-10 15:23:20 +00:00
|
|
|
: sequences_(sequences), strategy_(str) {}
|
2011-11-03 10:27:53 +00:00
|
|
|
|
2011-12-16 21:02:59 +00:00
|
|
|
virtual ~RankFirstIntervalVars() {}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
|
|
|
|
virtual Decision* Next(Solver* const s) {
|
2013-10-10 15:23:20 +00:00
|
|
|
SequenceVar* best_sequence = nullptr;
|
2012-07-21 01:19:32 +00:00
|
|
|
best_possible_firsts_.clear();
|
2011-12-16 21:02:59 +00:00
|
|
|
while (true) {
|
2012-07-21 01:19:32 +00:00
|
|
|
if (FindSequenceVar(s, &best_sequence)) {
|
2011-12-16 21:02:59 +00:00
|
|
|
// No not create a choice point if it is not needed.
|
2013-10-10 15:23:20 +00:00
|
|
|
DCHECK(best_sequence != nullptr);
|
2012-07-21 01:19:32 +00:00
|
|
|
if (best_possible_firsts_.size() == 1 &&
|
2013-10-10 15:23:20 +00:00
|
|
|
best_sequence->Interval(best_possible_firsts_.back())
|
|
|
|
|
->MustBePerformed()) {
|
2012-07-21 01:19:32 +00:00
|
|
|
best_sequence->RankFirst(best_possible_firsts_.back());
|
2011-12-16 21:02:59 +00:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
int best_interval = -1;
|
2012-07-21 01:19:32 +00:00
|
|
|
if (!FindIntervalVar(s, best_sequence, &best_interval)) {
|
2011-12-16 21:02:59 +00:00
|
|
|
s->Fail();
|
|
|
|
|
}
|
|
|
|
|
CHECK_NE(-1, best_interval);
|
|
|
|
|
return s->RevAlloc(new RankFirst(best_sequence, best_interval));
|
2013-10-10 15:23:20 +00:00
|
|
|
} else {
|
|
|
|
|
return nullptr;
|
2011-12-16 21:02:59 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void Accept(ModelVisitor* const visitor) const {
|
|
|
|
|
visitor->BeginVisitExtension(ModelVisitor::kVariableGroupExtension);
|
|
|
|
|
visitor->VisitSequenceArrayArgument(ModelVisitor::kSequencesArgument,
|
2013-10-10 15:23:20 +00:00
|
|
|
sequences_);
|
2011-12-16 21:02:59 +00:00
|
|
|
visitor->EndVisitExtension(ModelVisitor::kVariableGroupExtension);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
// Selects the interval var to rank.
|
|
|
|
|
bool FindIntervalVarOnStartMin(Solver* const s,
|
|
|
|
|
SequenceVar* const best_sequence,
|
|
|
|
|
int* const best_interval_index) {
|
|
|
|
|
int best_interval = -1;
|
|
|
|
|
int64 best_start_min = kint64max;
|
2012-07-21 01:19:32 +00:00
|
|
|
for (int index = 0; index < best_possible_firsts_.size(); ++index) {
|
|
|
|
|
const int candidate = best_possible_firsts_[index];
|
2011-12-16 21:02:59 +00:00
|
|
|
IntervalVar* const interval = best_sequence->Interval(candidate);
|
|
|
|
|
if (interval->StartMin() < best_start_min) {
|
|
|
|
|
best_interval = candidate;
|
|
|
|
|
best_start_min = interval->StartMin();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (best_interval == -1) {
|
|
|
|
|
return false;
|
|
|
|
|
} else {
|
|
|
|
|
*best_interval_index = best_interval;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool FindIntervalVarRandomly(Solver* const s,
|
|
|
|
|
SequenceVar* const best_sequence,
|
|
|
|
|
int* const best_interval_index) {
|
2012-07-21 01:19:32 +00:00
|
|
|
DCHECK(!best_possible_firsts_.empty());
|
|
|
|
|
const int index = s->Rand32(best_possible_firsts_.size());
|
|
|
|
|
*best_interval_index = best_possible_firsts_[index];
|
2011-12-16 21:02:59 +00:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-10 15:23:20 +00:00
|
|
|
bool FindIntervalVar(Solver* const s, SequenceVar* const best_sequence,
|
2011-12-16 21:02:59 +00:00
|
|
|
int* const best_interval_index) {
|
|
|
|
|
switch (strategy_) {
|
|
|
|
|
case Solver::SEQUENCE_DEFAULT:
|
|
|
|
|
case Solver::SEQUENCE_SIMPLE:
|
|
|
|
|
case Solver::CHOOSE_MIN_SLACK_RANK_FORWARD:
|
2013-10-10 15:23:20 +00:00
|
|
|
return FindIntervalVarOnStartMin(s, best_sequence, best_interval_index);
|
2011-12-16 21:02:59 +00:00
|
|
|
case Solver::CHOOSE_RANDOM_RANK_FORWARD:
|
2013-10-10 15:23:20 +00:00
|
|
|
return FindIntervalVarRandomly(s, best_sequence, best_interval_index);
|
2011-12-16 21:02:59 +00:00
|
|
|
default:
|
|
|
|
|
LOG(FATAL) << "Unknown strategy " << strategy_;
|
2012-08-19 17:31:03 +00:00
|
|
|
return false;
|
2011-12-16 21:02:59 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Selects the sequence var to start ranking.
|
|
|
|
|
bool FindSequenceVarOnSlack(Solver* const s,
|
2013-01-10 17:01:34 +00:00
|
|
|
SequenceVar** const best_sequence) {
|
2011-11-03 10:27:53 +00:00
|
|
|
int64 best_slack = kint64max;
|
|
|
|
|
int64 best_ahmin = kint64max;
|
2013-10-10 15:23:20 +00:00
|
|
|
*best_sequence = nullptr;
|
2012-07-21 01:19:32 +00:00
|
|
|
best_possible_firsts_.clear();
|
2013-10-10 15:23:20 +00:00
|
|
|
for (int i = 0; i < sequences_.size(); ++i) {
|
2011-11-03 10:27:53 +00:00
|
|
|
SequenceVar* const candidate_sequence = sequences_[i];
|
2012-07-21 01:19:32 +00:00
|
|
|
int ranked = 0;
|
|
|
|
|
int not_ranked = 0;
|
|
|
|
|
int unperformed = 0;
|
|
|
|
|
candidate_sequence->ComputeStatistics(&ranked, ¬_ranked, &unperformed);
|
|
|
|
|
if (not_ranked > 0) {
|
2013-06-11 14:49:19 +00:00
|
|
|
candidate_possible_firsts_.clear();
|
|
|
|
|
candidate_possible_lasts_.clear();
|
2011-12-16 21:02:59 +00:00
|
|
|
candidate_sequence->ComputePossibleFirstsAndLasts(
|
2013-10-10 15:23:20 +00:00
|
|
|
&candidate_possible_firsts_, &candidate_possible_lasts_);
|
2011-11-03 10:27:53 +00:00
|
|
|
// No possible first, failing.
|
2013-06-11 14:49:19 +00:00
|
|
|
if (candidate_possible_firsts_.size() == 0) {
|
2011-11-03 10:27:53 +00:00
|
|
|
s->Fail();
|
|
|
|
|
}
|
|
|
|
|
// Only 1 candidate, and non optional: ranking without branching.
|
2013-06-11 14:49:19 +00:00
|
|
|
if (candidate_possible_firsts_.size() == 1 &&
|
2013-10-10 15:23:20 +00:00
|
|
|
candidate_sequence->Interval(candidate_possible_firsts_.back())
|
|
|
|
|
->MustBePerformed()) {
|
2011-12-16 21:02:59 +00:00
|
|
|
*best_sequence = candidate_sequence;
|
2013-06-11 14:49:19 +00:00
|
|
|
best_possible_firsts_ = candidate_possible_firsts_;
|
2011-12-16 21:02:59 +00:00
|
|
|
return true;
|
2011-11-03 10:27:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Evaluating the sequence.
|
2010-09-15 12:42:33 +00:00
|
|
|
int64 hmin, hmax, dmin, dmax;
|
2011-11-03 10:27:53 +00:00
|
|
|
candidate_sequence->HorizonRange(&hmin, &hmax);
|
|
|
|
|
candidate_sequence->DurationRange(&dmin, &dmax);
|
|
|
|
|
int64 ahmin, ahmax;
|
|
|
|
|
candidate_sequence->ActiveHorizonRange(&ahmin, &ahmax);
|
2010-09-15 12:42:33 +00:00
|
|
|
const int64 current_slack = (hmax - hmin - dmax);
|
2011-11-03 10:27:53 +00:00
|
|
|
if (current_slack < best_slack ||
|
|
|
|
|
(current_slack == best_slack && ahmin < best_ahmin)) {
|
|
|
|
|
best_slack = current_slack;
|
2011-12-16 21:02:59 +00:00
|
|
|
*best_sequence = candidate_sequence;
|
2013-06-11 14:49:19 +00:00
|
|
|
best_possible_firsts_ = candidate_possible_firsts_;
|
2011-11-03 10:27:53 +00:00
|
|
|
best_ahmin = ahmin;
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-10-10 15:23:20 +00:00
|
|
|
return *best_sequence != nullptr;
|
2011-12-16 21:02:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool FindSequenceVarRandomly(Solver* const s,
|
2013-01-10 17:01:34 +00:00
|
|
|
SequenceVar** const best_sequence) {
|
2013-07-30 21:41:29 +00:00
|
|
|
std::vector<SequenceVar*> all_candidates;
|
|
|
|
|
std::vector<std::vector<int>> all_possible_firsts;
|
2013-10-10 15:23:20 +00:00
|
|
|
for (int i = 0; i < sequences_.size(); ++i) {
|
2011-12-16 21:02:59 +00:00
|
|
|
SequenceVar* const candidate_sequence = sequences_[i];
|
2012-07-21 01:19:32 +00:00
|
|
|
int ranked = 0;
|
|
|
|
|
int not_ranked = 0;
|
|
|
|
|
int unperformed = 0;
|
|
|
|
|
candidate_sequence->ComputeStatistics(&ranked, ¬_ranked, &unperformed);
|
|
|
|
|
if (not_ranked > 0) {
|
2013-06-11 14:49:19 +00:00
|
|
|
candidate_possible_firsts_.clear();
|
|
|
|
|
candidate_possible_lasts_.clear();
|
2011-12-16 21:02:59 +00:00
|
|
|
candidate_sequence->ComputePossibleFirstsAndLasts(
|
2013-10-10 15:23:20 +00:00
|
|
|
&candidate_possible_firsts_, &candidate_possible_lasts_);
|
2011-12-16 21:02:59 +00:00
|
|
|
// No possible first, failing.
|
2013-06-11 14:49:19 +00:00
|
|
|
if (candidate_possible_firsts_.size() == 0) {
|
2011-12-16 21:02:59 +00:00
|
|
|
s->Fail();
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
2011-12-16 21:02:59 +00:00
|
|
|
// Only 1 candidate, and non optional: ranking without branching.
|
2013-06-11 14:49:19 +00:00
|
|
|
if (candidate_possible_firsts_.size() == 1 &&
|
2013-10-10 15:23:20 +00:00
|
|
|
candidate_sequence->Interval(candidate_possible_firsts_.back())
|
|
|
|
|
->MustBePerformed()) {
|
2011-12-16 21:02:59 +00:00
|
|
|
*best_sequence = candidate_sequence;
|
2013-06-11 14:49:19 +00:00
|
|
|
best_possible_firsts_ = candidate_possible_firsts_;
|
2011-12-16 21:02:59 +00:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-30 21:41:29 +00:00
|
|
|
all_candidates.push_back(candidate_sequence);
|
2013-06-11 14:49:19 +00:00
|
|
|
all_possible_firsts.push_back(candidate_possible_firsts_);
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
2011-12-16 21:02:59 +00:00
|
|
|
if (all_candidates.empty()) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
const int chosen = s->Rand32(all_candidates.size());
|
2013-07-30 21:41:29 +00:00
|
|
|
*best_sequence = all_candidates[chosen];
|
2012-07-21 01:19:32 +00:00
|
|
|
best_possible_firsts_ = all_possible_firsts[chosen];
|
2011-12-16 21:02:59 +00:00
|
|
|
return true;
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
2011-08-11 05:15:18 +00:00
|
|
|
|
2013-10-10 15:23:20 +00:00
|
|
|
bool FindSequenceVar(Solver* const s, SequenceVar** const best_sequence) {
|
2011-12-16 21:02:59 +00:00
|
|
|
switch (strategy_) {
|
|
|
|
|
case Solver::SEQUENCE_DEFAULT:
|
|
|
|
|
case Solver::SEQUENCE_SIMPLE:
|
|
|
|
|
case Solver::CHOOSE_MIN_SLACK_RANK_FORWARD:
|
2012-07-21 01:19:32 +00:00
|
|
|
return FindSequenceVarOnSlack(s, best_sequence);
|
2011-12-16 21:02:59 +00:00
|
|
|
case Solver::CHOOSE_RANDOM_RANK_FORWARD:
|
2012-07-21 01:19:32 +00:00
|
|
|
return FindSequenceVarRandomly(s, best_sequence);
|
2011-12-16 21:02:59 +00:00
|
|
|
default:
|
|
|
|
|
LOG(FATAL) << "Unknown strategy " << strategy_;
|
|
|
|
|
}
|
2011-08-11 05:15:18 +00:00
|
|
|
}
|
|
|
|
|
|
2013-10-10 15:23:20 +00:00
|
|
|
const std::vector<SequenceVar*> sequences_;
|
2011-12-16 21:02:59 +00:00
|
|
|
const Solver::SequenceStrategy strategy_;
|
2013-01-10 17:01:34 +00:00
|
|
|
std::vector<int> best_possible_firsts_;
|
2013-06-11 14:49:19 +00:00
|
|
|
std::vector<int> candidate_possible_firsts_;
|
|
|
|
|
std::vector<int> candidate_possible_lasts_;
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
2011-08-11 05:15:18 +00:00
|
|
|
} // namespace
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2013-10-10 15:23:20 +00:00
|
|
|
Decision* Solver::MakeScheduleOrPostpone(IntervalVar* const var, int64 est,
|
2011-12-16 21:02:59 +00:00
|
|
|
int64* const marker) {
|
2013-10-10 15:23:20 +00:00
|
|
|
CHECK(var != nullptr);
|
|
|
|
|
CHECK(marker != nullptr);
|
2011-12-16 21:02:59 +00:00
|
|
|
return RevAlloc(new ScheduleOrPostpone(var, est, marker));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DecisionBuilder* Solver::MakePhase(const std::vector<IntervalVar*>& intervals,
|
|
|
|
|
IntervalStrategy str) {
|
2013-10-10 15:23:20 +00:00
|
|
|
return RevAlloc(new SetTimesForward(intervals));
|
2011-12-16 21:02:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Decision* Solver::MakeRankFirstInterval(SequenceVar* const sequence,
|
|
|
|
|
int index) {
|
2013-10-10 15:23:20 +00:00
|
|
|
CHECK(sequence != nullptr);
|
2011-12-16 21:02:59 +00:00
|
|
|
return RevAlloc(new RankFirst(sequence, index));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Decision* Solver::MakeRankLastInterval(SequenceVar* const sequence, int index) {
|
2013-10-10 15:23:20 +00:00
|
|
|
CHECK(sequence != nullptr);
|
2011-12-16 21:02:59 +00:00
|
|
|
return RevAlloc(new RankLast(sequence, index));
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-03 10:27:53 +00:00
|
|
|
DecisionBuilder* Solver::MakePhase(const std::vector<SequenceVar*>& sequences,
|
2010-09-15 12:42:33 +00:00
|
|
|
SequenceStrategy str) {
|
2013-10-10 15:23:20 +00:00
|
|
|
return RevAlloc(new RankFirstIntervalVars(sequences, str));
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace operations_research
|