summaryrefslogtreecommitdiffstats
path: root/05-advanced_algorithms_and_complexity/02-linear_programming
diff options
context:
space:
mode:
authorJérémy Zurcher <jeremy@asynk.ch>2022-03-25 09:37:06 +0100
committerJérémy Zurcher <jeremy@asynk.ch>2022-03-25 09:37:06 +0100
commit623c5d60f54c62fd50d115859cf60ea41785d5d2 (patch)
treea1a08cbd3795cab502aa53efc5de4a3dec11f447 /05-advanced_algorithms_and_complexity/02-linear_programming
parent7b224832b3795baaa5334f5f8f352c7aec330ae5 (diff)
downloadcoursera-623c5d60f54c62fd50d115859cf60ea41785d5d2.zip
coursera-623c5d60f54c62fd50d115859cf60ea41785d5d2.tar.gz
Algorithms : complete 05-advanced_algorithms_and_complexity 02-linear_programming
Diffstat (limited to '05-advanced_algorithms_and_complexity/02-linear_programming')
-rw-r--r--05-advanced_algorithms_and_complexity/02-linear_programming/01-energy_values/energy_values.cpp90
-rw-r--r--05-advanced_algorithms_and_complexity/02-linear_programming/02-diet/diet.cpp205
-rw-r--r--05-advanced_algorithms_and_complexity/02-linear_programming/03-SimplexMethod.pdfbin0 -> 34699 bytes
-rw-r--r--05-advanced_algorithms_and_complexity/02-linear_programming/03-SolvingLinearPrograms.pdfbin0 -> 2325272 bytes
-rw-r--r--05-advanced_algorithms_and_complexity/02-linear_programming/03-ad_allocation/ad_allocation.cpp323
-rwxr-xr-x05-advanced_algorithms_and_complexity/02-linear_programming/03-ad_allocation/check40
-rw-r--r--05-advanced_algorithms_and_complexity/02-linear_programming/URLs3
-rwxr-xr-x05-advanced_algorithms_and_complexity/02-linear_programming/check47
8 files changed, 634 insertions, 74 deletions
diff --git a/05-advanced_algorithms_and_complexity/02-linear_programming/01-energy_values/energy_values.cpp b/05-advanced_algorithms_and_complexity/02-linear_programming/01-energy_values/energy_values.cpp
index b7956a7..253c961 100644
--- a/05-advanced_algorithms_and_complexity/02-linear_programming/01-energy_values/energy_values.cpp
+++ b/05-advanced_algorithms_and_complexity/02-linear_programming/01-energy_values/energy_values.cpp
@@ -3,7 +3,7 @@
#include <vector>
const double EPS = 1e-6;
-const int PRECISION = 20;
+const int PRECISION = 5;
typedef std::vector<double> Column;
typedef std::vector<double> Row;
@@ -19,16 +19,6 @@ struct Equation {
Column b;
};
-struct Position {
- Position(int column, int row):
- column(column),
- row(row)
- {}
-
- int column;
- int row;
-};
-
Equation ReadEquation() {
int size;
std::cin >> size;
@@ -42,48 +32,50 @@ Equation ReadEquation() {
return Equation(a, b);
}
-Position SelectPivotElement(
- const Matrix &a,
- std::vector <bool> &used_rows,
- std::vector <bool> &used_columns) {
- // This algorithm selects the first free element.
- // You'll need to improve it to pass the problem.
- Position pivot_element(0, 0);
- while (used_rows[pivot_element.row])
- ++pivot_element.row;
- while (used_columns[pivot_element.column])
- ++pivot_element.column;
- return pivot_element;
-}
-
-void SwapLines(Matrix &a, Column &b, std::vector <bool> &used_rows, Position &pivot_element) {
- std::swap(a[pivot_element.column], a[pivot_element.row]);
- std::swap(b[pivot_element.column], b[pivot_element.row]);
- std::swap(used_rows[pivot_element.column], used_rows[pivot_element.row]);
- pivot_element.row = pivot_element.column;
-}
-
-void ProcessPivotElement(Matrix &a, Column &b, const Position &pivot_element) {
- // Write your code here
-}
-
-void MarkPivotElementUsed(const Position &pivot_element, std::vector <bool> &used_rows, std::vector <bool> &used_columns) {
- used_rows[pivot_element.row] = true;
- used_columns[pivot_element.column] = true;
-}
-
Column SolveEquation(Equation equation) {
Matrix &a = equation.a;
Column &b = equation.b;
int size = a.size();
-
- std::vector <bool> used_columns(size, false);
- std::vector <bool> used_rows(size, false);
- for (int step = 0; step < size; ++step) {
- Position pivot_element = SelectPivotElement(a, used_rows, used_columns);
- SwapLines(a, b, used_rows, pivot_element);
- ProcessPivotElement(a, b, pivot_element);
- MarkPivotElementUsed(pivot_element, used_rows, used_columns);
+ int np_row = 0;
+
+ if (size == 0)
+ return b;
+
+ // Gaussian Elimination
+ // each column
+ for (int col = 0; col < a[0].size(); col++) {
+ // each non-pivot row
+ for (int row = np_row; row < size; row++) {
+ // leftmost non-zero
+ if (a[row][col] != 0) {
+ // swap row with np_row
+ if (row != np_row) {
+ std::swap(a[np_row], a[row]);
+ std::swap(b[np_row], b[row]);
+ }
+ Row& pivot_row = a[np_row];
+ // scale pivot row
+ if (pivot_row[col] != 1) {
+ double f = 1 / pivot_row[col];
+ for (int i = 0; i < a[0].size(); i++)
+ pivot_row[i] *= f;
+ b[np_row] *= f;
+ }
+ // scale then add to non-zero other rows
+ for (int i = 0; i < size; i++) {
+ if (i != np_row && a[i][col] != 0) {
+ Row& r = a[i];
+ double f = r[col] / pivot_row[col];
+ for (int j = 0; j < a[0].size(); j++)
+ r[j] -= pivot_row[j] * f;
+ b[i] -= b[np_row] * f;
+ }
+ }
+
+ np_row++;
+ break;
+ }
+ }
}
return b;
diff --git a/05-advanced_algorithms_and_complexity/02-linear_programming/02-diet/diet.cpp b/05-advanced_algorithms_and_complexity/02-linear_programming/02-diet/diet.cpp
index efe4e89..7e1056a 100644
--- a/05-advanced_algorithms_and_complexity/02-linear_programming/02-diet/diet.cpp
+++ b/05-advanced_algorithms_and_complexity/02-linear_programming/02-diet/diet.cpp
@@ -1,21 +1,208 @@
#include <algorithm>
+#include <limits>
#include <iostream>
#include <vector>
#include <cstdio>
using namespace std;
+// #define DEBUG
+
typedef vector<vector<double>> matrix;
-pair<int, vector<double>> solve_diet_problem(
- int n,
- int m,
- matrix A,
- vector<double> b,
- vector<double> c) {
+void print(matrix A, vector<double> b)
+{
+#ifdef DEBUG
+ for (int i = 0; i < A.size(); i++) {
+ for (int j = 0; j < A[0].size(); j++) {
+ cerr << A[i][j] << " ";
+ }
+ cerr << ": " << b[i] << endl;
+ }
+ cerr << endl;
+#endif
+}
+
+#define DELTA 0.000001
+static inline bool same(double a, double b)
+{
+ double d = (a - b);
+ return (d < 0 ? -d : d) < DELTA;
+}
+
+void gaussian_elimination(matrix& m)
+{
+ int rows = m.size();
+ int cols = m[0].size();
+ int np_row = 0;
+
+ // each column
+ for (int col = 0; col < (cols - 1); col++) {
+ // each non-pivot row
+ for (int row = np_row; row < rows; row++) {
+ // leftmost non-zero
+ if (m[row][col] != 0) {
+ // swap row with np_row
+ if (row != np_row)
+ std::swap(m[np_row], m[row]);
+
+ vector<double>& pivot_row = m[np_row];
+ // scale pivot row
+ if (pivot_row[col] != 1.0) {
+ double f = 1.0 / pivot_row[col];
+ for (int i = 0; i < cols; i++)
+ pivot_row[i] *= f;
+ }
+
+ // scale then add to non-zero other rows
+ for (int i = 0; i < rows; i++) {
+ if (i != np_row && m[i][col] != 0) {
+ vector<double>& r = m[i];
+ double f = r[col] / pivot_row[col];
+ for (int j = 0; j < cols; j++)
+ r[j] -= pivot_row[j] * f;
+ }
+ }
+
+ np_row++;
+ break;
+ }
+ }
+ }
+}
+
+#define BIG_NUM 1000000000
+#define BEST -std::numeric_limits<double>::max()
+
+pair<int, vector<double>> solve(
+ matrix A,
+ vector<double> b,
+ vector<double> c)
+{
+ int cstrs = A.size(); // n
+ int vars = A[0].size(); // m
+
+ matrix M(vars, vector<double>(vars + 1));
+ double best = BEST;
+ vector<double> sol(vars);
+
+ // build permutations of A
+ int nbits = 0;
+ int v = 0;
+ int max = (1 << cstrs) - 1;
+ vector<bool> bits(cstrs, false);
+
+ bool augmented = false; // will be set to true when the last constraint is used
+
+ // for each permutation of size vars
+ for (int v = 0; v < max; v++) {
+ // build next value
+ for (int i = 0; i < bits.size(); i++) {
+ if (!bits[i]) {
+ bits[i] = true;
+ nbits++;
+ break;
+ }
+ bits[i] = !bits[i];
+ nbits--;
+ }
- // Write your code here
+#ifdef DEBUG
+ cerr << "####" << v + 1 << " : ";
+ for (int i = 0; i < bits.size(); i++)
+ cerr << bits[i] << " ";
+ cerr << endl;
+#endif
+
+ if (nbits != vars)
+ continue;
+
+ if (!augmented && bits[bits.size() - 1]) {
+ // no solution found so far
+ if (same(best, BEST))
+ return {-1, sol}; // no solution
+ augmented = true;
+ }
+
+ // build matrix to solve
+ int x = 0;
+ for (int i = 0; i < bits.size(); i++) {
+ if (bits[i]) {
+ for (int j = 0; j < vars; j++)
+ M[x][j] = A[i][j];
+ M[x][vars] = b[i];
+ x++;
+ }
+ }
+
+ print(M, b);
+ gaussian_elimination(M);
+ print(M, b);
+
+ bool ok = true;
+
+ // check that solution matrix pivots are 1's
+ for (int i = 0; i < vars; i++) {
+ if (!same(M[i][i], 1.0)) {
+ ok = false;
+ break;
+ }
+ }
+ if (!ok)
+ continue;
+
+ // check that other inequalities holds
+ for (int i = 0; i < bits.size(); i++) {
+ if (!bits[i]) {
+ double r = 0;
+ for (int j = 0; j < vars; j++)
+ r += (M[j][vars] * A[i][j]);
+ if (r > (b[i] + DELTA)) {
+ ok = false;
+ break;
+ }
+ }
+ }
+ if (!ok)
+ continue;
+
+ // compute fitness
+ double r = 0;
+ for (int j = 0; j < vars; j++)
+ r += (M[j][vars] * c[j]);
+ if (r > best) {
+ if (augmented)
+ return { 1, sol}; // infinity, see last paragraph in What To Do
+ best = r;
+ for (int j = 0; j < vars; j++)
+ sol[j] = M[j][vars];
+ }
+ }
+
+ if (same(best, BEST))
+ return {-1, sol}; // no solution
+
+ return {0, sol};
+}
+
+pair<int, vector<double>> solve_diet_problem(
+ int n,
+ int m,
+ matrix A,
+ vector<double> b,
+ vector<double> c)
+{
+ // add m constraints : -var <= 0
+ for (int i = 0; i < m; i++) {
+ vector<double> v(m, 0);
+ v[i] = -1;
+ A.push_back(v);
+ b.push_back(0);
+ }
+ // add augmented constraint : sum vars < BIG_NUM
+ A.push_back(vector<double>(m, 1));
+ b.push_back(BIG_NUM);
- return {0, vector<double>(m, 0)};
+ return solve(A, b, c);
}
int main(){
@@ -45,7 +232,7 @@ int main(){
case 0:
printf("Bounded solution\n");
for (int i = 0; i < m; i++) {
- printf("%.18f%c", ans.second[i], " \n"[i + 1 == m]);
+ printf("%.14f%c", ans.second[i], " \n"[i + 1 == m]);
}
break;
case 1:
diff --git a/05-advanced_algorithms_and_complexity/02-linear_programming/03-SimplexMethod.pdf b/05-advanced_algorithms_and_complexity/02-linear_programming/03-SimplexMethod.pdf
new file mode 100644
index 0000000..1fe3c42
--- /dev/null
+++ b/05-advanced_algorithms_and_complexity/02-linear_programming/03-SimplexMethod.pdf
Binary files differ
diff --git a/05-advanced_algorithms_and_complexity/02-linear_programming/03-SolvingLinearPrograms.pdf b/05-advanced_algorithms_and_complexity/02-linear_programming/03-SolvingLinearPrograms.pdf
new file mode 100644
index 0000000..f227818
--- /dev/null
+++ b/05-advanced_algorithms_and_complexity/02-linear_programming/03-SolvingLinearPrograms.pdf
Binary files differ
diff --git a/05-advanced_algorithms_and_complexity/02-linear_programming/03-ad_allocation/ad_allocation.cpp b/05-advanced_algorithms_and_complexity/02-linear_programming/03-ad_allocation/ad_allocation.cpp
index 88bd8e6..b9566a0 100644
--- a/05-advanced_algorithms_and_complexity/02-linear_programming/03-ad_allocation/ad_allocation.cpp
+++ b/05-advanced_algorithms_and_complexity/02-linear_programming/03-ad_allocation/ad_allocation.cpp
@@ -1,42 +1,333 @@
#include <algorithm>
+#include <cmath>
+#include <limits>
#include <iostream>
+#include <iomanip>
#include <vector>
#include <cstdio>
using namespace std;
-typedef vector<vector<double>> matrix;
+// #define DEBUG 1
-pair<int, vector<double>> allocate_ads(
- int n,
- int m,
- matrix A,
- vector<double> b,
- vector<double> c) {
+#ifdef DEBUG
+# define say_dbg(more) cerr << "INF " << more << std::endl
+#else
+# define say_dbg(more) {}
+#endif
- // Write your code here
+using my_type = long double;
+using matrix = vector<vector<my_type>>;
+using row = vector<my_type>;
- return {0, vector<double>(m, 0)};
-}
+const my_type EPS = numeric_limits<my_type>::epsilon();
+
+struct position {
+ int row;
+ int column;
+ bool is_optimal() { return row == -1 || column == -1; }
+};
+
+enum class solution_state {
+ optimal,
+ infeasible,
+ unbounded
+};
+
+enum class method_phase {
+ one,
+ two
+};
+
+struct simplex_method {
+ int eqs, vars;
+ matrix A;
+ vector<my_type> rhs, obj, obj_phase1;
+ solution_state state;
+ method_phase phase;
+
+ static inline bool equals(my_type a, my_type b, my_type epsilon = 0.00001) {
+ return abs(a - b) < epsilon;
+ }
+
+ static inline bool equals_zero(my_type a, my_type epsilon = 0.001) {
+ return abs(a) < epsilon;
+ }
+
+ static inline my_type fmt(my_type v) { return (abs(v) < 0.0000005f) ? 0 : v; }
+
+ void print() const {
+#ifdef DEBUG
+ #define PR 2
+ cerr << endl;
+ for (size_t i = 0; i < A.size(); i++) {
+ for (size_t j = 0; j < A[i].size(); j++) {
+ cerr << fixed << setw(7) << setprecision(PR) << fmt(A[i][j]) << ' ';
+ }
+ cerr << fixed << " = " << setw(5) << setprecision(PR) << fmt(rhs[i]) << endl;
+ }
+ for (const auto &v : obj) {
+ cerr << setw(7) << fmt(v) << ' ';
+ }
+ cerr << fixed << " = " << setw(5) << setprecision(PR) << fmt(rhs[A.size()]) << endl;
+ if (phase == method_phase::one) {
+ for (const auto &v : obj_phase1) {
+ cerr << setw(7) << fmt(v) << ' ';
+ }
+ cerr << fixed << " = " << setw(5) << setprecision(PR) << fmt(rhs[A.size() + 1]) << endl;
+ }
+ cerr << endl;
+#endif
+ }
+
+ bool prepare() {
+ int negative_rhs = count_if(rhs.cbegin(), rhs.cend(), [](my_type v){return v < 0.0;});
+ // FIXME remove from negs the rows that have at least 1 basic variables (they won't need an artificial variable)
+ int delta = eqs - negative_rhs;
+ if (delta > 0) {
+ for (auto &v : A) {
+ v.resize(v.size() - delta);
+ }
+ }
+ for(size_t i = 0; i < negative_rhs; i++) {
+ obj.push_back(0.0);
+ }
+ // add slacks | surplus (will be inverted)
+ for (size_t i = 0; i < A.size(); i++) {
+ A[i][i + vars] = 1;
+ }
+ if (negative_rhs > 0) {
+ obj_phase1 = vector<my_type>(vars + eqs + negative_rhs, 0);
+ for (size_t i = 0; i < rhs.size(); i++) {
+ if (rhs[i] < 0.0) {
+ // invert row and rhs
+ rhs[i] = -rhs[i];
+ transform(A[i].begin(), A[i].end(), A[i].begin(), negate<my_type>());
+ // sum row to obj_phase1 and last rhs
+ for (size_t j = 0; j < obj_phase1.size(); j++) {
+ obj_phase1[j] += A[i][j];
+ }
+ rhs[rhs.size() -1] += rhs[i];
+ // add artificial variable
+ A[i][A[i].size() - negative_rhs--] = 1;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ bool is_column_basic(int col) { // FIXME not used
+ bool basic = false;
+ for (size_t row = 0; row < A.size(); row++) {
+ double v = A[row][col];
+ if (!equals_zero(v, EPS)) {
+ if (!basic && equals(v, 1.0f)) {
+ basic = true;
+ } else {
+ basic = false;
+ break;
+ }
+ }
+ }
+ return basic;
+ }
+
+ position find_pivot(row &cw) {
+ // Optimality test : search largest positive coefficient in objective function
+ // Bland's rule : Choose the leftmost nonbasic column with a negative (reduced) cost TODO
+ int j = distance(cw.begin(), max_element(cw.begin(), cw.end()));
+ if (cw[j] <= 0.000000000001L) { // FIXME
+ say_dbg("pivot col not found" << endl);
+ return {-1, -1}; // is_optimal
+ }
+
+ // Unboundedness test : search a positive coefficient
+ // Bland's rule : Chose the lowest ratio (RHS vs coefficient) where the coefficient is greater than zero.
+ // Bland's rule : If the minimum ratio is shared by several rows, choose the row with the lowest-numbered column (variable) basic in it.
+ int i = -1;
+ vector<int> pivot_rows;
+ my_type ratio = numeric_limits<my_type>::max() - 1;
+ for (size_t k = 0; k < A.size(); k++) {
+ my_type v = A[k][j];
+ if (v > 0.0) {
+ my_type r = (rhs[k] / v);
+ bool tiny = (fabs(r - ratio) < 0.000000001L); // FIXME could divert with time ;) || (tiny && r > 0) ????
+ if (r < ratio || tiny) {
+ if (!tiny) {
+ ratio = r;
+ pivot_rows.clear();
+ }
+ pivot_rows.push_back(k);
+ }
+ }
+ }
+ int s = pivot_rows.size();
+ if (s == 0) {
+ state = solution_state::unbounded;
+ } else if (s > 1) {
+ say_dbg("chose 1 pivot amongs " << s);
+ size_t first = 0;
+ for (auto it = pivot_rows.begin(); it != pivot_rows.end(); it++) {
+ int r = *it;
+ for (size_t k = 0; k < A[0].size(); k++) {
+ if (equals(A[r][k], 1.0f)) {
+ if (is_column_basic(k)) {
+ if (k >= first) { // choose the right most !!!
+ first = k;
+ i = r;
+ }
+ break;
+ }
+ }
+ }
+ }
+ } else {
+ i = pivot_rows[0];
+ }
+ say_dbg("pivot : [ " << i << " ; " << j << " ] " << setprecision(15) << A[i][j]<< " " << ratio);
+ return {i, j};
+ }
+
+ void scale_pivot(position p) {
+ auto d = A[p.row][p.column]; // optimization with 1/factor fails !!!
+ rhs[p.row] /= d;
+ for (auto &n : A[p.row]) {
+ n /= d;
+ }
+ }
+
+ void process_pivot(position p, row &w) {
+ for (int i = 0, s = A.size(); i < s; i++) {
+ if (p.row != i && !equals_zero(A[i][p.column], EPS)) {
+ my_type f = A[i][p.column];
+ for (size_t j = 0; j < A[i].size(); j++) {
+ A[i][j] -= A[p.row][j] * f;
+ }
+ rhs[i] -= rhs[p.row] * f;
+ }
+ }
+
+ if (phase == method_phase::one) {
+ auto o = obj[p.column];
+ auto o1 = obj_phase1[p.column];
+ rhs[rhs.size() - 2] -= rhs[p.row] * o;
+ rhs[rhs.size() - 1] -= rhs[p.row] * o1;
+ for (size_t i = 0; i < w.size(); i++) {
+ obj[i] -= A[p.row][i] * o;
+ obj_phase1[i] -= A[p.row][i] * o1;
+ }
+ } else {
+ auto o = obj[p.column];
+ rhs[rhs.size() - 1] -= rhs[p.row] * o;
+ for (size_t i = 0; i < w.size(); i++) {
+ obj[i] -= A[p.row][i] * o;
+ }
+ }
+ }
+
+ void Gauss_Jordam_eliminations(row &obj) {
+ for(;;) {
+ position p = find_pivot(obj);
+ if (p.is_optimal() || state == solution_state::unbounded) {
+ break;
+ }
+ scale_pivot(p);
+ process_pivot(p, obj);
+ print();
+ }
+ }
+
+ void trim_table_from_avars() {
+ obj.resize(vars + eqs);
+ rhs.pop_back();
+ for (auto &r : A) {
+ r.resize(vars + eqs);
+ }
+ }
+
+ void phase_I() {
+ say_dbg("*** Phase I" << endl);
+ phase = method_phase::one;
+ Gauss_Jordam_eliminations(obj_phase1);
+ state = equals_zero(rhs.back()) ? solution_state::optimal : solution_state::infeasible;
+ }
-int main(){
+ void phase_II() {
+ say_dbg("*** Phase II");
+ phase = method_phase::two;
+ trim_table_from_avars();
+ print();
+ Gauss_Jordam_eliminations(obj);
+ }
+
+ void round_values(vector<my_type> &result) {
+ for (auto it = result.begin(); it != result.end(); it++) {
+ if (equals(*it, ((int)*it)+1)) { // slightly under int value
+ *it = (my_type)((int)*it+1);
+ } else if (equals(*it, ((int)*it))) { // slightly over int value
+ *it = (my_type)((int)*it);
+ }
+ }
+ }
+
+ pair<int, vector<my_type> > solve() {
+ state = solution_state::optimal;
+ bool mixed_constraints = prepare();
+ print();
+ if (mixed_constraints) {
+ phase_I();
+ if (state == solution_state::infeasible) {
+ return {-1, {}};
+ }
+ }
+ phase_II();
+ if (state == solution_state::unbounded) {
+ return {1, {}};
+ }
+
+ vector<my_type> result(vars, 0);
+ for (int i = 0; i < vars; i++) {
+ int k = -1;
+ my_type sum = 0.0;
+ for (int j = 0; j < eqs; j++) {
+ sum += fabs(A[j][i]);
+ if (equals(A[j][i], 1.0)) {
+ k = j;
+ }
+ }
+ if (k != -1) {
+ result[i] = (sum - 1.0 > EPS) ? 0.0 : rhs[k]; // use RHS unless there more then 1 cumulated factor
+ }
+ }
+
+ round_values(result);
+
+ return {0, move(result)};
+ }
+
+};
+
+int main() {
int n, m;
cin >> n >> m;
- matrix A(n, vector<double>(m));
+ matrix A(n, vector<my_type>(m + n + n, 0.0)); // variables[m], slacks|surplus[n], artificials[0;n]
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cin >> A[i][j];
}
}
- vector<double> b(n);
+ vector<my_type> b(n + 2, 0); // rhs + 2 objective
for (int i = 0; i < n; i++) {
cin >> b[i];
}
- vector<double> c(m);
+ vector<my_type> c(m + n); // variables + slacks
for (int i = 0; i < m; i++) {
cin >> c[i];
}
- pair<int, vector<double>> ans = allocate_ads(n, m, A, b, c);
+ simplex_method sm{n, m, move(A), move(b), move(c)};
+
+ pair<int, vector<my_type>> ans = sm.solve();
switch (ans.first) {
case -1:
@@ -45,7 +336,7 @@ int main(){
case 0:
printf("Bounded solution\n");
for (int i = 0; i < m; i++) {
- printf("%.18f%c", ans.second[i], " \n"[i + 1 == m]);
+ printf("%.18Lf%c", ans.second[i], " \n"[i + 1 == m]); // format must match my_type !!!
}
break;
case 1:
diff --git a/05-advanced_algorithms_and_complexity/02-linear_programming/03-ad_allocation/check b/05-advanced_algorithms_and_complexity/02-linear_programming/03-ad_allocation/check
new file mode 100755
index 0000000..1f7160a
--- /dev/null
+++ b/05-advanced_algorithms_and_complexity/02-linear_programming/03-ad_allocation/check
@@ -0,0 +1,40 @@
+#! /bin/bash
+
+RESET="\033[0m"
+RED="\033[0;31m"
+GREEN="\033[0;32m"
+BROWN="\033[0;33m"
+
+GPP_OPTS="-std=c++11 -O0 -ggdb"
+#GPP_OPTS="-std=c++11 -O2"
+
+binaries=()
+
+for src in $(find . -name \*.cpp | sort)
+do
+ bin=/tmp/${src##*/}.bin
+ sed -i 's/^\/\/ #define DEBUG 1/#define DEBUG 1/' $src
+ echo -e "${RED}compile $GREEN${src}$RESET" && g++ $GPP_OPTS "$src" -o "$bin" || exit 1
+ binaries+=("$bin")
+done
+
+for t in "$@"
+do
+ tf="./tests/$t"
+ echo -en "$GREEN*****$RESET try $RED$t$RESET ...\n$BROWN>$RESET\n"
+ # cat "$tf"
+ cat "$tf.a"
+ cat "$tf.a" | sed 's/\([0-9]\+\.[0-9]\{4\}\)[0-9]\+/\1/g' > "/tmp/$t.a"
+ for bin in ${binaries[@]}
+ do
+ echo -en "$BROWN> $bin$RESET\n"
+ cat "$tf" | "$bin" 2>"${bin}-${t}-steps" | sed 's/\([0-9]\+\.[0-9]\{4\}\)[0-9]\+/\1/g' > "${bin}-${t}-out"
+ cmp "/tmp/$t.a" "${bin}-${t}-out" >/dev/null
+ if [ $? -ne 0 ]; then
+ echo -e " $BROWN$t$RESET is ${RED}KO$RESET"
+ # cat "${bin}-${t}-out"
+ else
+ echo -e " $BROWN$t$RESET is ${GREEN}ok$RESET"
+ fi
+ done
+done
diff --git a/05-advanced_algorithms_and_complexity/02-linear_programming/URLs b/05-advanced_algorithms_and_complexity/02-linear_programming/URLs
new file mode 100644
index 0000000..6944ff1
--- /dev/null
+++ b/05-advanced_algorithms_and_complexity/02-linear_programming/URLs
@@ -0,0 +1,3 @@
+http://reshmat.ru/simplex_method_lpp.html
+http://www.phpsimplex.com/simplex/simplex.htm?l=en
+http://cbom.atozmath.com/CBOM/Simplex.aspx
diff --git a/05-advanced_algorithms_and_complexity/02-linear_programming/check b/05-advanced_algorithms_and_complexity/02-linear_programming/check
new file mode 100755
index 0000000..b449883
--- /dev/null
+++ b/05-advanced_algorithms_and_complexity/02-linear_programming/check
@@ -0,0 +1,47 @@
+#! /bin/bash
+
+RESET="\033[0m"
+RED="\033[0;31m"
+GREEN="\033[0;32m"
+BROWN="\033[0;33m"
+
+BIN=/tmp/bin
+OUTA=/tmp/_outa
+OUTB=/tmp/_outb
+# GPP_OPTS="-std=c++11 -O0 -ggdb"
+GPP_OPTS="-std=c++11 -O2"
+
+for path in $(find . -name \*.cpp | sort); do
+ src=${path##*/}
+ dir=${path%/*}
+ echo -e "${RED}validate $BROWN$dir$RESET/$GREEN$src$RESET"
+ pushd $dir >/dev/null || exit 1
+ sed -i 's/^#define DEBUG 1/\/\/ #define DEBUG 1/' $src
+ echo -e " ${RED}compile $GREEN$src$RESET" && g++ $GPP_OPTS $src -o $BIN || exit 1
+ if [ -d tests ]; then
+ start=`date +%s.%N`
+ echo -e " ${RED}check $GREEN$src$RESET"
+ # if [ "$src" == "good.cpp" -o "$src" == "ad_allocation-new.cpp" ]; then
+ for t in $(find ./tests -name "*[^a~]"|sort); do
+ if [ -f $t -a -f "$t.a" ]; then
+ cat $t | $BIN 2>/dev/null | sed 's/\([0-9]\+\.[0-9]\{4\}\)[0-9]\+/\1/g' > $OUTA || echo "segfault"
+ cat $t.a | sed 's/\([0-9]\+\.[0-9]\{4\}\)[0-9]\+/\1/g' > $OUTB
+ cmp $OUTA $OUTB >/dev/null
+ if [ $? -ne 0 ]; then
+ echo -e " $BROWN$t$RESET is ${RED}KO$RESET"
+ # cat $OUTA
+ # cat $OUTB
+ # else
+ # echo -e " $BROWN$t$RESET is ${GREEN}ok$RESET"
+ fi
+ fi
+ done
+ end=`date +%s.%N`
+ echo "runtime : $(echo "$end - $start" | bc -l)"
+ # fi
+ else
+ echo -e " ${RED}no tests$RESET"
+ fi
+ popd > /dev/null
+done
+