Create struct ConvLFreeSet

selection
Alinson S. Xavier 9 years ago
parent 3ded5cd96f
commit 1e45817d76

@ -16,12 +16,6 @@
#ifndef MULTIROW_GREEDY_ND_H #ifndef MULTIROW_GREEDY_ND_H
#define MULTIROW_GREEDY_ND_H #define MULTIROW_GREEDY_ND_H
int GREEDY_ND_next_lattice_point(int dim,
const double *lb,
const double *ub,
double *p,
int *finished);
int GREEDY_create_psi_lp(const int nrows, int GREEDY_create_psi_lp(const int nrows,
const int nrays, const int nrays,
const double *f, const double *f,
@ -49,16 +43,8 @@ int GREEDY_ND_pi(const int nrows,
struct LP *lp, struct LP *lp,
double *value); double *value);
int GREEDY_ND_generate_cut(const struct MultiRowModel *model, double *beta); int INFINITY_ND_generate_lfree(const struct MultiRowModel *model,
struct ConvLFreeSet *lfree);
int GREEDY_ND_bound(int nrows,
int nrays,
const double *f,
const double *rays,
const double *x,
const double *beta,
double *epsilon,
int *tx);
int GREEDY_ND_cone_bound(int nrows, int GREEDY_ND_cone_bound(int nrows,
int nrays, int nrays,

@ -19,6 +19,7 @@
#include <multirow/cg.h> #include <multirow/cg.h>
int INFINITY_2D_generate_cut(const struct MultiRowModel *model, double *bounds); int INFINITY_2D_generate_lfree(const struct MultiRowModel *model,
struct ConvLFreeSet *lfree);
#endif //MULTIROW_INFINITY_2D_H #endif //MULTIROW_INFINITY_2D_H

File diff suppressed because it is too large Load Diff

@ -524,29 +524,29 @@ CLEANUP:
#ifndef TEST_SOURCE #ifndef TEST_SOURCE
int INFINITY_2D_generate_cut(const struct MultiRowModel *model, double *bounds) int INFINITY_2D_generate_lfree(const struct MultiRowModel *model,
struct ConvLFreeSet *lfree)
{ {
log_verbose("INFINITY_2D_generate_cut\n");
int rval = 0; int rval = 0;
int count = 0; int count = 0;
int nrays = model->rays.nrays; int nrays = model->rays.nrays;
double *f = model->f;
double *scale = 0; double *scale = 0;
double *rays = 0;
double lb[2], ub[2]; double lb[2], ub[2];
for (int i = 0; i < nrays; i++) double *f = lfree->f;
bounds[i] = GREEDY_BIG_E; double *beta = lfree->beta;
double *rays = lfree->rays.values;
lfree->nrows = 2;
lfree->rays.nrays = nrays;
memcpy(f, model->f, 2 * sizeof(double));
memcpy(rays, model->rays.values, 2 * nrays * sizeof(double));
for (int i = 0; i < nrays; i++) beta[i] = GREEDY_BIG_E;
scale = (double*) malloc(nrays * sizeof(double)); scale = (double*) malloc(nrays * sizeof(double));
rays = (double*) malloc(2 * nrays * sizeof(double));
abort_if(!rays, "could not allocate rays");
abort_if(!scale, "could not allocate scale"); abort_if(!scale, "could not allocate scale");
memcpy(rays, model->rays.values, 2 * nrays * sizeof(double));
rval = scale_to_chull(rays, nrays, scale); rval = scale_to_chull(rays, nrays, scale);
abort_if(rval, "scale_to_chull failed"); abort_if(rval, "scale_to_chull failed");
@ -558,7 +558,7 @@ int INFINITY_2D_generate_cut(const struct MultiRowModel *model, double *bounds)
abort_if(count++ > 2 * nrays, "infinite loop"); abort_if(count++ > 2 * nrays, "infinite loop");
rval = get_bounding_box(2, nrays, rays, bounds, GREEDY_BIG_E, lb, ub); rval = get_bounding_box(2, nrays, rays, beta, GREEDY_BIG_E, lb, ub);
abort_if(rval, "get_bounding_box failed"); abort_if(rval, "get_bounding_box failed");
log_verbose(" box=[%.2lf %.2lf] [%.2lf %.2lf]\n", lb[0], ub[0], lb[1], ub[1]); log_verbose(" box=[%.2lf %.2lf] [%.2lf %.2lf]\n", lb[0], ub[0], lb[1], ub[1]);
@ -581,7 +581,7 @@ int INFINITY_2D_generate_cut(const struct MultiRowModel *model, double *bounds)
log_verbose(" p=%.2lf %.2lf\n", p[0], p[1]); log_verbose(" p=%.2lf %.2lf\n", p[0], p[1]);
rval = bound(rays, bounds, nrays, f, p, &epsilon, v1, v2, &i1, &i2); rval = bound(rays, beta, nrays, f, p, &epsilon, v1, v2, &i1, &i2);
abort_if(rval, "bound failed"); abort_if(rval, "bound failed");
log_verbose(" epsilon=%.2lf\n", epsilon); log_verbose(" epsilon=%.2lf\n", epsilon);
@ -590,7 +590,7 @@ int INFINITY_2D_generate_cut(const struct MultiRowModel *model, double *bounds)
{ {
log_verbose(" found smaller epsilon: %.8lf\n", epsilon); log_verbose(" found smaller epsilon: %.8lf\n", epsilon);
rval = get_bounding_box(2, nrays, rays, bounds, epsilon, lb, ub); rval = get_bounding_box(2, nrays, rays, beta, epsilon, lb, ub);
abort_if(rval, "get_bounding_box failed"); abort_if(rval, "get_bounding_box failed");
log_verbose(" p=%.2lf %.2lf\n", p[0], p[1]); log_verbose(" p=%.2lf %.2lf\n", p[0], p[1]);
@ -625,11 +625,11 @@ int INFINITY_2D_generate_cut(const struct MultiRowModel *model, double *bounds)
break; break;
} }
log_verbose(" updating bounds\n"); log_verbose(" updating beta\n");
if(isinf(best_v1[0])) if(isinf(best_v1[0]))
{ {
bounds[best_i1] = best_epsilon; beta[best_i1] = best_epsilon;
log_verbose(" bounds[%d]=%.8lf (exact)\n", best_i1, best_epsilon); log_verbose(" beta[%d]=%.8lf (exact)\n", best_i1, best_epsilon);
} }
else else
{ {
@ -646,15 +646,15 @@ int INFINITY_2D_generate_cut(const struct MultiRowModel *model, double *bounds)
if(!DOUBLE_geq(lambda, 0)) continue; if(!DOUBLE_geq(lambda, 0)) continue;
bounds[i] = fmin(bounds[i], lambda); beta[i] = fmin(beta[i], lambda);
log_verbose(" bounds[%d]=%.8lf\n", i, bounds[i]); log_verbose(" beta[%d]=%.8lf\n", i, beta[i]);
} }
} }
//if(count > 0) //if(count > 0)
//{ //{
// for (int i = 0; i < nrays; i++) // for (int i = 0; i < nrays; i++)
// bounds[i] = fmin(bounds[i], best_epsilon); // beta[i] = fmin(beta[i], best_epsilon);
// break; // break;
//} //}
@ -663,7 +663,7 @@ int INFINITY_2D_generate_cut(const struct MultiRowModel *model, double *bounds)
for (int k = 0; k < nrays; k++) for (int k = 0; k < nrays; k++)
{ {
if(bounds[k] < 100) continue; if(beta[k] < 100) continue;
is_split = 1; is_split = 1;
double *split_direction = &rays[2 * k]; double *split_direction = &rays[2 * k];
@ -700,13 +700,13 @@ int INFINITY_2D_generate_cut(const struct MultiRowModel *model, double *bounds)
{ {
const double *r = &rays[2 * i]; const double *r = &rays[2 * i];
lhs = (f[0] + r[0] * bounds[i]) * pi[0]; lhs = (f[0] + r[0] * beta[i]) * pi[0];
lhs += (f[1] + r[1] * bounds[i]) * pi[1]; lhs += (f[1] + r[1] * beta[i]) * pi[1];
if (!(DOUBLE_leq(pi_zero, lhs) && DOUBLE_leq(lhs, pi_zero+1))) if (!(DOUBLE_leq(pi_zero, lhs) && DOUBLE_leq(lhs, pi_zero+1)))
{ {
log_verbose(" point %.4lf %.4lf falls outside of the split\n", log_verbose(" point %.4lf %.4lf falls outside of the split\n",
f[0] + r[0]*bounds[i], f[1] + r[1] * bounds[i]); f[0] + r[0]*beta[i], f[1] + r[1] * beta[i]);
is_split = 0; is_split = 0;
} }
} }
@ -722,11 +722,10 @@ int INFINITY_2D_generate_cut(const struct MultiRowModel *model, double *bounds)
} }
for(int i=0; i<nrays; i++) for(int i=0; i<nrays; i++)
bounds[i] *= scale[i]; beta[i] *= scale[i];
CLEANUP: CLEANUP:
if(scale) free(scale); if(scale) free(scale);
if(rays) free(rays);
return rval; return rval;
} }

@ -85,30 +85,25 @@ CLEANUP:
return rval; return rval;
} }
static int create_cut(const struct Tableau *tableau, static int create_cut_from_lfree(const struct Tableau *tableau,
const struct RayMap *map, const struct RayMap *map,
const struct MultiRowModel *model, const struct ConvLFreeSet *lfree,
const double *beta, struct Row *cut)
struct Row *cut)
{ {
int rval = 0; int rval = 0;
struct LP lp;
int nvars = map->nvars; int nvars = map->nvars;
int nrows = tableau->nrows; int nrows = tableau->nrows;
cut->nz = nvars;
cut->pi = (double *) malloc(nvars * sizeof(double));
cut->indices = (int *) malloc(nvars * sizeof(int));
abort_if(!cut->pi, "could not allocate cut->pi");
abort_if(!cut->indices, "could not allocate cut->indices");
struct LP lp;
rval = LP_open(&lp); rval = LP_open(&lp);
abort_if(rval, "LP_open failed"); abort_if(rval, "LP_open failed");
rval = GREEDY_create_psi_lp(nrows, model->rays.nrays, model->f, rval = GREEDY_create_psi_lp(nrows, lfree->rays.nrays, lfree->f,
model->rays.values, beta, &lp); lfree->rays.values, lfree->beta, &lp);
abort_if(rval, "create_psi_lp failed"); abort_if(rval, "create_psi_lp failed");
cut->nz = nvars;
for(int i = 0; i < nvars; i++) for(int i = 0; i < nvars; i++)
{ {
double value; double value;
@ -117,15 +112,15 @@ static int create_cut(const struct Tableau *tableau,
if(ENABLE_LIFTING && if(ENABLE_LIFTING &&
tableau->column_types[map->indices[i]] == MILP_INTEGER) tableau->column_types[map->indices[i]] == MILP_INTEGER)
{ {
rval = GREEDY_ND_pi(nrows, model->rays.nrays, model->f, rval = GREEDY_ND_pi(nrows, lfree->rays.nrays, lfree->f,
model->rays.values, beta, q, map->ray_scale[i], &lp, lfree->rays.values, lfree->beta, q, map->ray_scale[i], &lp,
&value); &value);
abort_if(rval, "GREEDY_ND_pi failed"); abort_if(rval, "GREEDY_ND_pi failed");
} }
else else
{ {
rval = GREEDY_ND_psi(nrows, model->rays.nrays, model->f, rval = GREEDY_ND_psi(nrows, lfree->rays.nrays, lfree->f,
model->rays.values, beta, q, map->ray_scale[i], &lp, lfree->rays.values, lfree->beta, q, map->ray_scale[i], &lp,
&value); &value);
abort_if(rval, "GREEDY_ND_psi failed"); abort_if(rval, "GREEDY_ND_psi failed");
} }
@ -146,7 +141,7 @@ CLEANUP:
return rval; return rval;
} }
static int select_rays(const struct RayMap *map, static int filter_rays(const struct RayMap *map,
const struct Tableau *tableau, const struct Tableau *tableau,
struct MultiRowModel *model) struct MultiRowModel *model)
{ {
@ -166,8 +161,8 @@ static int select_rays(const struct RayMap *map,
for(int j = 0; j < (rays->nrays); j++) for(int j = 0; j < (rays->nrays); j++)
{ {
double *q = LFREE_get_ray(&map->rays, j); double *q = LFREE_get_ray(&map->rays, j);
double norm = 0;
double norm = 0;
for(int k = 0; k < nrows; k++) for(int k = 0; k < nrows; k++)
norm += fabs(r[k] - q[k]); norm += fabs(r[k] - q[k]);
@ -182,7 +177,7 @@ static int select_rays(const struct RayMap *map,
} }
log_debug(" norm_cutoff=%8.2lf nrays=%8d\n", norm_cutoff, log_debug(" norm_cutoff=%8.2lf nrays=%8d\n", norm_cutoff,
model->nrays); model->rays.nrays);
if(rays->nrays < MAX_N_RAYS) break; if(rays->nrays < MAX_N_RAYS) break;
} }
@ -253,7 +248,7 @@ CLEANUP:
} }
static int write_sage_file(const struct MultiRowModel *model, static int write_sage_file(const struct MultiRowModel *model,
const double *beta, const struct ConvLFreeSet *lfree,
const char *filename) const char *filename)
{ {
int rval = 0; int rval = 0;
@ -280,7 +275,7 @@ static int write_sage_file(const struct MultiRowModel *model,
fprintf(fsage, "pi=vector([\n"); fprintf(fsage, "pi=vector([\n");
for(int k = 0; k < model->rays.nrays; k++) for(int k = 0; k < model->rays.nrays; k++)
fprintf(fsage, " %.12lf,\n", 1 / beta[k]); fprintf(fsage, " %.12lf,\n", 1 / lfree->beta[k]);
fprintf(fsage, "])\n"); fprintf(fsage, "])\n");
CLEANUP: CLEANUP:
@ -288,7 +283,8 @@ CLEANUP:
return rval; return rval;
} }
static int dump_cut(const struct MultiRowModel *model, const double *beta) static int dump_cut(const struct MultiRowModel *model,
const struct ConvLFreeSet *lfree)
{ {
int rval = 0; int rval = 0;
@ -296,7 +292,7 @@ static int dump_cut(const struct MultiRowModel *model, const double *beta)
sprintf(filename, "cut-%03d.sage", DUMP_CUT_N++); sprintf(filename, "cut-%03d.sage", DUMP_CUT_N++);
time_printf("Writing %s...\n", filename); time_printf("Writing %s...\n", filename);
rval = write_sage_file(model, beta, filename); rval = write_sage_file(model, lfree, filename);
abort_if(rval, "write_sage_file failed"); abort_if(rval, "write_sage_file failed");
CLEANUP: CLEANUP:
@ -315,8 +311,8 @@ static int extract_model_from_tableau(const struct Tableau *tableau,
rval = CG_extract_rays_from_tableau(tableau, map); rval = CG_extract_rays_from_tableau(tableau, map);
abort_if(rval, "CG_extract_rays_from_rows failed"); abort_if(rval, "CG_extract_rays_from_rows failed");
rval = select_rays(map, tableau, model); rval = filter_rays(map, tableau, model);
abort_if(rval, "select_rays failed"); abort_if(rval, "filter_rays failed");
if(ENABLE_LIFTING) if(ENABLE_LIFTING)
{ {
@ -339,16 +335,16 @@ CLEANUP:
int INFINITY_generate_cut(const struct Tableau *tableau, struct Row *cut) int INFINITY_generate_cut(const struct Tableau *tableau, struct Row *cut)
{ {
int rval = 0; int rval = 0;
int nrows = tableau->nrows;
int max_nrays = CG_total_nz(tableau); int max_nrays = CG_total_nz(tableau);
double *beta = 0;
struct RayMap map;
struct MultiRowModel model; struct MultiRowModel model;
rval = CG_malloc_model(&model, nrows, max_nrays + 100); struct ConvLFreeSet lfree;
abort_if(rval, "CG_malloc_model failed");
struct RayMap map; rval = CG_init_model(&model, tableau->nrows, max_nrays + 100);
rval = CG_init_ray_map(&map, max_nrays, nrows); abort_if(rval, "CG_init_model failed");
rval = CG_init_ray_map(&map, max_nrays, tableau->nrows);
abort_if(rval, "CG_init_ray_map failed"); abort_if(rval, "CG_init_ray_map failed");
rval = extract_model_from_tableau(tableau, &model, &map); rval = extract_model_from_tableau(tableau, &model, &map);
@ -357,16 +353,16 @@ int INFINITY_generate_cut(const struct Tableau *tableau, struct Row *cut)
if(model.rays.nrays < 3) if(model.rays.nrays < 3)
{ {
rval = ERR_NO_CUT; rval = ERR_NO_CUT;
cut->pi = 0;
cut->indices = 0;
goto CLEANUP; goto CLEANUP;
} }
beta = (double *) malloc(model.rays.nrays * sizeof(double)); rval = LFREE_init_conv(&lfree, tableau->nrows, model.rays.nrays);
abort_if(!beta, "could not allocate beta"); abort_if(rval, "LFREE_init_conv failed");
if(nrows == 2) rval = INFINITY_2D_generate_cut(&model, beta); if(tableau->nrows == 2)
else rval = GREEDY_ND_generate_cut(&model, beta); rval = INFINITY_2D_generate_lfree(&model, &lfree);
else
rval = INFINITY_ND_generate_lfree(&model, &lfree);
if(rval) if(rval)
{ {
@ -376,15 +372,15 @@ int INFINITY_generate_cut(const struct Tableau *tableau, struct Row *cut)
if(SHOULD_DUMP_CUTS) if(SHOULD_DUMP_CUTS)
{ {
rval = dump_cut(&model, beta); rval = dump_cut(&model, &lfree);
abort_if(rval, "dump_cut failed"); abort_if(rval, "dump_cut failed");
} }
rval = create_cut(tableau, &map, &model, beta, cut); rval = create_cut_from_lfree(tableau, &map, &lfree, cut);
abort_if(rval, "create_cut failed"); abort_if(rval, "create_cut_from_lfree failed");
CLEANUP: CLEANUP:
if(beta) free(beta); LFREE_free_conv(&lfree);
CG_free_model(&model); CG_free_model(&model);
CG_free_ray_map(&map); CG_free_ray_map(&map);
return rval; return rval;

@ -25,6 +25,7 @@ extern "C" {
#include <multirow/lfree2d.h> #include <multirow/lfree2d.h>
#include <multirow/cg.h> #include <multirow/cg.h>
#include <infinity/greedy-nd.h> #include <infinity/greedy-nd.h>
#include "../src/greedy-nd.c"
} }
int ENABLE_LIFTING = 0; int ENABLE_LIFTING = 0;
@ -242,8 +243,8 @@ TEST(GreedyNDTest, bound_test_1)
double epsilon; double epsilon;
int tx[6]; int tx[6];
rval = GREEDY_ND_bound(2, 6, f, rays, x, beta1, &epsilon, tx); rval = bound(2, 6, f, rays, x, beta1, &epsilon, tx);
abort_if(rval, "GREEDY_ND_bound failed"); abort_if(rval, "bound failed");
EXPECT_NEAR(epsilon, 0.5, 1e-6); EXPECT_NEAR(epsilon, 0.5, 1e-6);
EXPECT_TRUE(tx[0]); EXPECT_TRUE(tx[0]);
EXPECT_FALSE(tx[1]); EXPECT_FALSE(tx[1]);
@ -252,8 +253,8 @@ TEST(GreedyNDTest, bound_test_1)
EXPECT_FALSE(tx[4]); EXPECT_FALSE(tx[4]);
EXPECT_FALSE(tx[5]); EXPECT_FALSE(tx[5]);
rval = GREEDY_ND_bound(2, 6, f, rays, x, beta2, &epsilon, tx); rval = bound(2, 6, f, rays, x, beta2, &epsilon, tx);
abort_if(rval, "GREEDY_ND_bound failed"); abort_if(rval, "bound failed");
EXPECT_NEAR(epsilon, 1.0, 1e-6); EXPECT_NEAR(epsilon, 1.0, 1e-6);
EXPECT_TRUE(tx[0]); EXPECT_TRUE(tx[0]);
EXPECT_FALSE(tx[1]); EXPECT_FALSE(tx[1]);
@ -262,8 +263,8 @@ TEST(GreedyNDTest, bound_test_1)
EXPECT_TRUE(tx[4]); EXPECT_TRUE(tx[4]);
EXPECT_TRUE(tx[5]); EXPECT_TRUE(tx[5]);
rval = GREEDY_ND_bound(2, 6, f, rays, x, beta3, &epsilon, tx); rval = bound(2, 6, f, rays, x, beta3, &epsilon, tx);
abort_if(rval, "GREEDY_ND_bound failed"); abort_if(rval, "bound failed");
EXPECT_EQ(epsilon, INFINITY); EXPECT_EQ(epsilon, INFINITY);
EXPECT_FALSE(tx[0]); EXPECT_FALSE(tx[0]);
EXPECT_FALSE(tx[1]); EXPECT_FALSE(tx[1]);
@ -371,10 +372,9 @@ TEST(GreedyNDTest, generate_cut_test_1)
double r3[] = { -1.0, 1.0 }; double r3[] = { -1.0, 1.0 };
double r4[] = { 0.0, 1.0 }; double r4[] = { 0.0, 1.0 };
double r5[] = { 1.0, 0.0 }; double r5[] = { 1.0, 0.0 };
double beta[6];
struct MultiRowModel model; struct MultiRowModel model;
CG_malloc_model(&model, 2, 6); CG_init_model(&model, 2, 6);
LFREE_push_ray(&model.rays, r0); LFREE_push_ray(&model.rays, r0);
LFREE_push_ray(&model.rays, r1); LFREE_push_ray(&model.rays, r1);
LFREE_push_ray(&model.rays, r2); LFREE_push_ray(&model.rays, r2);
@ -384,15 +384,18 @@ TEST(GreedyNDTest, generate_cut_test_1)
model.f[0] = 0.5; model.f[0] = 0.5;
model.f[1] = 0.5; model.f[1] = 0.5;
rval = GREEDY_ND_generate_cut(&model, beta); struct ConvLFreeSet lfree;
abort_if(rval, "GREEDY_ND_generate_cut failed"); LFREE_init_conv(&lfree, 2, 6);
EXPECT_NEAR(beta[0], 0.5, 1e-6); rval = INFINITY_ND_generate_lfree(&model, &lfree);
EXPECT_NEAR(beta[1], 0.5, 1e-6); abort_if(rval, "INFINITY_ND_generate_lfree failed");
EXPECT_NEAR(beta[2], 0.5, 1e-6);
EXPECT_NEAR(beta[3], 0.5, 1e-6); EXPECT_NEAR(lfree.beta[0], 0.5, 1e-6);
EXPECT_NEAR(beta[4], 1.0, 1e-6); EXPECT_NEAR(lfree.beta[1], 0.5, 1e-6);
EXPECT_NEAR(beta[5], 1.0, 1e-6); EXPECT_NEAR(lfree.beta[2], 0.5, 1e-6);
EXPECT_NEAR(lfree.beta[3], 0.5, 1e-6);
EXPECT_NEAR(lfree.beta[4], 1.0, 1e-6);
EXPECT_NEAR(lfree.beta[5], 1.0, 1e-6);
CLEANUP: CLEANUP:
if(rval) FAIL(); if(rval) FAIL();
@ -408,10 +411,9 @@ TEST(GreedyNDTest, generate_cut_test_2)
double r3[] = { 0.0, -1.0, 0.0 }; double r3[] = { 0.0, -1.0, 0.0 };
double r4[] = { 0.0, 0.0, 1.0 }; double r4[] = { 0.0, 0.0, 1.0 };
double r5[] = { 0.0, 0.0, -1.0 }; double r5[] = { 0.0, 0.0, -1.0 };
double beta[6];
struct MultiRowModel model; struct MultiRowModel model;
CG_malloc_model(&model, 3, 6); CG_init_model(&model, 3, 6);
LFREE_push_ray(&model.rays, r0); LFREE_push_ray(&model.rays, r0);
LFREE_push_ray(&model.rays, r1); LFREE_push_ray(&model.rays, r1);
LFREE_push_ray(&model.rays, r2); LFREE_push_ray(&model.rays, r2);
@ -422,15 +424,18 @@ TEST(GreedyNDTest, generate_cut_test_2)
model.f[1] = 0.75; model.f[1] = 0.75;
model.f[2] = 0.75; model.f[2] = 0.75;
rval = GREEDY_ND_generate_cut(&model, beta); struct ConvLFreeSet lfree;
abort_if(rval, "GREEDY_ND_generate_cut failed"); LFREE_init_conv(&lfree, 3, 6);
rval = INFINITY_ND_generate_lfree(&model, &lfree);
abort_if(rval, "INFINITY_ND_generate_lfree failed");
EXPECT_NEAR(beta[0], 0.75, 1e-6); EXPECT_NEAR(lfree.beta[0], 0.75, 1e-6);
EXPECT_NEAR(beta[1], 2.25, 1e-6); EXPECT_NEAR(lfree.beta[1], 2.25, 1e-6);
EXPECT_NEAR(beta[2], 0.75, 1e-6); EXPECT_NEAR(lfree.beta[2], 0.75, 1e-6);
EXPECT_NEAR(beta[3], 2.25, 1e-6); EXPECT_NEAR(lfree.beta[3], 2.25, 1e-6);
EXPECT_NEAR(beta[4], 0.75, 1e-6); EXPECT_NEAR(lfree.beta[4], 0.75, 1e-6);
EXPECT_NEAR(beta[5], 2.25, 1e-6); EXPECT_NEAR(lfree.beta[5], 2.25, 1e-6);
CLEANUP: CLEANUP:
CG_free_model(&model); CG_free_model(&model);

@ -30,7 +30,6 @@ extern "C" {
TEST(Infinity2DTest, test_generate_cut_1) TEST(Infinity2DTest, test_generate_cut_1)
{ {
int rval = 0; int rval = 0;
double bounds[100];
double f[] = {1 / 4.0, 3 / 4.0}; double f[] = {1 / 4.0, 3 / 4.0};
double rays[] = { double rays[] = {
@ -43,14 +42,17 @@ TEST(Infinity2DTest, test_generate_cut_1)
const struct MultiRowModel model = {f , rays, 5, 2}; const struct MultiRowModel model = {f , rays, 5, 2};
rval = INFINITY_2D_generate_cut(&model, bounds); struct ConvLFreeSet lfree;
abort_if(rval, "INFINITY_2D_generate_cut failed"); LFREE_init_conv(&lfree, 2, 5);
EXPECT_NEAR(23 / 50.0, bounds[0], BOUNDS_EPSILON); rval = INFINITY_2D_generate_lfree(&model, &lfree);
EXPECT_NEAR(23 / 42.0, bounds[1], BOUNDS_EPSILON); abort_if(rval, "INFINITY_2D_generate_lfree failed");
EXPECT_NEAR(9 / 11.0, bounds[2], BOUNDS_EPSILON);
EXPECT_NEAR(9 / 11.0, bounds[3], BOUNDS_EPSILON); EXPECT_NEAR(23 / 50.0, lfree.beta[0], BOUNDS_EPSILON);
EXPECT_NEAR(23 / 50.0, bounds[4], BOUNDS_EPSILON); EXPECT_NEAR(23 / 42.0, lfree.beta[1], BOUNDS_EPSILON);
EXPECT_NEAR(9 / 11.0, lfree.beta[2], BOUNDS_EPSILON);
EXPECT_NEAR(9 / 11.0, lfree.beta[3], BOUNDS_EPSILON);
EXPECT_NEAR(23 / 50.0, lfree.beta[4], BOUNDS_EPSILON);
CLEANUP: CLEANUP:
if (rval) FAIL(); if (rval) FAIL();
@ -59,7 +61,6 @@ TEST(Infinity2DTest, test_generate_cut_1)
TEST(Infinity2DTest, test_generate_cut_2) TEST(Infinity2DTest, test_generate_cut_2)
{ {
int rval = 0; int rval = 0;
double bounds[100];
double f[] = {1 / 2.0, 1 / 2.0}; double f[] = {1 / 2.0, 1 / 2.0};
double rays[] = { double rays[] = {
-1.0, -1.0, -1.0, -1.0,
@ -70,15 +71,17 @@ TEST(Infinity2DTest, test_generate_cut_2)
}; };
const struct MultiRowModel model = {f , rays, 5, 2}; const struct MultiRowModel model = {f , rays, 5, 2};
struct ConvLFreeSet lfree;
LFREE_init_conv(&lfree, 2, 5);
rval = INFINITY_2D_generate_cut(&model, bounds); rval = INFINITY_2D_generate_lfree(&model, &lfree);
abort_if(rval, "INFINITY_2D_generate_cut failed"); abort_if(rval, "INFINITY_2D_generate_lfree failed");
EXPECT_NEAR(0.5, bounds[0], BOUNDS_EPSILON); EXPECT_NEAR(0.5, lfree.beta[0], BOUNDS_EPSILON);
EXPECT_NEAR(0.5, bounds[1], BOUNDS_EPSILON); EXPECT_NEAR(0.5, lfree.beta[1], BOUNDS_EPSILON);
EXPECT_NEAR(0.5, bounds[2], BOUNDS_EPSILON); EXPECT_NEAR(0.5, lfree.beta[2], BOUNDS_EPSILON);
EXPECT_EQ(GREEDY_BIG_E, bounds[3]); EXPECT_EQ(GREEDY_BIG_E, lfree.beta[3]);
EXPECT_NEAR(0.5, bounds[4], BOUNDS_EPSILON); EXPECT_NEAR(0.5, lfree.beta[4], BOUNDS_EPSILON);
CLEANUP: CLEANUP:
if (rval) FAIL(); if (rval) FAIL();
@ -87,18 +90,19 @@ TEST(Infinity2DTest, test_generate_cut_2)
TEST(Infinity2DTest, test_generate_cut_3) TEST(Infinity2DTest, test_generate_cut_3)
{ {
int rval = 0; int rval = 0;
double bounds[100];
double f[] = {5 / 22.0, 0.0}; double f[] = {5 / 22.0, 0.0};
double rays[] = {-1 / 22.0, 0.0, 0.0, 1 / 18.0, 1 / 22.0, 0.0}; double rays[] = {-1 / 22.0, 0.0, 0.0, 1 / 18.0, 1 / 22.0, 0.0};
const struct MultiRowModel model = {f , rays, 3, 2}; const struct MultiRowModel model = {f , rays, 3, 2};
struct ConvLFreeSet lfree;
LFREE_init_conv(&lfree, 2, 5);
rval = INFINITY_2D_generate_cut(&model, bounds); rval = INFINITY_2D_generate_lfree(&model, &lfree);
abort_if(rval, "INFINITY_2D_generate_cut failed"); abort_if(rval, "INFINITY_2D_generate_lfree failed");
EXPECT_NEAR(5.0, bounds[0], BOUNDS_EPSILON); EXPECT_NEAR(5.0, lfree.beta[0], BOUNDS_EPSILON);
EXPECT_NEAR(17.0, bounds[2], BOUNDS_EPSILON); EXPECT_NEAR(17.0, lfree.beta[2], BOUNDS_EPSILON);
EXPECT_EQ(GREEDY_BIG_E, bounds[1]); EXPECT_EQ(GREEDY_BIG_E, lfree.beta[1]);
CLEANUP: CLEANUP:
if (rval) FAIL(); if (rval) FAIL();
@ -277,8 +281,8 @@ TEST(Infinity2DTest, find_containing_cone_test_3)
// double rays[] = {0, -1 / 38.0, -1 / 22.0, -1 / 38.0, 0, 1 / 38.0, -1 / 22.0, // double rays[] = {0, -1 / 38.0, -1 / 22.0, -1 / 38.0, 0, 1 / 38.0, -1 / 22.0,
// 0, 1 / 22.0, 0, 1 / 22.0, 1 / 38.0}; // 0, 1 / 22.0, 0, 1 / 22.0, 1 / 38.0};
// //
// rval = INFINITY_2D_generate_cut(rays, 6, f, bounds); // rval = INFINITY_2D_generate_lfree(rays, 6, f, bounds);
// abort_if(rval, "INFINITY_2D_generate_cut failed"); // abort_if(rval, "INFINITY_2D_generate_lfree failed");
// //
// EXPECT_NEAR(20.0, bounds[0], BOUNDS_EPSILON); // EXPECT_NEAR(20.0, bounds[0], BOUNDS_EPSILON);
// EXPECT_NEAR(20.0, bounds[1], BOUNDS_EPSILON); // EXPECT_NEAR(20.0, bounds[1], BOUNDS_EPSILON);
@ -303,8 +307,8 @@ TEST(Infinity2DTest, find_containing_cone_test_3)
// 0.04545454545454545581, 0.00000000000000000000, // 0.04545454545454545581, 0.00000000000000000000,
// 0.04545454545454545581, 0.02631578947368420907}; // 0.04545454545454545581, 0.02631578947368420907};
// //
// rval = INFINITY_2D_generate_cut(rays, 6, f, bounds); // rval = INFINITY_2D_generate_lfree(rays, 6, f, bounds);
// abort_if(rval, "INFINITY_2D_generate_cut failed"); // abort_if(rval, "INFINITY_2D_generate_lfree failed");
// //
// EXPECT_NEAR(20.0, bounds[0], BOUNDS_EPSILON); // EXPECT_NEAR(20.0, bounds[0], BOUNDS_EPSILON);
// EXPECT_NEAR(20.0, bounds[1], BOUNDS_EPSILON); // EXPECT_NEAR(20.0, bounds[1], BOUNDS_EPSILON);

@ -107,7 +107,7 @@ void CG_free_ray_map(struct RayMap *map);
int CG_extract_f_from_tableau(const struct Tableau *tableau, double *f); int CG_extract_f_from_tableau(const struct Tableau *tableau, double *f);
int CG_malloc_model(struct MultiRowModel *model, int nrows, int rays_capacity); int CG_init_model(struct MultiRowModel *model, int nrows, int rays_capacity);
void CG_free_model(struct MultiRowModel *model); void CG_free_model(struct MultiRowModel *model);

@ -40,6 +40,15 @@ struct RayList
int dim; int dim;
}; };
struct ConvLFreeSet
{
double *f;
struct RayList rays;
int nrows;
double *beta;
};
int LFREE_2D_init(struct LFreeSet2D *set, int LFREE_2D_init(struct LFreeSet2D *set,
int n_vertices, int n_vertices,
int n_lattice_points, int n_lattice_points,
@ -69,4 +78,8 @@ void LFREE_free_ray_list(struct RayList *list);
int LFREE_init_ray_list(struct RayList *list, int dim, int capacity); int LFREE_init_ray_list(struct RayList *list, int dim, int capacity);
int LFREE_init_conv(struct ConvLFreeSet *lfree, int dim, int max_nrays);
void LFREE_free_conv(struct ConvLFreeSet *lfree);
#endif //LFREE_2D_H #endif //LFREE_2D_H

@ -31,7 +31,7 @@
* LOG_LEVEL_WARNING * LOG_LEVEL_WARNING
* LOG_LEVEL_ERROR * LOG_LEVEL_ERROR
*/ */
#define LOG_LEVEL LOG_LEVEL_INFO #define LOG_LEVEL LOG_LEVEL_DEBUG
/* /*
* Maximum bounding-box size for naive algorithm * Maximum bounding-box size for naive algorithm
@ -48,7 +48,7 @@
*/ */
#define N_RAYS 100 #define N_RAYS 100
#define ONLY_CUT -1 #define ONLY_CUT 242
/* /*
* Time limit for the computation (user time, in seconds). * Time limit for the computation (user time, in seconds).

@ -575,7 +575,10 @@ void CG_free(struct CG *cg)
if (cg->tableau_rows) if (cg->tableau_rows)
{ {
for (int i = 0; i < cg->nrows; i++) for (int i = 0; i < cg->nrows; i++)
{
LP_free_row(cg->tableau_rows[i]); LP_free_row(cg->tableau_rows[i]);
free(cg->tableau_rows[i]);
}
free(cg->tableau_rows); free(cg->tableau_rows);
} }
@ -598,19 +601,16 @@ int CG_add_single_row_cuts(struct CG *cg, SingleRowGeneratorCallback generate)
log_verbose("Generating cut %d...\n", i); log_verbose("Generating cut %d...\n", i);
struct Row *cut = 0; struct Row cut;
cut = (struct Row *) malloc(sizeof(struct Row));
abort_if(!cut, "could not allocate cut");
rval = generate(row, cg->column_types, cut); rval = generate(row, cg->column_types, &cut);
abort_if(rval, "generate failed"); abort_if(rval, "generate failed");
int ignored; int ignored;
rval = add_cut(cg, cut, &ignored); rval = add_cut(cg, &cut, &ignored);
abort_if(rval, "add_cut failed"); abort_if(rval, "add_cut failed");
LP_free_row(cut); LP_free_row(&cut);
} }
CLEANUP: CLEANUP:
@ -856,23 +856,24 @@ int CG_add_multirow_cuts(struct CG *cg,
progress_increment(); progress_increment();
} }
struct Row *cut = 0; struct Tableau tableau = {nrows, rows, cg->column_types};
struct Row cut;
cut = (struct Row *) malloc(sizeof(struct Row));
abort_if(!cut, "could not allocate cut");
cut->pi = 0; int max_nz = CG_total_nz(&tableau);
cut->indices = 0; cut.pi = (double *) malloc(max_nz * sizeof(double));
cut.indices = (int *) malloc(max_nz * sizeof(int));
abort_if(!cut.pi, "could not allocate cut.pi");
abort_if(!cut.indices, "could not allocate cut.indices");
double initial_time = get_user_time(); double initial_time = get_user_time();
struct Tableau tableau = {nrows, rows, cg->column_types};
rval = generate(&tableau, cut); SHOULD_DUMP_CUTS = 1;
rval = generate(&tableau, &cut);
if (rval == ERR_NO_CUT) if (rval == ERR_NO_CUT)
{ {
rval = 0; rval = 0;
log_verbose("combination does not yield cut\n"); log_verbose("combination does not yield cut\n");
LP_free_row(cut); LP_free_row(&cut);
goto NEXT_COMBINATION; goto NEXT_COMBINATION;
} }
else abort_iff(rval, "generate failed (cut %d)", count); else abort_iff(rval, "generate failed (cut %d)", count);
@ -881,36 +882,36 @@ int CG_add_multirow_cuts(struct CG *cg,
log_debug(" generate: %.2lf ms\n", elapsed_time * 1000); log_debug(" generate: %.2lf ms\n", elapsed_time * 1000);
double dynamism; double dynamism;
rval = cut_dynamism(cut, &dynamism); rval = cut_dynamism(&cut, &dynamism);
abort_if(rval, "cut_dynamism failed"); abort_if(rval, "cut_dynamism failed");
if (dynamism > MAX_CUT_DYNAMISM) if (dynamism > MAX_CUT_DYNAMISM)
{ {
log_debug("Discarding cut (dynamism=%.2lf)\n", dynamism); log_debug("Discarding cut (dynamism=%.2lf)\n", dynamism);
LP_free_row(cut); LP_free_row(&cut);
goto NEXT_COMBINATION; goto NEXT_COMBINATION;
} }
int ignored; int ignored;
rval = add_cut(cg, cut, &ignored); rval = add_cut(cg, &cut, &ignored);
if (rval) if (rval)
{ {
log_warn("invalid cut skipped (cut %d)\n", count); log_warn("invalid cut skipped (cut %d)\n", count);
rval = 0; rval = 0;
LP_free_row(cut); LP_free_row(&cut);
goto NEXT_COMBINATION; goto NEXT_COMBINATION;
} }
if_debug_level if (!ignored) if_debug_level if (!ignored)
{ {
SHOULD_DUMP_CUTS = 1; SHOULD_DUMP_CUTS = 1;
generate(&tableau, cut); generate(&tableau, &cut);
SHOULD_DUMP_CUTS = 0; SHOULD_DUMP_CUTS = 0;
} }
LP_free_row(cut); LP_free_row(&cut);
} }
NEXT_COMBINATION: NEXT_COMBINATION:
@ -1019,7 +1020,7 @@ int CG_extract_f_from_tableau(const struct Tableau *tableau, double *f)
return 0; return 0;
} }
int CG_malloc_model(struct MultiRowModel *model, int nrows, int rays_capacity) int CG_init_model(struct MultiRowModel *model, int nrows, int rays_capacity)
{ {
int rval = 0; int rval = 0;
model->nrows = nrows; model->nrows = nrows;

@ -541,3 +541,28 @@ void LFREE_push_ray(struct RayList *list, const double *ray)
memcpy(dest, ray, list->dim * sizeof(double)); memcpy(dest, ray, list->dim * sizeof(double));
list->nrays++; list->nrays++;
} }
int LFREE_init_conv(struct ConvLFreeSet *lfree, int dim, int max_nrays)
{
int rval = 0;
lfree->nrows = dim;
lfree->f = (double*) malloc(dim * sizeof(double));
lfree->beta = (double*) malloc(max_nrays * sizeof(double));
abort_if(!lfree->f, "could not allocate lfree->f");
abort_if(!lfree->beta, "could not allocate lfree->beta");
rval = LFREE_init_ray_list(&lfree->rays, dim, max_nrays);
abort_if(rval, "LFREE_init_ray_list failed");
CLEANUP:
return rval;
}
void LFREE_free_conv(struct ConvLFreeSet *lfree)
{
if(!lfree) return;
free(lfree->f);
free(lfree->beta);
LFREE_free_ray_list(&lfree->rays);
}

@ -80,10 +80,8 @@ void LP_free(struct LP *lp)
void LP_free_row(struct Row *row) void LP_free_row(struct Row *row)
{ {
if (!row) return; if (!row) return;
if (row->pi) free(row->pi); if (row->pi) free(row->pi);
if (row->indices) free(row->indices); if (row->indices) free(row->indices);
free(row);
} }
int LP_add_rows(struct LP *lp, int LP_add_rows(struct LP *lp,

@ -26,6 +26,7 @@ extern "C" {
int BOOST_VAR = -1; int BOOST_VAR = -1;
double BOOST_FACTOR = 1.0; double BOOST_FACTOR = 1.0;
int SHOULD_DUMP_CUTS = 0;
TEST(CGTest, next_combination_test_1) TEST(CGTest, next_combination_test_1)
{ {
@ -157,7 +158,7 @@ TEST(CGTest, extract_rays_from_rows_test)
rval = CG_extract_rays_from_tableau(&tableau, &map); rval = CG_extract_rays_from_tableau(&tableau, &map);
abort_if(rval, "CG_extract_rays_from_rows failed"); abort_if(rval, "CG_extract_rays_from_rows failed");
EXPECT_EQ(rays.nrays, 4); EXPECT_EQ(map.rays.nrays, 4);
EXPECT_EQ(map.nvars, 7); EXPECT_EQ(map.nvars, 7);
EXPECT_DOUBLE_EQ(rays.values[0], 0.0); EXPECT_DOUBLE_EQ(rays.values[0], 0.0);