Compare commits
15 Commits
selection
...
77a5d93527
| Author | SHA1 | Date | |
|---|---|---|---|
| 77a5d93527 | |||
| 00298630da | |||
| 0f4480a16d | |||
| 53553c4db5 | |||
| a828a3caf7 | |||
| 8c132efe2d | |||
| 5d64d24ad6 | |||
| a89473d67d | |||
| cbba147097 | |||
| 6d45ca39e8 | |||
| 6f502eae51 | |||
| ac621cd41d | |||
| cc1e3962d0 | |||
| 355da317ba | |||
| fac2c3e6e9 |
@@ -1,10 +1,6 @@
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
project(multirow)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
|
||||
find_package(CPLEX REQUIRED)
|
||||
include_directories(${CPLEX_INCLUDE_DIR})
|
||||
@@ -12,6 +8,10 @@ include_directories(${CPLEX_INCLUDE_DIR})
|
||||
find_package(GMP REQUIRED)
|
||||
find_package(OpenMP REQUIRED)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror ${OpenMP_CXX_FLAGS} -O3")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} -Werror ${OpenMP_C_FLAGS} -O3")
|
||||
|
||||
include_directories(${gtest_SOURCE_DIR}/include)
|
||||
include_directories(infinity/library/include)
|
||||
include_directories(lifting/library/include)
|
||||
|
||||
0
build/.keep
Normal file
0
build/.keep
Normal file
@@ -1,4 +1,6 @@
|
||||
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH}
|
||||
$ENV{HOME}/lib/
|
||||
/opt/cplex-12.6/cplex/lib/x86-64_linux/static_pic
|
||||
/software/cplex-12.6/distribution/cplex/lib/x86-64_linux/static_pic
|
||||
/Users/axavier/Applications/IBM/ILOG/CPLEX_Studio1262/cplex/lib/x86-64_osx/static_pic)
|
||||
|
||||
@@ -6,7 +8,9 @@ find_library(CPLEX_LIBRARIES
|
||||
NAMES cplex cplex1220 cplex1240 cplex1260 cplex1261 cplex1262)
|
||||
|
||||
find_path(CPLEX_INCLUDE_DIR NAMES ilcplex/cplex.h PATHS
|
||||
/Users/axavier/Applications/IBM/ILOG/CPLEX_Studio1262/cplex/include
|
||||
$ENV{HOME}/include/
|
||||
/opt/cplex-12.6/cplex/include/
|
||||
/Users/axavier/Applications/IBM/ILOG/CPLEX_Studio1262/cplex/include/
|
||||
/software/cplex-12.6/distribution/cplex/include/)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
@@ -365,10 +365,6 @@ static int create_tight_rays_lp(int nrows,
|
||||
rval = LP_relax(lp);
|
||||
abort_if(rval, "LP_relax failed");
|
||||
|
||||
//rval = LP_write(lp, "tight-rays.lp");
|
||||
//abort_if(rval, "LP_write failed");
|
||||
|
||||
|
||||
CLEANUP:
|
||||
if(rmatind) free(rmatind);
|
||||
if(rmatval) free(rmatval);
|
||||
@@ -602,7 +598,7 @@ static int find_interior_point_enum(const int nrows,
|
||||
}
|
||||
}
|
||||
|
||||
if(!DOUBLE_geq(best_value, 1)) *found = 1;
|
||||
if(best_value < 0.999) *found = 1;
|
||||
|
||||
CLEANUP:
|
||||
if(beta2) free(beta2);
|
||||
@@ -665,7 +661,7 @@ static int find_interior_point_cplex(const int nrows,
|
||||
|
||||
log_debug(" obj = %.8lf\n", objval);
|
||||
|
||||
if(DOUBLE_geq(objval, 1.0))
|
||||
if(objval > 0.999)
|
||||
{
|
||||
log_debug(" set is lattice-free\n");
|
||||
*found = 0;
|
||||
@@ -1320,9 +1316,7 @@ int INFINITY_ND_generate_lfree(const struct MultiRowModel *model,
|
||||
&epsilon_x, tx);
|
||||
abort_if(rval, "bound failed");
|
||||
|
||||
if(isinf(epsilon_x)) break;
|
||||
|
||||
// epsilon_x = (floor(epsilon_x * 128) / 128);
|
||||
abort_if(isinf(epsilon_x), "epsilon_x is infinite");
|
||||
log_debug(" epsilon_x = %.8lf\n", epsilon_x);
|
||||
|
||||
if(DOUBLE_eq(epsilon_x, epsilon))
|
||||
@@ -1347,7 +1341,7 @@ int INFINITY_ND_generate_lfree(const struct MultiRowModel *model,
|
||||
{
|
||||
if(t[i])
|
||||
{
|
||||
beta[i] = min(beta[i], epsilon);
|
||||
beta[i] = min(beta[i] * 0.999, epsilon);
|
||||
}
|
||||
else if(!skip_ahull)
|
||||
{
|
||||
@@ -1364,7 +1358,6 @@ int INFINITY_ND_generate_lfree(const struct MultiRowModel *model,
|
||||
continue;
|
||||
}
|
||||
|
||||
// alpha = (floor(alpha * 128) / 128);
|
||||
beta[i] = min(beta[i], alpha);
|
||||
}
|
||||
|
||||
|
||||
@@ -108,6 +108,7 @@ static int create_cut_from_lfree(const struct Tableau *tableau,
|
||||
struct Row *cut)
|
||||
{
|
||||
int rval = 0;
|
||||
double *ray = 0;
|
||||
|
||||
struct LP lp;
|
||||
int nvars = map->nvars;
|
||||
@@ -122,40 +123,41 @@ static int create_cut_from_lfree(const struct Tableau *tableau,
|
||||
rval = INFINITY_create_psi_lp(lfree, &lp);
|
||||
abort_if(rval, "create_psi_lp failed");
|
||||
|
||||
ray = (double*) malloc(nrows * sizeof(double));
|
||||
abort_if(!ray, "could not allocate ray");
|
||||
|
||||
cut->nz = nvars;
|
||||
for(int i = 0; i < nvars; i++)
|
||||
{
|
||||
double value;
|
||||
const double *q = LFREE_get_ray(rays, map->variable_to_ray[i]);
|
||||
double value, norm = 0;
|
||||
double *original_ray = LFREE_get_ray(rays, map->variable_to_ray[i]);
|
||||
char type = tableau->column_types[map->indices[i]];
|
||||
|
||||
for (int j = 0; j < nrows; j++)
|
||||
{
|
||||
ray[j] = original_ray[j];
|
||||
norm += fabs(ray[j]);
|
||||
}
|
||||
|
||||
if (norm < 0.001)
|
||||
for (int j = 0; j < nrows; j++)
|
||||
ray[j] *= 0.001 / norm;
|
||||
|
||||
if(ENABLE_LIFTING && type == MILP_INTEGER)
|
||||
{
|
||||
rval = INFINITY_pi(nrows, q, map->ray_scale[i], &lp, &value);
|
||||
rval = INFINITY_pi(nrows, ray, map->ray_scale[i], &lp, &value);
|
||||
abort_if(rval, "INFINITY_pi failed");
|
||||
}
|
||||
else
|
||||
{
|
||||
rval = INFINITY_psi(nrows, q, map->ray_scale[i], &lp, &value);
|
||||
rval = INFINITY_psi(nrows, ray, map->ray_scale[i], &lp, &value);
|
||||
abort_if(rval, "INFINITY_psi failed");
|
||||
}
|
||||
|
||||
value *= 1.001;
|
||||
value = fmax(value, 0.001);
|
||||
log_verbose(" psi[%4d] = %20.12lf %d\n", map->indices[i], value);
|
||||
|
||||
if_debug_level
|
||||
{
|
||||
time_printf(" q=[");
|
||||
for(int j = 0; j < nrows; j++)
|
||||
printf("%25.20lf ", q[j] * map->ray_scale[i]);
|
||||
printf("] value=%25.20lf\n", value);
|
||||
}
|
||||
|
||||
value = fmax(value, 1 / 1024.0);
|
||||
|
||||
// value *= 1.001;
|
||||
// value = DOUBLE_max(value, 0.001);
|
||||
|
||||
cut->indices[i] = map->indices[i];
|
||||
cut->pi[i] = -value;
|
||||
}
|
||||
@@ -163,6 +165,7 @@ static int create_cut_from_lfree(const struct Tableau *tableau,
|
||||
cut->pi_zero = -1.0;
|
||||
|
||||
CLEANUP:
|
||||
if(ray) free(ray);
|
||||
LP_free(&lp);
|
||||
return rval;
|
||||
}
|
||||
@@ -186,12 +189,7 @@ static int filter_model(const struct MultiRowModel *original_model,
|
||||
struct RayList *filtered_rays = &filtered_model->rays;
|
||||
const struct RayList *original_rays = &original_model->rays;
|
||||
|
||||
memcpy(f, original_model->f, 2 * sizeof(double));
|
||||
for(int i = 0; i < nrows; i++)
|
||||
{
|
||||
f[i] = (ceil(f[i] * 128) / 128);
|
||||
if(f[i] <= 0.01) f[i] = 0;
|
||||
}
|
||||
memcpy(f, original_model->f, nrows * sizeof(double));
|
||||
|
||||
r = (double*) malloc(nrows * sizeof(double));
|
||||
abort_if(!r, "could not allocate r");
|
||||
@@ -268,11 +266,18 @@ static int append_extra_rays(struct MultiRowModel *model)
|
||||
|
||||
for(int i = 0; i < nrows; i++)
|
||||
{
|
||||
int found, index;
|
||||
double scale;
|
||||
|
||||
for(int j = 0; j < nrows; j++) r[j] = (i == j ? e : 0);
|
||||
LFREE_push_ray(&model->rays, r);
|
||||
rval = CG_find_ray(&model->rays, r, &found, &scale, &index);
|
||||
abort_if(rval, "CG_find_ray failed");
|
||||
if(!found) LFREE_push_ray(&model->rays, r);
|
||||
|
||||
for(int j = 0; j < nrows; j++) r[j] = (i == j ? -e : 0);
|
||||
LFREE_push_ray(&model->rays, r);
|
||||
rval = CG_find_ray(&model->rays, r, &found, &scale, &index);
|
||||
abort_if(rval, "CG_find_ray failed");
|
||||
if(!found) LFREE_push_ray(&model->rays, r);
|
||||
}
|
||||
|
||||
if(nrows == 2)
|
||||
@@ -409,6 +414,9 @@ int INFINITY_generate_cut(const struct Tableau *tableau, struct Row *cut)
|
||||
rval = CG_init_map(&original_map, max_nrays, tableau->nrows);
|
||||
abort_if(rval, "CG_init_map failed");
|
||||
|
||||
rval = LFREE_init_conv(&lfree, tableau->nrows, max_nrays);
|
||||
abort_if(rval, "LFREE_init_conv failed");
|
||||
|
||||
rval = extract_models(tableau, &original_model, &filtered_model,
|
||||
&original_map);
|
||||
abort_if(rval, "extract_models failed");
|
||||
@@ -419,41 +427,18 @@ int INFINITY_generate_cut(const struct Tableau *tableau, struct Row *cut)
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
rval = LFREE_init_conv(&lfree, tableau->nrows, max_nrays);
|
||||
abort_if(rval, "LFREE_init_conv failed");
|
||||
|
||||
// if(tableau->nrows == 2)
|
||||
// rval = INFINITY_2D_generate_lfree(&filtered_model, &lfree);
|
||||
// else
|
||||
// rval = INFINITY_ND_generate_lfree(&filtered_model, &lfree);
|
||||
//
|
||||
// if(rval)
|
||||
// {
|
||||
// rval = ERR_NO_CUT;
|
||||
// goto CLEANUP;
|
||||
// }
|
||||
//
|
||||
// for(int i = 0; i < filtered_model.rays.nrays; i++)
|
||||
// {
|
||||
// double *r = LFREE_get_ray(&filtered_model.rays, i);
|
||||
// for(int j = 0; j < tableau->nrows; j++)
|
||||
// r[j] *= lfree.beta[j];
|
||||
// }
|
||||
|
||||
rval = append_extra_rays(&filtered_model);
|
||||
abort_if(rval, "append_extra_rays failed");
|
||||
|
||||
// if(tableau->nrows == 2)
|
||||
// rval = INFINITY_2D_generate_lfree(&filtered_model, &lfree);
|
||||
// else
|
||||
rval = INFINITY_ND_generate_lfree(&filtered_model, &lfree);
|
||||
|
||||
if(rval)
|
||||
if_debug_level
|
||||
{
|
||||
rval = ERR_NO_CUT;
|
||||
goto CLEANUP;
|
||||
rval = CG_print_model(&filtered_model);
|
||||
abort_if(rval, "CG_print_model failed");
|
||||
}
|
||||
|
||||
rval = INFINITY_ND_generate_lfree(&filtered_model, &lfree);
|
||||
abort_if(rval, "INFINITY_ND_generate_lfree failed");
|
||||
|
||||
if(SHOULD_DUMP_CUTS)
|
||||
{
|
||||
rval = dump_cut(&lfree);
|
||||
|
||||
@@ -370,6 +370,53 @@ CLEANUP:
|
||||
if(rval) FAIL();
|
||||
}
|
||||
|
||||
TEST(InfinityNDTest, psi_test_3)
|
||||
{
|
||||
int rval = 0;
|
||||
|
||||
double f[] = { 0.671875, 0.671875 };
|
||||
double rays[] = {
|
||||
-0.007812500000, 0.000000000000,
|
||||
-0.039062500000, 0.046875000000,
|
||||
0.000000000000, 0.046875000000,
|
||||
0.046875000000, 0.000000000000,
|
||||
0.000000000000, -0.039062500000
|
||||
};
|
||||
|
||||
double beta[] = {
|
||||
66.909090909091,
|
||||
29.440000000000,
|
||||
14.000000000000,
|
||||
14.000000000000,
|
||||
29.440000000000,
|
||||
};
|
||||
|
||||
double q[] = { 0 - f[0], 1 - f[1]};
|
||||
|
||||
struct ConvLFreeSet lfree;
|
||||
lfree.f = f;
|
||||
lfree.beta = beta;
|
||||
lfree.rays.nrays = 5;
|
||||
lfree.rays.values = rays;
|
||||
lfree.nrows = lfree.rays.dim = 2;
|
||||
|
||||
double value;
|
||||
struct LP lp;
|
||||
|
||||
rval = LP_open(&lp);
|
||||
abort_if(rval, "LP_open failed");
|
||||
|
||||
rval = INFINITY_create_psi_lp(&lfree, &lp);
|
||||
abort_if(rval, "INFINITY_create_psi_lp failed");
|
||||
|
||||
rval = INFINITY_psi(lfree.nrows, q, 1.0, &lp, &value);
|
||||
abort_if(rval, "GREDDY_ND_psi failed");
|
||||
EXPECT_NEAR(value, 1.0, 1e-6);
|
||||
|
||||
CLEANUP:
|
||||
if(rval) FAIL();
|
||||
}
|
||||
|
||||
TEST(InfinityNDTest, generate_cut_test_1)
|
||||
{
|
||||
int rval = 0;
|
||||
|
||||
File diff suppressed because one or more lines are too long
52
lifting/README.md
Normal file
52
lifting/README.md
Normal file
@@ -0,0 +1,52 @@
|
||||
lifting
|
||||
=======
|
||||
|
||||
This package contains the source code for the paper **The (not so) Trivial
|
||||
Lifting in Two Dimensions**, by Ricardo Fukasawa, Laurent Poirrier and Álinson
|
||||
S. Xavier.
|
||||
|
||||
Required Tools and Libraries
|
||||
----------------------------
|
||||
|
||||
To produce the tables in the paper, the following tools and libraries were
|
||||
used. Different versions may produce slightly different outputs.
|
||||
|
||||
- GNU Make, version 3.81
|
||||
- CMake, version 3.7.2
|
||||
- GCC, the GNU Compiler Collection, version 6.3.0
|
||||
- Ruby, version 2.4.0
|
||||
- IBM® ILOG® CPLEX®, version 12.6
|
||||
|
||||
Build instructions
|
||||
------------------
|
||||
|
||||
1. Navigate to the folder `../build`
|
||||
2. Run `cmake ..` followed by `make lifting-benchmark.run`
|
||||
3. Two binaries (`lifting-benchmark.run` and `liblifting.a`) will be generated
|
||||
|
||||
Running the experiments
|
||||
-----------------------
|
||||
|
||||
1. Build the project, following the instructions above.
|
||||
2. Navigate to the folder `lifting/benchmark` and execute
|
||||
|
||||
./run_experiments.sh
|
||||
|
||||
3. Two CSV files will be generated inside the folder `lifting/benchmark/tables`,
|
||||
corresponding to the two tables that appear in the paper.
|
||||
|
||||
Modifying the instances
|
||||
-----------------------
|
||||
|
||||
In order to run the experiments with a different set of instances,
|
||||
the file `lifting/benchmark/instances/filtered/all.txt` should be modified.
|
||||
Each line in this file describes the origin `f` and a lattice-free set `B`.
|
||||
The set `B` is described by the coordinates of its vertices. Since the
|
||||
benchmark code only deals with maximal lattice-free sets, it is also necessary
|
||||
to specify the lattice-points that belong to each facet of `B`.
|
||||
If `n` is the number of facets, `v` is an n-by-2 matrix of doubles corresponding
|
||||
to the vertices and l is an n-by-2 matrix of doubles corresponding to the
|
||||
lattice-points, then each line of the file should be written as
|
||||
|
||||
f[0] f[1] n v[0][0] v[0][1] ... v[n-1][0] v[n-1][1] n l[0][0] l[0][1] ... l[n-1][0] l[n-1][1]
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6917,7 +6917,7 @@
|
||||
69 16 0.68683156580163995386
|
||||
69 17 0.92943801855653873645
|
||||
69 18 0.10740586958127096295
|
||||
69 19 0.92496934696100652218
|
||||
69 19 0.92497488891240209341
|
||||
69 20 0.60183083702384010394
|
||||
69 21 0.49150980007834732533
|
||||
69 22 0.42780977682599541367
|
||||
@@ -51695,7 +51695,7 @@
|
||||
516 94 0.76878394367395230802
|
||||
516 95 0.38042760308826473192
|
||||
516 96 0.39931448388506396441
|
||||
516 97 0.47279282059935212601
|
||||
516 97 0.47279361768801209109
|
||||
516 98 0.97282870978187929722
|
||||
516 99 0.62348135864249343285
|
||||
517 0 0.50616530635928924653
|
||||
@@ -94349,7 +94349,7 @@
|
||||
943 48 0.76196620377269397295
|
||||
943 49 0.22952707635243996265
|
||||
943 50 0.41734143911918408776
|
||||
943 51 0.91839681508463399950
|
||||
943 51 0.91840633855952091835
|
||||
943 52 0.37241285013528369063
|
||||
943 53 0.82926766528856887817
|
||||
943 54 0.54408107882613876427
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1177
lifting/benchmark/orig-100/bound.log
Normal file
1177
lifting/benchmark/orig-100/bound.log
Normal file
File diff suppressed because it is too large
Load Diff
2002
lifting/benchmark/orig-100/bound.yaml
Normal file
2002
lifting/benchmark/orig-100/bound.yaml
Normal file
File diff suppressed because it is too large
Load Diff
62042
lifting/benchmark/orig-100/heur.log
Normal file
62042
lifting/benchmark/orig-100/heur.log
Normal file
File diff suppressed because it is too large
Load Diff
2002
lifting/benchmark/orig-100/heur.yaml
Normal file
2002
lifting/benchmark/orig-100/heur.yaml
Normal file
File diff suppressed because it is too large
Load Diff
1180
lifting/benchmark/orig-100/mip-pre.log
Normal file
1180
lifting/benchmark/orig-100/mip-pre.log
Normal file
File diff suppressed because it is too large
Load Diff
2002
lifting/benchmark/orig-100/mip-pre.yaml
Normal file
2002
lifting/benchmark/orig-100/mip-pre.yaml
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1193
lifting/benchmark/orig-100/naive-bbox-pre.log
Normal file
1193
lifting/benchmark/orig-100/naive-bbox-pre.log
Normal file
File diff suppressed because it is too large
Load Diff
2002
lifting/benchmark/orig-100/naive-bbox-pre.yaml
Normal file
2002
lifting/benchmark/orig-100/naive-bbox-pre.yaml
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -8,6 +8,8 @@ function title()
|
||||
}
|
||||
|
||||
RUN=../../build/lifting/benchmark/lifting-benchmark.run
|
||||
make -C ../../build lifting-benchmark.run || exit 1
|
||||
|
||||
if [ ! -f $RUN ]; then
|
||||
echo "not found: $RUN"
|
||||
echo "please build the project before running this script"
|
||||
@@ -15,12 +17,9 @@ if [ ! -f $RUN ]; then
|
||||
fi
|
||||
|
||||
INSTANCES="instances/filtered/all.txt"
|
||||
# SAMPLES_SLOW=10
|
||||
# SAMPLES_MEDIUM=100
|
||||
# SAMPLES_FAST=1000
|
||||
SAMPLES_SLOW=1
|
||||
SAMPLES_MEDIUM=1
|
||||
SAMPLES_FAST=1
|
||||
SAMPLES_SLOW=10
|
||||
SAMPLES_MEDIUM=100
|
||||
SAMPLES_FAST=1000
|
||||
SEED=1240
|
||||
|
||||
# ORIGINAL
|
||||
@@ -36,8 +35,11 @@ COMMON_OPTS="$COMMON_OPTS --check-answers $ANSWERS"
|
||||
DIR=orig-100
|
||||
mkdir -p $DIR; rm -f $DIR/*log $DIR/*yaml
|
||||
|
||||
title Heuristic
|
||||
$RUN $COMMON_OPTS --samples $SAMPLES_FAST --heuristic --log $DIR/heur.log --stats $DIR/heur.yaml || exit
|
||||
|
||||
title Bound Original
|
||||
$RUN $COMMON_OPTS --samples $SAMPLES_FAST --bound --log $DIR/bound-nopre.log --stats $DIR/bound-nopre.yaml || exit
|
||||
$RUN $COMMON_OPTS --samples $SAMPLES_FAST --bound --log $DIR/bound.log --stats $DIR/bound.yaml || exit
|
||||
|
||||
title Bound Pre-processing
|
||||
$RUN $COMMON_OPTS --samples $SAMPLES_FAST --bound --preprocess --log $DIR/bound-pre.log --stats $DIR/bound-pre.yaml || exit
|
||||
@@ -47,11 +49,17 @@ $RUN $COMMON_OPTS --samples $SAMPLES_MEDIUM --naive --log $DIR/naive-bbox.log --
|
||||
|
||||
title Naive Fixed-M
|
||||
M=50
|
||||
$RUN $COMMON_OPTS --samples $SAMPLES_MEDIUM --naive --fixed-bounds $M --log $DIR/naive-fixed-$M.log --stats $DIR/naive-fixed-$M.yaml || exit
|
||||
$RUN $COMMON_OPTS --samples $SAMPLES_SLOW --naive --fixed-bounds $M --log $DIR/naive-fixed-$M.log --stats $DIR/naive-fixed-$M.yaml || exit
|
||||
|
||||
title Naive Bounding-Box Pre-processing
|
||||
$RUN $COMMON_OPTS --samples $SAMPLES_SLOW --naive --preprocess --log $DIR/naive-bbox-pre.log --stats $DIR/naive-bbox-pre.yaml || exit
|
||||
|
||||
title MIP
|
||||
$RUN $COMMON_OPTS --samples $SAMPLES_SLOW --mip --log $DIR/mip.log --stats $DIR/mip.yaml || exit
|
||||
|
||||
title MIP Pre-processing
|
||||
$RUN $COMMON_OPTS --samples $SAMPLES_SLOW --mip --preprocess --log $DIR/mip-pre.log --stats $DIR/mip-pre.yaml || exit
|
||||
|
||||
# SHEAR
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
@@ -69,7 +77,7 @@ title Bound Pre-processing + Shear
|
||||
$RUN $COMMON_OPTS --samples $SAMPLES_FAST --bound --preprocess --log $DIR/bound-pre.log --stats $DIR/bound-pre.yaml || exit
|
||||
|
||||
title Bound Original + Shear
|
||||
$RUN $COMMON_OPTS --samples $SAMPLES_MEDIUM --bound --log $DIR/bound-nopre.log --stats $DIR/bound-nopre.yaml || exit
|
||||
$RUN $COMMON_OPTS --samples $SAMPLES_MEDIUM --bound --log $DIR/bound.log --stats $DIR/bound.yaml || exit
|
||||
|
||||
title Naive Bounding-Box + Shear
|
||||
$RUN $COMMON_OPTS --samples $SAMPLES_SLOW --naive --log $DIR/naive-bbox.log --stats $DIR/naive-bbox.yaml || exit
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
require 'yaml'
|
||||
require 'bigdecimal'
|
||||
|
||||
BIG_M = 1000000
|
||||
|
||||
def sum(a)
|
||||
a.inject(0){ |accum, i| accum + i }
|
||||
end
|
||||
@@ -35,7 +33,7 @@ ARGV.each_with_index do |filename,idx|
|
||||
filenames[idx] = filename
|
||||
.gsub(/.*\//,"")
|
||||
.gsub(".yaml", "")
|
||||
.gsub(/[^A-Za-z]/, "")
|
||||
.gsub(/[^A-Za-z0-9]/, "")
|
||||
files[idx] = YAML::load(File.open(filename))
|
||||
end
|
||||
|
||||
@@ -59,14 +57,14 @@ files.each_with_index do |f,idx|
|
||||
for i in 0..(n_instances-1) do
|
||||
time = f['cpu_time'][i]
|
||||
next if time.nil?
|
||||
|
||||
times[idx].push(time)
|
||||
all_times[idx].push(time)
|
||||
|
||||
if(time == BIG_M)
|
||||
wrong = f['wrong_answer'][i]
|
||||
if(wrong == 1)
|
||||
fail_count[idx] += 1
|
||||
else
|
||||
success_count[idx] += 1
|
||||
times[idx].push(time)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -75,6 +73,7 @@ end
|
||||
|
||||
best_percentage = [0] * files.length
|
||||
|
||||
BIG_M = 1000000000
|
||||
for i in 0..(n_instances-1) do
|
||||
best_time = BIG_M
|
||||
files.each_with_index do |f,idx|
|
||||
@@ -87,7 +86,6 @@ for i in 0..(n_instances-1) do
|
||||
best_percentage[idx] += 1 if time == best_time
|
||||
|
||||
next if best_time <= 0
|
||||
next if time >= BIG_M
|
||||
ratios_to_best[idx].push(time / best_time)
|
||||
end
|
||||
end
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1177
lifting/benchmark/shear-100/bound.log
Normal file
1177
lifting/benchmark/shear-100/bound.log
Normal file
File diff suppressed because it is too large
Load Diff
2002
lifting/benchmark/shear-100/bound.yaml
Normal file
2002
lifting/benchmark/shear-100/bound.yaml
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -40,10 +40,12 @@ unsigned int SEED = 0;
|
||||
#define ALGORITHM_BOUND 0
|
||||
#define ALGORITHM_NAIVE 1
|
||||
#define ALGORITHM_MIP 2
|
||||
#define ALGORITHM_HEUR 3
|
||||
|
||||
int SELECT_NAIVE_ALGORITHM = 0;
|
||||
int SELECT_BOUND_ALGORITHM = 0;
|
||||
int SELECT_MIP_ALGORITHM = 0;
|
||||
int SELECT_HEUR_ALGORITHM = 0;
|
||||
|
||||
int ENABLE_PREPROCESSING = 0;
|
||||
int ENABLE_SHEAR = 0;
|
||||
@@ -83,6 +85,7 @@ static const struct option options_tab[] =
|
||||
{"check-answers", required_argument, 0, 'c'},
|
||||
{"samples", required_argument, 0, 'a'},
|
||||
{"mip", no_argument, 0, 'm'},
|
||||
{"heuristic", no_argument, 0, 'r'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
@@ -108,6 +111,8 @@ static void print_usage(char **argv)
|
||||
"select MIP algorithm");
|
||||
printf("%4s %-20s %s\n", "-u", "--bound",
|
||||
"select bound algorithm");
|
||||
printf("%4s %-20s %s\n", "-e", "--heuristic",
|
||||
"select heuristic algorithm");
|
||||
printf("%4s %-20s %s\n", "-p", "--preprocess",
|
||||
"enable pre-processing step in bound algorithm");
|
||||
printf("%4s %-20s %s\n", "-e", "--shear",
|
||||
@@ -144,7 +149,7 @@ static int parse_args(int argc,
|
||||
{
|
||||
int c = 0;
|
||||
int option_index = 0;
|
||||
c = getopt_long(argc, argv, "hb:k:s:f:o:nupew:c:a:m", options_tab,
|
||||
c = getopt_long(argc, argv, "hb:k:s:f:o:nupew:c:a:mr", options_tab,
|
||||
&option_index);
|
||||
|
||||
if (c < 0) break;
|
||||
@@ -208,6 +213,10 @@ static int parse_args(int argc,
|
||||
SELECT_BOUND_ALGORITHM = 1;
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
SELECT_HEUR_ALGORITHM = 1;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
ENABLE_PREPROCESSING = 1;
|
||||
break;
|
||||
@@ -243,7 +252,8 @@ static int parse_args(int argc,
|
||||
rval = 1;
|
||||
}
|
||||
|
||||
if (SELECT_NAIVE_ALGORITHM + SELECT_BOUND_ALGORITHM + SELECT_MIP_ALGORITHM != 1)
|
||||
if (SELECT_NAIVE_ALGORITHM + SELECT_BOUND_ALGORITHM + SELECT_MIP_ALGORITHM
|
||||
+ SELECT_HEUR_ALGORITHM != 1)
|
||||
{
|
||||
fprintf(stderr, "You must select exactly one algorithm.\n");
|
||||
rval = 1;
|
||||
@@ -298,6 +308,18 @@ int benchmark_set_sample(int algorithm,
|
||||
int *wrong_answer)
|
||||
{
|
||||
int rval = 0;
|
||||
double xi_plus, xi_minus, ignored;
|
||||
|
||||
if(algorithm == ALGORITHM_BOUND)
|
||||
{
|
||||
rval = LIFTING_2D_optimize_continuous(set->n_halfspaces,
|
||||
set->halfspaces, 1, &ignored, &xi_plus);
|
||||
abort_if(rval, "LIFTING_2D_optimize_continuous failed");
|
||||
|
||||
rval = LIFTING_2D_optimize_continuous(set->n_halfspaces,
|
||||
set->halfspaces, -1, &ignored, &xi_minus);
|
||||
abort_if(rval, "LIFTING_2D_optimize_continuous failed");
|
||||
}
|
||||
|
||||
for (int i = 0; i < N_RAYS; i++)
|
||||
{
|
||||
@@ -319,8 +341,8 @@ int benchmark_set_sample(int algorithm,
|
||||
switch (algorithm)
|
||||
{
|
||||
case ALGORITHM_BOUND:
|
||||
rval = LIFTING_2D_bound(set->n_halfspaces, set->halfspaces, ray,
|
||||
&value);
|
||||
rval = LIFTING_2D_bound(set->n_halfspaces, set->halfspaces,
|
||||
ray, xi_plus, xi_minus, &value);
|
||||
abort_if(rval, "LIFTING_2D_bound failed");
|
||||
break;
|
||||
|
||||
@@ -336,6 +358,12 @@ int benchmark_set_sample(int algorithm,
|
||||
abort_if(rval, "LIFTING_2D_mip failed");
|
||||
break;
|
||||
|
||||
case ALGORITHM_HEUR:
|
||||
rval = LIFTING_2D_heur(set->n_halfspaces, set->halfspaces, ray,
|
||||
&value);
|
||||
abort_if(rval, "LIFTING_2D_heur failed");
|
||||
break;
|
||||
|
||||
default:
|
||||
abort_if(1, "Invalid algorithm");
|
||||
}
|
||||
@@ -371,8 +399,6 @@ int benchmark_set_sample(int algorithm,
|
||||
" expected=%.8lf delta=%.8lf)\n", set_idx,
|
||||
i, value, expected_value, delta);
|
||||
*wrong_answer = 1;
|
||||
|
||||
LFREE_2D_print_set(set);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -440,11 +466,17 @@ int benchmark(int n_sets, struct LFreeSet2D *sets, double *rays,
|
||||
int algorithm)
|
||||
{
|
||||
int rval = 0;
|
||||
double *times = 0;
|
||||
int *wrong = 0;
|
||||
|
||||
wrong = (int*) malloc(n_sets * sizeof(int));
|
||||
times = (double*) malloc(n_sets * sizeof(double));
|
||||
abort_if(!wrong, "could not allocate wrong");
|
||||
abort_if(!times, "could not allocate times");
|
||||
|
||||
log_info("Running benchmark...\n");
|
||||
|
||||
double total_initial_time = get_user_time();
|
||||
stats_printf("cpu_time:\n");
|
||||
|
||||
for (int j = 0; j < n_sets; j++)
|
||||
{
|
||||
@@ -467,12 +499,20 @@ int benchmark(int n_sets, struct LFreeSet2D *sets, double *rays,
|
||||
double set_duration = get_user_time() - set_initial_time;
|
||||
double avg = (set_duration / N_SAMPLES_PER_SET) * 1000;
|
||||
|
||||
if(wrong_answer) avg = 1000000;
|
||||
times[j] = avg;
|
||||
wrong[j] = wrong_answer;
|
||||
|
||||
stats_printf(" %d: %.8lf\n", j, avg);
|
||||
log_info(" %3d: %12.3lf ms\n", j, avg);
|
||||
}
|
||||
|
||||
stats_printf("cpu_time:\n");
|
||||
for(int j = 0; j < n_sets; j++)
|
||||
stats_printf(" %d: %.8lf\n", j, times[j]);
|
||||
|
||||
stats_printf("wrong_answer:\n");
|
||||
for(int j = 0; j < n_sets; j++)
|
||||
stats_printf(" %d: %d\n", j, wrong[j]);
|
||||
|
||||
double total_duration = get_user_time() - total_initial_time;
|
||||
|
||||
log_info(" %.3lf ms per set \n",
|
||||
@@ -485,6 +525,8 @@ int benchmark(int n_sets, struct LFreeSet2D *sets, double *rays,
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
if(wrong) free(wrong);
|
||||
if(times) free(times);
|
||||
return rval;
|
||||
}
|
||||
|
||||
@@ -550,22 +592,32 @@ int main(int argc, char **argv)
|
||||
ray[1] = DOUBLE_random(0.0, 1.0);
|
||||
}
|
||||
|
||||
int algorithm = ALGORITHM_BOUND;
|
||||
if(SELECT_MIP_ALGORITHM) algorithm = ALGORITHM_MIP;
|
||||
else if(SELECT_NAIVE_ALGORITHM) algorithm = ALGORITHM_NAIVE;
|
||||
int algorithm = -1;
|
||||
|
||||
if(algorithm == ALGORITHM_NAIVE)
|
||||
if(SELECT_BOUND_ALGORITHM)
|
||||
{
|
||||
log_info("Enabling bound algorithm\n");
|
||||
algorithm = ALGORITHM_BOUND;
|
||||
}
|
||||
else if(SELECT_MIP_ALGORITHM)
|
||||
{
|
||||
log_info("Enabling MIP algorithm\n");
|
||||
algorithm = ALGORITHM_MIP;
|
||||
}
|
||||
else if(SELECT_NAIVE_ALGORITHM)
|
||||
{
|
||||
log_info("Enabling naive algorithm\n");
|
||||
algorithm = ALGORITHM_NAIVE;
|
||||
|
||||
if(USE_FIXED_BOUNDS)
|
||||
log_info("Using fixed big M: %d\n", NAIVE_BIG_M);
|
||||
else
|
||||
log_info("Enabling bounding boxes\n");
|
||||
}
|
||||
else
|
||||
else if(SELECT_HEUR_ALGORITHM)
|
||||
{
|
||||
log_info("Enabling bound algorithm\n");
|
||||
log_info("Enabling heuristic algorithm\n");
|
||||
algorithm = ALGORITHM_HEUR;
|
||||
}
|
||||
|
||||
log_info("Setting %d samples per set\n", N_SAMPLES_PER_SET);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
metric,boundnopre,boundpre,mip,naivebbox,naivefixed,
|
||||
Average (ms),0.565,0.059,141.938,9.341,23.278,
|
||||
Median (ms),0.068,0.060,129.200,2.120,23.080,
|
||||
Maximum (ms),33.264,0.100,947.600,1769.880,30.080,
|
||||
Failure Rate,0.0 \%,0.0 \%,0.0 \%,0.0 \%,0.3 \%,
|
||||
Best,37.2 \%,83.6 \%,0.0 \%,0.0 \%,0.0 \%,
|
||||
Avg Ratio to Best,9.483,1.015,2449.938,159.449,402.950,
|
||||
metric,boundpre,bound,heur,mippre,mip,naivebboxpre,naivebbox,naivefixed50,
|
||||
Average (ms),0.078,0.937,0.004,70.080,81.738,6.353,12.490,34.874,
|
||||
Median (ms),0.079,0.099,0.004,67.590,73.889,2.900,3.120,34.195,
|
||||
Maximum (ms),0.152,55.998,0.008,175.773,1705.441,96.585,2483.652,122.881,
|
||||
Failure Rate,0.0 \%,0.0 \%,100.0 \%,0.0 \%,0.0 \%,0.0 \%,0.1 \%,0.3 \%,
|
||||
Best,0.0 \%,0.0 \%,100.0 \%,0.0 \%,0.0 \%,0.0 \%,0.0 \%,0.0 \%,
|
||||
Avg Ratio to Best,18.918,223.183,1.000,17133.363,20066.439,1539.254,3223.466,8511.913,
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
metric,boundnopre,boundpre,mip,naivebbox,naivefixed,
|
||||
Average (ms),4.709,0.062,1906.081,5473.688,23.374,
|
||||
Median (ms),0.440,0.064,582.800,21.200,23.160,
|
||||
Maximum (ms),485.760,0.108,94620.000,392259.600,32.120,
|
||||
Failure Rate,0.0 \%,0.0 \%,1.7 \%,0.1 \%,10.0 \%,
|
||||
Best,0.0 \%,100.0 \%,0.0 \%,0.0 \%,0.0 \%,
|
||||
Avg Ratio to Best,74.602,1.000,31250.644,87472.010,380.532,
|
||||
metric,boundpre,bound,mip,naivebbox,naivefixed50,
|
||||
Average (ms),0.080,7.723,659.486,478.703,34.680,
|
||||
Median (ms),0.080,0.730,131.680,31.395,34.105,
|
||||
Maximum (ms),0.352,800.768,53099.128,9450.563,48.423,
|
||||
Failure Rate,0.0 \%,0.0 \%,2.1 \%,0.5 \%,10.0 \%,
|
||||
Best,100.0 \%,0.0 \%,0.0 \%,0.0 \%,0.0 \%,
|
||||
Avg Ratio to Best,1.000,96.571,8243.616,6018.030,446.701,
|
||||
|
||||
|
@@ -44,6 +44,13 @@ int LIFTING_2D_naive(int n_halfspaces,
|
||||
double *value);
|
||||
|
||||
int LIFTING_2D_bound(int n_halfspaces,
|
||||
const double *halfspaces,
|
||||
const double *ray,
|
||||
const double xi_plus,
|
||||
const double xi_minus,
|
||||
double *value);
|
||||
|
||||
int LIFTING_2D_heur(int n_halfspaces,
|
||||
const double *halfspaces,
|
||||
const double *ray,
|
||||
double *value);
|
||||
|
||||
@@ -205,15 +205,32 @@ CLEANUP:
|
||||
return rval;
|
||||
}
|
||||
|
||||
int LIFTING_2D_bound(int n_halfspaces,
|
||||
int LIFTING_2D_heur(int n_halfspaces,
|
||||
const double *halfspaces,
|
||||
const double *ray,
|
||||
double *value)
|
||||
{
|
||||
int rval = 0;
|
||||
|
||||
double q[2] = { ray[0] - ceil(ray[0]), ray[1] - ceil(ray[1])};
|
||||
|
||||
rval = LIFTING_2D_psi(n_halfspaces, halfspaces, q, value);
|
||||
abort_if(rval, "LIFTING_2D_ps failed");
|
||||
|
||||
CLEANUP:
|
||||
return rval;
|
||||
}
|
||||
|
||||
int LIFTING_2D_bound(int n_halfspaces,
|
||||
const double *halfspaces,
|
||||
const double *ray,
|
||||
const double xi_plus,
|
||||
const double xi_minus,
|
||||
double *value)
|
||||
{
|
||||
int rval = 0;
|
||||
|
||||
double eta_star, eta_plus, eta_minus;
|
||||
double xi_plus, xi_minus;
|
||||
double m_plus, m_minus;
|
||||
double ignored;
|
||||
int k1 = 1;
|
||||
@@ -221,14 +238,6 @@ int LIFTING_2D_bound(int n_halfspaces,
|
||||
rval = LIFTING_2D_lift_fixed(n_halfspaces, halfspaces, ray, 0, &eta_star);
|
||||
abort_if(rval, "LIFTING_2D_lift_fixed failed");
|
||||
|
||||
rval = LIFTING_2D_optimize_continuous(n_halfspaces, halfspaces, 1, &ignored,
|
||||
&xi_plus);
|
||||
abort_if(rval, "LIFTING_2D_optimize_continuous failed");
|
||||
|
||||
rval = LIFTING_2D_optimize_continuous(n_halfspaces, halfspaces, -1,
|
||||
&ignored, &xi_minus);
|
||||
abort_if(rval, "LIFTING_2D_optimize_continuous failed");
|
||||
|
||||
m_plus = m_minus = INFINITY;
|
||||
|
||||
log_debug("Level 0:\n");
|
||||
|
||||
@@ -116,4 +116,6 @@ int CG_total_nz(const struct Tableau *tableau);
|
||||
|
||||
double CG_replace_x(const struct Row *row, const double *x);
|
||||
|
||||
int CG_print_model(const struct MultiRowModel *model);
|
||||
|
||||
#endif //MULTIROW_CG_H
|
||||
|
||||
@@ -40,7 +40,6 @@ struct RayList
|
||||
int dim;
|
||||
};
|
||||
|
||||
|
||||
struct ConvLFreeSet
|
||||
{
|
||||
double *f;
|
||||
@@ -82,4 +81,6 @@ int LFREE_init_conv(struct ConvLFreeSet *lfree, int dim, int max_nrays);
|
||||
|
||||
void LFREE_free_conv(struct ConvLFreeSet *lfree);
|
||||
|
||||
int LFREE_print_set(const struct ConvLFreeSet *lfree);
|
||||
|
||||
#endif //LFREE_2D_H
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
/*
|
||||
* Maximum bounding-box size for naive algorithm
|
||||
*/
|
||||
#define MAX_BOX_SIZE 10000
|
||||
#define MAX_BOX_SIZE 1000
|
||||
|
||||
/*
|
||||
* Maximum number of sets that should be considered
|
||||
|
||||
@@ -945,7 +945,10 @@ int CG_add_multirow_cuts(struct CG *cg,
|
||||
LP_free_row(&cut);
|
||||
goto NEXT_COMBINATION;
|
||||
}
|
||||
else abort_iff(rval, "generate failed (cut %d)", count);
|
||||
else if(rval) {
|
||||
dump_tableau(&tableau, count);
|
||||
abort_iff(1, "generate failed (cut %d)", count);
|
||||
}
|
||||
|
||||
if_verbose_level dump_cut(&cut, count);
|
||||
|
||||
@@ -1115,4 +1118,32 @@ int CG_total_nz(const struct Tableau *tableau)
|
||||
return total_nz;
|
||||
}
|
||||
|
||||
int CG_print_model(const struct MultiRowModel *model)
|
||||
{
|
||||
int rval = 0;
|
||||
int nrows = model->nrows;
|
||||
|
||||
time_printf(" f = [");
|
||||
for (int i = 0; i < nrows; i++)
|
||||
printf("%20.12lf ", model->f[i]);
|
||||
printf("]\n");
|
||||
|
||||
for (int i = 0; i < model->rays.nrays; i++)
|
||||
{
|
||||
double *ray = LFREE_get_ray(&model->rays, i);
|
||||
double norm = 0;
|
||||
|
||||
time_printf("ray[%3d] = [", i);
|
||||
for (int j = 0; j < nrows; j++)
|
||||
{
|
||||
printf("%20.12lf ", ray[j]);
|
||||
norm += fabs(ray[j]);
|
||||
}
|
||||
printf("] norm=%20.12lf \n", norm);
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
return rval;
|
||||
}
|
||||
|
||||
#endif // TEST_SOURCE
|
||||
|
||||
@@ -559,6 +559,41 @@ CLEANUP:
|
||||
return rval;
|
||||
}
|
||||
|
||||
int LFREE_print_set(const struct ConvLFreeSet *set)
|
||||
{
|
||||
int rval = 0;
|
||||
|
||||
log_debug("f=%12.6lf %12.6lf\n", set->f[0], set->f[1]);
|
||||
|
||||
for (int i = 0; i < set->rays.nrays; i++)
|
||||
{
|
||||
double *ray = LFREE_get_ray(&set->rays, i);
|
||||
log_debug("ray[%-3d] = ", i);
|
||||
for (int j = 0; j < set->nrows; j++)
|
||||
printf("%20.12lf ", ray[j]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
for (int i = 0; i < set->rays.nrays; i++)
|
||||
{
|
||||
double beta = set->beta[i];
|
||||
log_debug("beta[%-3d] = %20.12lf\n", i, beta);
|
||||
}
|
||||
|
||||
for (int i = 0; i < set->rays.nrays; i++)
|
||||
{
|
||||
double *ray = LFREE_get_ray(&set->rays, i);
|
||||
double beta = set->beta[i];
|
||||
log_debug("vertex[%-3d] = ", i);
|
||||
for (int j = 0; j < set->nrows; j++)
|
||||
printf("%20.12lf ", ray[j] * beta + set->f[j]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
return rval;
|
||||
}
|
||||
|
||||
void LFREE_free_conv(struct ConvLFreeSet *lfree)
|
||||
{
|
||||
if(!lfree) return;
|
||||
|
||||
@@ -35,6 +35,7 @@ int LP_open(struct LP *lp)
|
||||
|
||||
CPXsetintparam(lp->cplex_env, CPX_PARAM_DATACHECK, CPX_ON);
|
||||
CPXsetintparam(lp->cplex_env, CPX_PARAM_NUMERICALEMPHASIS, CPX_ON);
|
||||
CPXsetintparam(lp->cplex_env, CPX_PARAM_THREADS, 1);
|
||||
CPXsetlogfile(lp->cplex_env, 0);
|
||||
|
||||
CLEANUP:
|
||||
|
||||
@@ -1,2 +1,9 @@
|
||||
add_executable(onerow-benchmark.run src/main.cpp)
|
||||
target_link_libraries (onerow-benchmark.run LINK_PUBLIC qxx_static onerow_static m pthread ${GMP_LIBRARIES} ${CPLEX_LIBRARIES})
|
||||
target_link_libraries (onerow-benchmark.run LINK_PUBLIC
|
||||
qxx_static
|
||||
onerow_static
|
||||
m
|
||||
pthread
|
||||
${GMP_LIBRARIES}
|
||||
${CPLEX_LIBRARIES}
|
||||
${OpenMP_LIBRARIES})
|
||||
|
||||
@@ -3,28 +3,21 @@ for i in out/*yaml; do
|
||||
IN=${i/.pre.yaml/}
|
||||
IN=${IN/out\//}
|
||||
grep -q mip_value $i && continue
|
||||
echo $IN
|
||||
grep $IN instances/opt.tab | awk '{ print "mip_value:\n "$2 }' >> $i
|
||||
done
|
||||
|
||||
echo " TABLE 1 "
|
||||
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'
|
||||
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'
|
||||
for i in out/*.yaml; do
|
||||
IN=${i/.yaml/}
|
||||
IN=${IN/out\//}
|
||||
printf "%s," $IN
|
||||
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
|
||||
echo
|
||||
echo " TABLE 2 "
|
||||
echo "--------------------------------------------------------------------------------"
|
||||
printf "%s,%s,%s,%s,%s,%s\n" instance cutsmir cutsw mirt wedget avgm | tee 'tables/speed.csv'
|
||||
printf "%s,%s,%s,%s,%s,%s\n" instance cutsmir cutsw mirt wedget avgm > 'tables/speed.csv'
|
||||
for i in out/*.yaml; do
|
||||
IN=${i/.yaml/}
|
||||
IN=${IN/out\//}
|
||||
printf "%s," $IN
|
||||
scripts/speed.rb $i
|
||||
done | sort | sed -e 's/,$//g' | tee -a 'tables/speed.csv'
|
||||
done | sort | sed -e 's/,$//g' >> 'tables/speed.csv'
|
||||
|
||||
@@ -98,6 +98,8 @@ int main(int argc, char **argv)
|
||||
|
||||
Stats::set_input_filename(string(input_filename));
|
||||
|
||||
time_printf("Using OpenMP (%d threads)\n", omp_get_max_threads());
|
||||
|
||||
// reads input file
|
||||
time_printf("Reading input file: %s...\n", input_filename);
|
||||
status = CPXreadcopyprob(env, lp, input_filename, NULL);
|
||||
@@ -149,21 +151,21 @@ int main(int argc, char **argv)
|
||||
if (enable_gomory_cuts)
|
||||
{
|
||||
time_printf("Generating Gomory cuts...\n");
|
||||
cplexHelper.add_single_row_cuts<GomoryCutGenerator>();
|
||||
cplexHelper.add_single_row_cuts<GomoryCutGenerator>(0);
|
||||
cplexHelper.solve(true);
|
||||
}
|
||||
|
||||
if (enable_mir_cuts)
|
||||
{
|
||||
time_printf("Generating MIR cuts...\n");
|
||||
cplexHelper.add_single_row_cuts<MIRCutGenerator>();
|
||||
cplexHelper.add_single_row_cuts<MIRCutGenerator>(0);
|
||||
cplexHelper.solve(true);
|
||||
}
|
||||
|
||||
if (enable_wedge_cuts)
|
||||
{
|
||||
time_printf("Generating wedge cuts...\n");
|
||||
cplexHelper.add_single_row_cuts<WedgeCutGenerator>();
|
||||
cplexHelper.add_single_row_cuts<WedgeCutGenerator>(MAX_GOOD_ROWS);
|
||||
cplexHelper.solve(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -69,10 +69,11 @@ public:
|
||||
* cuts as possible. The cuts are generated by the provided generator class.
|
||||
*
|
||||
* @tparam Generator Class used to generate the cuts.
|
||||
* @param max_rows The maximum number of rows to consider.
|
||||
* @returns The number of cuts added.
|
||||
*/
|
||||
template<class Generator>
|
||||
int add_single_row_cuts();
|
||||
int add_single_row_cuts(int max_rows);
|
||||
|
||||
/**
|
||||
* Gets a single row from the current tableau.
|
||||
@@ -90,7 +91,7 @@ public:
|
||||
*
|
||||
* @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 = "");
|
||||
|
||||
@@ -107,7 +108,7 @@ public:
|
||||
|
||||
void print_solution(double *x);
|
||||
|
||||
void find_good_rows();
|
||||
void find_good_rows(int max_rows);
|
||||
|
||||
int n_rows;
|
||||
int n_cols;
|
||||
@@ -134,6 +135,9 @@ public:
|
||||
|
||||
int n_good_rows;
|
||||
int *good_rows;
|
||||
|
||||
double *reduced_costs;
|
||||
double cost_cutoff;
|
||||
};
|
||||
|
||||
#include "cplex_helper.tpp"
|
||||
|
||||
@@ -30,12 +30,17 @@ using std::endl;
|
||||
|
||||
|
||||
template<class Generator>
|
||||
int CplexHelper::add_single_row_cuts()
|
||||
int CplexHelper::add_single_row_cuts(int max_rows)
|
||||
{
|
||||
total_cuts = 0;
|
||||
|
||||
if(n_good_rows < 0)
|
||||
find_good_rows();
|
||||
if(n_good_rows > 0)
|
||||
{
|
||||
n_good_rows = 0;
|
||||
delete good_rows;
|
||||
}
|
||||
|
||||
find_good_rows(max_rows);
|
||||
|
||||
eta_reset();
|
||||
eta_count = 0;
|
||||
@@ -48,7 +53,6 @@ int CplexHelper::add_single_row_cuts()
|
||||
for (int i = 0; i < n_good_rows; i++)
|
||||
{
|
||||
Row *row = get_tableau_row(good_rows[i]);
|
||||
//Row *row = good_rows[i];
|
||||
|
||||
Generator generator(*row);
|
||||
|
||||
|
||||
@@ -25,16 +25,14 @@ const long REDUCE_FACTOR_RHS = 1000000;
|
||||
const long REDUCE_FACTOR_R1 = 1000;
|
||||
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 unsigned int MAX_CUT_BUFFER_SIZE = 100;
|
||||
|
||||
const double COEFFICIENT_SAFETY_MARGIN = 0.00001;
|
||||
|
||||
#define INTERSECTION_CUT_USE_DOUBLE
|
||||
|
||||
#define ENABLE_TRIVIAL_LIFTING
|
||||
// #define ENABLE_EXTENDED_STATISTICS
|
||||
// #define PRETEND_TO_ADD_CUTS
|
||||
|
||||
|
||||
@@ -66,6 +66,8 @@ struct Row {
|
||||
int basic_var_index;
|
||||
|
||||
bool* is_integer;
|
||||
double* reduced_costs;
|
||||
double cost_cutoff;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <onerow/geometry.hpp>
|
||||
#include <onerow/stats.hpp>
|
||||
#include <onerow/params.hpp>
|
||||
#include <cstring>
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
@@ -39,7 +40,7 @@ static bool debug = false;
|
||||
CplexHelper::CplexHelper(CPXENVptr _env, CPXLPptr _lp) :
|
||||
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),
|
||||
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->c = cplex_row_to_constraint(cplex_rows[index]);
|
||||
|
||||
row->reduced_costs = reduced_costs;
|
||||
row->cost_cutoff = cost_cutoff;
|
||||
|
||||
if (optimal_solution)
|
||||
assert(cplex_rows[index].get_violation(optimal_solution) <= 0.001);
|
||||
|
||||
@@ -272,7 +276,7 @@ Row* CplexHelper::get_tableau_row(int index)
|
||||
return row;
|
||||
}
|
||||
|
||||
int CplexHelper::solve(bool should_end_round)
|
||||
void CplexHelper::solve(bool should_end_round)
|
||||
{
|
||||
// Optimize
|
||||
int status = CPXlpopt(env, lp);
|
||||
@@ -312,8 +316,6 @@ int CplexHelper::solve(bool should_end_round)
|
||||
|
||||
if (should_end_round)
|
||||
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);
|
||||
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];
|
||||
assert(cplex_rows != 0);
|
||||
|
||||
@@ -509,10 +521,10 @@ void CplexHelper::eta_print()
|
||||
FINISHED:;
|
||||
}
|
||||
|
||||
void CplexHelper::find_good_rows()
|
||||
void CplexHelper::find_good_rows(int max_rows)
|
||||
{
|
||||
n_good_rows = 0;
|
||||
good_rows = new int[n_rows];
|
||||
bool *is_good = new bool[n_rows];
|
||||
double *fractionality = new double[n_rows];
|
||||
|
||||
time_printf("Finding interesting rows...\n");
|
||||
|
||||
@@ -521,14 +533,37 @@ void CplexHelper::find_good_rows()
|
||||
{
|
||||
Row *row = get_tableau_row(i);
|
||||
|
||||
if (row->c.pi_zero.frac() != 0 &&
|
||||
row->is_integer[row->basic_var_index])
|
||||
{
|
||||
good_rows[n_good_rows++] = i;
|
||||
}
|
||||
fractionality[i] = row->c.pi_zero.frac().get_double();
|
||||
fractionality[i] = fabs(fractionality[i] - 0.5);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
if(row.reduced_costs[r1_index] < row.cost_cutoff)
|
||||
continue;
|
||||
|
||||
r1[0] = -row.c.pi.value(r1_offset).reduce(REDUCE_FACTOR_R1);
|
||||
r1[1] = 1;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user