Commit eb255909 authored by ehebrard's avatar ehebrard
Browse files

bug

parent 35012861
......@@ -76,7 +76,10 @@ int main(int argc, char *argv[]) {
// S2.addEdge(END(x), END(y));
// }
// }
#ifdef DEBUG_CONSTRAINT
cons.back()->debug_flag = true;
#endif
}
auto ub{osp::getUb(duration, resource)};
......
#ifndef SCHEDULE_CONSTRAINT
#define SCHEDULE_CONSTRAINT
#include "DistanceGraph.hpp"
#define DEBUG_CONSTRAINT
namespace schedcl {
class Constraint {
public:
virtual void propagate() = 0;
// virtual bool trigger(const edge_idx newedge) { return true; }
// used to pass the list of task the constraint want to be awaken on
virtual void post(const int idx) = 0;
virtual ostream &display(ostream &os) const {
os << "a scheduling constraint";
return os;
}
};
} // namespace
#endif
......@@ -64,15 +64,38 @@ public:
virtual void xplain(const int hint, vector<DistanceLiteral<T>> &Cl) const {};
// virtual void xplain(const int hint, vector<DistanceLiteral>& Cl)
// const {};
virtual ostream &print_reason(ostream &os, const int hint) const { os << "no reason"; return os; }
};
template<typename T>
class Explanation {
public:
Explainer<T> *expl;
int hint;
void get(vector<DistanceLiteral<T>> &Cl) const { expl->xplain(hint, Cl); }
ostream &display(ostream &os) const {
// os << "b/c ";
expl->print_reason(os, hint);
return os;
}
};
template <typename T> class Constant {
public:
static Explainer<T> *NoReason;
// static Explainer<T> *NoReason;
static DistanceLiteral<T> NoLiteral;
static Explanation<T> NoReason;
};
template <typename T> Explainer<T> *Constant<T>::NoReason = new Explainer<T>();
// template <typename T> Explainer<T> *Constant<T>::NoReason = new Explainer<T>();
template <typename T> Explanation<T> Constant<T>::NoReason = {new Explainer<T>(), NoHint};
template <typename T>
DistanceLiteral<T> Constant<T>::NoLiteral = {
......@@ -81,8 +104,9 @@ DistanceLiteral<T> Constant<T>::NoLiteral = {
template <typename T> struct Bound {
T value;
const Explainer<T> *reason;
const int hint;
const Explanation<T> reason;
// const Explainer<T> *reason;
// const int hint;
};
......@@ -111,7 +135,8 @@ public:
void intialise(const event x, const event y, const T d) {
from = x;
to = y;
literals.push_back({d, Constant<T>::NoReason, NoHint});
// literals.push_back({d, Constant<T>::NoReason, NoHint});
literals.push_back({d, Constant<T>::NoReason});
// trail.push_back(d);
// reason.push_back(Constant<T>::NoReason);
......@@ -143,10 +168,12 @@ public:
// }
// }
void set(const T d, const Explainer<T> *e, const int h) {
void set(const T d,
const Explanation<T> e){
// const Explainer<T> *e, const int h) {
if (get() > d) {
ReversibleObject::save();
literals.push_back({d, e, h});
literals.push_back({d, e});
// trail.push_back(d);
// reason.push_back(e);
......@@ -154,7 +181,8 @@ public:
}
void set(const T d) {
set(d, Constant<T>::NoReason, NoHint);
set(d, Constant<T>::NoReason);
// set(d, Constant<T>::NoReason, NoHint);
// if (get() > d) {
// ReversibleObject::save();
// literals.push_back({d, Constant<T>::NoReason, NoHint});
......@@ -234,6 +262,11 @@ protected:
// vector<const int> hint;
};
template <typename T>
ostream &operator<<(ostream &os, const Explanation<T> &x) {
return x.display(os);
}
template <typename T>
ostream &operator<<(ostream &os, const DistanceVariable<T> &x) {
return x.display(os);
......
......@@ -18,9 +18,13 @@
#define SEARCH 1
#define PROPAGATION 2
// #define TRACE 3
#define TRACE 3
namespace schedcl {
class ChoicePoint {
......@@ -56,6 +60,7 @@ public:
virtual ostream &display(ostream &os) const = 0;
};
template <class T> class Schedule;
template <typename T, int N> class ConstraintQueue {
class Trigger {
......@@ -66,6 +71,8 @@ template <typename T, int N> class ConstraintQueue {
};
public:
Schedule<T>& schedule;
// all constraints
vector<ResourceConstraint<T> *> constraints;
// which ones need to be propagated
......@@ -74,7 +81,7 @@ public:
// for every variable, its triggers
vector<vector<Trigger>> triggers;
ConstraintQueue();
ConstraintQueue(Schedule<T>& s);
// void initialise_triggers();
......@@ -118,7 +125,8 @@ public:
// int NOT(const int i) { return (i % 2 ? i-1 : i+1); }
// DistanceVariable<T> * NOT(const DistanceVariable<T> * v) { auto i{v->id};
// return (i % 2 ? variables[i-1] : variables[i+1]); }
bool makeCycle(const DistanceVariable<T> *v, const int l);
bool makeCycle(const DistanceVariable<T> *v, const int l) const;
DistanceVariable<T> * opposite(const DistanceVariable<T> *v) const;
void post(ResourceConstraint<T> *c);
void wake_me_on(DistanceVariable<T> *x, const int c, const int h);
......@@ -146,18 +154,20 @@ public:
/*!@name Pruning and Solving*/
//@{
void addConstraint(DistanceVariable<T> *v, const T d);
// void addConstraint(DistanceVariable<T> *v, const T d, const Explanation<T> e=Constant<T>::NoReason);
void addConstraint(DistanceVariable<T> *v, const T d, const Explanation<T> e);
void updateDistances();
void propagate();
void fail(Explainer<T> *expl, const int hint);
// void fail(Explainer<T> *expl, const int hint);
void fail(Explanation<T> e);
// set the distance var v to 'bound' and update all shortest paths
void set(DistanceVariable<T> *v, const T bound);
void set(DistanceVariable<T> *v, const T bound, const Explanation<T> e);
void explore(const ChoicePoint &cp, const bool branch);
void explore(const ChoicePoint &cp, const bool branch, const Explanation<T> e);
// void exploreRight(const ChoicePoint &cp);
ChoicePoint selectChoicePoint();
void search();
......@@ -180,6 +190,10 @@ public:
// SparseDistanceGraph<T> graph;
SparseGraph<T> graph;
ostream &print_reason(ostream &os, const int hint) const override { os << *variables[hint]; return os; }
const Explanation<T> get_explanation(const int id) const { return explanation[id]; }
private:
/*!@name Private Parameters*/
......@@ -200,6 +214,7 @@ private:
SparseSet<> changes;
// the value corresponding to the requests above
vector<T> new_bound;
vector<Explanation<T>> explanation;
// tail[i] == last variable mapped to i
vector<int> tail;
......@@ -232,7 +247,7 @@ public:
ostream &displayChoicePoint(ostream &os, const ChoicePoint &cp) const;
};
template <class T> Schedule<T>::Schedule() {
template <class T> Schedule<T>::Schedule() : queue(*this) {
// variables.push_back(new DistanceVariable<T>(*this, ORIGIN, HORIZON, 0));
addMaximumLag(ORIGIN, HORIZON, INFTY);
addMaximumLag(HORIZON, ORIGIN, 0);
......@@ -412,6 +427,7 @@ DistanceVariable<T> *Schedule<T>::addMaximumLag(const event x, const event y,
variables.push_back(newvar);
changes.reserve(idvar + 1);
new_bound.resize(idvar + 1);
explanation.resize(idvar + 1);
} else {
// cout << " x[" << v->second << "] = (" << variables[v->second]->from << "
......@@ -432,7 +448,7 @@ DistanceVariable<T> *Schedule<T>::addMaximumLag(const event x, const event y,
// new_bound[idvar] = lag;
// }
if (lag != INFTY) {
addConstraint(variables[idvar], lag);
addConstraint(variables[idvar], lag, Constant<T>::NoReason);
}
return variables[idvar];
......@@ -462,21 +478,21 @@ template <class T> void Schedule<T>::addEdge(const event x, const event y) {
template <class T> void Schedule<T>::setUpperBound(const T b) {
addConstraint(variables[CMAX], b);
addConstraint(variables[CMAX], b, Constant<T>::NoReason);
// addMaximumLag(ORIGIN, HORIZON, b);
// variables[CMAX]->set(b);
// set(variables[CMAX], b);
}
template <class T>
void Schedule<T>::addConstraint(DistanceVariable<T> *v, const T d) {
void Schedule<T>::addConstraint(DistanceVariable<T> *v, const T d, const Explanation<T> e) {
// cout << "ADD CONSTRAINT ON " << *v << ": " << d << " (was " << v->get() <<
// ")" << endl;
#ifdef TRACE
if (TRACE & PROPAGATION) {
cout << "add literal " << *v << " <= " << d << endl;
cout << "add literal " << *v << " <= " << d << " b/c " << e << endl;
}
#endif
......@@ -484,6 +500,7 @@ void Schedule<T>::addConstraint(DistanceVariable<T> *v, const T d) {
if (changes.has(vid)) {
if (new_bound[vid] > d) {
new_bound[vid] = d;
explanation[vid] = e;
}
#ifdef TRACE
else if (TRACE & PROPAGATION) {
......@@ -494,6 +511,7 @@ void Schedule<T>::addConstraint(DistanceVariable<T> *v, const T d) {
if (v->get() > d) {
changes.add(vid);
new_bound[vid] = d;
explanation[vid] = e;
}
#ifdef TRACE
else if (TRACE & PROPAGATION) {
......@@ -518,7 +536,19 @@ void Schedule<T>::addConstraint(DistanceVariable<T> *v, const T d) {
// #endif
}
template <class T> void Schedule<T>::fail(Explainer<T> *expl, const int hint) {
// template <class T> void Schedule<T>::fail(Explainer<T> *expl, const int hint) {
//
// #ifdef TRACE
// if (TRACE) {
// cout << "FAIL!!\n"; // TODO
// }
// #endif
//
// queue.clear();
//
// throw Failure();
// }
template <class T> void Schedule<T>::fail(Explanation<T> e) {
#ifdef TRACE
if (TRACE) {
......@@ -536,8 +566,8 @@ template <class T> void Schedule<T>::fail(Explainer<T> *expl, const int hint) {
// }
template <class T>
void Schedule<T>::explore(const ChoicePoint &cp, const bool branch) {
addConstraint(variables[cp.x[branch]], (branch ? -Gap<T>::epsilon() : 0));
void Schedule<T>::explore(const ChoicePoint &cp, const bool branch, const Explanation<T> e) {
addConstraint(variables[cp.x[branch]], (branch ? -Gap<T>::epsilon() : 0), e);
}
// template <class T> void Schedule<T>::exploreRight(const ChoicePoint &cp) {
......@@ -601,29 +631,29 @@ template <class T> ChoicePoint Schedule<T>::selectChoicePoint() {
template <class T> void Schedule<T>::search() {
double start_time = cpu_time();
cout << choicepoints[16].x[0] << " <> " << choicepoints[16].x[1] << endl;
cout << *variables[157] << " / " << *variables[159] << endl;
// // exit(1);
//
// for(auto c : queue.constraints) {
// cout << *c << endl;
// }
// exit(1);
// cout << choicepoints[16].x[0] << " <> " << choicepoints[16].x[1] << endl;
//
// cout << *variables[157] << " / " << *variables[159] << endl;
//
// // // exit(1);
// //
// // for(auto c : queue.constraints) {
// // cout << *c << endl;
// // }
// // exit(1);
// initialisation
sequence.reserve(choicepoints.size());
sequence.fill();
for(auto x : sequence) {
cout << x << ": " ;
displayChoicePoint(cout, choicepoints[x]);
cout << endl;
}
// exit(1);
// for(auto x : sequence) {
// cout << x << ": " ;
// displayChoicePoint(cout, choicepoints[x]);
// cout << endl;
// }
// // exit(1);
// for (auto &cp : choicepoints) {
// std::cout << *variables[cp.x] << " or " << *variables[cp.y] << endl;
......@@ -716,7 +746,8 @@ template <class T> void Schedule<T>::search() {
// cout << "restart!\n" << *this << endl;
addConstraint(variables[CMAX], ub - Gap<T>::epsilon());
setUpperBound(ub - Gap<T>::epsilon());
// addConstraint(variables[CMAX], ub - Gap<T>::epsilon());
// cout << "update CMAX\n" << *this << endl;
......@@ -735,7 +766,7 @@ template <class T> void Schedule<T>::search() {
}
#endif
explore(cp, 0);
explore(cp, 0, Constant<T>::NoReason);
}
} catch (const Failure &f) {
......@@ -745,6 +776,9 @@ template <class T> void Schedule<T>::search() {
backtrack();
// cout << "@" << ReversibleObject::env->level() << ": " << sequence << endl;
} catch (const SearchExhausted &f) {
cout << "optimal! (" << ub << ")\n";
break;
}
// } else {
......@@ -775,18 +809,26 @@ template <class T> void Schedule<T>::backtrack() {
ChoicePoint cp{choicepoints[k]};
bool otherbranch{variables[cp.x[0]]->get() <= 0};
ReversibleObject::env->restore(ReversibleObject::env->level() - 1);
#ifdef TRACE
if (TRACE & SEARCH) {
cout << "backtrack on choice point " << k << " @LEVEL "
<< ReversibleObject::env->level() << ": ";
displayChoicePoint(cout, choicepoints[k]);
cout << endl;
cout << endl << *this << endl;
}
#endif
assert(not ground(cp));
ReversibleObject::env->restore(ReversibleObject::env->level() - 1);
explore(cp, otherbranch);
explore(cp, otherbranch, Constant<T>::NoReason); // TODO: use conflict!!
// // addConstraint(variables[cp.x[otherbranch]], otherbranch);
//
// cout << *this << endl;
......@@ -820,13 +862,24 @@ template <class T> void Schedule<T>::backtrack() {
template <class T> void Schedule<T>::propagate() {
ResourceConstraint<T> *algorithm{NULL};
while (true) {
#ifdef TRACE
if (TRACE & PROPAGATION) {
cout << "propagation step: " << changes << endl;
cout << "start propagation of" ;
for(auto i : changes) {
cout << " " << label(variables[i]->to) << " - " << label(variables[i]->from) << " <= " << new_bound[i] ;
}
cout << endl;
}
#endif
while (true) {
// #ifdef TRACE
// if (TRACE & PROPAGATION) {
// cout << "propagation step: " << changes << endl;
// }
// #endif
updateDistances();
......@@ -851,12 +904,10 @@ template <class T> void Schedule<T>::propagate() {
if (algorithm == NULL)
break;
else
cout << "propag\n";
#ifdef TRACE
if (TRACE & PROPAGATION) {
cout << "trigger " << *algorithm << endl;
cout << " propagate " << *algorithm << endl;
}
#endif
......@@ -889,27 +940,27 @@ template <class T> void Schedule<T>::updateDistances() {
// int k{3};
#ifdef TRACE
if (TRACE & PROPAGATION) {
cout << "update distances\n";
cout << changes << endl;
// for(auto i : changes)
}
#endif
// #ifdef TRACE
// if (TRACE & PROPAGATION) {
// cout << "update distances\n";
// cout << changes << endl;
// // for(auto i : changes)
// }
// #endif
while (not changes.empty()) {
auto i{changes.front()};
changes.pop_front();
// for(auto i : changes) {
#ifdef TRACE
if (TRACE & PROPAGATION) {
cout << "change on " << *variables[i] << ": " << new_bound[i] << endl;
}
#endif
// #ifdef TRACE
// if (TRACE & PROPAGATION) {
// cout << "change on " << *variables[i] << ": " << new_bound[i] << " " << explanation[i] << endl;
// }
// #endif
assert(new_bound[i] != -INFTY);
set(variables[i], new_bound[i]);
set(variables[i], new_bound[i], explanation[i]);
// queue.notifyChange(i);
......@@ -918,16 +969,17 @@ template <class T> void Schedule<T>::updateDistances() {
// cout << k << endl << *this << endl;
}
#ifdef TRACE
if (TRACE & PROPAGATION) {
cout << "end update distances\n" << *this << endl;
}
#endif
// #ifdef TRACE
// if (TRACE & PROPAGATION) {
// cout << "end update distances\n" << *this << endl;
// }
// #endif
}
template <class T>
bool Schedule<T>::makeCycle(const DistanceVariable<T> *v, const int lv) {
auto w{(v->id % 2 ? variables[v->id - 1] : variables[v->id + 1])};
bool Schedule<T>::makeCycle(const DistanceVariable<T> *v, const int lv) const {
// auto w{(v->id % 2 ? variables[v->id - 1] : variables[v->id + 1])};
auto w{opposite(v)};
T lw{w->get()};
if (lw != INFTY and lw + lv < 0) {
// cout << *v << " <- " << lv << endl << *w << endl;
......@@ -937,7 +989,12 @@ bool Schedule<T>::makeCycle(const DistanceVariable<T> *v, const int lv) {
}
template <class T>
void Schedule<T>::set(DistanceVariable<T> *v, const T bound) {
DistanceVariable<T> * Schedule<T>::opposite(const DistanceVariable<T> *v) const {
return (v->id % 2 ? variables[v->id - 1] : variables[v->id + 1]);
}
template <class T>
void Schedule<T>::set(DistanceVariable<T> *v, const T bound, const Explanation<T> e) {
if (bound >= v->get())
return;
......@@ -946,7 +1003,7 @@ void Schedule<T>::set(DistanceVariable<T> *v, const T bound) {
// fail(this, v->id);
assert(bound != -INFTY);
if (makeCycle(v, bound))
fail(this, v->id);
fail({this, opposite(v)->id});
auto x{v->from};
auto y{v->to};
......@@ -986,7 +1043,7 @@ void Schedule<T>::set(DistanceVariable<T> *v, const T bound) {
// << shortest_path_to_y[i] << endl;
// }
v->set(bound);
v->set(bound, e);
queue.notifyChange(v->id);
// algo.allShorterPaths(x, y, bound, graph.successor,
......@@ -1033,9 +1090,9 @@ void Schedule<T>::set(DistanceVariable<T> *v, const T bound) {
// fail(this, e.var->id);
assert(nd != -INFTY);
if (makeCycle(e.var, nd))
fail(this, e.var->id);
fail({this, opposite(e.var)->id});
e.var->set(nd);
e.var->set(nd, {this, v->id});
queue.notifyChange(e.var->id);
}
}
......@@ -1055,9 +1112,9 @@ void Schedule<T>::set(DistanceVariable<T> *v, const T bound) {
// fail(this, e.var->id);
assert(nd != -INFTY);
if (makeCycle(e.var, nd))
fail(this, e.var->id);
fail({this, opposite(e.var)->id});
e.var->set(nd);
e.var->set(nd, {this, v->id});
queue.notifyChange(e.var->id);
}
}
......@@ -1402,7 +1459,7 @@ ostream &Schedule<T>::displayChoicePoint(ostream &os,
template <class T> void Schedule<T>::verifyAPSP() {
cout << "VERIFY APSP\n";
// cout << "VERIFY APSP\n";
vector<vector<T>> distance;
auto n{graph.vertexCount()};
......@@ -1566,7 +1623,7 @@ template <class T> ostream &Schedule<T>::display(ostream &os) const {
// // for every variable, its triggers
// vector<vector<Trigger>> triggers;
template <typename T, int N> ConstraintQueue<T, N>::ConstraintQueue() {}
template <typename T, int N> ConstraintQueue<T, N>::ConstraintQueue(Schedule<T>& s) : schedule(s) {}
// add a new constraint to the queue, returns the index of that constraint
// in
......@@ -1597,7 +1654,8 @@ void ConstraintQueue<T, N>::notifyChange(const int id) {
#ifdef TRACE
if (TRACE & PROPAGATION) {
cout << "notify change on var_" << id << " (" << triggers[id].size() << ")"
cout << "new literal: " << *(schedule.variables[id])
<< " b/c "<< schedule.get_explanation(id)
<< endl;
}
#endif
......@@ -1606,11 +1664,11 @@ void ConstraintQueue<T, N>::notifyChange(const int id) {
auto cons_id{trigger.constraint_id};
auto cons{constraints[cons_id]};
#ifdef TRACE
if (TRACE & PROPAGATION) {
cout << "notify constraint_" << cons_id << " = " << *cons << endl;