move jobshop ls and lns operator in separate header file; use it (effectively) in jobshop early tardy
This commit is contained in:
@@ -45,6 +45,7 @@
|
||||
#include "linear_solver/linear_solver.h"
|
||||
#include "util/string_array.h"
|
||||
#include "cpp/jobshop_earlytardy.h"
|
||||
#include "cpp/jobshop_ls.h"
|
||||
|
||||
DEFINE_string(
|
||||
jet_file,
|
||||
@@ -66,6 +67,13 @@ DEFINE_int32(scale_factor, 130, "Scale factor (in percent)");
|
||||
DEFINE_int32(seed, 1, "Random seed");
|
||||
DEFINE_int32(time_limit_in_ms, 0, "Time limit in ms, 0 means no limit.");
|
||||
DEFINE_bool(time_placement, false, "Use MIP based time placement");
|
||||
DEFINE_int32(shuffle_length, 4, "Length of sub-sequences to shuffle LS.");
|
||||
DEFINE_int32(sub_sequence_length, 4,
|
||||
"Length of sub-sequences to relax in LNS.");
|
||||
DEFINE_int32(lns_seed, 1, "Seed of the LNS random search");
|
||||
DEFINE_int32(lns_limit, 30,
|
||||
"Limit the size of the search tree in a LNS fragment");
|
||||
DEFINE_bool(use_ls, false, "Use ls");
|
||||
DECLARE_bool(log_prefix);
|
||||
|
||||
namespace operations_research {
|
||||
@@ -294,7 +302,7 @@ void EtJobShop(const EtJobShopData& data) {
|
||||
|
||||
// This decision builder will rank all tasks on all machines.
|
||||
DecisionBuilder* const sequence_phase =
|
||||
solver.MakePhase(all_sequences, Solver::SEQUENCE_DEFAULT);
|
||||
solver.MakePhase(all_sequences, Solver::CHOOSE_MIN_SLACK_RANK_FORWARD);
|
||||
|
||||
// After the ranking of tasks, the schedule is still loose and any
|
||||
// task can be postponed at will. But, because the problem is now a PERT
|
||||
@@ -309,23 +317,102 @@ void EtJobShop(const EtJobShopData& data) {
|
||||
Solver::CHOOSE_FIRST_UNBOUND,
|
||||
Solver::ASSIGN_MIN_VALUE);
|
||||
|
||||
// The main decision builder (ranks all tasks, then fixes the
|
||||
// objective_variable).
|
||||
DecisionBuilder* const main_phase =
|
||||
solver.Compose(sequence_phase, obj_phase);
|
||||
if (FLAGS_use_ls) {
|
||||
Assignment* const first_solution = solver.MakeAssignment();
|
||||
first_solution->Add(all_sequences);
|
||||
first_solution->AddObjective(objective_var);
|
||||
// Store the first solution in the 'solution' object.
|
||||
DecisionBuilder* const store_db =
|
||||
solver.MakeStoreAssignment(first_solution);
|
||||
|
||||
// Search log.
|
||||
const int kLogFrequency = 1000000;
|
||||
SearchMonitor* const search_log =
|
||||
solver.MakeSearchLog(kLogFrequency, objective_monitor);
|
||||
// The main decision builder (ranks all tasks, then fixes the
|
||||
// objective_variable).
|
||||
DecisionBuilder* const first_solution_phase =
|
||||
solver.Compose(sequence_phase, obj_phase, store_db);
|
||||
|
||||
SearchLimit* limit = NULL;
|
||||
if (FLAGS_time_limit_in_ms > 0) {
|
||||
limit = solver.MakeTimeLimit(FLAGS_time_limit_in_ms);
|
||||
LOG(INFO) << "Looking for the first solution";
|
||||
const bool first_solution_found = solver.Solve(first_solution_phase);
|
||||
if (first_solution_found) {
|
||||
LOG(INFO) << "Solution found with penalty cost of = "
|
||||
<< first_solution->ObjectiveValue();
|
||||
} else {
|
||||
LOG(INFO) << "No initial solution found!";
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(INFO) << "Switching to local search";
|
||||
std::vector<LocalSearchOperator*> operators;
|
||||
LOG(INFO) << " - use swap operator";
|
||||
LocalSearchOperator* const swap_operator =
|
||||
solver.RevAlloc(new SwapIntervals(all_sequences.data(),
|
||||
all_sequences.size()));
|
||||
operators.push_back(swap_operator);
|
||||
LOG(INFO) << " - use shuffle operator with a max length of "
|
||||
<< FLAGS_shuffle_length;
|
||||
LocalSearchOperator* const shuffle_operator =
|
||||
solver.RevAlloc(new ShuffleIntervals(all_sequences.data(),
|
||||
all_sequences.size(),
|
||||
FLAGS_shuffle_length));
|
||||
operators.push_back(shuffle_operator);
|
||||
LOG(INFO) << " - use free sub sequences of length "
|
||||
<< FLAGS_sub_sequence_length << " lns operator";
|
||||
LocalSearchOperator* const lns_operator =
|
||||
solver.RevAlloc(new SequenceLns(all_sequences.data(),
|
||||
all_sequences.size(),
|
||||
FLAGS_lns_seed,
|
||||
FLAGS_sub_sequence_length));
|
||||
operators.push_back(lns_operator);
|
||||
|
||||
// Creates the local search decision builder.
|
||||
LocalSearchOperator* const concat =
|
||||
solver.ConcatenateOperators(operators, true);
|
||||
|
||||
SearchLimit* const ls_limit =
|
||||
solver.MakeLimit(kint64max, FLAGS_lns_limit, kint64max, kint64max);
|
||||
DecisionBuilder* const random_sequence_phase =
|
||||
solver.MakePhase(all_sequences, Solver::CHOOSE_RANDOM_RANK_FORWARD);
|
||||
DecisionBuilder* const ls_db =
|
||||
solver.MakeSolveOnce(solver.Compose(random_sequence_phase, obj_phase),
|
||||
ls_limit);
|
||||
|
||||
LocalSearchPhaseParameters* const parameters =
|
||||
solver.MakeLocalSearchPhaseParameters(concat, ls_db);
|
||||
DecisionBuilder* const final_db =
|
||||
solver.MakeLocalSearchPhase(first_solution, parameters);
|
||||
|
||||
OptimizeVar* const objective_monitor =
|
||||
solver.MakeMinimize(objective_var, 1);
|
||||
|
||||
// Search log.
|
||||
const int kLogFrequency = 1000000;
|
||||
SearchMonitor* const search_log =
|
||||
solver.MakeSearchLog(kLogFrequency, objective_monitor);
|
||||
|
||||
SearchLimit* const limit = FLAGS_time_limit_in_ms > 0 ?
|
||||
solver.MakeTimeLimit(FLAGS_time_limit_in_ms) :
|
||||
NULL;
|
||||
|
||||
// Search.
|
||||
solver.Solve(final_db, search_log, objective_monitor, limit);
|
||||
} else {
|
||||
// The main decision builder (ranks all tasks, then fixes the
|
||||
// objective_variable).
|
||||
DecisionBuilder* const main_phase =
|
||||
solver.Compose(sequence_phase, obj_phase);
|
||||
|
||||
// Search log.
|
||||
const int kLogFrequency = 1000000;
|
||||
SearchMonitor* const search_log =
|
||||
solver.MakeSearchLog(kLogFrequency, objective_monitor);
|
||||
|
||||
SearchLimit* limit = NULL;
|
||||
if (FLAGS_time_limit_in_ms > 0) {
|
||||
limit = solver.MakeTimeLimit(FLAGS_time_limit_in_ms);
|
||||
}
|
||||
|
||||
// Search.
|
||||
solver.Solve(main_phase, search_log, objective_monitor, limit);
|
||||
}
|
||||
|
||||
// Search.
|
||||
solver.Solve(main_phase, search_log, objective_monitor, limit);
|
||||
}
|
||||
} // namespace operations_research
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
#include "constraint_solver/constraint_solver.h"
|
||||
#include "constraint_solver/constraint_solveri.h"
|
||||
#include "cpp/jobshop.h"
|
||||
#include "cpp/jobshop_ls.h"
|
||||
|
||||
DEFINE_string(
|
||||
data_file,
|
||||
@@ -65,210 +66,6 @@ DEFINE_int32(lns_limit, 30,
|
||||
|
||||
|
||||
namespace operations_research {
|
||||
// ----- Exchange 2 intervals on a sequence variable -----
|
||||
|
||||
class SwapIntervals : public SequenceVarLocalSearchOperator {
|
||||
public:
|
||||
SwapIntervals(const SequenceVar* const* vars, int size)
|
||||
: SequenceVarLocalSearchOperator(vars, size),
|
||||
current_var_(-1),
|
||||
current_first_(-1),
|
||||
current_second_(-1) {}
|
||||
|
||||
virtual ~SwapIntervals() {}
|
||||
|
||||
virtual bool MakeNextNeighbor(Assignment* delta, Assignment* deltadelta) {
|
||||
CHECK_NOTNULL(delta);
|
||||
while (true) {
|
||||
RevertChanges(true);
|
||||
if (!Increment()) {
|
||||
VLOG(1) << "finished neighborhood";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<int> sequence = Sequence(current_var_);
|
||||
const int tmp = sequence[current_first_];
|
||||
sequence[current_first_] = sequence[current_second_];
|
||||
sequence[current_second_] = tmp;
|
||||
SetForwardSequence(current_var_, sequence);
|
||||
if (ApplyChanges(delta, deltadelta)) {
|
||||
VLOG(1) << "Delta = " << delta->DebugString();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void OnStart() {
|
||||
VLOG(1) << "start neighborhood";
|
||||
current_var_ = 0;
|
||||
current_first_ = 0;
|
||||
current_second_ = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
bool Increment() {
|
||||
const SequenceVar* const var = Var(current_var_);
|
||||
if (++current_second_ >= var->size()) {
|
||||
if (++current_first_ >= var->size() - 1) {
|
||||
current_var_++;
|
||||
current_first_ = 0;
|
||||
}
|
||||
current_second_ = current_first_ + 1;
|
||||
}
|
||||
return current_var_ < Size();
|
||||
}
|
||||
|
||||
int current_var_;
|
||||
int current_first_;
|
||||
int current_second_;
|
||||
};
|
||||
|
||||
// ----- Shuffle a fixed-length sub-sequence on one sequence variable -----
|
||||
|
||||
class ShuffleIntervals : public SequenceVarLocalSearchOperator {
|
||||
public:
|
||||
ShuffleIntervals(const SequenceVar* const* vars, int size, int max_length)
|
||||
: SequenceVarLocalSearchOperator(vars, size),
|
||||
max_length_(max_length),
|
||||
current_var_(-1),
|
||||
current_first_(-1),
|
||||
current_index_(-1),
|
||||
current_length_(-1) {}
|
||||
|
||||
virtual ~ShuffleIntervals() {}
|
||||
|
||||
virtual bool MakeNextNeighbor(Assignment* delta, Assignment* deltadelta) {
|
||||
CHECK_NOTNULL(delta);
|
||||
while (true) {
|
||||
RevertChanges(true);
|
||||
if (!Increment()) {
|
||||
VLOG(1) << "finished neighborhood";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<int> sequence = Sequence(current_var_);
|
||||
std::vector<int> sequence_backup(current_length_);
|
||||
for (int i = 0; i < current_length_; ++i) {
|
||||
sequence_backup[i] = sequence[i + current_first_];
|
||||
}
|
||||
for (int i = 0; i < current_length_; ++i) {
|
||||
sequence[i + current_first_] =
|
||||
sequence_backup[current_permutation_[i]];
|
||||
}
|
||||
SetForwardSequence(current_var_, sequence);
|
||||
if (ApplyChanges(delta, deltadelta)) {
|
||||
VLOG(1) << "Delta = " << delta->DebugString();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void OnStart() {
|
||||
VLOG(1) << "start neighborhood";
|
||||
current_var_ = 0;
|
||||
current_first_ = 0;
|
||||
current_index_ = -1;
|
||||
current_length_ = std::min(Var(current_var_)->size(), max_length_);
|
||||
current_permutation_.resize(current_length_);
|
||||
for (int i = 0; i < current_length_; ++i) {
|
||||
current_permutation_[i] = i;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool Increment() {
|
||||
if (!std::next_permutation(current_permutation_.begin(),
|
||||
current_permutation_.end())) {
|
||||
if (++current_first_ >= Var(current_var_)->size() - current_length_) {
|
||||
if (++current_var_ >= Size()) {
|
||||
return false;
|
||||
}
|
||||
current_first_ = 0;
|
||||
current_length_ = std::min(Var(current_var_)->size(), max_length_);
|
||||
current_permutation_.resize(current_length_);
|
||||
}
|
||||
current_index_ = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const int max_length_;
|
||||
int current_var_;
|
||||
int current_first_;
|
||||
int current_index_;
|
||||
int current_length_;
|
||||
std::vector<int> current_permutation_;
|
||||
};
|
||||
|
||||
// ----- LNS Operator -----
|
||||
|
||||
class SequenceLns : public SequenceVarLocalSearchOperator {
|
||||
public:
|
||||
SequenceLns(const SequenceVar* const* vars,
|
||||
int size,
|
||||
int seed,
|
||||
int max_length)
|
||||
: SequenceVarLocalSearchOperator(vars, size),
|
||||
random_(seed),
|
||||
max_length_(max_length) {}
|
||||
|
||||
virtual ~SequenceLns() {}
|
||||
|
||||
virtual bool MakeNextNeighbor(Assignment* delta, Assignment* deltadelta) {
|
||||
CHECK_NOTNULL(delta);
|
||||
while (true) {
|
||||
RevertChanges(true);
|
||||
if (random_.Uniform(2) == 0) {
|
||||
FreeTimeWindow();
|
||||
} else {
|
||||
FreeTwoResources();
|
||||
}
|
||||
if (ApplyChanges(delta, deltadelta)) {
|
||||
VLOG(1) << "Delta = " << delta->DebugString();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
void FreeTimeWindow() {
|
||||
for (int i = 0; i < Size(); ++i) {
|
||||
std::vector<int> sequence = Sequence(i);
|
||||
const int current_length =
|
||||
std::min(static_cast<int>(sequence.size()), max_length_);
|
||||
const int start_position =
|
||||
random_.Uniform(sequence.size() - current_length);
|
||||
std::vector<int> forward;
|
||||
for (int j = 0; j < start_position; ++j) {
|
||||
forward.push_back(sequence[j]);
|
||||
}
|
||||
std::vector<int> backward;
|
||||
for (int j = sequence.size() - 1;
|
||||
j >= start_position + current_length;
|
||||
--j) {
|
||||
backward.push_back(sequence[j]);
|
||||
}
|
||||
SetForwardSequence(i, forward);
|
||||
SetBackwardSequence(i, backward);
|
||||
}
|
||||
}
|
||||
|
||||
void FreeTwoResources() {
|
||||
std::vector<int> free_sequence;
|
||||
SetForwardSequence(random_.Uniform(Size()), free_sequence);
|
||||
SetForwardSequence(random_.Uniform(Size()), free_sequence);
|
||||
}
|
||||
|
||||
ACMRandom random_;
|
||||
const int max_length_;
|
||||
};
|
||||
|
||||
|
||||
// ----- Model and Solve -----
|
||||
|
||||
void JobshopLs(const JobShopData& data) {
|
||||
|
||||
253
examples/cpp/jobshop_ls.h
Normal file
253
examples/cpp/jobshop_ls.h
Normal file
@@ -0,0 +1,253 @@
|
||||
// Copyright 2010-2012 Google
|
||||
// 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.
|
||||
//
|
||||
// This model implements a simple jobshop problem.
|
||||
//
|
||||
// A jobshop is a standard scheduling problem where you must schedule a
|
||||
// set of jobs on a set of machines. Each job is a sequence of tasks
|
||||
// (a task can only start when the preceding task finished), each of
|
||||
// which occupies a single specific machine during a specific
|
||||
// duration. Therefore, a job is simply given by a sequence of pairs
|
||||
// (machine id, duration).
|
||||
|
||||
// The objective is to minimize the 'makespan', which is the duration
|
||||
// between the start of the first task (across all machines) and the
|
||||
// completion of the last task (across all machines).
|
||||
//
|
||||
// This will be modelled by sets of intervals variables (see class
|
||||
// IntervalVar in constraint_solver/constraint_solver.h), one per
|
||||
// task, representing the [start_time, end_time] of the task. Tasks
|
||||
// in the same job will be linked by precedence constraints. Tasks on
|
||||
// the same machine will be covered by Sequence constraints.
|
||||
//
|
||||
// Search will be implemented as local search on the sequence variables.
|
||||
|
||||
#ifndef OR_TOOLS_EXAMPLES_JOBSHOP_LS_H_
|
||||
#define OR_TOOLS_EXAMPLES_JOBSHOP_LS_H_
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "base/commandlineflags.h"
|
||||
#include "base/commandlineflags.h"
|
||||
#include "base/integral_types.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/stringprintf.h"
|
||||
#include "base/bitmap.h"
|
||||
#include "constraint_solver/constraint_solver.h"
|
||||
#include "constraint_solver/constraint_solveri.h"
|
||||
|
||||
namespace operations_research {
|
||||
// ----- Exchange 2 intervals on a sequence variable -----
|
||||
|
||||
class SwapIntervals : public SequenceVarLocalSearchOperator {
|
||||
public:
|
||||
SwapIntervals(const SequenceVar* const* vars, int size)
|
||||
: SequenceVarLocalSearchOperator(vars, size),
|
||||
current_var_(-1),
|
||||
current_first_(-1),
|
||||
current_second_(-1) {}
|
||||
|
||||
virtual ~SwapIntervals() {}
|
||||
|
||||
virtual bool MakeNextNeighbor(Assignment* delta, Assignment* deltadelta) {
|
||||
CHECK_NOTNULL(delta);
|
||||
while (true) {
|
||||
RevertChanges(true);
|
||||
if (!Increment()) {
|
||||
VLOG(1) << "finished neighborhood";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<int> sequence = Sequence(current_var_);
|
||||
const int tmp = sequence[current_first_];
|
||||
sequence[current_first_] = sequence[current_second_];
|
||||
sequence[current_second_] = tmp;
|
||||
SetForwardSequence(current_var_, sequence);
|
||||
if (ApplyChanges(delta, deltadelta)) {
|
||||
VLOG(1) << "Delta = " << delta->DebugString();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void OnStart() {
|
||||
VLOG(1) << "start neighborhood";
|
||||
current_var_ = 0;
|
||||
current_first_ = 0;
|
||||
current_second_ = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
bool Increment() {
|
||||
const SequenceVar* const var = Var(current_var_);
|
||||
if (++current_second_ >= var->size()) {
|
||||
if (++current_first_ >= var->size() - 1) {
|
||||
current_var_++;
|
||||
current_first_ = 0;
|
||||
}
|
||||
current_second_ = current_first_ + 1;
|
||||
}
|
||||
return current_var_ < Size();
|
||||
}
|
||||
|
||||
int current_var_;
|
||||
int current_first_;
|
||||
int current_second_;
|
||||
};
|
||||
|
||||
// ----- Shuffle a fixed-length sub-sequence on one sequence variable -----
|
||||
|
||||
class ShuffleIntervals : public SequenceVarLocalSearchOperator {
|
||||
public:
|
||||
ShuffleIntervals(const SequenceVar* const* vars, int size, int max_length)
|
||||
: SequenceVarLocalSearchOperator(vars, size),
|
||||
max_length_(max_length),
|
||||
current_var_(-1),
|
||||
current_first_(-1),
|
||||
current_index_(-1),
|
||||
current_length_(-1) {}
|
||||
|
||||
virtual ~ShuffleIntervals() {}
|
||||
|
||||
virtual bool MakeNextNeighbor(Assignment* delta, Assignment* deltadelta) {
|
||||
CHECK_NOTNULL(delta);
|
||||
while (true) {
|
||||
RevertChanges(true);
|
||||
if (!Increment()) {
|
||||
VLOG(1) << "finished neighborhood";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<int> sequence = Sequence(current_var_);
|
||||
std::vector<int> sequence_backup(current_length_);
|
||||
for (int i = 0; i < current_length_; ++i) {
|
||||
sequence_backup[i] = sequence[i + current_first_];
|
||||
}
|
||||
for (int i = 0; i < current_length_; ++i) {
|
||||
sequence[i + current_first_] =
|
||||
sequence_backup[current_permutation_[i]];
|
||||
}
|
||||
SetForwardSequence(current_var_, sequence);
|
||||
if (ApplyChanges(delta, deltadelta)) {
|
||||
VLOG(1) << "Delta = " << delta->DebugString();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void OnStart() {
|
||||
VLOG(1) << "start neighborhood";
|
||||
current_var_ = 0;
|
||||
current_first_ = 0;
|
||||
current_index_ = -1;
|
||||
current_length_ = std::min(Var(current_var_)->size(), max_length_);
|
||||
current_permutation_.resize(current_length_);
|
||||
for (int i = 0; i < current_length_; ++i) {
|
||||
current_permutation_[i] = i;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool Increment() {
|
||||
if (!std::next_permutation(current_permutation_.begin(),
|
||||
current_permutation_.end())) {
|
||||
if (++current_first_ >= Var(current_var_)->size() - current_length_) {
|
||||
if (++current_var_ >= Size()) {
|
||||
return false;
|
||||
}
|
||||
current_first_ = 0;
|
||||
current_length_ = std::min(Var(current_var_)->size(), max_length_);
|
||||
current_permutation_.resize(current_length_);
|
||||
}
|
||||
current_index_ = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const int max_length_;
|
||||
int current_var_;
|
||||
int current_first_;
|
||||
int current_index_;
|
||||
int current_length_;
|
||||
std::vector<int> current_permutation_;
|
||||
};
|
||||
|
||||
// ----- LNS Operator -----
|
||||
|
||||
class SequenceLns : public SequenceVarLocalSearchOperator {
|
||||
public:
|
||||
SequenceLns(const SequenceVar* const* vars,
|
||||
int size,
|
||||
int seed,
|
||||
int max_length)
|
||||
: SequenceVarLocalSearchOperator(vars, size),
|
||||
random_(seed),
|
||||
max_length_(max_length) {}
|
||||
|
||||
virtual ~SequenceLns() {}
|
||||
|
||||
virtual bool MakeNextNeighbor(Assignment* delta, Assignment* deltadelta) {
|
||||
CHECK_NOTNULL(delta);
|
||||
while (true) {
|
||||
RevertChanges(true);
|
||||
if (random_.Uniform(2) == 0) {
|
||||
FreeTimeWindow();
|
||||
} else {
|
||||
FreeTwoResources();
|
||||
}
|
||||
if (ApplyChanges(delta, deltadelta)) {
|
||||
VLOG(1) << "Delta = " << delta->DebugString();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
void FreeTimeWindow() {
|
||||
for (int i = 0; i < Size(); ++i) {
|
||||
std::vector<int> sequence = Sequence(i);
|
||||
const int current_length =
|
||||
std::min(static_cast<int>(sequence.size()), max_length_);
|
||||
const int start_position =
|
||||
random_.Uniform(sequence.size() - current_length);
|
||||
std::vector<int> forward;
|
||||
for (int j = 0; j < start_position; ++j) {
|
||||
forward.push_back(sequence[j]);
|
||||
}
|
||||
std::vector<int> backward;
|
||||
for (int j = sequence.size() - 1;
|
||||
j >= start_position + current_length;
|
||||
--j) {
|
||||
backward.push_back(sequence[j]);
|
||||
}
|
||||
SetForwardSequence(i, forward);
|
||||
SetBackwardSequence(i, backward);
|
||||
}
|
||||
}
|
||||
|
||||
void FreeTwoResources() {
|
||||
std::vector<int> free_sequence;
|
||||
SetForwardSequence(random_.Uniform(Size()), free_sequence);
|
||||
SetForwardSequence(random_.Uniform(Size()), free_sequence);
|
||||
}
|
||||
|
||||
ACMRandom random_;
|
||||
const int max_length_;
|
||||
};
|
||||
} // namespace operations_research
|
||||
#endif // OR_TOOLS_EXAMPLES_JOBSHOP_LS_H_
|
||||
Reference in New Issue
Block a user