Compare commits

..

5 Commits

@ -7,6 +7,8 @@ include_directories(${CPLEX_INCLUDE_DIR})
find_package(GMP REQUIRED) find_package(GMP REQUIRED)
find_package(OpenMP REQUIRED) find_package(OpenMP REQUIRED)
find_package(BLAS REQUIRED)
find_package(LAPACKE REQUIRED)
set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror ${OpenMP_CXX_FLAGS} -O3") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror ${OpenMP_CXX_FLAGS} -O3")

@ -0,0 +1,11 @@
find_library(LAPACKE_LIBRARIES
NAMES lapacke)
find_path(LAPACKE_INCLUDE_DIR NAMES lapacke.h)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(LAPACKE
DEFAULT_MSG
LAPACKE_LIBRARIES
LAPACKE_INCLUDE_DIR)
mark_as_advanced(LAPACKE_LIBRARIES LAPACKE_INCLUDE_DIR)

@ -22,6 +22,7 @@
#include <multirow/util.h> #include <multirow/util.h>
#include <infinity/infinity-nd.h> #include <infinity/infinity-nd.h>
#include <multirow/linalg.h>
static long lp_count = 0; static long lp_count = 0;
static double lp_time = 0; static double lp_time = 0;
@ -41,6 +42,41 @@ static double sfree_mip_time = 0;
static long scale_ahull_lp_count = 0; static long scale_ahull_lp_count = 0;
static double scale_ahull_lp_time = 0; static double scale_ahull_lp_time = 0;
static int cone_bound_find_lambda(const struct RayList *rays,
const double *f,
const double *x,
double *lambda)
{
int rval = 0;
double *A = 0;
double *b = 0;
int dim = rays->dim;
int nrays = rays->nrays;
A = (double*) malloc(nrays * dim * sizeof(double));
b = (double*) malloc(dim * sizeof(double));
abort_if(!A, "could not allocate A");
abort_if(!b, "could not allocate b");
for (int i = 0; i < dim; i++)
{
b[i] = x[i] - f[i];
for (int j = 0; j < nrays; j++)
A[i * nrays + j] = rays->values[j * dim + i];
}
rval = LINALG_solve(nrays, dim, A, b, lambda);
abort_if(rval, "LINALG_solve failed");
for (int i = 0; i < dim; i++)
abort_iff(lambda[0] < 0, "lambda[i] is negative (%lf)", i, lambda[i]);
CLEANUP:
if(A) free(A);
if(b) free(b);
return rval;
}
static int create_sfree_mip(int nrows, static int create_sfree_mip(int nrows,
int nrays, int nrays,
const double *f, const double *f,
@ -426,9 +462,8 @@ static int create_violated_cone_lp(int nrows,
rval = LP_relax(lp); rval = LP_relax(lp);
abort_if(rval, "LP_relax failed"); abort_if(rval, "LP_relax failed");
//rval = LP_write(lp, "violated-cone.lp"); // rval = LP_write(lp, "violated-cone.lp");
//abort_if(rval, "LP_write failed"); // abort_if(rval, "LP_write failed");
//UTIL_pause();
CLEANUP: CLEANUP:
if(rmatind) free(rmatind); if(rmatind) free(rmatind);
@ -631,14 +666,14 @@ static int find_interior_point_cplex(const int nrows,
rval = create_sfree_mip(nrows, nrays, f, rays, beta, epsilon, &lp); rval = create_sfree_mip(nrows, nrays, f, rays, beta, epsilon, &lp);
abort_if(rval, "greate_sfree_mip failed"); abort_if(rval, "greate_sfree_mip failed");
log_debug(" solving sfree mip...\n"); log_debug(" solving sfree mip...\n");
rval = LP_optimize(&lp, &infeasible); rval = LP_optimize(&lp, &infeasible);
if(rval == ERR_MIP_TIMEOUT) goto CLEANUP; if(rval == ERR_MIP_TIMEOUT) goto CLEANUP;
abort_if(rval, "LP_optimize failed"); abort_if(rval, "LP_optimize failed");
if(infeasible) if(infeasible)
{ {
log_debug(" mip is infeasible. Stopping.\n"); log_debug(" mip is infeasible. Stopping.\n");
*found = 0; *found = 0;
goto CLEANUP; goto CLEANUP;
} }
@ -659,11 +694,11 @@ static int find_interior_point_cplex(const int nrows,
rval = LP_get_obj_val(&lp, &objval); rval = LP_get_obj_val(&lp, &objval);
abort_if(rval, "LP_get_obj_val failed"); abort_if(rval, "LP_get_obj_val failed");
log_debug(" obj = %.8lf\n", objval); log_debug(" obj: %.8lf\n", objval);
if(objval > 0.999) if(objval > 0.999)
{ {
log_debug(" set is lattice-free\n"); log_debug(" set is lattice-free\n");
*found = 0; *found = 0;
goto CLEANUP; goto CLEANUP;
} }
@ -853,7 +888,7 @@ static int find_violated_cone(int nrows,
double *sbar, double *sbar,
int *violated_found) int *violated_found)
{ {
log_verbose(" find_violated_cone\n"); log_debug(" finding violated cone:\n");
int rval = 0; int rval = 0;
struct LP lp; struct LP lp;
@ -890,30 +925,30 @@ static int find_violated_cone(int nrows,
rval = LP_get_obj_val(&lp, &obj); rval = LP_get_obj_val(&lp, &obj);
abort_if(rval, "LP_get_obj_val failed"); abort_if(rval, "LP_get_obj_val failed");
log_verbose(" o=%.8lf\n", obj); log_debug(" obj: %.8lf\n", obj);
if(DOUBLE_geq(obj, 0.999)) if(obj > 0.999)
{ {
*violated_found = 0; *violated_found = 0;
log_debug(" no violated cone found\n");
} }
else else
{ {
*violated_found = 1; *violated_found = 1;
log_verbose("Violated cone found\n"); log_debug(" violated cone found:\n");
log_verbose(" f=%.8lf %.8lf\n", f[0], f[1]); log_debug(" f: %12.8lf %12.8lf\n", f[0], f[1]);
log_verbose(" x=%.8lf %.8lf\n", x[0], x[1]); log_debug(" x: %12.8lf %12.8lf\n", x[0], x[1]);
for(int i = 0; i < nrays; i++) for(int i = 0; i < nrays; i++)
{ {
rx[i] = (sbar[i] > 1e-9); rx[i] = (sbar[i] > 1e-9);
if(rx[i]) if_verbose_level if(rx[i]) if_debug_level
{ {
double m = min(epsilon, beta[i]); const double m = fmin(epsilon, beta[i]);
const double *r = &rays[nrows * i]; const double *r = &rays[nrows * i];
time_printf(" r[%d]=%.8lf %.8lf\n", i, r[0], r[1]); time_printf(" r[%d]: %12.8lf %12.8lf\n", i, m * sbar[i] * r[0], m * sbar[i] * r[1]);
time_printf(" r[%d]=%.8lf %.8lf\n", i, m * r[0], m * r[1]);
} }
} }
} }
@ -974,15 +1009,12 @@ static int bound(int nrows,
fbar[i] -= min(*epsilon, beta[j]) * r[i] * sbar[j]; fbar[i] -= min(*epsilon, beta[j]) * r[i] * sbar[j];
} }
log_verbose("%.12lf %.12lf\n", f[0], f[1]);
log_verbose("%.12lf %.12lf\n", fbar[0], fbar[1]);
prev_epsilon = *epsilon; prev_epsilon = *epsilon;
rval = cone_bound(nrows, nrays, fbar, rays, rx, x, beta, epsilon); rval = cone_bound(nrows, nrays, fbar, rays, rx, x, beta, epsilon);
abort_if(rval, "cone_bound failed"); abort_if(rval, "cone_bound failed");
log_verbose(" e=%.12lf\n", *epsilon); log_debug(" cone bound: %.20lf\n", epsilon);
abort_if(prev_epsilon < *epsilon, "epsilon should never increase"); abort_if(prev_epsilon < *epsilon, "epsilon should never increase");
} }
@ -1211,8 +1243,6 @@ CLEANUP:
int INFINITY_ND_generate_lfree(const struct MultiRowModel *model, int INFINITY_ND_generate_lfree(const struct MultiRowModel *model,
struct ConvLFreeSet *lfree) struct ConvLFreeSet *lfree)
{ {
log_debug("INFINITY_ND_generate_lfree\n");
int rval = 0; int rval = 0;
int nrows = model->nrows; int nrows = model->nrows;
int nrays = model->rays.nrays; int nrays = model->rays.nrays;
@ -1245,24 +1275,6 @@ int INFINITY_ND_generate_lfree(const struct MultiRowModel *model,
int it = 0; int it = 0;
//lp_time = 0;
//lp_count = 0;
//epsilon_lp_count = 0;
//epsilon_lp_time = 0;
//
//sfree_mip_count = 0;
//sfree_mip_time = 0;
//tight_lp_count = 0;
//tight_lp_time = 0;
//violated_lp_count = 0;
//violated_lp_time = 0;
//scale_ahull_lp_time = 0;
//scale_ahull_lp_count = 0;
long x_count = 0; long x_count = 0;
double epsilon; double epsilon;
@ -1285,7 +1297,7 @@ int INFINITY_ND_generate_lfree(const struct MultiRowModel *model,
while(1) while(1)
{ {
log_debug(" epsilon = %.8lf\n", epsilon); log_debug(" epsilon: %.8lf\n", epsilon);
int found = 0; int found = 0;
@ -1305,8 +1317,14 @@ int INFINITY_ND_generate_lfree(const struct MultiRowModel *model,
if(!found) break; if(!found) break;
} }
log_debug(" found interior point:\n"); if_debug_level {
for(int i = 0; i < nrows; i++) log_debug(" %.2lf\n", x[i]); time_printf(" found interior point:\n");
time_printf(" x: ");
for (int i = 0; i < nrows; i++)
printf("%.2lf ", x[i]);
printf("\n");
}
x_count++; x_count++;
abort_if(x_count > 1000, "infinite loop"); abort_if(x_count > 1000, "infinite loop");
@ -1317,7 +1335,7 @@ int INFINITY_ND_generate_lfree(const struct MultiRowModel *model,
abort_if(rval, "bound failed"); abort_if(rval, "bound failed");
abort_if(isinf(epsilon_x), "epsilon_x is infinite"); abort_if(isinf(epsilon_x), "epsilon_x is infinite");
log_debug(" epsilon_x = %.8lf\n", epsilon_x); log_debug(" epsilon_x: %.8lf\n", epsilon_x);
if(DOUBLE_eq(epsilon_x, epsilon)) if(DOUBLE_eq(epsilon_x, epsilon))
{ {
@ -1337,6 +1355,7 @@ int INFINITY_ND_generate_lfree(const struct MultiRowModel *model,
int skip_ahull = 0; int skip_ahull = 0;
log_debug(" updating beta:\n");
for(int i = 0; i < nrays; i++) for(int i = 0; i < nrays; i++)
{ {
if(t[i]) if(t[i])
@ -1361,10 +1380,8 @@ int INFINITY_ND_generate_lfree(const struct MultiRowModel *model,
beta[i] = min(beta[i], alpha); beta[i] = min(beta[i], alpha);
} }
log_debug(" beta[%2d] = %20.12lf\n", i, beta[i]); log_debug(" beta[%2d]: %20.12lf\n", i, beta[i]);
} }
log_debug("epsilon = %.6lf\n", epsilon);
} }
log_debug(" %6ld lattice points, %ld iterations\n", x_count, it); log_debug(" %6ld lattice points, %ld iterations\n", x_count, it);

@ -27,6 +27,7 @@ extern "C" {
#include "../src/infinity-nd.c" #include "../src/infinity-nd.c"
} }
const double E = 1e-6;
TEST(InfinityNDTest, find_violated_cone_test) TEST(InfinityNDTest, find_violated_cone_test)
{ {
@ -164,11 +165,11 @@ TEST(InfinityNDTest, cone_bound_test_1)
rval = cone_bound(2, 6, f, rays, rx1, x, beta, &epsilon); rval = cone_bound(2, 6, f, rays, rx1, x, beta, &epsilon);
abort_if(rval, "cone_bound failed"); abort_if(rval, "cone_bound failed");
EXPECT_NEAR(0.5, epsilon, 1e-6); EXPECT_NEAR(0.5, epsilon, E);
rval = cone_bound(2, 6, f, rays, rx2, x, beta, &epsilon); rval = cone_bound(2, 6, f, rays, rx2, x, beta, &epsilon);
abort_if(rval, "cone_bound failed"); abort_if(rval, "cone_bound failed");
EXPECT_NEAR(1.0, epsilon, 1e-6); EXPECT_NEAR(1.0, epsilon, E);
CLEANUP: CLEANUP:
if(rval) FAIL(); if(rval) FAIL();
@ -197,7 +198,7 @@ TEST(InfinityNDTest, cone_bound_test_2)
rval = cone_bound(2, 2, f, rays, rx, x1, beta1, &epsilon); rval = cone_bound(2, 2, f, rays, rx, x1, beta1, &epsilon);
abort_if(rval, "cone_bound failed"); abort_if(rval, "cone_bound failed");
EXPECT_NEAR(1.0, epsilon, 1e-6); EXPECT_NEAR(1.0, epsilon, E);
rval = cone_bound(2, 2, f, rays, rx, x1, beta2, &epsilon); rval = cone_bound(2, 2, f, rays, rx, x1, beta2, &epsilon);
abort_if(rval, "cone_bound failed"); abort_if(rval, "cone_bound failed");
@ -205,7 +206,7 @@ TEST(InfinityNDTest, cone_bound_test_2)
rval = cone_bound(2, 2, f, rays, rx, x2, beta2, &epsilon); rval = cone_bound(2, 2, f, rays, rx, x2, beta2, &epsilon);
abort_if(rval, "cone_bound failed"); abort_if(rval, "cone_bound failed");
EXPECT_NEAR(1.0, epsilon, 1e-6); EXPECT_NEAR(1.0, epsilon, E);
rval = cone_bound(2, 2, f, rays, rx, x2, beta3, &epsilon); rval = cone_bound(2, 2, f, rays, rx, x2, beta3, &epsilon);
abort_if(rval, "cone_bound failed"); abort_if(rval, "cone_bound failed");
@ -239,7 +240,7 @@ TEST(InfinityNDTest, bound_test_1)
rval = bound(2, 6, f, rays, x, beta1, &epsilon, tx); rval = bound(2, 6, f, rays, x, beta1, &epsilon, tx);
abort_if(rval, "bound failed"); abort_if(rval, "bound failed");
EXPECT_NEAR(epsilon, 0.5, 1e-6); EXPECT_NEAR(epsilon, 0.5, E);
EXPECT_TRUE(tx[0]); EXPECT_TRUE(tx[0]);
EXPECT_FALSE(tx[1]); EXPECT_FALSE(tx[1]);
EXPECT_FALSE(tx[2]); EXPECT_FALSE(tx[2]);
@ -249,7 +250,7 @@ TEST(InfinityNDTest, bound_test_1)
rval = bound(2, 6, f, rays, x, beta2, &epsilon, tx); rval = bound(2, 6, f, rays, x, beta2, &epsilon, tx);
abort_if(rval, "bound failed"); abort_if(rval, "bound failed");
EXPECT_NEAR(epsilon, 1.0, 1e-6); EXPECT_NEAR(epsilon, 1.0, E);
EXPECT_TRUE(tx[0]); EXPECT_TRUE(tx[0]);
EXPECT_FALSE(tx[1]); EXPECT_FALSE(tx[1]);
EXPECT_FALSE(tx[2]); EXPECT_FALSE(tx[2]);
@ -308,11 +309,11 @@ TEST(InfinityNDTest, psi_test)
rval = INFINITY_psi(2, q1, 1.0, &lp, &value); rval = INFINITY_psi(2, q1, 1.0, &lp, &value);
abort_if(rval, "GREDDY_ND_psi failed"); abort_if(rval, "GREDDY_ND_psi failed");
EXPECT_NEAR(value, 2.0, 1e-6); EXPECT_NEAR(value, 2.0, E);
rval = INFINITY_psi(2, q2, 2.0, &lp, &value); rval = INFINITY_psi(2, q2, 2.0, &lp, &value);
abort_if(rval, "GREDDY_ND_psi failed"); abort_if(rval, "GREDDY_ND_psi failed");
EXPECT_NEAR(value, 8.0, 1e-6); EXPECT_NEAR(value, 8.0, E);
CLEANUP: CLEANUP:
LP_free(&lp); LP_free(&lp);
@ -360,11 +361,11 @@ TEST(InfinityNDTest, psi_test_2)
rval = INFINITY_psi(3, q1, 1.0, &lp, &value); rval = INFINITY_psi(3, q1, 1.0, &lp, &value);
abort_if(rval, "GREDDY_ND_psi failed"); abort_if(rval, "GREDDY_ND_psi failed");
EXPECT_NEAR(value, 1.0, 1e-6); EXPECT_NEAR(value, 1.0, E);
rval = INFINITY_psi(3, q2, 1.0, &lp, &value); rval = INFINITY_psi(3, q2, 1.0, &lp, &value);
abort_if(rval, "GREDDY_ND_psi failed"); abort_if(rval, "GREDDY_ND_psi failed");
EXPECT_NEAR(value, 2.0, 1e-6); EXPECT_NEAR(value, 2.0, E);
CLEANUP: CLEANUP:
if(rval) FAIL(); if(rval) FAIL();
@ -411,13 +412,13 @@ TEST(InfinityNDTest, psi_test_3)
rval = INFINITY_psi(lfree.nrows, q, 1.0, &lp, &value); rval = INFINITY_psi(lfree.nrows, q, 1.0, &lp, &value);
abort_if(rval, "GREDDY_ND_psi failed"); abort_if(rval, "GREDDY_ND_psi failed");
EXPECT_NEAR(value, 1.0, 1e-6); EXPECT_NEAR(value, 1.0, E);
CLEANUP: CLEANUP:
if(rval) FAIL(); if(rval) FAIL();
} }
TEST(InfinityNDTest, generate_cut_test_1) TEST(DISABLED_InfinityNDTest, generate_cut_test_1)
{ {
int rval = 0; int rval = 0;
@ -445,12 +446,12 @@ TEST(InfinityNDTest, generate_cut_test_1)
rval = INFINITY_ND_generate_lfree(&model, &lfree); rval = INFINITY_ND_generate_lfree(&model, &lfree);
abort_if(rval, "INFINITY_ND_generate_lfree failed"); abort_if(rval, "INFINITY_ND_generate_lfree failed");
EXPECT_NEAR(lfree.beta[0], 0.5, 1e-6); EXPECT_NEAR(lfree.beta[0], 0.5, E);
EXPECT_NEAR(lfree.beta[1], 0.5, 1e-6); EXPECT_NEAR(lfree.beta[1], 0.5, E);
EXPECT_NEAR(lfree.beta[2], 0.5, 1e-6); EXPECT_NEAR(lfree.beta[2], 0.5, E);
EXPECT_NEAR(lfree.beta[3], 0.5, 1e-6); EXPECT_NEAR(lfree.beta[3], 0.5, E);
EXPECT_NEAR(lfree.beta[4], 1.0, 1e-6); EXPECT_NEAR(lfree.beta[4], 1.0, E);
EXPECT_NEAR(lfree.beta[5], 1.0, 1e-6); EXPECT_NEAR(lfree.beta[5], 1.0, E);
CLEANUP: CLEANUP:
if(rval) FAIL(); if(rval) FAIL();
@ -485,12 +486,12 @@ TEST(InfinityNDTest, generate_cut_test_2)
rval = INFINITY_ND_generate_lfree(&model, &lfree); rval = INFINITY_ND_generate_lfree(&model, &lfree);
abort_if(rval, "INFINITY_ND_generate_lfree failed"); abort_if(rval, "INFINITY_ND_generate_lfree failed");
EXPECT_NEAR(lfree.beta[0], 0.75, 1e-6); EXPECT_NEAR(lfree.beta[0], 0.75, E);
EXPECT_NEAR(lfree.beta[1], 2.25, 1e-6); EXPECT_NEAR(lfree.beta[1], 2.25, E);
EXPECT_NEAR(lfree.beta[2], 0.75, 1e-6); EXPECT_NEAR(lfree.beta[2], 0.75, E);
EXPECT_NEAR(lfree.beta[3], 2.25, 1e-6); EXPECT_NEAR(lfree.beta[3], 2.25, E);
EXPECT_NEAR(lfree.beta[4], 0.75, 1e-6); EXPECT_NEAR(lfree.beta[4], 0.75, E);
EXPECT_NEAR(lfree.beta[5], 2.25, 1e-6); EXPECT_NEAR(lfree.beta[5], 2.25, E);
CLEANUP: CLEANUP:
CG_free_model(&model); CG_free_model(&model);
@ -534,3 +535,68 @@ TEST(InfinityNDTest, scale_to_ahull_test)
CLEANUP: CLEANUP:
if(rval) FAIL(); if(rval) FAIL();
} }
TEST(InfinityNDTest, cone_bound_find_lambda_test)
{
int rval = 0;
double f[] = { 1/2.0, 1/3.0 };
double x[] = { 3.0, 3.0 };
double ray_values[] = {
1.0, 2.0,
3.0, 2.0,
};
struct RayList rays = {.values = ray_values, .nrays = 2, .dim = 2};
double lambda[2];
rval = cone_bound_find_lambda(&rays, f, x, lambda);
abort_if(rval, "cone_bound_find_lambda failed");
EXPECT_NEAR(lambda[0], 3/4.0, E);
EXPECT_NEAR(lambda[1], 7/12.0, E);
CLEANUP:
if(rval) FAIL();
}
TEST(InfinityNDTest, cone_bound_find_lambda_test_2)
{
int rval = 0;
double f[] = { 1/2.0, 1/3.0, 5/6.0 };
double x[] = { 3.0, 3.0, 6.0 };
double ray_values[] = {
1.0, 2.0, 3.0,
3.0, 2.0, 5.0,
};
struct RayList rays = {.values = ray_values, .nrays = 2, .dim = 3};
double lambda[2];
rval = cone_bound_find_lambda(&rays, f, x, lambda);
abort_if(rval, "cone_bound_find_lambda failed");
EXPECT_NEAR(lambda[0], 3/4.0, E);
EXPECT_NEAR(lambda[1], 7/12.0, E);
CLEANUP:
if(rval) FAIL();
}
TEST(InfinityNDTest, cone_bound_find_lambda_test_3)
{
int rval = 0;
double f[] = { 1/2.0, 1/2.0 };
double x[] = { 3.0, 3.0 };
double ray_values[] = {
0.0, -1.0,
-1.0, 0.0,
};
struct RayList rays = {.values = ray_values, .nrays = 2, .dim = 2};
double lambda[2];
rval = cone_bound_find_lambda(&rays, f, x, lambda);
EXPECT_NE(rval, 0);
}

@ -571,7 +571,7 @@ CLEANUP:
if (rval) FAIL(); if (rval) FAIL();
} }
TEST(InfinityTest, generate_cut_test_14) TEST(DISABLED_InfinityTest, generate_cut_test_14)
{ {
int rval = 0; int rval = 0;

@ -17,9 +17,6 @@ if [ ! -f $RUN ]; then
fi fi
INSTANCES="instances/filtered/all.txt" INSTANCES="instances/filtered/all.txt"
SAMPLES_SLOW=10
SAMPLES_MEDIUM=100
SAMPLES_FAST=1000
SEED=1240 SEED=1240
# ORIGINAL # ORIGINAL
@ -36,29 +33,29 @@ DIR=orig-100
mkdir -p $DIR; rm -f $DIR/*log $DIR/*yaml mkdir -p $DIR; rm -f $DIR/*log $DIR/*yaml
title Heuristic title Heuristic
$RUN $COMMON_OPTS --samples $SAMPLES_FAST --heuristic --log $DIR/heur.log --stats $DIR/heur.yaml || exit $RUN $COMMON_OPTS --samples 100000 --heuristic --log $DIR/heur.log --stats $DIR/heur.yaml || exit
title Bound Original title Bound Original
$RUN $COMMON_OPTS --samples $SAMPLES_FAST --bound --log $DIR/bound.log --stats $DIR/bound.yaml || exit $RUN $COMMON_OPTS --samples 1000 --bound --log $DIR/bound.log --stats $DIR/bound.yaml || exit
title Bound Pre-processing title Bound Pre-processing
$RUN $COMMON_OPTS --samples $SAMPLES_FAST --bound --preprocess --log $DIR/bound-pre.log --stats $DIR/bound-pre.yaml || exit $RUN $COMMON_OPTS --samples 1000 --bound --preprocess --log $DIR/bound-pre.log --stats $DIR/bound-pre.yaml || exit
title Naive Bounding-Box title Naive Bounding-Box
$RUN $COMMON_OPTS --samples $SAMPLES_MEDIUM --naive --log $DIR/naive-bbox.log --stats $DIR/naive-bbox.yaml || exit $RUN $COMMON_OPTS --samples 100 --naive --log $DIR/naive-bbox.log --stats $DIR/naive-bbox.yaml || exit
title Naive Fixed-M title Naive Fixed-M
M=50 M=50
$RUN $COMMON_OPTS --samples $SAMPLES_SLOW --naive --fixed-bounds $M --log $DIR/naive-fixed-$M.log --stats $DIR/naive-fixed-$M.yaml || exit $RUN $COMMON_OPTS --samples 100 --naive --fixed-bounds $M --log $DIR/naive-fixed-$M.log --stats $DIR/naive-fixed-$M.yaml || exit
title Naive Bounding-Box Pre-processing 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 $RUN $COMMON_OPTS --samples 100 --naive --preprocess --log $DIR/naive-bbox-pre.log --stats $DIR/naive-bbox-pre.yaml || exit
title MIP title MIP
$RUN $COMMON_OPTS --samples $SAMPLES_SLOW --mip --log $DIR/mip.log --stats $DIR/mip.yaml || exit $RUN $COMMON_OPTS --samples 10 --mip --log $DIR/mip.log --stats $DIR/mip.yaml || exit
title MIP Pre-processing title MIP Pre-processing
$RUN $COMMON_OPTS --samples $SAMPLES_SLOW --mip --preprocess --log $DIR/mip-pre.log --stats $DIR/mip-pre.yaml || exit $RUN $COMMON_OPTS --samples 10 --mip --preprocess --log $DIR/mip-pre.log --stats $DIR/mip-pre.yaml || exit
# SHEAR # SHEAR
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
@ -73,21 +70,28 @@ COMMON_OPTS="$COMMON_OPTS --check-answers $ANSWERS"
DIR=shear-100 DIR=shear-100
mkdir -p $DIR; rm -f $DIR/*log $DIR/*yaml mkdir -p $DIR; rm -f $DIR/*log $DIR/*yaml
title Bound Pre-processing + Shear title Heuristic + Shear
$RUN $COMMON_OPTS --samples $SAMPLES_FAST --bound --preprocess --log $DIR/bound-pre.log --stats $DIR/bound-pre.yaml || exit $RUN $COMMON_OPTS --samples 100000 --heuristic --log $DIR/heur.log --stats $DIR/heur.yaml || exit
title Bound Original + Shear title Bound Original + Shear
$RUN $COMMON_OPTS --samples $SAMPLES_MEDIUM --bound --log $DIR/bound.log --stats $DIR/bound.yaml || exit $RUN $COMMON_OPTS --samples 1000 --bound --log $DIR/bound.log --stats $DIR/bound.yaml || exit
title Bound Pre-processing + Shear
$RUN $COMMON_OPTS --samples 1000 --bound --preprocess --log $DIR/bound-pre.log --stats $DIR/bound-pre.yaml || exit
title Naive Bounding-Box + Shear title Naive Bounding-Box + Shear
$RUN $COMMON_OPTS --samples $SAMPLES_SLOW --naive --log $DIR/naive-bbox.log --stats $DIR/naive-bbox.yaml || exit $RUN $COMMON_OPTS --samples 10 --naive --log $DIR/naive-bbox.log --stats $DIR/naive-bbox.yaml || exit
title Naive Fixed-M + Shear title Naive Fixed-M + Shear
M=50 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 100 --naive --fixed-bounds $M --log $DIR/naive-fixed-$M.log --stats $DIR/naive-fixed-$M.yaml || exit
title MIP + Shear
$RUN $COMMON_OPTS --samples 10 --mip --log $DIR/mip.log --stats $DIR/mip.yaml || exit
title MIP Pre-processing + Shear
$RUN $COMMON_OPTS --samples 10 --mip --preprocess --log $DIR/mip-pre.log --stats $DIR/mip-pre.yaml || exit
title MIP
$RUN $COMMON_OPTS --samples $SAMPLES_SLOW --mip --log $DIR/mip.log --stats $DIR/mip.yaml || exit
# TABLES # TABLES
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------

@ -1,33 +1,43 @@
set(COMMON_SOURCES set(COMMON_SOURCES
src/cg.c src/cg.c
src/double.c src/double.c
src/geometry.c src/geometry.c
src/lfree2d.c src/lfree2d.c
src/lp.c src/lp.c
src/mir.c src/mir.c
src/util.c src/util.c
src/rational.c src/rational.c
src/stats.c src/stats.c
include/multirow/cg.h src/linalg.c
include/multirow/double.h include/multirow/cg.h
include/multirow/geometry.h include/multirow/double.h
include/multirow/lfree2d.h include/multirow/geometry.h
include/multirow/lp.h include/multirow/lfree2d.h
include/multirow/mir.h include/multirow/lp.h
include/multirow/rational.h include/multirow/mir.h
include/multirow/stats.h include/multirow/rational.h
include/multirow/params.h include/multirow/stats.h
include/multirow/util.h) include/multirow/params.h
include/multirow/util.h
include/multirow/linalg.h)
set(TEST_SOURCES set(TEST_SOURCES
tests/double-test.cpp tests/double-test.cpp
tests/cg-test.cpp tests/cg-test.cpp
tests/geometry-test.cpp) tests/geometry-test.cpp
tests/linalg-test.cpp)
add_library(multirow_static ${COMMON_SOURCES}) add_library(multirow_static ${COMMON_SOURCES})
set_target_properties(multirow_static PROPERTIES OUTPUT_NAME lifting) set_target_properties(multirow_static PROPERTIES OUTPUT_NAME lifting)
target_link_libraries(multirow_static ${CPLEX_LIBRARIES}) target_link_libraries(multirow_static
target_include_directories (multirow_static PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) ${CPLEX_LIBRARIES}
${BLAS_LIBRARIES}
${LAPACKE_LIBRARIES})
target_include_directories(multirow_static PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
add_executable(multirow-test.run ${COMMON_SOURCES} ${TEST_SOURCES}) add_executable(multirow-test.run ${COMMON_SOURCES} ${TEST_SOURCES})
target_link_libraries(multirow-test.run ${CPLEX_LIBRARIES} gtest_main) target_link_libraries(multirow-test.run
${CPLEX_LIBRARIES}
${BLAS_LIBRARIES}
${LAPACKE_LIBRARIES}
gtest_main)

@ -0,0 +1,40 @@
/* Copyright (c) 2015-2017 Alinson Xavier
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
/**
* Receives an n-dimensional vector x, a scalar alpha and sets x <- alpha * x
*/
void LINALG_scale(int n, double *x, double alpha);
/**
* Receives two n-dimensional vectors x and y and returns the dot product of x
* and y.
*/
double LINALG_dot(int n, double *x, double *y);
/**
* Receives an n-dimensional vector x and returns the 1-norm of x.
*/
double LINALG_norm(int n, double *x);
/**
* Given a full rank m-by-n matrix A and an m-dimensional vector b, this
* function finds x such that Ax = b. Returns zero if the operation is
* successful and non-zero otherwise.
*/
int LINALG_solve(int n, int m, double *A, double *b, double *x);

@ -78,6 +78,7 @@ void time_printf(const char *fmt,
#define UNUSED(x) (void)(x) #define UNUSED(x) (void)(x)
#define min(x,y) ((x) < (y) ? (x) : (y)) #define min(x,y) ((x) < (y) ? (x) : (y))
#define max(x,y) ((x) > (y) ? (x) : (y))
#define sign(x) ((x) > 0 ? 1 : ((x) < 0 ? -1 : 0)) #define sign(x) ((x) > 0 ? 1 : ((x) < 0 ? -1 : 0))
#define swap(x, y, T) do { T SWAP = x; x = y; y = SWAP; } while (0) #define swap(x, y, T) do { T SWAP = x; x = y; y = SWAP; } while (0)

@ -0,0 +1,52 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <math.h>
#include <cblas.h>
#include <lapacke.h>
#include <multirow/util.h>
void LINALG_scale(int n, double *x, double alpha)
{
cblas_dscal(n, alpha, x, 1);
}
double LINALG_dot(int n, double *x, double *y)
{
return cblas_ddot(n, x, 1, y, 1);
}
double LINALG_norm(int n, double *x)
{
return cblas_dasum(n, x, 1);
}
int LINALG_solve(int n, int m, double *A, double *b, double *x)
{
int rval = 0;
double A_copy[n * m];
memcpy(x, b, m * sizeof(double));
memcpy(A_copy, A, n * m * sizeof(double));
LAPACKE_dgels(LAPACK_ROW_MAJOR, 'N', m, n, 1, A_copy, n, x, 1);
abort_if(rval, "LAPACKE_dgesv failed");
CLEANUP:
return rval;
}

@ -0,0 +1,107 @@
/* Copyright (c) 2015-2017 Alinson Xavier
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <gtest/gtest.h>
extern "C" {
#include <multirow/util.h>
#include <multirow/linalg.h>
}
const double E = 1e-6;
TEST(LinAlgTest, scale_test)
{
double x[] = {1.0, 2.0, 3.0};
LINALG_scale(3, x, 2.0);
EXPECT_NEAR(x[0], 2.0, E);
EXPECT_NEAR(x[1], 4.0, E);
EXPECT_NEAR(x[2], 6.0, E);
}
TEST(LinAlgTest, dot_test)
{
double x[] = { 1.0, 2.0, 3.0 };
double y[] = { 3.0, 4.0, 5.0 };
double dot = LINALG_dot(3, x, y);
EXPECT_NEAR(dot, 26.0, E);
}
TEST(LinAlgTest, norm_test)
{
double x[] = { 1.0, 2.0, -3.0 };
double y[] = { 3.0, -4.0, -5.0 };
double x_norm = LINALG_norm(3, x);
double y_norm = LINALG_norm(3, y);
EXPECT_NEAR(x_norm, 6.0, E);
EXPECT_NEAR(y_norm, 12.0, E);
}
TEST(LinAlgTest, solve_test)
{
int rval = 0;
double A[] = {
2.0, 1.0, 3.0,
2.0, 6.0, 8.0,
6.0, 8.0, 18.0,
};
double b[] = { 1.0, 3.0, 5.0 };
double x[] = { 0.0, 0.0, 0.0 };
rval = LINALG_solve(3, 3, A, b, x);
abort_if(rval, "LINALG_solve failed");
// Should compute x correctly
EXPECT_NEAR(x[0], 0.3, E);
EXPECT_NEAR(x[1], 0.4, E);
EXPECT_NEAR(x[2], 0.0, E);
// Should not modify A and b
EXPECT_EQ(A[0], 2.0);
EXPECT_EQ(A[1], 1.0);
EXPECT_EQ(A[2], 3.0);
EXPECT_EQ(b[0], 1.0);
EXPECT_EQ(b[1], 3.0);
EXPECT_EQ(b[2], 5.0);
CLEANUP:
if(rval) FAIL();
}
TEST(LinAlgTest, solve_test_2)
{
int rval = 0;
double A[] = {
1.0, 3.0,
0.0, 0.0,
2.0, 2.0,
3.0, 5.0,
};
double b[] = { 5/2.0, 0.0, 8/3.0, 31/6.0 };
double x[2];
rval = LINALG_solve(2, 4, A, b, x);
abort_if(rval, "LINALG_solve failed");
// Should compute x correctly
EXPECT_NEAR(x[0], 3/4.0, E);
EXPECT_NEAR(x[1], 7/12.0, E);
CLEANUP:
if(rval) FAIL();
}