Commit 7c82793b authored by Valentin Antuori's avatar Valentin Antuori
Browse files

Dfs integration - restart

parent 45ee57d6
......@@ -45,6 +45,10 @@ double DFSRollout::fitness_func(const int action) const
auto prev_tardiness{maximum_positive_tardiness[maximum_positive_tardiness.size() - 2]};
// double lambda1{static_cast<double>(prev_tardiness-tardiness[action]) / static_cast<double>(data.max_slack)};
double lambda1{fast_sigmoid(prev_tardiness - tardiness[action], sigmoid_slope)};
// For Lambda1, test was with :
// double lambda1{static_cast<double>(data.due_date(action) - ect) / static_cast<double>(data.max_slack)};
double lambda2{static_cast<double>(start[action] - tour_length) / static_cast<double>(data.max_dist)};
double lambda3{1 - (static_cast<double>(data.trolley_length(action)) / static_cast<double>(data.T_max))};
double lambda4{static_cast<double>(data.is_pickup(action))};
......@@ -52,7 +56,7 @@ double DFSRollout::fitness_func(const int action) const
return 1 - (THETA_1 * lambda1 + THETA_2 * lambda2 + THETA_3 * lambda3 + THETA_4 * lambda4);
}
double DFSRollout::DFSRollout::get_avg_travel_time(const int op) const {
double DFSRollout::get_avg_travel_time(const int op) const {
return avg_travel_time[op % 4][data.component(op)];
}
......@@ -76,24 +80,34 @@ int DFSRollout::get_cur_train_time(const int op) const {
DFSRollout::DFSRollout(const Instance& data) : data(data) {
period.resize(data.nb_components, 0);
prev_operation.resize(data.nb_components, -1);
num_operation.resize(data.nb_components, 0);
start_period.resize(data.nb_components, 0);
saved_period.resize(data.nb_components, 0);
prev_operation.resize(data.nb_components, -1);
start_prev_operation.resize(data.nb_components, -1);
saved_prev_operation.resize(data.nb_components, -1);
num_operation.resize(data.nb_components, 0);
start_num_operation.resize(data.nb_components, 0);
saved_num_operation.resize(data.nb_components, 0);
start.resize(data.nb_tasks, 0);
distance.resize(data.nb_tasks, 0);
tardiness.resize(data.nb_tasks, 0);
proba.resize(data.nb_tasks, 0);
saved_start.resize(data.nb_tasks, 0);
maximum_positive_tardiness.push_back(0);
saved_maximum_positive_tardiness.push_back(0);
maximum_tardiness.push_back(numeric_limits<int>::min());
saved_maximum_tardiness.push_back(numeric_limits<int>::min());
domain.resize(data.nb_tasks);
action.resize(data.nb_tasks);
distance.resize(data.nb_tasks, 0);
tardiness.resize(data.nb_tasks, 0);
proba.resize(data.nb_tasks, 0);
domain.resize(data.nb_tasks);
action.resize(data.nb_tasks);
random_generator.seed(12345);
......@@ -110,41 +124,6 @@ DFSRollout::DFSRollout(const Instance& data) : data(data) {
}
void DFSRollout::clear(const int lvl) {
sequence.resize(lvl);
// std::fill(period.begin(), period.end(), 0);
// std::fill(num_operation.begin(), num_operation.end(), 0);
// std::fill(prev_operation.begin(), prev_operation.end(), -1);
for(auto i{0}; i<data.nb_components; ++i) {
period[i] = start_period[i];
num_operation[i] = start_num_operation[i];
prev_operation[i] = start_prev_operation[i];
}
// maximum_positive_tardiness.clear();
// maximum_positive_tardiness.push_back(0);
maximum_positive_tardiness.resize(1+lvl);
// maximum_tardiness.clear();
// maximum_tardiness.push_back(numeric_limits<int>::min());
maximum_tardiness.resize(1+lvl);
tour_length = start_tour_length;
train_length = start_train_length;
tardi_depth = lvl;
best_seq_max_tardiness.clear();
_period.clear();
_num_operation.clear();
_prev_operation.clear();
_tardi_depth = 0;
}
void DFSRollout::verify(const char* msg, const int offset) {
......@@ -321,6 +300,9 @@ void DFSRollout::compute_distance(const int op) {
}
tardiness[op] = component_ect(op) - data.due_date(op);
// Test was with :
// tardiness[op] = start[op] + data.duration(op) - data.due_date(op);
// auto f{(1.0 - fast_sigmoid(tardiness[op] - get_tardiness()))};
......@@ -451,8 +433,8 @@ void DFSRollout::greedy_stochastic(int upper_bound) {
compute_distances();
if(maximum_tardiness.back() == 0)
tardi_depth = sequence.size();
if(get_tardiness() == 0)
first_tard_depth = sequence.size();
if(!can_stop && get_tardiness() > 0)
{
......@@ -492,7 +474,7 @@ void DFSRollout::extend_rollout() {
if(get_tardiness() > 0)
{
timeout = tardi_depth + 1000;
timeout = first_tard_depth + 1000;
can_stop = true;
}
......@@ -501,6 +483,10 @@ void DFSRollout::extend_rollout() {
compute_distances();
// get_tardiness should be greater than 0 when extend a rollout
if(get_tardiness() == 0)
first_tard_depth = sequence.size();
if(!can_stop && get_tardiness() > 0)
{
timeout = sequence.size() + 1000;
......@@ -532,8 +518,13 @@ void DFSRollout::extend_rollout() {
void DFSRollout::do_op(const int op) {
compute_distance(op);
maximum_tardiness.push_back(tardiness[op]);
maximum_positive_tardiness.push_back(std::max(0,tardiness[op]));
// We shouldn't have tardiness
if(get_tardiness() == 0)
first_tard_depth = sequence.size();
commit(op);
}
......@@ -638,34 +629,107 @@ void DFSRollout::save_state()
}
verify("Saving state", offset);
#endif
best_solution = sequence;
best_sequence = sequence;
best_seq_max_tardiness = maximum_tardiness;
// remove the last tardiness computation, prevent bug when completing the rollout
if(best_sequence.size() != data.nb_tasks)
best_seq_max_tardiness.pop_back();
best_tardiness = get_tardiness();
_period = period;
_num_operation = num_operation;
_prev_operation = prev_operation;
_tour_length = tour_length;
_train_length = train_length;
_tardi_depth = tardi_depth;
_start = start;
saved_maximum_tardiness = maximum_tardiness;
saved_maximum_positive_tardiness = maximum_positive_tardiness;
// remove the last tardiness computation
// Extends-rollout re-adds it, then prevent bug
if(sequence.size() != data.nb_tasks){
saved_maximum_tardiness.pop_back();
saved_maximum_positive_tardiness.pop_back();
}
saved_sequence = sequence;
saved_period = period;
saved_num_operation = num_operation;
saved_prev_operation = prev_operation;
saved_tour_length = tour_length;
saved_train_length = train_length;
saved_first_tard_depth = first_tard_depth;
saved_start = start;
}
void DFSRollout::restore_state()
{
sequence = std::move(best_sequence);
maximum_tardiness = std::move(best_seq_max_tardiness);
period = std::move(_period);
num_operation = std::move(_num_operation);
prev_operation = std::move(_prev_operation);
start = std::move(_start);
tour_length = _tour_length;
train_length = _train_length;
tardi_depth = _tardi_depth;
// std::cout << "Restore solution, tard= " << get_tardiness() << ", size = " << sequence.size() << std::endl;
maximum_tardiness = std::move(saved_maximum_tardiness);
maximum_positive_tardiness = std::move(saved_maximum_positive_tardiness);
sequence = std::move(saved_sequence);
period = std::move(saved_period);
num_operation = std::move(saved_num_operation);
prev_operation = std::move(saved_prev_operation);
tour_length = saved_tour_length;
train_length = saved_train_length;
first_tard_depth = saved_first_tard_depth;
start = std::move(saved_start);
}
void DFSRollout::restart(const int lvl, int& restart_size, int& restart_limit)
{
restart_size *= restart_factor;
restart_limit += restart_size;
if(verbose)
cout << "o restart\n";
sequence.resize(lvl);
for(auto i{0}; i<data.nb_components; ++i) {
period[i] = start_period[i];
num_operation[i] = start_num_operation[i];
prev_operation[i] = start_prev_operation[i];
}
maximum_positive_tardiness.resize(1+lvl);
maximum_tardiness.resize(1+lvl);
tour_length = start_tour_length;
train_length = start_train_length;
if(get_tardiness() == 0)
{
first_tard_depth = sequence.size();
}
}
void DFSRollout::clear() {
sequence.clear();
best_solution.clear();
saved_sequence.clear();
std::fill(period.begin(), period.end(), 0);
std::fill(start_period.begin(), start_period.end(), 0);
std::fill(saved_period.begin(), saved_period.end(), 0);
std::fill(num_operation.begin(), num_operation.end(), 0);
std::fill(start_num_operation.begin(), start_num_operation.end(), 0);
std::fill(saved_num_operation.begin(), saved_num_operation.end(), 0);
std::fill(prev_operation.begin(), prev_operation.end(), -1);
std::fill(start_prev_operation.begin(), start_prev_operation.end(), -1);
std::fill(saved_prev_operation.begin(), saved_prev_operation.end(), -1);
maximum_tardiness.clear();
saved_maximum_tardiness.clear();
maximum_tardiness.push_back(0);
saved_maximum_tardiness.push_back(0);
maximum_positive_tardiness.clear();
saved_maximum_positive_tardiness.clear();
maximum_positive_tardiness.push_back(0);
saved_maximum_positive_tardiness.push_back(0);
tour_length = 0;
start_tour_length = 0;
saved_tour_length = 0;
train_length = 0;
start_train_length = 0;
saved_train_length = 0;
best_tardiness = numeric_limits<int>::max();
first_tard_depth = 0;
saved_first_tard_depth = 0;
}
......@@ -683,16 +747,12 @@ int DFSRollout::search(int ub, int ub_depth) {
start_prev_operation = prev_operation;
start_num_operation = num_operation;
best_tardiness = numeric_limits<int>::max(); // best sol for this run may be worst than the UB
tardi_depth = 0;
best_sequence.clear();
int iter{0};
int restart_limit{restart_base};
int restart_size{restart_base};
bool first_fail = true;
int tardiness_at_fail;
while(true) {
......@@ -705,19 +765,17 @@ int DFSRollout::search(int ub, int ub_depth) {
get_operations();
compute_distances();
if(sequence.size() > tardi_depth && get_tardiness() == 0){
tardi_depth = sequence.size();
if(sequence.size() > first_tard_depth && get_tardiness() == 0){
first_tard_depth = sequence.size();
}
// fail because of the upper bound
if(get_tardiness() >= ub) {
if(sequence.size() > best_sequence.size())
if(sequence.size() > saved_sequence.size())
{
save_state();
}
maximum_positive_tardiness.pop_back();
if(first_fail)
tardiness_at_fail = get_tardiness();
maximum_tardiness.pop_back();
break;
}
......@@ -768,16 +826,14 @@ int DFSRollout::search(int ub, int ub_depth) {
if(first_fail and auto_limit)
{
max_iter = 1;
if(sequence.size() == data.nb_tasks)
tardiness_at_fail = get_tardiness();
first_fail = false;
if(tardiness_at_fail < ub || tardi_depth > ub_depth)
if(sequence.size() == data.nb_tasks || first_tard_depth > ub_depth)
{
max_iter = FAIL_LIMIT;
}else if(tardi_depth > ALPHA * ub_depth)
}else if(first_tard_depth > ALPHA * ub_depth)
{
double term = (1 - (ub_depth - tardi_depth)/(ub_depth - ALPHA*ub_depth));
double term = (1 - (ub_depth - first_tard_depth)/(ub_depth - ALPHA*ub_depth));
max_iter = FAIL_LIMIT * term * term;
// std::cout << max_iter << " : "<< tardiness_at_fail <<"/"<<ub << std::endl;
}
......@@ -786,7 +842,7 @@ int DFSRollout::search(int ub, int ub_depth) {
// the branch is full
if(sequence.size() == data.nb_tasks) {
save_state();
ub = best_tardiness;
ub = get_tardiness();
if(verbose)
cout << "d lmax=" << best_tardiness << " iter=" << iter << endl;
if(verified)
......@@ -802,11 +858,7 @@ int DFSRollout::search(int ub, int ub_depth) {
}
if(restart_base and iter >= restart_limit) {
restart_size *= restart_factor;
restart_limit += restart_size;
if(verbose)
cout << "o restart\n";
clear(start_level);
restart(start_level, restart_size, restart_limit);
continue;
}
......@@ -832,14 +884,12 @@ int DFSRollout::search(int ub, int ub_depth) {
commit(*action[i]);
break;
}
}
}
// if no tardiness after backtrack, then update tardi_depth
if(get_tardiness() == 0)
{
tardi_depth = sequence.size();
first_tard_depth = sequence.size();
}
// check if the algorithm should stop
......
......@@ -10,6 +10,7 @@
#include <random>
#include "instance.h"
#include <assert.h>
using namespace std;
......@@ -37,9 +38,8 @@ public:
// return the number of fail before stop
int search(int ub, int ub_depth=0);
void do_op(const int op);
void undo();
void clear(const int lvl=0);
void do_op(const int op);
void clear();
void print_step() const;
void print_sol() const;
......@@ -51,11 +51,10 @@ public:
int train_length{0};
vector<int> best_solution;
int best_tardiness{numeric_limits<int>::max()};
int tardi_depth;
// Used only in greedy procesures
vector<int> best_solution;
int best_tardiness{numeric_limits<int>::max()};
void verify(const char* msg, const int offset=0);
......@@ -66,11 +65,12 @@ public:
bool verified{false};
bool randomized{true};
bool auto_limit{true};
int restart_base{0};
double restart_factor{1.2};
// Used in DFS, automatically set if auto_limit
int max_iter{numeric_limits<int>::max()};
......@@ -80,72 +80,77 @@ public:
// the actual sequence of operations
vector<int> sequence;
vector<int> maximum_tardiness;
// Position of the first tardiness for the actual sequence
int first_tard_depth{0};
double get_avg_travel_time(const int op) const;
double get_avg_train_time(const int op) const;
int get_cur_train_time(const int op) const;
double fast_sigmoid(const int t, const double slope=.01) const {
// return .5 * (slope * t / (1 + abs(slope * t))) + .5;
return slope * t / (1 + abs(slope * t));
}
int get_tardiness() const {
return maximum_positive_tardiness.back();
}
int get_marginal_tardiness(int pos) const {
assert(pos+2 < maximum_positive_tardiness.size());
return maximum_positive_tardiness[pos+2] - maximum_positive_tardiness[pos+1];
}
private:
const Instance& data;
vector<int> saved_sequence;
int saved_first_tard_depth{0};
int start_tour_length{0};
int saved_tour_length{0};
int start_train_length{0};
int saved_train_length{0};
//
vector<int> maximum_tardiness;
vector<int> saved_maximum_tardiness;
vector<int> maximum_positive_tardiness;
int min_action_tardiness;
int max_action_tardiness;
// the set of possible operations
vector<int> actions;
vector<int> saved_maximum_positive_tardiness;
// the current period, for every component
vector<int> period;
vector<int> start_period;
vector<int> saved_period;
// the latest operation, for every component
vector<int> prev_operation;
vector<int> start_prev_operation;
vector<int> saved_prev_operation;
// the number of operations in the period, for every component
vector<int> num_operation;
vector<int> start_num_operation;
vector<int> best_sequence;
// Copy in order to save a state
vector<int> _num_operation;
vector<int> _prev_operation;
vector<int> _period;
vector<int> _start;
int _tour_length;
int _train_length;
int _tardi_depth;
vector<int> best_seq_max_tardiness;
vector<int> saved_num_operation;
// for every operation, its start time if scheduled, or a lower bound on it if it is a possible actions choice
vector<int> start;
vector<int> saved_start;
// used to store the tardiness of the actions
vector<int> tardiness;
int min_action_tardiness;
int max_action_tardiness;
// the set of possible operations
vector<int> actions;
// used to store the distance of the actions
vector<int> distance;
// used to store the tardiness of the actions
vector<int> tardiness;
// used to store the probabilities of the actions
vector<long int> proba;
......@@ -166,10 +171,8 @@ private:
// int get_tardiness() const {
// return maximum_positive_tardiness.back();
// }
int get_marginal_tardiness(const int i) const {
return maximum_positive_tardiness[i+1] - maximum_positive_tardiness[i];
}
void undo();
void restart(const int lvl, int& restart_size, int& restart_limit);
int back() const {
return sequence.back();
......@@ -196,8 +199,14 @@ private:
// void verify(const char* msg, const int offset=0);
void save_state();
void save_state();
void restore_state();
double fast_sigmoid(const int t, const double slope=.01) const {
// return .5 * (slope * t / (1 + abs(slope * t))) + .5;
return slope * t / (1 + abs(slope * t));
}
};
......
......@@ -12,7 +12,6 @@
#include "mcts.h"
#include "heuristic.h"
#include "DFSRollout.h"
/*Option de sortie et debug*/
#define DEBUG_MODE false
......@@ -289,7 +288,7 @@ Solution solve(const Instance& data, double c, int timeout)
}
// finished by a greedy, using the best solution found
rollout.extend_rollout();
rollout_depth = rollout.tardi_depth;
rollout_depth = rollout.first_tard_depth;
rollout_tardiness = rollout.get_tardiness();
}else{
......@@ -303,7 +302,7 @@ Solution solve(const Instance& data, double c, int timeout)
// rollout_tardiness = sol.lmax();
rollout.greedy_stochastic(upper_bound);
rollout_depth = rollout.tardi_depth;
rollout_depth = rollout.first_tard_depth;
rollout_tardiness = rollout.get_tardiness();
}
if(rollout_depth > best_depth)
......@@ -343,8 +342,11 @@ Solution solve(const Instance& data, double c, int timeout)
// std::cout << " " << v << std::endl;
// }
double gamma = 1;
for(int i = node_vector[current_node_idx].depth; i < rollout.sequence.size() && i+2 < rollout.maximum_tardiness.size(); ++i){
int marginal_incr = rollout.maximum_tardiness[i+2] - rollout.maximum_tardiness[i+1];
// The first task added in the rollout is at position node_vector[current_node_idx].depth
// node_vector[current_node_idx].position = node_vector[current_node_idx].depth - 1
for(int pos = node_vector[current_node_idx].depth; pos < rollout.sequence.size() && pos < data.nb_tasks-1; ++pos){
int marginal_incr = rollout.get_marginal_tardiness(pos);
// std::cout << marginal_incr << " ";
backup_value += gamma * marginal_incr;
gamma *= decay;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment