Commit 99a89b3b authored by Valentin Antuori's avatar Valentin Antuori
Browse files

version post CPAIOR

parent 6362e5eb
......@@ -6,7 +6,8 @@
#include "heuristic.h"
#define DEBUG_H_MACCRO false
#define SHIFT_TIME 43500
#define SHIFT_DURATION 43500
#define NB_TASK_STOP 1000
using namespace std;
......@@ -97,7 +98,43 @@ void build(Solution& sol, bool stop)
}
void build(Solution& sol, State& s, bool stop)
{
int date_out = sol.end() + SHIFT_TIME;
// int date_out = sol.end() + SHIFT_DURATION;
bool can_stop = false;
int nb_task_end;
for(int i = sol.size(); i < sol.data->nb_tasks; ++i)
{
if(DEBUG_H)
std::cerr << "step "<< i << std::endl;
append_action(sol, s);
// if(stop && sol.lmax() > 0 && sol.end() >= date_out){
// break;
// }
if(stop && !can_stop && sol.lmax() > 0)
{
can_stop = true;
// date_out = sol.end() + SHIFT_DURATION;
nb_task_end = sol.size() + NB_TASK_STOP;
}
// if(can_stop && sol.end() >= date_out)
if(can_stop && sol.size() >= nb_task_end)
{
break;
}
}
if(DEBUG_H)
std::cerr << "End Build" << std::endl;
}
double build(Solution& sol, State& s, int best_lmax)
{
// int date_out = sol.end() + SHIFT_DURATION;
bool can_stop = false;
int nb_task_end;
for(int i = sol.size(); i < sol.data->nb_tasks; ++i)
{
......@@ -105,11 +142,24 @@ void build(Solution& sol, State& s, bool stop)
std::cerr << "step "<< i << std::endl;
append_action(sol, s);
if(stop && sol.lmax() > 0 && sol.end() >= date_out){
// if(stop && sol.lmax() > 0 && sol.end() >= date_out){
// break;
// }
if(!can_stop && sol.lmax() > 0)
{
can_stop = true;
// date_out = sol.end() + SHIFT_DURATION;
nb_task_end = sol.size() + NB_TASK_STOP;
}
// if(can_stop && sol.end() >= date_out)
if(can_stop && sol.lmax() >= best_lmax && sol.size() >= nb_task_end)
{
// std::cout << nb_task_end << "/" << sol.size() << std::endl;
break;
}
}
if(DEBUG_H)
std::cerr << "End Build" << std::endl;
}
......@@ -123,7 +173,7 @@ void append_action(Solution& sol, State& s)
// compute proba;
vector<double> proba = get_distribution(*sol.data, s, actions);
vector<double> proba = get_distribution(s, actions);
if(DEBUG_H)
for(size_t i = 0; i < proba.size(); ++i){
std::cerr << actions[i] << " : " << proba[i] << std::endl;
......@@ -142,12 +192,12 @@ void append_action(Solution& sol, State& s)
}
vector<double> get_distribution(const Instance& data, const State& s, const std::vector<int>& actions)
vector<double> get_distribution(const State& s, const std::vector<int>& actions)
{
return get_distribution(data, s, actions, default_temperature);
return get_distribution(s, actions, default_temperature);
}
vector<double> get_distribution(const Instance& data, const State& s, const std::vector<int>& actions, const double temperature)
vector<double> get_distribution(const State& s, const std::vector<int>& actions, const double temperature)
{
if(DEBUG_H)
std::cerr << "Get distribution : " << std::endl;
......@@ -171,7 +221,7 @@ vector<double> get_distribution(const Instance& data, const State& s, const std:
for(size_t i = 0; i < actions.size(); ++i)
{
//compute fitness for action i
double fitness = fitness_func(data, s, actions[i]);
double fitness = fitness_func(s, actions[i]);
if(DEBUG_H){
std::cerr << actions[i] << " : " ;
std::cerr << "Fitness="<<fitness << std::endl;
......@@ -194,20 +244,20 @@ vector<double> get_distribution(const Instance& data, const State& s, const std:
return proba; // compiler should optimize this
}
double fitness_func(const Instance& data, const State& s, int action)
double fitness_func(const State& s, int action)
{
// distance return 0 if last_task < 0
int dist = data.distance(s.last_action, action);
int dist = s.data->distance(s.last_action, action);
if(s.last_action < 0)
{
dist = 0;
}
double lambda1 = (double)(s.lst(action) - max(data.release_date(action), s.date - s.tardiness + dist)) / data.max_slack;
double lambda2 = (double)(max(data.release_date(action) - (s.date - s.tardiness), dist)) / data.max_dist;
double lambda3 = 1 - (double)data.trolley_length(action) / data.T_max;
double lambda4 = data.is_pickup(action) ? 1 : 0;
double lambda1 = (double)(s.lst(action) - max(s.data->release_date(action), s.date - s.tardiness + dist)) / s.data->max_slack;
double lambda2 = (double)(max(s.data->release_date(action) - (s.date - s.tardiness), dist)) / s.data->max_dist;
double lambda3 = 1 - (double)s.data->trolley_length(action) / s.data->T_max;
double lambda4 = s.data->is_pickup(action) ? 1 : 0;
......@@ -216,6 +266,28 @@ double fitness_func(const Instance& data, const State& s, int action)
return 1 - (THETA_1 * lambda1 + THETA_2 * lambda2 + THETA_3 * lambda3 + THETA_4 * lambda4);
}
// double debug_fitness_func(const Instance& data, const State& s, int action)
// {
// // distance return 0 if last_task < 0
// int dist = data.distance(s.last_action, action);
// if(s.last_action < 0)
// {
// dist = 0;
// }
// double lambda1 = (double)(s.lst(action) - std::max(data.release_date(action), s.date - s.tardiness + dist)) / data.max_slack;
// double lambda2 = (double)(std::max(data.release_date(action) - (s.date - s.tardiness), dist)) / data.max_dist;
// double lambda3 = 1 - (double)data.trolley_length(action) / data.T_max;
// double lambda4 = data.is_pickup(action) ? 1 : 0;
// std::cerr << "lst=" << s.lst(action) << ", release=" << data.release_date(action) << ",date=" << s.date << ", tard="<< s.tardiness << std::endl;
// std::cerr << lambda1 << " / " << lambda2 << " / " << lambda3 << " / " << lambda4 << std::endl;
// return 1 - (THETA_1 * lambda1 + THETA_2 * lambda2 + THETA_3 * lambda3 + THETA_4 * lambda4);
// }
// vector<double> get_distrib(const State& s)
......
......@@ -26,6 +26,13 @@ void build(Solution& sol, bool stop=false);
*/
void build(Solution& sol, State& state, bool stop=false);
/**
* Build a solution, compute backup value in the mean time
* Stop when the backup value is becoming worse than the one passed in parameter
* Hypotheses : Provided solution isn't already late
*/
double build(Solution& sol, State& s, int best_lmax);
/**
* One iteration
*/
......@@ -38,11 +45,11 @@ std::unique_ptr<Solution> random_sample(const Instance& data);
/**
* With default temperature
*/
std::vector<double> get_distribution(const Instance& data, const State& s, const std::vector<int>& actions);
std::vector<double> get_distribution(const State& s, const std::vector<int>& actions);
/**
* Return distribution over action
*/
std::vector<double> get_distribution(const Instance& data, const State& s, const std::vector<int>& actions, const double temperature);
std::vector<double> get_distribution(const State& s, const std::vector<int>& actions, const double temperature);
/**
* return action number in {0, 1, ..., |proba|}
*/
......@@ -51,8 +58,10 @@ unsigned int choice(std::vector<double> proba);
/**
* Return fitness
*/
double fitness_func(const Instance& data, const State& s, int action);
double fitness_func(const State& s, int action);
// double debug_fitness_func(const Instance& data, const State& s, int action);
......
......@@ -61,10 +61,6 @@ Instance::Instance(const std::string& filename)
if(due - release > max_slack)
max_slack = due - release;
if(last_compo != 0 && last_compo != m_components.back())
{
nb_periods.push_back(m_periods.back());
}
if(last_compo != m_components.back())
{
......
......@@ -14,8 +14,6 @@ class Instance
int nb_machines; // should be 2 * nb_components
/** Limit not to exceed with the train size**/
int T_max;
/** nb periods for each components **/
std::vector<int> nb_periods;
int max_dist;
int max_slack;
......
......@@ -20,6 +20,7 @@
#include "options.h"
#include "mcts.h"
#include "heuristic.h"
#include "dfs.h"
#include "test.h"
......@@ -185,6 +186,7 @@ int main(int argc, char **argv){
cerr << "No file or directory found : " << opt.instance_file << endl;
}
srand (opt.seed);
/*
if(opt.learn)
......@@ -227,10 +229,19 @@ int main(int argc, char **argv){
else */
if(opt.mcts)
{
set_open_nodes(opt.open_nodes);
normalized(opt.normalized_without_biais);
set_epsilon(opt.epsilon);
Solution sol = solve(data[0], opt.c,/*print_stat=*/true, opt.time, opt.mcts_backup);
set_c_mode(opt.c_mode);
set_dfs(opt.dfs_mode);
set_aggregation(opt.aggregation);
set_c_decay(opt.c_decay);
set_stop_rollout(!opt.complete_rollout);
Solution sol = solve(data[0], opt.c, opt.time);
if(!sol.is_valid())
{
std::cout << "Solution is not valid" << std::endl;
}
}
else if(opt.heuristic)
{
......@@ -240,8 +251,18 @@ int main(int argc, char **argv){
}
else{
set_default_temperature(0.01);
Solution sol(&data[0]);
State s(&data[0]);
std::vector<int> hint{};
for(auto t : hint){
sol.append(t);
s.update(t);
}
dfs(sol, s);
// test_sample(data[0], opt.stat);
solve_by_sample(data[0], opt.stat);
// solve_by_sample(data[0], opt.stat);
// range_children(data[0], opt.stat);
}
......
This diff is collapsed.
......@@ -8,25 +8,20 @@
#include "solution.h"
#include "SparseSet.hpp"
#define BACKUP_MEAN 0
#define BACKUP_BEST 1
extern bool DEBUG;
extern std::vector<int> node_per_depth;
extern double epsilon;
extern bool normalized_without_biais;
extern bool open_nodes_at_best;
void set_aggregation(int agg);
void set_dfs(bool dfs);
void set_epsilon(double ep);
void set_open_nodes(bool active);
void normalized(bool without_biais);
void set_c_mode(int c_mode);
void set_c_decay(double decay);
void set_stop_rollout(bool stop);
class Node;
/**
Main function, run the algorithm on the instance in data
@param data : the instance to solve
*/
Solution solve(const Instance& data, double c, bool print_stat, int timeout, int backup);
Solution solve(const Instance& data, double c, int timeout);
/**
* Samples from the partial solution *sol*
* compute the mean value and the std deviation of the current_node
......@@ -35,6 +30,12 @@ Solution solve(const Instance& data, double c, bool print_stat, int timeout, int
*/
int samples(Node& current_node, const Solution& sol, const State& s, Solution& best_sol);
/**
* Selection phase
* Return the idx of the selected leaf
*/
int select(std::vector<Node>& node_vector, Solution& sol, State& s, double c, int tree_depth = 0);
/**
* Expansion phase, return the number of node added to the tree, -1 if the node need to be deleted
*/
......@@ -44,6 +45,11 @@ int expand(const State& s, std::vector<Node>& node_vector, SparseSet& node_set,
*/
void sample(Solution& sol, State& s);
/**
* Perform a Depth first search from the solution in parameter with a budget (of backtrack maybe ?)
*/
void intensification(Solution& sol, State& s);
/**
* Return the idx of the added node
......@@ -53,8 +59,10 @@ void add_node(std::vector<Node>& node_vector, SparseSet& node_idx_set, double pr
void delete_node(std::vector<Node>& node_vector, SparseSet& node_set, int current_node_idx);
void open_nodes_in_solution(const Solution& sol, double backup_value, std::vector<Node>& node_vector, SparseSet& node_set, int last_node_idx,
State& last_state, int& added_node, int& depth_reached);
// void open_nodes_in_solution(const Solution& sol, double backup_value, std::vector<Node>& node_vector, SparseSet& node_set, int last_node_idx,
// State& last_state, int& added_node, int& depth_reached);
class Node
......@@ -62,6 +70,11 @@ class Node
public:
static int count;
int depth_open;
int iter_open;
int iter_reuse;
int nb_reuse;
/**/
double W; // Sum of Rewards
double P; // Prior probability
......@@ -74,6 +87,7 @@ class Node
int best_obj;
double best_backup;
int best_backup_depth;
int action; // Action taken from the parent
int end_date; //end date of the task
......@@ -102,10 +116,11 @@ class Node
void update(double v, const Solution& sol, int sub_tree_depth, int added_node);
bool is_leaf();
bool is_root();
double get_Q();
bool is_leaf() const;
bool is_root() const;
double get_Q() const;
friend std::ostream& operator<<(std::ostream& os, const Node& dt);
};
......
......@@ -163,17 +163,36 @@ ChariotOptions parse(int argc, char *argv[]) {
cmd.add<SwitchArg>(opt.heuristic, "", "greedy", "Greedy run",
false);
cmd.add<SwitchArg>(opt.normalized_without_biais, "", "norm", "normalized without biais",
cmd.add<ValueArg<int>>(opt.normalization, "", "norm", "normalization options(1:Equation2, 2:Equation2 in red, 3: Equation3)",
false, 1, "int");
cmd.add<SwitchArg>(opt.bonus, "", "bonus", "Use a bonus with the best solution at each node",
false);
cmd.add<SwitchArg>(opt.open_nodes, "", "open", "open nodes when a best solution is found", false);
cmd.add<SwitchArg>(opt.open_nodes_bonus, "", "open_bonus", "Count depth as nb selection in open nodes", false);
cmd.add<SwitchArg>(opt.dfs_mode, "", "dfs", "Brute force mode", false);
cmd.add<SwitchArg>(opt.complete_rollout, "", "complete_rollout", "don't stop rollout before end", false);
cmd.add<ValueArg<double>>(opt.c, "", "c", "Exploitation/exploration parameter",/*required=*/false, /*default=*/1,
"double");
cmd.add<ValueArg<double>>(opt.c_decay, "", "c_decay", "Decay for the c parameter",/*required=*/false, /*default=*/0.99,
"double");
cmd.add<ValueArg<double>>(opt.epsilon, "", "epsilon", "epsilon",/*required=*/false, /*default=*/0.000001,
"double");
cmd.add<ValueArg<int>>(
opt.aggregation, "", "aggregation",
"Q-value : (0 : lmax, 1: diminishing return)", false,
0, "int");
cmd.add<ValueArg<int>>(
opt.c_mode, "", "c_mode",
"mode static/dynamic for c : (0 : static(default), 1: dynamic increasing(depending on the depth), 2: static decreasing)", false,
0, "int");
cmd.add<ValueArg<int>>(
opt.stat, "", "stat",
......@@ -213,14 +232,26 @@ ostream &ChariotOptions::display(ostream &os) {
<< endl;
os << setw(20) << left << "p c coefficient" << setw(30) << right << c
<< endl;
os << setw(20) << left << "p c mode" << setw(30) << right << c_mode
<< endl;
os << setw(20) << left << "p c_decay" << setw(30) << right << c_decay
<< endl;
os << setw(20) << left << "p epsilon" << setw(30) << right
<< epsilon
<< endl;
os << setw(20) << left << "p norm" << setw(30) << right << normalized_without_biais
os << setw(20) << left << "p norm" << setw(30) << right << normalization
<< endl;
os << setw(20) << left << "p open" << setw(30) << right << open_nodes
<< endl;
os << setw(20) << left << "p bonus" << setw(30) << right << bonus
<< endl;
os << setw(20) << left << "p dfs" << setw(30) << right << dfs_mode
<< endl;
os << setw(20) << left << "p aggregation" << setw(30) << right << aggregation
<< endl;
os << setw(20) << left << "p complete_rollout" << setw(30) << right << complete_rollout
<< endl;
}
return os;
......
......@@ -40,10 +40,17 @@ public:
double epsilon;
int mcts_backup;
bool normalized_without_biais;
int normalization;
bool open_nodes;
bool open_nodes_bonus;
bool bonus;
bool dfs_mode;
int stat;
int aggregation;
bool complete_rollout;
int c_mode;
double c_decay;
double time;
......
......@@ -4,7 +4,22 @@
#include <iterator>
#include "instance.h"
void Solution::copy(const Solution& sol)
{
data = sol.data; //ptr
m_size = sol.m_size;
m_sum_tardiness = sol.m_sum_tardiness;
m_first_tardiness = sol.m_first_tardiness;
for(int i = 0; i < sol.size(); ++i)
{
sequence[i] = sol.sequence[i];
m_positions[i] = sol.m_positions[i];
m_starts[i] = sol.m_starts[i];
m_max_tardiness[i] = sol.m_max_tardiness[i];
m_trains[i] = sol.m_trains[i];
}
}
Solution::Solution(const Instance* inst): data(inst),sequence(data->nb_tasks, -1),m_positions(data->nb_tasks, -1),
m_starts(data->nb_tasks, 0),m_max_tardiness(data->nb_tasks, 0),m_trains(data->nb_tasks, 0),m_size(0), m_sum_tardiness(0),
......@@ -50,6 +65,8 @@ int Solution::end_of_task(const int task)const
}
int Solution::tardiness(const int pos)const
{
if(pos < 0)
return 0;
return std::max(0, end(pos) - data->due_date(sequence[pos]));
}
int Solution::lmax() const
......@@ -231,6 +248,53 @@ void Solution::complete_print() const
}
}
void Solution::pop_back()
{
if(size() > 0)
{
m_size--;
m_sum_tardiness -= tardiness(size());
m_max_tardiness[size()] = 0;
m_positions[size()] = -1;
sequence[size()] = -1;
m_starts[size()] = 0;
m_trains[size()] = 0;
if(m_first_tardiness >= size())
{
if(size() == 0 || max_tardiness(size()-1) == 0){
m_first_tardiness = -1;
}else{
//look for first tardiness by dychotomy
int ub = size()-2;
int i = ub/2;
int lb = 0;
bool end = false;
while(!end)
{
if(max_tardiness(i) == 0 && max_tardiness(i+1) > 0)
{
m_first_tardiness = i+1;
end = true;
}else if(max_tardiness(i) > 0 && max_tardiness(i-1) == 0)
{
m_first_tardiness = i;
end = true;
}else if(tardiness(i) == 0)
{
lb = i+1;
}else{
ub = i-1;
}
i = lb + (ub-lb)/2;
}
}
}
}
}
std::ostream& operator << (std::ostream& out, const Solution& sol)
{
out << "Size = " << sol.size() << std::endl;
......@@ -325,6 +389,53 @@ void State::update(int task)
//std::cout << task << ", comp="<<comp<<", goback="<<go_back[comp]<<", next="<<nexts[comp]<< ", period="<<curr_period[comp]<< std::endl;
}
void State::rewind(const Solution& sol)
{
int task = last_action;
int comp = data->component(task);
train_size -= data->train_use(task);
if(sol.size() > 0)
last_action = sol.sequence[sol.size()-1];
else
last_action = NO_ACTION;
tardiness = sol.lmax();
date = sol.end();
curr_period[comp] = data->period(task);
if(data->is_delivery(task))
{
if(nexts[comp] == NEW_PERIOD)// We remove the second delivery
{
_lst[comp] = data->due_date(task) - data->duration(task);
}else{ // Remove the first delivery
_lst[comp] -= data->duration(task);
_lst[comp] -= data->distance(task, nexts[comp]);
}
nexts[comp] = task;
go_back[comp] = !go_back[comp];
}else{//pickup
// next can be either delivery, or NEW_PERIOD
_lst[comp] -= data->duration(task);
_lst[comp] -= data->distance(task, nexts[comp]);
if(go_back[comp]) // The first delivery is schedule => we remove the second pickup
{
nexts[comp] = task;
}else
{
// NEW PERIOD
nexts[comp] = NEW_PERIOD;
}
}
//std::cout << task << ", comp="<<comp<<", goback="<<go_back[comp]<<", next="<<nexts[comp]<< ", period="<<curr_period[comp]<< std::endl;
}
int State::lst(int task) const
{
return _lst[data->component(task)];
......