This documentation is automatically generated by online-judge-tools/verification-helper
View the Project on GitHub kmyk/competitive-programming-library
vector<double> debug_c;
void linsolve_tableau(vector<double> & z, vector<vector<double> > & tableau, vector<double> & k, vector<int> & ix) {
constexpr double eps = 1e-8;
vector<vector<double > > & m = tableau;
int h = k.size();
int w = z.size();
while (true) {
double value = 0;
repeat (y, h) if (ix[y] < debug_c.size()) {
value += debug_c[ix[y]] * k[y];
}
fprintf(stderr, "value %lf\n", value);
fprintf(stderr, " z : ");
repeat (x, w) {
fprintf(stderr, "%6.2lf ", z[x]);
}
fprintf(stderr, "\n");
repeat (y, h) {
fprintf(stderr, "%3d : ", ix[y]);
repeat (x, w) {
fprintf(stderr, "%6.2lf ", m[y][x]);
}
fprintf(stderr, "%6.2lf\n", k[y]);
}
fprintf(stderr, "\n");
// select column
int x = min_element(whole(z)) - z.begin();
if (z[x] > - eps) break;
// select row
vector<double> delta(h, INFINITY);
repeat (y, h) if (m[y][x] > + eps) {
delta[y] = k[y] / m[y][x];
}
int y = min_element(whole(delta)) - delta.begin();
if (isinf(delta[y])) break;
fprintf(stderr, "pivot x = %d (%lf) ; y = %d (%lf / %lf = %lf)\n", x, z[x], y, k[y], m[y][x], delta[y]);
// eliminate
ix[y] = x;
double m_y_x = m[y][x];
repeat (j, w) {
m[y][j] /= m_y_x;
}
k[y] /= m_y_x;
double z_x = z[x];
repeat (j, w) {
z[j] -= z_x * m[y][j];
}
repeat (i, h) if (i != y) {
double m_i_x = m[i][x];
repeat (j, w) {
m[i][j] -= m_i_x * m[y][j];
}
k[i] -= m_i_x * k[y];
}
}
}
/*
* max : c^T x
* sub.to. : Ax <= b
* x >= 0
*/
vector<double> linsolve(vector<vector<double> > const & a, vector<double> const & b, vector<double> const & c) {
debug_c = c;
// prepare
constexpr double eps = 1e-8;
int h = b.size();
int w = c.size();
// make tableau
int artificial = 0;
vector<vector<double> > tableau(h, vector<double>(w + h)); // the tableau
vector<double> k = b;
repeat (y, h) {
if (b[y] >= 0) {
copy(whole(a[y]), tableau[y].begin());
tableau[y][w + y] = 1; // slack variable
} else {
repeat (x, w) {
tableau[y][x] = - a[y][x];
}
tableau[y][w + y] = -1; // surplus variable
k[y] *= -1;
artificial += 1;
}
}
vector<int> ix(h); // labels of rows
iota(whole(ix), w);
// two-phase method
if (artificial) {
fprintf(stderr, "artificial %d\n", artificial);
vector<double> z(w + h + artificial); // target function
int var = 0;
repeat (y, h) {
tableau[y].resize(w + h + artificial);
if (b[y] < 0) {
tableau[y][w + h + var] = 1;
repeat (x, w + h) {
z[x] -= tableau[y][x];
}
ix[y] = w + h + var;
++ var;
}
}
linsolve_tableau(z, tableau, k, ix);
repeat (y, h) {
assert (ix[y] < w + h);
tableau[y].resize(w + h);
}
}
// solve
vector<double> z(w + h); // target function
repeat (x, w) z[x] = - c[x];
if (artificial) {
repeat (y, h) {
int x = ix[y];
int z_x = z[x];
if (z_x) {
repeat (j, w + h) {
z[j] -= z_x * tableau[y][j];
}
}
}
}
linsolve_tableau(z, tableau, k, ix);
// finalize
vector<double> result(w + h);
repeat (y, h) {
result[ix[y]] = k[y];
}
return result;
}
unittest {
// http://zeus.mech.kyushu-u.ac.jp/~tsuji/java_edu/Simplex_st.html
vector<vector<double> > a {
{ 1, 2 },
{ 1, 1 },
{ 3, 1 },
};
vector<double> b {
14,
8,
18,
};
vector<double> c {
2, 3,
};
vector<double> x = linsolve(a, b, c);
constexpr double eps = 1e-8;
assert (abs(x[0] - 2) < eps);
assert (abs(x[1] - 6) < eps);
}
unittest {
vector<vector<double> > a {
{ -2, -1 },
{ -1, -1 },
{ -1, -2 },
};
vector<double> b {
-8,
-6,
-8,
};
vector<double> c {
-4, -3,
};
vector<double> x = linsolve(a, b, c);
fprintf(stderr, "%lf\n", x[0]);
fprintf(stderr, "%lf\n", x[1]);
constexpr double eps = 1e-8;
repeat (y, 3) {
assert (a[y][0] * x[0] + a[y][1] * x[1] < b[y] + eps);
}
assert (abs(x[0] - 2) < eps);
assert (abs(x[1] - 4) < eps);
}
unittest {
// http://optlab.mcmaster.ca/feng/4O03/Two.Phase.Simplex.pdf
vector<vector<double> > a {
{ 1, 1, 1 },
{ -2, -1, 1 },
{ 0, 1, -1 },
};
vector<double> b {
40,
-10,
-10,
};
vector<double> c {
2, 3, 1,
};
vector<double> x = linsolve(a, b, c);
constexpr double eps = 1e-8;
assert (abs(x[0] - 10) < eps);
assert (abs(x[1] - 10) < eps);
assert (abs(x[2] - 20) < eps);
}
unittest {
vector<vector<double> > a {
{ 1, 1, 1 },
{ -2, -1, 1 },
{ 0, 1, -1 },
};
vector<double> b {
40,
-10,
-10,
};
vector<double> c {
-2, 3, -1,
};
vector<double> x = linsolve(a, b, c);
constexpr double eps = 1e-8;
fprintf(stderr, "%lf\n", x[0]);
fprintf(stderr, "%lf\n", x[1]);
fprintf(stderr, "%lf\n", x[2]);
}
vector<double> linsolve_glpk(vector<vector<double> > const & a, vector<double> const & b, vector<double> const & c) {
int preserved_term_out = glp_term_out(GLP_OFF);
int h = b.size();
int w = c.size();
glp_prob *lp = glp_create_prob();
glp_set_obj_dir(lp, GLP_MAX);
glp_add_cols(lp, w);
repeat (x, w) {
glp_set_col_bnds(lp, x + 1, GLP_LO, 0, INFINITY); // non-negative
glp_set_obj_coef(lp, x + 1, c[x]);
}
glp_add_rows(lp, h);
repeat (y, h) {
glp_set_row_bnds(lp, y + 1, GLP_UP, - INFINITY, b[y]);
}
vector<int> ia, ja;
vector<double> ar;
ia.push_back(0);
ja.push_back(0);
ar.push_back(0); // dummy for 1-based
constexpr double eps = 1e-8;
repeat (y, h) repeat (x, w) {
if (abs(a[y][x]) > eps) {
ia.push_back(y + 1);
ja.push_back(x + 1);
ar.push_back(a[y][x]);
}
}
glp_load_matrix(lp, ar.size() - 1, ia.data(), ja.data(), ar.data());
glp_simplex(lp, NULL);
assert (glp_get_status(lp) == GLP_OPT);
vector<double> result(w);
repeat (x, w) {
result[x] = glp_get_col_prim(lp, x + 1);
}
glp_delete_prob(lp);
glp_free_env();
glp_term_out(preserved_term_out);
return result;
}
#line 1 "old/simplex.inc.cpp"
vector<double> debug_c;
void linsolve_tableau(vector<double> & z, vector<vector<double> > & tableau, vector<double> & k, vector<int> & ix) {
constexpr double eps = 1e-8;
vector<vector<double > > & m = tableau;
int h = k.size();
int w = z.size();
while (true) {
double value = 0;
repeat (y, h) if (ix[y] < debug_c.size()) {
value += debug_c[ix[y]] * k[y];
}
fprintf(stderr, "value %lf\n", value);
fprintf(stderr, " z : ");
repeat (x, w) {
fprintf(stderr, "%6.2lf ", z[x]);
}
fprintf(stderr, "\n");
repeat (y, h) {
fprintf(stderr, "%3d : ", ix[y]);
repeat (x, w) {
fprintf(stderr, "%6.2lf ", m[y][x]);
}
fprintf(stderr, "%6.2lf\n", k[y]);
}
fprintf(stderr, "\n");
// select column
int x = min_element(whole(z)) - z.begin();
if (z[x] > - eps) break;
// select row
vector<double> delta(h, INFINITY);
repeat (y, h) if (m[y][x] > + eps) {
delta[y] = k[y] / m[y][x];
}
int y = min_element(whole(delta)) - delta.begin();
if (isinf(delta[y])) break;
fprintf(stderr, "pivot x = %d (%lf) ; y = %d (%lf / %lf = %lf)\n", x, z[x], y, k[y], m[y][x], delta[y]);
// eliminate
ix[y] = x;
double m_y_x = m[y][x];
repeat (j, w) {
m[y][j] /= m_y_x;
}
k[y] /= m_y_x;
double z_x = z[x];
repeat (j, w) {
z[j] -= z_x * m[y][j];
}
repeat (i, h) if (i != y) {
double m_i_x = m[i][x];
repeat (j, w) {
m[i][j] -= m_i_x * m[y][j];
}
k[i] -= m_i_x * k[y];
}
}
}
/*
* max : c^T x
* sub.to. : Ax <= b
* x >= 0
*/
vector<double> linsolve(vector<vector<double> > const & a, vector<double> const & b, vector<double> const & c) {
debug_c = c;
// prepare
constexpr double eps = 1e-8;
int h = b.size();
int w = c.size();
// make tableau
int artificial = 0;
vector<vector<double> > tableau(h, vector<double>(w + h)); // the tableau
vector<double> k = b;
repeat (y, h) {
if (b[y] >= 0) {
copy(whole(a[y]), tableau[y].begin());
tableau[y][w + y] = 1; // slack variable
} else {
repeat (x, w) {
tableau[y][x] = - a[y][x];
}
tableau[y][w + y] = -1; // surplus variable
k[y] *= -1;
artificial += 1;
}
}
vector<int> ix(h); // labels of rows
iota(whole(ix), w);
// two-phase method
if (artificial) {
fprintf(stderr, "artificial %d\n", artificial);
vector<double> z(w + h + artificial); // target function
int var = 0;
repeat (y, h) {
tableau[y].resize(w + h + artificial);
if (b[y] < 0) {
tableau[y][w + h + var] = 1;
repeat (x, w + h) {
z[x] -= tableau[y][x];
}
ix[y] = w + h + var;
++ var;
}
}
linsolve_tableau(z, tableau, k, ix);
repeat (y, h) {
assert (ix[y] < w + h);
tableau[y].resize(w + h);
}
}
// solve
vector<double> z(w + h); // target function
repeat (x, w) z[x] = - c[x];
if (artificial) {
repeat (y, h) {
int x = ix[y];
int z_x = z[x];
if (z_x) {
repeat (j, w + h) {
z[j] -= z_x * tableau[y][j];
}
}
}
}
linsolve_tableau(z, tableau, k, ix);
// finalize
vector<double> result(w + h);
repeat (y, h) {
result[ix[y]] = k[y];
}
return result;
}
unittest {
// http://zeus.mech.kyushu-u.ac.jp/~tsuji/java_edu/Simplex_st.html
vector<vector<double> > a {
{ 1, 2 },
{ 1, 1 },
{ 3, 1 },
};
vector<double> b {
14,
8,
18,
};
vector<double> c {
2, 3,
};
vector<double> x = linsolve(a, b, c);
constexpr double eps = 1e-8;
assert (abs(x[0] - 2) < eps);
assert (abs(x[1] - 6) < eps);
}
unittest {
vector<vector<double> > a {
{ -2, -1 },
{ -1, -1 },
{ -1, -2 },
};
vector<double> b {
-8,
-6,
-8,
};
vector<double> c {
-4, -3,
};
vector<double> x = linsolve(a, b, c);
fprintf(stderr, "%lf\n", x[0]);
fprintf(stderr, "%lf\n", x[1]);
constexpr double eps = 1e-8;
repeat (y, 3) {
assert (a[y][0] * x[0] + a[y][1] * x[1] < b[y] + eps);
}
assert (abs(x[0] - 2) < eps);
assert (abs(x[1] - 4) < eps);
}
unittest {
// http://optlab.mcmaster.ca/feng/4O03/Two.Phase.Simplex.pdf
vector<vector<double> > a {
{ 1, 1, 1 },
{ -2, -1, 1 },
{ 0, 1, -1 },
};
vector<double> b {
40,
-10,
-10,
};
vector<double> c {
2, 3, 1,
};
vector<double> x = linsolve(a, b, c);
constexpr double eps = 1e-8;
assert (abs(x[0] - 10) < eps);
assert (abs(x[1] - 10) < eps);
assert (abs(x[2] - 20) < eps);
}
unittest {
vector<vector<double> > a {
{ 1, 1, 1 },
{ -2, -1, 1 },
{ 0, 1, -1 },
};
vector<double> b {
40,
-10,
-10,
};
vector<double> c {
-2, 3, -1,
};
vector<double> x = linsolve(a, b, c);
constexpr double eps = 1e-8;
fprintf(stderr, "%lf\n", x[0]);
fprintf(stderr, "%lf\n", x[1]);
fprintf(stderr, "%lf\n", x[2]);
}
vector<double> linsolve_glpk(vector<vector<double> > const & a, vector<double> const & b, vector<double> const & c) {
int preserved_term_out = glp_term_out(GLP_OFF);
int h = b.size();
int w = c.size();
glp_prob *lp = glp_create_prob();
glp_set_obj_dir(lp, GLP_MAX);
glp_add_cols(lp, w);
repeat (x, w) {
glp_set_col_bnds(lp, x + 1, GLP_LO, 0, INFINITY); // non-negative
glp_set_obj_coef(lp, x + 1, c[x]);
}
glp_add_rows(lp, h);
repeat (y, h) {
glp_set_row_bnds(lp, y + 1, GLP_UP, - INFINITY, b[y]);
}
vector<int> ia, ja;
vector<double> ar;
ia.push_back(0);
ja.push_back(0);
ar.push_back(0); // dummy for 1-based
constexpr double eps = 1e-8;
repeat (y, h) repeat (x, w) {
if (abs(a[y][x]) > eps) {
ia.push_back(y + 1);
ja.push_back(x + 1);
ar.push_back(a[y][x]);
}
}
glp_load_matrix(lp, ar.size() - 1, ia.data(), ja.data(), ar.data());
glp_simplex(lp, NULL);
assert (glp_get_status(lp) == GLP_OPT);
vector<double> result(w);
repeat (x, w) {
result[x] = glp_get_col_prim(lp, x + 1);
}
glp_delete_prob(lp);
glp_free_env();
glp_term_out(preserved_term_out);
return result;
}