onerow: add cut selection parameters
This commit is contained in:
@@ -3,28 +3,21 @@ for i in out/*yaml; do
|
|||||||
IN=${i/.pre.yaml/}
|
IN=${i/.pre.yaml/}
|
||||||
IN=${IN/out\//}
|
IN=${IN/out\//}
|
||||||
grep -q mip_value $i && continue
|
grep -q mip_value $i && continue
|
||||||
echo $IN
|
|
||||||
grep $IN instances/opt.tab | awk '{ print "mip_value:\n "$2 }' >> $i
|
grep $IN instances/opt.tab | awk '{ print "mip_value:\n "$2 }' >> $i
|
||||||
done
|
done
|
||||||
|
|
||||||
echo " TABLE 1 "
|
printf "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n" instance cutsmir cutsw origgap mirperf wperf mircontrib wcontrib wimprov wtime > 'tables/gap.csv'
|
||||||
echo "--------------------------------------------------------------------------------"
|
|
||||||
printf "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n" instance cutsmir cutsw origgap mirperf wperf mircontrib wcontrib wimprov wtime | tee 'tables/gap.csv'
|
|
||||||
for i in out/*.yaml; do
|
for i in out/*.yaml; do
|
||||||
IN=${i/.yaml/}
|
IN=${i/.yaml/}
|
||||||
IN=${IN/out\//}
|
IN=${IN/out\//}
|
||||||
printf "%s," $IN
|
printf "%s," $IN
|
||||||
scripts/gap.rb $i
|
scripts/gap.rb $i
|
||||||
done | sort -t',' -nrsk 8 | sed -e 's/,$//g' | tee -a 'tables/gap.csv'
|
done | sed -e 's/,$//g' >> 'tables/gap.csv'
|
||||||
|
|
||||||
echo
|
printf "%s,%s,%s,%s,%s,%s\n" instance cutsmir cutsw mirt wedget avgm > 'tables/speed.csv'
|
||||||
echo
|
|
||||||
echo " TABLE 2 "
|
|
||||||
echo "--------------------------------------------------------------------------------"
|
|
||||||
printf "%s,%s,%s,%s,%s,%s\n" instance cutsmir cutsw mirt wedget avgm | tee 'tables/speed.csv'
|
|
||||||
for i in out/*.yaml; do
|
for i in out/*.yaml; do
|
||||||
IN=${i/.yaml/}
|
IN=${i/.yaml/}
|
||||||
IN=${IN/out\//}
|
IN=${IN/out\//}
|
||||||
printf "%s," $IN
|
printf "%s," $IN
|
||||||
scripts/speed.rb $i
|
scripts/speed.rb $i
|
||||||
done | sort | sed -e 's/,$//g' | tee -a 'tables/speed.csv'
|
done | sort | sed -e 's/,$//g' >> 'tables/speed.csv'
|
||||||
|
|||||||
@@ -149,21 +149,21 @@ int main(int argc, char **argv)
|
|||||||
if (enable_gomory_cuts)
|
if (enable_gomory_cuts)
|
||||||
{
|
{
|
||||||
time_printf("Generating Gomory cuts...\n");
|
time_printf("Generating Gomory cuts...\n");
|
||||||
cplexHelper.add_single_row_cuts<GomoryCutGenerator>();
|
cplexHelper.add_single_row_cuts<GomoryCutGenerator>(0);
|
||||||
cplexHelper.solve(true);
|
cplexHelper.solve(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enable_mir_cuts)
|
if (enable_mir_cuts)
|
||||||
{
|
{
|
||||||
time_printf("Generating MIR cuts...\n");
|
time_printf("Generating MIR cuts...\n");
|
||||||
cplexHelper.add_single_row_cuts<MIRCutGenerator>();
|
cplexHelper.add_single_row_cuts<MIRCutGenerator>(0);
|
||||||
cplexHelper.solve(true);
|
cplexHelper.solve(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enable_wedge_cuts)
|
if (enable_wedge_cuts)
|
||||||
{
|
{
|
||||||
time_printf("Generating wedge cuts...\n");
|
time_printf("Generating wedge cuts...\n");
|
||||||
cplexHelper.add_single_row_cuts<WedgeCutGenerator>();
|
cplexHelper.add_single_row_cuts<WedgeCutGenerator>(MAX_GOOD_ROWS);
|
||||||
cplexHelper.solve(true);
|
cplexHelper.solve(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -69,10 +69,11 @@ public:
|
|||||||
* cuts as possible. The cuts are generated by the provided generator class.
|
* cuts as possible. The cuts are generated by the provided generator class.
|
||||||
*
|
*
|
||||||
* @tparam Generator Class used to generate the cuts.
|
* @tparam Generator Class used to generate the cuts.
|
||||||
|
* @param max_rows The maximum number of rows to consider.
|
||||||
* @returns The number of cuts added.
|
* @returns The number of cuts added.
|
||||||
*/
|
*/
|
||||||
template<class Generator>
|
template<class Generator>
|
||||||
int add_single_row_cuts();
|
int add_single_row_cuts(int max_rows);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a single row from the current tableau.
|
* Gets a single row from the current tableau.
|
||||||
@@ -90,7 +91,7 @@ public:
|
|||||||
*
|
*
|
||||||
* @returns The solution status, as returned by CPXgetstat.
|
* @returns The solution status, as returned by CPXgetstat.
|
||||||
*/
|
*/
|
||||||
int solve(bool save_stats = false);
|
void solve(bool save_stats = false);
|
||||||
|
|
||||||
void dump_constraint(const Constraint &c, const char *msg = "");
|
void dump_constraint(const Constraint &c, const char *msg = "");
|
||||||
|
|
||||||
@@ -107,7 +108,7 @@ public:
|
|||||||
|
|
||||||
void print_solution(double *x);
|
void print_solution(double *x);
|
||||||
|
|
||||||
void find_good_rows();
|
void find_good_rows(int max_rows);
|
||||||
|
|
||||||
int n_rows;
|
int n_rows;
|
||||||
int n_cols;
|
int n_cols;
|
||||||
@@ -134,6 +135,9 @@ public:
|
|||||||
|
|
||||||
int n_good_rows;
|
int n_good_rows;
|
||||||
int *good_rows;
|
int *good_rows;
|
||||||
|
|
||||||
|
double *reduced_costs;
|
||||||
|
double cost_cutoff;
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "cplex_helper.tpp"
|
#include "cplex_helper.tpp"
|
||||||
|
|||||||
@@ -30,12 +30,17 @@ using std::endl;
|
|||||||
|
|
||||||
|
|
||||||
template<class Generator>
|
template<class Generator>
|
||||||
int CplexHelper::add_single_row_cuts()
|
int CplexHelper::add_single_row_cuts(int max_rows)
|
||||||
{
|
{
|
||||||
total_cuts = 0;
|
total_cuts = 0;
|
||||||
|
|
||||||
if(n_good_rows < 0)
|
if(n_good_rows > 0)
|
||||||
find_good_rows();
|
{
|
||||||
|
n_good_rows = 0;
|
||||||
|
delete good_rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
find_good_rows(max_rows);
|
||||||
|
|
||||||
eta_reset();
|
eta_reset();
|
||||||
eta_count = 0;
|
eta_count = 0;
|
||||||
@@ -48,7 +53,6 @@ int CplexHelper::add_single_row_cuts()
|
|||||||
for (int i = 0; i < n_good_rows; i++)
|
for (int i = 0; i < n_good_rows; i++)
|
||||||
{
|
{
|
||||||
Row *row = get_tableau_row(good_rows[i]);
|
Row *row = get_tableau_row(good_rows[i]);
|
||||||
//Row *row = good_rows[i];
|
|
||||||
|
|
||||||
Generator generator(*row);
|
Generator generator(*row);
|
||||||
|
|
||||||
|
|||||||
@@ -25,16 +25,14 @@ const long REDUCE_FACTOR_RHS = 1000000;
|
|||||||
const long REDUCE_FACTOR_R1 = 1000;
|
const long REDUCE_FACTOR_R1 = 1000;
|
||||||
const long REDUCE_FACTOR_COEFFICIENT = 1000000;
|
const long REDUCE_FACTOR_COEFFICIENT = 1000000;
|
||||||
|
|
||||||
const int MAX_CUT_DEPTH = 200;
|
const int MAX_R1_RAYS = 1000000;
|
||||||
|
const int MAX_CUT_DEPTH = 1000000;
|
||||||
|
const int MAX_GOOD_ROWS = 1000000;
|
||||||
|
|
||||||
const int ETA_UPDATE_INTERVAL = 300;
|
const int ETA_UPDATE_INTERVAL = 300;
|
||||||
const unsigned int MAX_CUT_BUFFER_SIZE = 100;
|
const unsigned int MAX_CUT_BUFFER_SIZE = 100;
|
||||||
|
|
||||||
const double COEFFICIENT_SAFETY_MARGIN = 0.00001;
|
|
||||||
|
|
||||||
#define INTERSECTION_CUT_USE_DOUBLE
|
#define INTERSECTION_CUT_USE_DOUBLE
|
||||||
|
|
||||||
#define ENABLE_TRIVIAL_LIFTING
|
|
||||||
// #define ENABLE_EXTENDED_STATISTICS
|
// #define ENABLE_EXTENDED_STATISTICS
|
||||||
// #define PRETEND_TO_ADD_CUTS
|
// #define PRETEND_TO_ADD_CUTS
|
||||||
|
|
||||||
|
|||||||
@@ -66,6 +66,8 @@ struct Row {
|
|||||||
int basic_var_index;
|
int basic_var_index;
|
||||||
|
|
||||||
bool* is_integer;
|
bool* is_integer;
|
||||||
|
double* reduced_costs;
|
||||||
|
double cost_cutoff;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
#include <onerow/geometry.hpp>
|
#include <onerow/geometry.hpp>
|
||||||
#include <onerow/stats.hpp>
|
#include <onerow/stats.hpp>
|
||||||
#include <onerow/params.hpp>
|
#include <onerow/params.hpp>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
using std::cout;
|
using std::cout;
|
||||||
using std::endl;
|
using std::endl;
|
||||||
@@ -39,7 +40,7 @@ static bool debug = false;
|
|||||||
CplexHelper::CplexHelper(CPXENVptr _env, CPXLPptr _lp) :
|
CplexHelper::CplexHelper(CPXENVptr _env, CPXLPptr _lp) :
|
||||||
env(_env), lp(_lp), is_integer(0), n_cuts(0), n_rows(0), ub(0), lb(0),
|
env(_env), lp(_lp), is_integer(0), n_cuts(0), n_rows(0), ub(0), lb(0),
|
||||||
cstat(0), cplex_rows(0), first_solution(0), current_solution(0),
|
cstat(0), cplex_rows(0), first_solution(0), current_solution(0),
|
||||||
optimal_solution(0), current_round(0), n_good_rows(-1)
|
optimal_solution(0), current_round(0), n_good_rows(-1), reduced_costs(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,6 +261,9 @@ Row* CplexHelper::get_tableau_row(int index)
|
|||||||
row->is_integer = is_integer;
|
row->is_integer = is_integer;
|
||||||
row->c = cplex_row_to_constraint(cplex_rows[index]);
|
row->c = cplex_row_to_constraint(cplex_rows[index]);
|
||||||
|
|
||||||
|
row->reduced_costs = reduced_costs;
|
||||||
|
row->cost_cutoff = cost_cutoff;
|
||||||
|
|
||||||
if (optimal_solution)
|
if (optimal_solution)
|
||||||
assert(cplex_rows[index].get_violation(optimal_solution) <= 0.001);
|
assert(cplex_rows[index].get_violation(optimal_solution) <= 0.001);
|
||||||
|
|
||||||
@@ -272,7 +276,7 @@ Row* CplexHelper::get_tableau_row(int index)
|
|||||||
return row;
|
return row;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CplexHelper::solve(bool should_end_round)
|
void CplexHelper::solve(bool should_end_round)
|
||||||
{
|
{
|
||||||
// Optimize
|
// Optimize
|
||||||
int status = CPXlpopt(env, lp);
|
int status = CPXlpopt(env, lp);
|
||||||
@@ -312,8 +316,6 @@ int CplexHelper::solve(bool should_end_round)
|
|||||||
|
|
||||||
if (should_end_round)
|
if (should_end_round)
|
||||||
Stats::set_solution(current_round++, objval, string(buffer));
|
Stats::set_solution(current_round++, objval, string(buffer));
|
||||||
|
|
||||||
return objval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -364,6 +366,16 @@ void CplexHelper::read_basis()
|
|||||||
CPXgetlb(env, lp, lb, 0, n_cols - 1);
|
CPXgetlb(env, lp, lb, 0, n_cols - 1);
|
||||||
CPXgetbase(env, lp, cstat, rstat);
|
CPXgetbase(env, lp, cstat, rstat);
|
||||||
|
|
||||||
|
reduced_costs = new double[n_cols];
|
||||||
|
CPXgetdj(env, lp, reduced_costs, 0, n_cols-1);
|
||||||
|
|
||||||
|
cost_cutoff = -INFINITY;
|
||||||
|
double *costs_copy = new double[n_cols];
|
||||||
|
memcpy(costs_copy, reduced_costs, sizeof(double) * n_cols);
|
||||||
|
std::sort(costs_copy, costs_copy + n_cols, std::greater<double>());
|
||||||
|
if(n_cols > MAX_R1_RAYS) cost_cutoff = costs_copy[MAX_R1_RAYS];
|
||||||
|
delete costs_copy;
|
||||||
|
|
||||||
cplex_rows = new CplexRow[n_rows];
|
cplex_rows = new CplexRow[n_rows];
|
||||||
assert(cplex_rows != 0);
|
assert(cplex_rows != 0);
|
||||||
|
|
||||||
@@ -509,10 +521,10 @@ void CplexHelper::eta_print()
|
|||||||
FINISHED:;
|
FINISHED:;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CplexHelper::find_good_rows()
|
void CplexHelper::find_good_rows(int max_rows)
|
||||||
{
|
{
|
||||||
n_good_rows = 0;
|
bool *is_good = new bool[n_rows];
|
||||||
good_rows = new int[n_rows];
|
double *fractionality = new double[n_rows];
|
||||||
|
|
||||||
time_printf("Finding interesting rows...\n");
|
time_printf("Finding interesting rows...\n");
|
||||||
|
|
||||||
@@ -521,14 +533,37 @@ void CplexHelper::find_good_rows()
|
|||||||
{
|
{
|
||||||
Row *row = get_tableau_row(i);
|
Row *row = get_tableau_row(i);
|
||||||
|
|
||||||
if (row->c.pi_zero.frac() != 0 &&
|
fractionality[i] = row->c.pi_zero.frac().get_double();
|
||||||
row->is_integer[row->basic_var_index])
|
fractionality[i] = fabs(fractionality[i] - 0.5);
|
||||||
{
|
|
||||||
good_rows[n_good_rows++] = i;
|
is_good[i] = true;
|
||||||
}
|
if (row->c.pi_zero.frac() == 0) is_good[i] = false;
|
||||||
|
if (!row->is_integer[row->basic_var_index]) is_good[i] = false;
|
||||||
|
|
||||||
delete row;
|
delete row;
|
||||||
}
|
}
|
||||||
|
|
||||||
time_printf(" %d rows found\n", n_good_rows, n_rows);
|
if(max_rows > 0)
|
||||||
|
{
|
||||||
|
double frac_cutoff = 1.0;
|
||||||
|
std::sort(fractionality, fractionality + n_rows);
|
||||||
|
if (n_rows > max_rows) frac_cutoff = fractionality[max_rows];
|
||||||
|
|
||||||
|
for (int i = 0; i < n_rows; i++)
|
||||||
|
if (fractionality[i] > frac_cutoff)
|
||||||
|
is_good[i] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
n_good_rows = 0;
|
||||||
|
good_rows = new int[n_rows];
|
||||||
|
for (int i = 0; i < n_rows; i++)
|
||||||
|
{
|
||||||
|
if (!is_good[i]) continue;
|
||||||
|
good_rows[n_good_rows++] = i;
|
||||||
|
if(max_rows > 0 && n_good_rows >= max_rows) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete is_good;
|
||||||
|
delete fractionality;
|
||||||
|
time_printf(" %d rows found\n", n_good_rows);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -296,6 +296,9 @@ void WedgeCutGenerator::eval_next()
|
|||||||
}
|
}
|
||||||
|
|
||||||
int r1_index = row.c.pi.index(r1_offset);
|
int r1_index = row.c.pi.index(r1_offset);
|
||||||
|
if(row.reduced_costs[r1_index] < row.cost_cutoff)
|
||||||
|
continue;
|
||||||
|
|
||||||
r1[0] = -row.c.pi.value(r1_offset).reduce(REDUCE_FACTOR_R1);
|
r1[0] = -row.c.pi.value(r1_offset).reduce(REDUCE_FACTOR_R1);
|
||||||
r1[1] = 1;
|
r1[1] = 1;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user