Commit 0b6b0943 authored by ehebrard's avatar ehebrard
Browse files

prof

parent 68c7a036
......@@ -7,6 +7,8 @@
#include "Global.hpp"
#include "SparseSet.hpp"
#define DEBUG_BELLMANFORD
using namespace std;
namespace schedcl {
......@@ -28,13 +30,27 @@ public:
// updates all shortest paths from x (and through y) and put them in
// 'shortest_path'. Sets the flag 'negative_cycle' if it finds a negative
// cycle including x-y
template <class G>
template <class G
#ifdef DEBUG_BELLMANFORD
,
class P
#endif
>
void allShorterPaths(const int x, const int y, const T wxy,
const G &neighbors, vector<T> &shortest_path,
SparseSet<> &reached);
SparseSet<> &reached
#ifdef DEBUG_BELLMANFORD
,
P &printer
#endif
);
bool negative_cycle{false};
#ifdef DEBUG_BELLMANFORD
bool debug_flag{false};
#endif
// vector<T> shortest_path;
// SparseSet<> reached;
......@@ -98,8 +114,29 @@ void BellmanFord<T>::allShortestPaths(const int s, const G& neighbors, vector<T>
}
template <typename T>
template<class G>
void BellmanFord<T>::allShorterPaths(const int x, const int y, const T wxy, const G& neighbors, vector<T>& shortest_path, SparseSet<>& reached) {
template <class G
#ifdef DEBUG_BELLMANFORD
,
class P
#endif
>
void BellmanFord<T>::allShorterPaths(const int x, const int y, const T wxy,
const G &neighbors,
vector<T> &shortest_path,
SparseSet<> &reached
#ifdef DEBUG_BELLMANFORD
,
P &printer
#endif
) {
assert(changed.empty());
#ifdef DEBUG_BELLMANFORD
if (debug_flag)
cout << " ASP from " << printer.label(y) << " after edge "
<< printer.label(x) << "->" << printer.label(y) << " (" << wxy
<< ")\n";
#endif
shortest_path[y] = wxy;
......@@ -108,16 +145,52 @@ void BellmanFord<T>::allShorterPaths(const int x, const int y, const T wxy, cons
while (not changed.empty()) {
auto u{changed.front()};
#ifdef DEBUG_BELLMANFORD
if (debug_flag) {
cout << printer.label(u) << " (" << shortest_path[u] << ") stack:";
for (auto q : changed)
cout << " " << printer.label(q);
cout << " vis:";
for (auto q : reached)
cout << " " << printer.label(q);
cout << endl;
}
#endif
changed.pop_front();
for (auto e : neighbors[u]) {
auto v{e.neighbor()};
auto w{e.length()};
#ifdef DEBUG_BELLMANFORD
if (debug_flag)
cout << " -" << printer.label(v) << " (" << shortest_path[u] << "+" << w
<< "/" << shortest_path[v] << ")\n";
#endif
if (w != INFTY and shortest_path[u] + w < shortest_path[v]) {
if (v == x and wxy + w < 0) {
#ifdef DEBUG_BELLMANFORD
if (debug_flag)
cout << " explore\n";
#endif
if (v == x and wxy + shortest_path[u] + w < 0) {
#ifdef DEBUG_BELLMANFORD
if (debug_flag)
cout << "created a negative cycle between " << printer.label(x)
<< " and " << printer.label(y) << " (" << wxy << " + "
<< shortest_path[u] << " + " << w << ")" << endl;
#endif
negative_cycle = true;
changed.clear();
// exit(1);
return;
}
......@@ -127,6 +200,10 @@ void BellmanFord<T>::allShorterPaths(const int x, const int y, const T wxy, cons
if (not reached.has(v))
reached.add(v);
}
#ifdef DEBUG_BELLMANFORD
else if (debug_flag)
cout << " reject\n";
#endif
}
}
}
......
......@@ -139,6 +139,7 @@ public:
// get the current distance
T get() const { return literals.back().value; }
operator T() const { return literals.back().value; }
const Bound<T> &back() const { return literals.back(); }
......
......@@ -13,12 +13,16 @@
#include "SparseGraph.hpp"
// #include "SparseDistanceGraph.hpp"
// #define DEBUG_CONSTRAINT
// #define DEBUG_UPDATES
#define ONLY_MINIMAL
// #define DEBUG_FLOYDWARSHALL true
// #define DEBUG_CONSTRAINT
#define SEARCH 1
#define PROPAGATION 2
// #define TRACE 3
#define UPDATES 4
// #define TRACE 7
// #define debug_flag (num_literals >= 15762)
namespace schedcl {
......@@ -44,6 +48,7 @@ template <typename T> class ResourceConstraint {
public:
#ifdef DEBUG_CONSTRAINT
bool debug_flag{false};
int id;
#endif
const int priority{0};
......@@ -175,6 +180,10 @@ public:
/*!@name Public Parameters*/
//@{
vector<DistanceVariable<T> *> variables;
#if (defined(DEBUG_UPDATES) and !defined(ONLY_MINIMAL))
vector<DistanceVariable<T> *> clone_variables;
#endif
//@}
vector<ChoicePoint> choicepoints;
......@@ -187,14 +196,23 @@ public:
// the graph of distances
// SparseDistanceGraph<T> graph;
#ifdef ONLY_MINIMAL
vector<vector<DistanceVariable<T> *>> matrix;
#else
SparseGraph<T> full_graph;
#endif
SparseGraph<T> minimal_graph;
ostream &print_reason(ostream &os, const int hint) const override {
os << *variables[hint];
os << " tr. " << *variables[hint];
return os;
}
#ifdef TRACE
bool debug_flag{false};
#endif
// const Explanation<T> get_explanation(const int id) const { return
// explanation[id]; }
......@@ -235,9 +253,14 @@ private:
// changes
BellmanFord<T> algo;
#ifndef ONLY_MINIMAL
vector<int> shortest_path_from_x;
vector<int> shortest_path_to_y;
#else
vector<int> shortest_path_from_x_min;
vector<int> shortest_path_to_y_min;
#endif
SparseSet<> fCandidates;
SparseSet<> bCandidates;
//@}
......@@ -285,15 +308,44 @@ template <class T> void Schedule<T>::initialise() {
// full_graph.initialise(*this, true);
// minimal_graph.initialise(*this, false);
full_graph.initialise(this->numEvent());
for(auto v : variables) {
full_graph.addArc(v);
}
minimal_graph.initialise(this->numEvent());
#ifndef ONLY_MINIMAL
full_graph.initialise(this->numEvent());
for (auto v : variables) {
full_graph.addArc(v);
}
shortest_path_from_x.resize(numEvent(), INFTY);
shortest_path_to_y.resize(numEvent(), INFTY);
#else
matrix.resize(this->numEvent());
for (auto &m : matrix)
m.resize(this->numEvent(), NULL);
// for(auto i{0}; i<numEvent(); ++i) {
// for(auto j{0}; j<numEvent(); ++j) {
// cout << (matrix[i][j] == NULL);
// }
// cout << endl;
// }
for (auto v : variables)
matrix[v->from][v->to] = v;
// for(auto i{0}; i<numEvent(); ++i) {
// for(auto j{0}; j<numEvent(); ++j) {
// cout << (matrix[i][j] == NULL);
// }
// cout << endl;
// }
shortest_path_from_x_min.resize(numEvent(), INFTY);
shortest_path_to_y_min.resize(numEvent(), INFTY);
#endif
#if defined(DEBUG_UPDATES) or defined(ONLY_MINIMAL)
minimal_graph.initialise(this->numEvent());
#endif
fCandidates.reserve(numEvent());
bCandidates.reserve(numEvent());
......@@ -308,17 +360,25 @@ template <class T> void Schedule<T>::initialise() {
assert(variables[i]->to == variables[i + 1]->from);
}
#ifdef DEBUG_UPDATES
for (int i{0}; i < variables.size(); ++i) {
clone_variables.push_back(new DistanceVariable<T>(
*this, variables[i]->from, variables[i]->to, i, *variables[i]));
}
#endif
// exit(1);
// declared.resize(numVar(), 0);
// declared.clear();
// cout << *this << endl;
// exit(1);
}
// assert(x != y);
template <class T> int Schedule<T>::getUB() const {
return variables[0]->get();
}
template <class T> int Schedule<T>::getUB() const { return *variables[0]; }
template <class T> int Schedule<T>::numVar() const { return variables.size(); }
......@@ -392,6 +452,10 @@ const DistanceVariable<T> *Schedule<T>::getVariable(event x, event y) const {
template <class T> void Schedule<T>::post(ResourceConstraint<T> *c) {
auto idx = queue.add(c);
c->post(idx);
#ifdef DEBUG_CONSTRAINT
c->id = idx;
#endif
}
//
// template <class T>
......@@ -520,8 +584,9 @@ template <class T>
void Schedule<T>::addConstraint(DistanceVariable<T> *v, const T d, const Explanation<T> e) {
#ifdef TRACE
if (TRACE & PROPAGATION) {
cout << "add literal " << *v << " <= " << d << " b/c " << e << endl;
if (debug_flag and (TRACE & PROPAGATION)) {
cout << "add constraint (" << v->id << ") " << *v << " <= " << d << " b/c "
<< e << endl;
}
#endif
......@@ -531,23 +596,23 @@ void Schedule<T>::addConstraint(DistanceVariable<T> *v, const T d, const Explana
new_bound[vid] = d;
explanation[vid] = e;
++num_prunings;
minimal_graph.addArc(v);
// minimal_graph.addArc(v);
}
#ifdef TRACE
else if (TRACE & PROPAGATION) {
else if (debug_flag and (TRACE & PROPAGATION)) {
cout << "literal is not new\n";
}
#endif
} else {
if (v->get() > d) {
if (*v > d) {
changes.add(vid);
new_bound[vid] = d;
explanation[vid] = e;
++num_prunings;
minimal_graph.addArc(v);
// minimal_graph.addArc(v);
}
#ifdef TRACE
else if (TRACE & PROPAGATION) {
else if (debug_flag and (TRACE & PROPAGATION)) {
cout << "literal is not new\n";
}
#endif
......@@ -584,8 +649,8 @@ void Schedule<T>::addConstraint(DistanceVariable<T> *v, const T d, const Explana
template <class T> void Schedule<T>::fail(Explanation<T> e) {
#ifdef TRACE
if (TRACE) {
cout << "FAIL!!\n"; // TODO
if (debug_flag) {
cout << "FAIL!! (b/c " << e << ")\n"; // TODO
}
#endif
......@@ -672,13 +737,23 @@ template <class T> ostream &Schedule<T>::displayStats(ostream &os) const {
os << setfill(' ') << "] fails=" << setw(8) << left << num_fails
<< " updates=" << setw(10) << left << num_updates
<< " literals=" << setw(12) << left << num_literals
<< " prunings=" << setw(8) << left << num_prunings
<< " prunings=" << setw(8) << left << num_prunings
<< " cpu=" << (cpu_time() - start_time) << "\n";
return os;
}
template <class T> void Schedule<T>::search() {
start_time = cpu_time();
// for(auto i{0}; i<variables.size(); ++i) {
// cout << queue.triggers[i].size() << endl;
// }
//
// exit(1);
// cout <<matrix[0][27]->id << " " << *matrix[0][27] << endl;
// exit(1);
// initialisation
sequence.reserve(choicepoints.size());
......@@ -692,9 +767,13 @@ template <class T> void Schedule<T>::search() {
while (lb < ub) {
try {
propagate();
assert(queue.empty());
// if(ReversibleObject::env->level() > 0)
// exit(1);
#ifdef DEBUG_FLOYDWARSHALL
verifyAPSP();
#endif
......@@ -707,7 +786,7 @@ template <class T> void Schedule<T>::search() {
}
#ifdef TRACE
if (TRACE & SEARCH and !(TRACE & PROPAGATION)) {
if (debug_flag and (TRACE & SEARCH) and !(TRACE & PROPAGATION)) {
cout << "bounds = [" << lb << ".." << ub << "]\n" << *this << endl;
}
#endif
......@@ -724,7 +803,7 @@ template <class T> void Schedule<T>::search() {
displayStats(cout);
#ifdef TRACE
if (TRACE & SEARCH) {
if (debug_flag and (TRACE & SEARCH)) {
cout << "solution! (ub=" << ub << ")\n";
}
#endif
......@@ -747,11 +826,15 @@ template <class T> void Schedule<T>::search() {
++num_choicepoints;
#ifdef TRACE
if (TRACE & SEARCH) {
if (debug_flag and (TRACE & SEARCH)) {
cout << "new choice point @LEVEL " << ReversibleObject::env->level()
<< ": ";
// << " (" << cp.x[0] << "|" << cp.x[1] << ") : ";
<< " (" << num_literals << "): ";
displayChoicePoint(cout, cp);
// cout << " ** " << *variables[300] << " and " << *variables[301];
cout << endl;
}
#endif
......@@ -790,11 +873,13 @@ template <class T> void Schedule<T>::backtrack() {
ReversibleObject::env->restore(ReversibleObject::env->level() - 1);
#ifdef TRACE
if (TRACE & SEARCH) {
if (debug_flag and (TRACE & SEARCH)) {
cout << "backtrack on choice point " << k << " @LEVEL "
<< ReversibleObject::env->level() << ": ";
displayChoicePoint(cout, choicepoints[k]);
cout << endl << *this << endl;
cout
// << endl << *this
<< endl;
}
#endif
......@@ -808,7 +893,7 @@ template <class T> void Schedule<T>::propagate() {
ResourceConstraint<T> *algorithm{NULL};
#ifdef TRACE
if (TRACE & PROPAGATION) {
if (debug_flag and (TRACE & PROPAGATION)) {
cout << "start propagation of";
for (auto i : changes) {
cout << " " << label(variables[i]->to) << " - "
......@@ -828,7 +913,7 @@ template <class T> void Schedule<T>::propagate() {
break;
#ifdef TRACE
if (TRACE & PROPAGATION) {
if (debug_flag and (TRACE & PROPAGATION)) {
cout << " propagate " << *algorithm << endl;
}
#endif
......@@ -839,7 +924,7 @@ template <class T> void Schedule<T>::propagate() {
}
#ifdef TRACE
if (TRACE & PROPAGATION) {
if (debug_flag and (TRACE & PROPAGATION)) {
cout << "end propagation:\n" << *this << endl;
}
#endif
......@@ -854,6 +939,16 @@ template <class T> void Schedule<T>::updateDistances() {
assert(new_bound[i] != -INFTY);
assert(explanation[i].expl != NULL);
++num_updates;
#ifdef DEBUG_UPDATES
minimal_graph.addArc(clone_variables[i]);
#endif
#ifdef ONLY_MINIMAL
// cout << "add literal " << *variables[i] << " (" << i << ")"<< endl;
minimal_graph.addArc(variables[i]);
#endif
set(variables[i], new_bound[i], explanation[i]);
}
}
......@@ -872,7 +967,11 @@ bool Schedule<T>::makeCycle(const DistanceVariable<T> *v, const int lv) const {
template <class T>
DistanceVariable<T> * Schedule<T>::opposite(const DistanceVariable<T> *v) const {
#ifdef ONLY_MINIMAL
return matrix[v->to][v->from];
#else
return (v->id % 2 ? variables[v->id - 1] : variables[v->id + 1]);
#endif
}
template <class T>
......@@ -884,38 +983,202 @@ void Schedule<T>::set(DistanceVariable<T> *v, const T bound, const Explanation<T
assert(e.expl != NULL);
assert(bound != -INFTY);
if (makeCycle(v, bound))
if (makeCycle(v, bound)) {
fail({this, opposite(v)->id});
}
auto x{v->from};
auto y{v->to};
#ifndef ONLY_MINIMAL
fill(shortest_path_from_x.begin(), shortest_path_from_x.end(), INFTY);
fill(shortest_path_to_y.begin(), shortest_path_to_y.end(), INFTY);
#ifdef DEBUG_UPDATES
fill(shortest_path_from_x_min.begin(), shortest_path_from_x_min.end(), INFTY);
fill(shortest_path_to_y_min.begin(), shortest_path_to_y_min.end(), INFTY);
#endif
#else
fill(shortest_path_from_x_min.begin(), shortest_path_from_x_min.end(), INFTY);
fill(shortest_path_to_y_min.begin(), shortest_path_to_y_min.end(), INFTY);
#endif
// vector<T> shortest_path_from_x_min(numEvent(), INFTY);
// vector<T> shortest_path_to_y_min(numEvent(), INFTY);
fCandidates.clear();
bCandidates.clear();
#ifdef TRACE
if (debug_flag and (TRACE & UPDATES)) {
cout << endl << " update w.r.t. literal " << *v << " (" << bound << ")\n";
}
#endif
algo.initialise(numEvent());
// cout << *this << endl;
#ifdef ONLY_MINIMAL
for (auto i{0}; i < numEvent(); ++i) {
if (matrix[x][i] != NULL)
shortest_path_from_x_min[i] = *matrix[x][i];
if (matrix[i][y] != NULL)
shortest_path_to_y_min[i] = *matrix[i][y];
}
shortest_path_from_x_min[x] = 0;
shortest_path_to_y_min[y] = 0;
#else
#ifdef DEBUG_UPDATES
algo.allShortestPaths(x, minimal_graph.neighbor[SUCCESSOR],
shortest_path_from_x_min);
algo.allShortestPaths(y, minimal_graph.neighbor[PREDECESSOR],
shortest_path_to_y_min);
#endif
// cout << " ";
// for (auto i{0}; i < numEvent(); ++i)
// cout << " " << setw(5) << label(i);
// cout << endl << "(from " << setw(2) << label(x) << ")";
// for (auto i{0}; i < numEvent(); ++i)
// if (shortest_path_from_x_min[i] != INFTY)
// cout << " " << setw(5) << shortest_path_from_x_min[i];
// else
// cout << " oo";
// cout << endl;
#endif
#ifndef ONLY_MINIMAL
algo.allShortestPaths(x, full_graph.neighbor[SUCCESSOR],
shortest_path_from_x);
algo.allShortestPaths(y, full_graph.neighbor[PREDECESSOR],
shortest_path_to_y);
#endif
#ifdef DEBUG_UPDATES
// cout << " ";
// for (auto i{0}; i < numEvent(); ++i)
// cout << " " << setw(5) << label(i);
// cout << endl << "(from " << setw(2) << label(x) << ")";
// for (auto i{0}; i < numEvent(); ++i)
// if (shortest_path_from_x[i] != INFTY)
// cout << " " << setw(5) << shortest_path_from_x[i];
// else
// cout << " oo";
// cout << endl;
for (auto i{0}; i < numEvent(); ++i) {
if (shortest_path_from_x_min[i] != shortest_path_from_x[i]) {
cout << "difference on shortest path from " << label(x) << " to "
<< label(i) << ": " << shortest_path_from_x_min[i] << "/"
<< shortest_path_from_x[i] << endl;
cout << *this << endl;
exit(1);
}
if (shortest_path_to_y_min[i] != shortest_path_to_y[i]) {
cout << "difference on shortest path from " << label(i) << " to "
<< label(y) << ": " << shortest_path_to_y_min[i] << "/"
<< shortest_path_to_y[i] << endl;
cout << *this << endl;
exit(1);
}
}
#endif
v->set(bound, e);
queue.notifyChange(v->id);
#ifdef DEBUG_UPDATES
clone_variables[v->id]->set(bound, e);
#endif
#if (defined(DEBUG_UPDATES) or defined(ONLY_MINIMAL))
// cout << "\n\nASP from " << label(y) << " in:" << *this << endl;
algo.allShorterPaths(x, y, bound, minimal_graph.neighbor[SUCCESSOR],
shortest_path_from_x_min, fCandidates
#ifdef DEBUG_BELLMANFORD
,
*this
#endif