New project structure

This commit is contained in:
2017-04-28 15:44:24 -04:00
commit 7098f65110
50 changed files with 11246 additions and 0 deletions

View File

@@ -0,0 +1,20 @@
set(COMMON_SOURCES
src/greedy-2d.c
src/greedy-nd.c
src/greedy-bsearch.c
src/greedy.c
include/infinity/greedy-2d.h
include/infinity/greedy-nd.h
include/infinity/greedy-bsearch.h
include/infinity/greedy.h)
set(TEST_SOURCES
tests/greedy-2d-test.cpp
tests/greedy-nd-test.cpp)
add_library(infinity_static ${COMMON_SOURCES})
set_target_properties(infinity_static PROPERTIES OUTPUT_NAME lifting)
target_include_directories (infinity_static PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
add_executable(infinity-test.run ${COMMON_SOURCES} ${TEST_SOURCES})
target_link_libraries(infinity-test.run gtest_main multirow_static lifting_static)

View File

@@ -0,0 +1,37 @@
/* Copyright (c) 2015 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/>.
*/
#ifndef MULTIROW_GREEDY_2D_H
#define MULTIROW_GREEDY_2D_H
int GREEDY_2D_bound(const double *rays,
const double *bounds,
int nrays,
const double *f,
const double *p,
double *epsilon,
double *v1,
double *v2,
int *index1,
int *index2);
int GREEDY_2D_generate_cut(const double *rays,
int nrays,
const double *f,
double *bounds);
#endif //MULTIROW_GREEDY_2D_H

View File

@@ -0,0 +1,33 @@
/* Copyright (c) 2015 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/>.
*/
#ifndef MULTIROW_GREEDY_BSEARCH_H
#define MULTIROW_GREEDY_BSEARCH_H
int create_sfree_mip(int nrows,
int nrays,
const double *f,
const double *rays,
const double *bounds,
double e,
struct LP *lp);
int GREEDY_BSEARCH_compute_bounds(int nrows,
int nrays,
const double *f,
const double *rays,
double *bounds);
#endif //MULTIROW_GREEDY_BSEARCH_H

View File

@@ -0,0 +1,105 @@
/* Copyright (c) 2015 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/>.
*/
#ifndef 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,
const int nrays,
const double *f,
const double *rays,
const double *beta,
struct LP *lp);
int GREEDY_ND_psi(const int nrows,
const int nrays,
const double *f,
const double *rays,
const double *beta,
const double *q,
const double q_scale,
struct LP *lp,
double *value);
int GREEDY_ND_pi(const int nrows,
const int nrays,
const double *f,
const double *rays,
const double *beta,
const double *q,
const double q_scale,
struct LP *lp,
double *value);
int GREEDY_ND_generate_cut(int nrows,
int nrays,
const double *f,
const double *rays,
double *beta);
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 nrays,
const double *f,
const double *rays,
const int *rx,
const double *x,
const double *beta,
double *epsilon);
int GREEDY_ND_find_violated_cone(int nrows,
int nrays,
const double *f,
const double *rays,
const double *x,
const double *beta,
double epsilon,
int *rx,
double *sbar,
int *violated_found);
int GREEDY_ND_find_tight_rays(int nrows,
int nrays,
const double *f,
const double *rays,
const double *x,
const double *beta,
double epsilon,
int *tx);
int GREEDY_ND_scale_to_ahull(int nrows,
int nrays,
const double *rays,
const int *rx,
const double *beta,
double epsilon,
const double *d,
double *alpha);
#endif //MULTIROW_GREEDY_ND_H

View File

@@ -0,0 +1,31 @@
/* Copyright (c) 2015 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/>.
*/
#ifndef MULTIROW_GREEDY_H
#define MULTIROW_GREEDY_H
int GREEDY_write_sage_file(int nrows,
int nrays,
const double *f,
const double *rays,
const double *bounds,
const char *filename);
int GREEDY_generate_cut(int nrows,
struct Row **rows,
const char *column_types,
struct Row *cut);
#endif //MULTIROW_GREEDY_H

View File

@@ -0,0 +1,738 @@
/* Copyright (c) 2015 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/>.
*/
#define _GNU_SOURCE
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <multirow/geometry.h>
#include <multirow/double.h>
#include <multirow/util.h>
#include <multirow/rational.h>
#include <infinity/greedy-2d.h>
static int get_bounding_box(int nrows,
int nrays,
const double *rays,
const double *bounds,
double epsilon,
double *lb,
double *ub)
{
for(int i = 0; i < nrows; i++)
{
ub[i] = 0;
lb[i] = 0;
}
for (int i=0; i < nrays; i++)
{
double e = fmin(epsilon, bounds[i]);
for(int j = 0; j < nrows; j++)
{
double rij = rays[nrows * i + j] * e;
lb[j] = fmin(lb[j], floor(rij));
ub[j] = fmax(ub[j], ceil(rij));
}
}
return 0;
}
struct LatticeSequence
{
int square;
int direction;
int steps;
int eol;
int i;
int j;
};
static void lattice_sequence_init(struct LatticeSequence *seq)
{
seq->steps = 0;
seq->square = 0;
seq->direction = 0;
seq->i = 0;
seq->j = 0;
seq->eol = 0;
}
static int next_lattice_point(struct LatticeSequence *seq,
const double *lb,
const double *ub)
{
int rval = 0;
seq->eol = 1;
for(int k = 0; k < 8 * (seq->square+1); k++)
{
if(seq->steps > 0)
{
seq->steps--;
switch(seq->direction)
{
case 3:
seq->i++;
break;
case 2:
seq->j--;
break;
case 1:
seq->i--;
break;
case 0:
seq->j++;
break;
}
}
if(seq->steps == 0)
{
if(seq->direction > 0)
{
seq->direction--;
seq->steps = 2 * seq->square;
}
else
{
seq->square++;
seq->direction = 3;
seq->steps = 2 * seq->square;
seq->i--;
seq->j++;
}
}
if(seq->i >= lb[0] && seq->i <= ub[0] && seq->j >= lb[1] &&
seq->j <= ub[1])
{
seq->eol = 0;
break;
}
}
CLEANUP:
return rval;
}
/*
* Returns lambda1 and lambda2 such that p = r1 * lambda1 + r2 * lambda2
*/
static void find_linear_combination(const double *r1,
const double *r2,
const double *p,
double *lambda1,
double *lambda2)
{
int rval = 0;
double den = (r1[0] * r2[1] - r2[0] * r1[1]);
if(DOUBLE_iszero(den)) den = 0.0;
*lambda1 = (r2[1] * p[0] - r2[0] * p[1]) / den;
*lambda2 = (-r1[1] * p[0] + r1[0] * p[1]) / den;
}
static int generate_split(const double *f,
const double *d,
double *pi,
double *pi_zero,
long max_den)
{
int rval = 0;
Rational d1, d2;
double m;
rval = DOUBLE_to_rational(d[0], 10, d1);
abort_if(rval, "DOUBLE_to_rational failed");
rval = DOUBLE_to_rational(d[1], 10, d2);
abort_if(rval, "DOUBLE_to_rational failed");
m = lcm(d1->den, d2->den);
d1->den = m / d1->den;
d1->num *= d1->den;
d2->den = m / d2->den;
d2->num *= d2->den;
m = gcd(d1->num, d2->num);
if(m != 0)
{
d1->num /= m;
d2->num /= m;
pi[0] = (double) d2->num;
pi[1] = - ((double) d1->num);
*pi_zero = floor(pi[0] * f[0] + pi[1] * f[1]);
}
else
{
pi[0] = pi[1] = INFINITY;
*pi_zero = INFINITY;
}
CLEANUP:
return rval;
}
/*
* Receives a list of rays r1,...,rn and a point p. Returns i1,i2 such that
* p belongs to cone(r_i1,r_i2). Also returns lambda1, lambda2 such that
* p = r_i1 * lambda1 + r_i2 * lambda2.
*
* The rays must be sorted in clockwise order.
*/
static int find_containing_cone(const double *rays,
const int nrays,
const double *p,
int *index1,
int *index2,
double *lambda1,
double *lambda2)
{
int rval = 0;
int i1, i2;
for (i1 = 0; i1 < nrays; i1++)
{
i2 = (i1 + 1) % nrays;
const double *r1 = &rays[i1 * 2];
const double *r2 = &rays[i2 * 2];
double at1 = atan2(r1[1], r1[0]);
double at2 = atan2(r2[1], r2[0]) - at1;
if (at2 > 0) at2 -= 2 * M_PI;
if (at2 <= - M_PI)
{
log_verbose(" discarding obtuse rays\n");
log_verbose(" r1=%.12lf %.12lf\n", r1[0], r1[1]);
log_verbose(" r2=%.12lf %.12lf\n", r2[0], r2[1]);
continue;
}
find_linear_combination(r1, r2, p, lambda1, lambda2);
log_verbose(" r1=%.12lf %.12lf\n", r1[0], r1[1]);
log_verbose(" r2=%.12lf %.12lf\n", r2[0], r2[1]);
log_verbose(" %.8lf %.8lf\n", *lambda1, *lambda2);
if(DOUBLE_iszero(*lambda1)) *lambda1 = 0.0;
if(DOUBLE_iszero(*lambda2)) *lambda2 = 0.0;
if ((*lambda1) >= 0 && (*lambda2) >= 0 && (*lambda1) <= 1e9 &&
(*lambda2) <= 1e9)
{
log_verbose(" match!\n");
break;
}
}
if (i1 == nrays)
i1 = i2 = -1;
*index1 = i1;
*index2 = i2;
CLEANUP:
return rval;
}
/*
* Find lambda such that p lies on the line connecting lambda * r1 and lambda * r2
*/
static int scale_cone_to_point(const double *r1,
const double *r2,
const double *p,
double *lambda)
{
int rval = 0;
double a = r1[0], b = r1[1];
double c = r2[0], d = r2[1];
double den = (b * c - a * d);
//abort_iff(fabs(den) < 1e-9, "rays cannot be parallel (den=%.12lf)", den);
*lambda = p[0] * (b - d) - p[1] * (a - c);
*lambda /= den;
CLEANUP:
return rval;
}
/*
* Find lambda such that p lies in the line connecting r1 and lambda * r2
*/
static int shear_cone_to_point(const double *r1,
const double *r2,
const double *p,
double *lambda)
{
int rval = 0;
double a = r1[0], b = r1[1];
double c = r2[0], d = r2[1];
double den = d * (p[0] - a) - c * (p[1] - b);
*lambda = b * p[0] - a * p[1];
*lambda /= den;
CLEANUP:
return rval;
}
static int scale_to_chull(double *rays, int nrays, double *scale)
{
int rval = 0;
double *rays_extended = 0;
double *vertices = 0;
int nvertices;
rays_extended = (double*) malloc(2 * (nrays + 1) * sizeof(double));
vertices = (double*) malloc(2 * (nrays + 1) * sizeof(double));
abort_if(!rays_extended, "could not allocate rays_extended");
abort_if(!vertices, "could not allocate vertices");
memcpy(rays_extended, rays, 2 * nrays * sizeof(double));
rays_extended[2*nrays] = 0;
rays_extended[2*nrays + 1] = 0;
rval = chull_2d(rays_extended, nrays + 1, vertices, &nvertices);
abort_if(rval, "chull_2d failed");
for(int i = 0; i < nrays; i++)
scale[i] = 1.0;
log_verbose(" convex hull:\n");
for(int i = 0; i < nvertices; i++)
{
log_verbose(" v%-3d: %20.8lf %20.8lf\n", i, vertices[2 * i],
vertices[2 * i + 1]);
}
log_verbose(" rays:\n");
for(int i = 0; nrays >= 3 && i < nrays; i++)
{
int i1, i2;
double lambda1, lambda2, mu;
rval = find_containing_cone(vertices, nvertices, &rays[2*i], &i1, &i2,
&lambda1, &lambda2);
abort_if(rval, "find_containing_cone failed");
log_verbose("%.8lf %.8lf\n", lambda1, lambda2);
if(i1 < 0 || i2 < 0) continue;
if(DOUBLE_iszero(lambda1))
{
mu = lambda2;
}
else if(DOUBLE_iszero(lambda2))
{
mu = lambda1;
}
else
{
rval = scale_vector_to_line(&vertices[2*i1], &vertices[2*i2],
&rays[2*i], &mu);
abort_if(rval, "scale_vector_to_line failed");
}
abort_if(!isfinite(mu), "mu should be finite");
//log_verbose(" r%-3d: %.2lf %.2lf %.2lf\n", i, rays[2*i], rays[2*i+1], mu);
rays[2*i] *= mu;
rays[2*i+1] *= mu;
scale[i] = mu;
log_verbose(" r%-3d: %20.12lf %20.12lf (scale %.8lf)\n", i, rays[2*i],
rays[2*i+1], scale[i]);
}
CLEANUP:
if(rays_extended) free(rays_extended);
if(vertices) free(vertices);
return rval;
}
#ifndef TEST_SOURCE
int GREEDY_2D_bound(const double *rays,
const double *bounds,
int nrays,
const double *f,
const double *p,
double *epsilon,
double *v1,
double *v2,
int *index1,
int *index2)
{
int rval = 0;
int i1, i2, iexact = -1;
double e1, e2;
const double *r1, *r2;
double lambda1, lambda2;
double pp[2] = { p[0] - f[0], p[1] - f[1] };
rval = find_containing_cone(rays, nrays, pp, &i1, &i2, &lambda1, &lambda2);
abort_if(rval, "find_containing_cone failed");
if(i1 < 0 || i2 < 0)
{
log_verbose(" no cone\n");
*epsilon = INFINITY;
goto CLEANUP;
}
if(DOUBLE_iszero(lambda1)) iexact = i2;
if(DOUBLE_iszero(lambda2)) iexact = i1;
if(iexact >= 0)
{
int inext = (iexact + 1) % nrays;
int iprev = (iexact + (nrays-1)) % nrays;
double mu1, mu2;
find_linear_combination(&rays[2 * iprev], &rays[2 * inext],
&rays[2 * iexact], &mu1, &mu2);
log_verbose(" mu=%.12lf %.12lf\n", mu1, mu2);
int should_enlarge_cone = 1;
if(!DOUBLE_leq(bounds[iexact], lambda1+lambda2)) should_enlarge_cone = 0;
if(!DOUBLE_geq(mu1, 0) || !DOUBLE_geq(mu2, 0)) should_enlarge_cone = 0;
if(isinf(mu1) || isinf(mu2)) should_enlarge_cone = 0;
if(fabs(mu1) > 1e9 || fabs(mu2) > 1e9) should_enlarge_cone = 0;
if(should_enlarge_cone)
{
i1 = iprev;
i2 = inext;
}
else
{
v1[0] = v1[1] = INFINITY;
v2[0] = v2[1] = INFINITY;
*epsilon = (lambda1 + lambda2);
if(DOUBLE_leq(bounds[iexact], *epsilon))
*epsilon = INFINITY;
*index1 = *index2 = iexact;
goto CLEANUP;
}
}
if(bounds[i1] > bounds[i2])
{
swap(i1, i2, int);
swap(lambda1, lambda2, double);
}
*index1 = i1;
*index2 = i2;
r1 = &rays[2 * i1];
r2 = &rays[2 * i2];
log_verbose(" r%-4d %20.12lf %20.12lf\n", i1, r1[0], r1[1]);
log_verbose(" r%-4d %20.12lf %20.12lf\n", i2, r2[0], r2[1]);
log_verbose(" pp %20.12lf %20.12lf\n", pp[0], pp[1]);
log_verbose(" lambda %20.12lf %20.12lf\n", lambda1, lambda2);
double r1bound[2] = { r1[0] * bounds[i1], r1[1] * bounds[i1] };
rval = scale_cone_to_point(r1, r2, pp, &e1);
abort_if(rval, "scale_cone_to_point failed");
rval = shear_cone_to_point(r1bound, r2, pp, &e2);
abort_if(rval, "scale_cone_to_point failed");
log_verbose(" e1=%20.12lf\n", e1);
log_verbose(" e2=%20.12lf\n", e2);
log_verbose(" b1=%20.12lf\n", bounds[i1]);
log_verbose(" b2=%20.12lf\n", bounds[i2]);
switch(DOUBLE_cmp(e1, bounds[i1]))
{
case -1:
*epsilon = e1;
v1[0] = r1[0] * e1;
v1[1] = r1[1] * e1;
v2[0] = r2[0] * e1;
v2[1] = r2[1] * e1;
break;
case 0:
case 1:
if(DOUBLE_geq(e2, bounds[i2]))
{
*epsilon = INFINITY;
}
else
{
*epsilon = e2;
v1[0] = r1[0] * bounds[i1];
v1[1] = r1[1] * bounds[i1];
v2[0] = r2[0] * e2;
v2[1] = r2[1] * e2;
}
}
CLEANUP:
return rval;
}
int GREEDY_2D_generate_cut(const double *original_rays,
const int nrays,
const double *f,
double *bounds)
{
log_verbose("GREEDY_2D_generate_cut\n");
int rval = 0;
int count = 0;
double *scale = 0;
double *rays = 0;
double lb[2], ub[2];
for (int i = 0; i < nrays; i++)
bounds[i] = GREEDY_BIG_E;
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");
memcpy(rays, original_rays, 2 * nrays * sizeof(double));
rval = scale_to_chull(rays, nrays, scale);
abort_if(rval, "scale_to_chull failed");
long seq_count = 0;
while(1)
{
log_verbose(" starting iteration %d...\n", count);
abort_if(count++ > 2 * nrays, "infinite loop");
rval = get_bounding_box(2, nrays, rays, bounds, GREEDY_BIG_E, lb, ub);
abort_if(rval, "get_bounding_box failed");
log_verbose(" box=[%.2lf %.2lf] [%.2lf %.2lf]\n", lb[0], ub[0], lb[1], ub[1]);
int best_i1, best_i2;
double best_v1[2];
double best_v2[2];
double best_p[2];
double best_epsilon = INFINITY;
struct LatticeSequence seq;
lattice_sequence_init(&seq);
while(!seq.eol)
{
seq_count++;
double p[2] = { seq.i, seq.j };
double v1[2], v2[2], epsilon;
int i1, i2;
log_verbose(" p=%.2lf %.2lf\n", p[0], p[1]);
rval = GREEDY_2D_bound(rays, bounds, nrays, f, p, &epsilon, v1, v2,
&i1, &i2);
abort_if(rval, "GREEDY_2D_bound failed");
log_verbose(" epsilon=%.2lf\n", epsilon);
if(epsilon >= 0 && epsilon < best_epsilon)
{
log_verbose(" found smaller epsilon: %.8lf\n", epsilon);
rval = get_bounding_box(2, nrays, rays, bounds, epsilon, lb, ub);
abort_if(rval, "get_bounding_box failed");
log_verbose(" p=%.2lf %.2lf\n", p[0], p[1]);
log_verbose(" box=[%.2lf %.2lf] [%.2lf %.2lf]\n", lb[0], ub[0],
lb[1], ub[1]);
log_verbose(" v1=%12.8lf %12.8lf\n", v1[0], v1[1]);
log_verbose(" v2=%12.8lf %12.8lf\n", v2[0], v2[1]);
log_verbose(" rays=[%d %d]\n", i1, i2);
best_epsilon = epsilon;
best_v1[0] = v1[0];
best_v1[1] = v1[1];
best_v2[0] = v2[0];
best_v2[1] = v2[1];
best_p[0] = p[0];
best_p[1] = p[1];
best_i1 = i1;
best_i2 = i2;
}
next_lattice_point(&seq, lb, ub);
if(seq_count > MAX_LATTICE_POINTS)
{
rval = ERR_MIP_TIMEOUT;
goto CLEANUP;
}
}
if(isinf(best_epsilon))
{
log_verbose(" best_epsilon is infinity\n");
break;
}
log_verbose(" updating bounds\n");
if(isinf(best_v1[0]))
{
bounds[best_i1] = best_epsilon;
log_verbose(" bounds[%d]=%.8lf (exact)\n", best_i1, best_epsilon);
}
else
{
log_verbose(" v1=%.8lf %.8lf\n", best_v1[0], best_v1[1]);
log_verbose(" v2=%.8lf %.8lf\n", best_v2[0], best_v2[1]);
log_verbose(" i=%d %d\n", best_i1, best_i2);
for (int i = 0; i < nrays; i++)
{
double lambda;
rval = scale_vector_to_line(best_v1, best_v2, &rays[2 * i], &lambda);
abort_if(rval, "scale_vector_to_line failed");
if(!DOUBLE_geq(lambda, 0)) continue;
bounds[i] = fmin(bounds[i], lambda);
log_verbose(" bounds[%d]=%.8lf\n", i, bounds[i]);
}
}
//if(count > 0)
//{
// for (int i = 0; i < nrays; i++)
// bounds[i] = fmin(bounds[i], best_epsilon);
// break;
//}
int is_split;
for (int k = 0; k < nrays; k++)
{
if(bounds[k] < 100) continue;
is_split = 1;
double *split_direction = &rays[2 * k];
log_verbose(" split_direction=%.2lf %.2lf\n", split_direction[0],
split_direction[1]);
double pi[2];
double pi_zero;
rval = generate_split(f, split_direction, pi, &pi_zero, 10);
abort_if(rval, "generate_split failed");
log_verbose(" pi=%.2lf %.2lf\n", pi[0], pi[1]);
log_verbose(" pi_zero=%.2lf\n", pi_zero);
if(isinf(pi[0]))
{
is_split = 0;
break;
}
double lhs;
// reject splits that have f on the boundary
lhs = f[0] * pi[0] + f[1] * pi[1];
if(DOUBLE_eq(pi_zero, lhs) || DOUBLE_eq(lhs, pi_zero+1))
{
log_verbose(" split rejected\n");
is_split = 0;
}
for (int i = 0; i < nrays && is_split; i++)
{
const double *r = &rays[2 * i];
lhs = (f[0] + r[0] * bounds[i]) * pi[0];
lhs += (f[1] + r[1] * bounds[i]) * pi[1];
if (!(DOUBLE_leq(pi_zero, lhs) && DOUBLE_leq(lhs, pi_zero+1)))
{
log_verbose(" point %.4lf %.4lf falls outside of the split\n",
f[0] + r[0]*bounds[i], f[1] + r[1] * bounds[i]);
is_split = 0;
}
}
if(is_split)
{
log_verbose(" split confirmed. stopping.\n");
break;
}
}
if(is_split) break;
}
for(int i=0; i<nrays; i++)
bounds[i] *= scale[i];
CLEANUP:
if(scale) free(scale);
if(rays) free(rays);
return rval;
}
#endif // TEST_SOURCE

View File

@@ -0,0 +1,246 @@
/* Copyright (c) 2015 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 <math.h>
#include <stdlib.h>
#include <multirow/cg.h>
#include <multirow/double.h>
#include <multirow/geometry.h>
#include <multirow/lp.h>
#include <multirow/util.h>
#include <infinity/greedy-bsearch.h>
int create_sfree_mip(int nrows,
int nrays,
const double *f,
const double *rays,
const double *bounds,
double e,
struct LP *lp)
{
int rval = 0;
double rhs;
char sense;
int rmatbeg = 0;
int* rmatind = 0;
double *rmatval = 0;
rmatind = (int *) malloc((nrows + nrays) * sizeof(int));
rmatval = (double *) malloc((nrows + nrays) * sizeof(double));
abort_if(!rmatind, "could not allocate rmatind");
abort_if(!rmatval, "could not allocate rmatval");
rval = LP_create(lp, "greedy");
abort_if(rval, "LP_create failed");
// create x (basic) variables
for (int i = 0; i < nrows; i++)
{
rval = LP_new_col(lp, 0, -MILP_INFINITY, MILP_INFINITY, 'I');
abort_if(rval, "LP_new_col failed");
}
// create s (non-basic) variables
for (int i = 0; i < nrays; i++)
{
rval = LP_new_col(lp, 1.0, 0, MILP_INFINITY, 'C');
abort_if(rval, "LP_new_col failed");
}
// add constraint \sum_{i=1}^m s_i \leq 1
sense = 'L';
rhs = 1.0;
for (int i = 0; i < nrays; i++)
{
rmatind[i] = i + nrows;
rmatval[i] = 1.0;
}
rval = LP_add_rows(lp, 1, nrays, &rhs, &sense, &rmatbeg, rmatind, rmatval);
abort_if(rval, "LP_add_rows failed");
// add constraints x_i - \sum_{j=1}^m min{e,e_j} s_j R_ji = f_i
for (int i = 0; i < nrows; i++)
{
int k = 0;
sense = 'E';
rhs = f[i];
rmatind[k] = i;
rmatval[k] = 1.0;
k++;
for (int j = 0; j < nrays; j++)
{
rmatind[k] = j + nrows;
rmatval[k] = -rays[nrows * j + i] * fmin(e, bounds[j]);
k++;
}
rval = LP_add_rows(lp, 1, nrays + 1, &rhs, &sense, &rmatbeg, rmatind,
rmatval);
abort_if(rval, "LP_add_rows failed");
}
CLEANUP:
if (rmatind) free(rmatind);
if (rmatval) free(rmatval);
return rval;
}
int GREEDY_BSEARCH_compute_bounds(int nrows,
int nrays,
const double *f,
const double *rays,
double *bounds)
{
int rval = 0;
struct LP lp;
double e_upper = 2 * GREEDY_BIG_E;
double e_lower = 0.0;
int cplex_count = 0;
double cplex_time = 0;
int iteration_count = 0;
double *x = 0;
x = (double *) malloc((nrays + nrows) * sizeof(double));
abort_if(!x, "could not allocate x");
for (int i = 0; i < nrays; i++)
bounds[i] = GREEDY_BIG_E;
for (int it = 0;; it++)
{
abort_if(it > 2*nrays, "stuck in an infinite loop");
log_verbose("Starting iteration %d...\n", it);
iteration_count++;
int solution_found = 0;
int inner_count = 0;
while (fabs(e_upper - e_lower) > GREEDY_MAX_GAP)
{
inner_count++;
double e = (e_upper + e_lower) / 2;
log_verbose(" e=%.12lf\n", e);
rval = LP_open(&lp);
abort_if(rval, "LP_open failed");
rval = create_sfree_mip(nrows, nrays, f, rays, bounds, e, &lp);
abort_if(rval, "create_sfree_mip failed");
if_verbose_level
{
rval = LP_write(&lp, "greedy.lp");
abort_if(rval, "LP_write failed");
}
int infeasible;
cplex_count++;
double initial_time = get_user_time();
log_verbose(" Optimizing...\n");
rval = LP_optimize(&lp, &infeasible);
if (rval)
{
// Workaround for CPLEX bug. If CPLEX tell us that this problem
// is unbounded, we disable presolve and try again.
LP_free(&lp);
LP_open(&lp);
rval = create_sfree_mip(nrows, nrays, f, rays, bounds, e, &lp);
abort_if(rval, "create_sfree_mip failed");
LP_disable_presolve(&lp);
rval = LP_optimize(&lp, &infeasible);
abort_if(rval, "LP_optimize failed");
}
cplex_time += get_user_time() - initial_time;
if (infeasible)
{
e_lower = e;
log_verbose(" infeasible\n");
if (e > GREEDY_BIG_E-1)
{
LP_free(&lp);
goto OUT;
}
}
else
{
log_verbose(" feasible\n");
e_upper = e;
solution_found = 1;
rval = LP_get_x(&lp, x);
abort_if(rval, "LP_get_x failed");
}
LP_free(&lp);
}
if (solution_found)
{
for (int j = 0; j < nrays; j++)
{
if (!DOUBLE_geq(x[nrows + j], 0.001)) continue;
bounds[j] = fmin(bounds[j] * 0.99, e_lower * 0.99);
}
}
log_verbose(" %d iterations %12.8lf gap\n", inner_count, e_upper -
e_lower);
e_lower = e_upper;
e_upper = 2 * GREEDY_BIG_E;
}
OUT:
log_debug(" %6d IPs (%.2lfms per call, %.2lfs total)\n", cplex_count,
cplex_time * 1000.0 / cplex_count, cplex_time);
for(int i = 0; i < nrays; i++)
abort_if(DOUBLE_iszero(bounds[i]), "bounds should be positive");
if_verbose_level
{
time_printf("Bounds:\n");
for (int k = 0; k < nrays; k++)
time_printf(" %12.8lf %12.8lf\n", k, bounds[k], 1 / bounds[k]);
}
CLEANUP:
if (x) free(x);
return rval;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,478 @@
/* Copyright (c) 2015 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 <math.h>
#include <stdlib.h>
#include <multirow/cg.h>
#include <multirow/double.h>
#include <multirow/util.h>
#include <infinity/greedy.h>
#include <infinity/greedy-bsearch.h>
#include <infinity/greedy-2d.h>
#include <infinity/greedy-nd.h>
struct SortPair
{
int index;
void *data;
};
static int _qsort_cmp_rays_angle(const void *p1,
const void *p2)
{
double *r1 = (double *) (((struct SortPair *) p1)->data);
double *r2 = (double *) (((struct SortPair *) p2)->data);
return sign(atan2(r1[0], r1[1]) - atan2(r2[0], r2[1]));
}
static int sort_rays_angle(double *rays,
int nrays,
double *beta)
{
int rval = 0;
int *map = 0;
double *rays_copy = 0;
double *beta_copy = 0;
struct SortPair *pairs = 0;
pairs = (struct SortPair *) malloc(nrays * sizeof(struct SortPair));
rays_copy = (double *) malloc(2 * nrays * sizeof(double));
beta_copy = (double*) malloc(nrays * sizeof(double));
abort_if(!pairs, "could not allocate pairs");
abort_if(!rays_copy, "could not allocate rays_copy");
abort_if(!beta_copy, "could not allocate beta_copy");
memcpy(rays_copy, rays, 2 * nrays * sizeof(double));
memcpy(beta_copy, beta, nrays * sizeof(double));
for (int i = 0; i < nrays; i++)
{
pairs[i].index = i;
pairs[i].data = &rays[2 * i];
}
qsort(pairs, nrays, sizeof(struct SortPair), _qsort_cmp_rays_angle);
for (int i = 0; i < nrays; i++)
{
beta[i] = beta_copy[pairs[i].index];
memcpy(&rays[2 * i], &rays_copy[2 * pairs[i].index], 2 *
sizeof(double));
}
CLEANUP:
if (pairs) free(pairs);
if (rays_copy) free(rays_copy);
if (beta_copy) free(beta_copy);
return rval;
}
static int scale_rays(double *rays,
int nrays,
double *scale)
{
int rval = 0;
for (int i = 0; i < nrays; i++)
{
rays[2*i] *= scale[i];
rays[2*i+1] *= scale[i];
}
CLEANUP:
return rval;
}
static void print_row(const struct Row *row)
{
time_printf("Row:\n");
for (int i = 0; i < row->nz; i++)
time_printf(" %.4lfx%d\n", row->pi[i], row->indices[i]);
time_printf(" <= %.4lf [%d]\n", row->pi_zero, row->head);
}
static void print_rays(const int *map,
const int *indices,
const double *f,
const double *rays,
const double *scale,
int nrays,
int nz,
int nrows)
{
time_printf("Mapping:\n");
for (int i = 0; i < nz; i++)
time_printf(" %4d: %4d x%-4d (scale=%.4lf)\n", i, map[i], indices[i],
scale[i]);
time_printf("Origin:\n");
for (int i = 0; i < nrows; i++)
time_printf(" %20.12lf\n", f[i]);
time_printf("Rays:\n");
for (int i = 0; i < nrays; i++)
{
time_printf(" ");
for (int j = 0; j < nrows; j++)
printf("%20.12lf ", rays[i * nrows + j]);
printf("angle=%.4lf ", atan2(rays[i * nrows], rays[i * nrows + 1]));
printf("norm=%.4lf ", fabs(rays[i * nrows]) + fabs(rays[i * nrows + 1]));
printf("[ ");
for (int j = 0; j < nz; j++)
if (map[j] == i) printf("%d ", indices[j]);
printf("]\n");
}
}
static void print_cut(const struct Row *cut)
{
time_printf("Generated cut:\n");
for (int i = 0; i < cut->nz; i++)
time_printf(" %.4lfx%d\n", cut->pi[i], cut->indices[i]);
time_printf(" <= %.4lf\n", cut->pi_zero);
}
int GREEDY_write_sage_file(int nrows,
int nrays,
const double *f,
const double *rays,
const double *beta,
const char *filename)
{
int rval = 0;
FILE *fsage = fopen(filename, "w");
abort_iff(!fsage, "could not open %s", filename);
fprintf(fsage, "f=vector([");
for (int i = 0; i < nrows; i++)
fprintf(fsage, "%.20lf,", f[i]);
fprintf(fsage, "])\n");
fprintf(fsage, "R=matrix([\n");
for (int i = 0; i < nrays; i++)
{
fprintf(fsage, " [");
for (int j = 0; j < nrows; j++)
{
fprintf(fsage, "%.20lf,", rays[i * nrows + j]);
}
fprintf(fsage, "],\n");
}
fprintf(fsage, "])\n");
fprintf(fsage, "pi=vector([\n");
for (int k = 0; k < nrays; k++)
fprintf(fsage, " %.12lf,\n", 1 / beta[k]);
fprintf(fsage, "])\n");
CLEANUP:
fclose(fsage);
return rval;
}
static int create_cut(const int nrows,
const char *column_types,
const int nrays,
const double *f,
const int lfree_nrays,
const double *lfree_rays,
const double *beta,
const double *extracted_rays,
const int nvars,
const int *variable_to_ray,
const int *indices,
const double *scale,
struct Row *cut)
{
int rval = 0;
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);
abort_if(rval, "LP_open failed");
rval = GREEDY_create_psi_lp(nrows, lfree_nrays, f, lfree_rays, beta, &lp);
abort_if(rval, "create_psi_lp failed");
for (int i = 0; i < nvars; i++)
{
double value;
const double *q = &extracted_rays[variable_to_ray[i] * nrows];
if(ENABLE_LIFTING && column_types[indices[i]] == MILP_INTEGER)
{
rval = GREEDY_ND_pi(nrows, lfree_nrays, f, lfree_rays, beta, q,
scale[i], &lp, &value);
abort_if(rval, "GREEDY_ND_pi failed");
}
else
{
rval = GREEDY_ND_psi(nrows, lfree_nrays, f, lfree_rays, beta, q,
scale[i], &lp, &value);
abort_if(rval, "GREEDY_ND_psi failed");
}
log_verbose(" psi[%4d] = %20.12lf %d\n", indices[i], value);
value *= 1.0001;
value = DOUBLE_max(value, 0.0001);
cut->indices[i] = indices[i];
cut->pi[i] = - value;
}
cut->pi_zero = -1.0;
CLEANUP:
LP_free(&lp);
return rval;
}
#ifndef TEST_SOURCE
int GREEDY_generate_cut(int nrows,
struct Row **rows,
const char *column_types,
struct Row *cut)
{
int rval = 0;
double *f = 0;
long max_nrays = 0;
f = (double *) malloc(nrows * sizeof(double));
abort_if(!f, "could not allocate f");
for (int i = 0; i < nrows; i++)
{
f[i] = frac(rows[i]->pi_zero);
if (DOUBLE_eq(f[i], 1.0)) f[i] = 0.0;
max_nrays += rows[i]->nz;
}
int nz;
int nrays;
int *variable_to_ray = 0;
int *indices = 0;
double *extracted_rays = 0;
double *scale = 0;
double *beta = 0;
double *scaled_rays = 0;
int lfree_nrays = 0;
double *lfree_rays = 0;
variable_to_ray = (int *) malloc(max_nrays * sizeof(int));
indices = (int *) malloc(max_nrays * sizeof(int));
scale = (double *) malloc(max_nrays * sizeof(double));
extracted_rays = (double *) malloc(nrows * max_nrays * sizeof(double));
abort_if(!variable_to_ray, "could not allocate variable_to_ray");
abort_if(!indices, "could not allocate indices");
abort_if(!scale, "could not allocate scale");
abort_if(!extracted_rays, "could not allocate extracted_rays");
lfree_rays = (double*) malloc(nrows * (max_nrays + 100) * sizeof(double));
abort_if(!lfree_rays, "could not allocate lfree_rays");
rval = CG_extract_rays_from_rows(nrows, rows, extracted_rays, &nrays,
variable_to_ray, scale, indices, &nz);
abort_if(rval, "CG_extract_rays_from_rows failed");
for (double norm_cutoff = 0.00; norm_cutoff <= 5.0; norm_cutoff+= 0.1)
{
lfree_nrays = 0;
for (int i = 0; i < nrays; i++)
{
int keep = 1;
double *r = &extracted_rays[nrows * i];
for (int j = 0; j < lfree_nrays; j++)
{
double *q = &extracted_rays[nrows * j];
double norm = 0;
for(int k = 0; k < nrows; k++)
norm += fabs(r[k] - q[k]);
if(norm <= norm_cutoff)
{
keep = 0;
break;
}
}
if(keep)
{
memcpy(&lfree_rays[nrows * lfree_nrays], r, nrows * sizeof(double));
lfree_nrays++;
}
}
log_debug(" norm_cutoff=%8.2lf nrays=%8d\n", norm_cutoff, lfree_nrays);
if(lfree_nrays < MAX_N_RAYS) break;
}
if(ENABLE_LIFTING)
{
abort_if(nrows > 3, "not implemented");
int n_extra_rays;
double extra_rays[100];
if(nrows == 2)
{
extra_rays[0] = 0.0001;
extra_rays[1] = 0.0000;
extra_rays[2] = -0.0001;
extra_rays[3] = 0.0001;
extra_rays[4] = -0.0001;
extra_rays[5] = -0.0001;
n_extra_rays = 3;
}
else if(nrows == 3)
{
extra_rays[0] = 0.0000;
extra_rays[1] = 0.0000;
extra_rays[2] = 0.0001;
extra_rays[3] = 0.0001;
extra_rays[4] = 0.0000;
extra_rays[5] = -0.0001;
extra_rays[6] = -0.0001;
extra_rays[7] = 0.0000;
extra_rays[8] = -0.0001;
extra_rays[ 9] = -0.0001;
extra_rays[10] = -0.0001;
extra_rays[11] = -0.0001;
n_extra_rays = 4;
}
for(int i = 0; i < n_extra_rays; i++)
{
double *r = &extra_rays[nrows * i];
double scale;
int found, index;
rval = CG_find_ray(nrows, lfree_rays, lfree_nrays, r, &found,
&scale, &index);
abort_if(rval, "CG_find_ray failed");
if(!found) {
memcpy(&lfree_rays[nrows * lfree_nrays], r, nrows *
sizeof(double));
lfree_nrays++;
}
}
}
if(lfree_nrays < 3)
{
rval = ERR_NO_CUT;
cut->pi = 0;
cut->indices = 0;
goto CLEANUP;
}
log_debug("Extracted %d rays\n", lfree_nrays);
if_verbose_level
{
print_rays(variable_to_ray, indices, f, extracted_rays, scale, nrays,
nz, nrows);
}
beta = (double *) malloc((lfree_nrays) * sizeof(double));
abort_if(!beta, "could not allocate beta");
log_verbose("Computing lattice-free set...\n");
if(nrows == 2)
{
rval = sort_rays_angle(lfree_rays, lfree_nrays, beta);
abort_if(rval, "sort_rays_angle failed");
rval = GREEDY_2D_generate_cut(lfree_rays, lfree_nrays, f, beta);
if(rval)
{
rval = ERR_NO_CUT;
goto CLEANUP;
}
}
else
{
rval = GREEDY_ND_generate_cut(nrows, lfree_nrays, f, lfree_rays, beta);
if(rval)
{
rval = ERR_NO_CUT;
goto CLEANUP;
}
}
if(DUMP_CUT)
{
char filename[100];
sprintf(filename, "cut-%03d.sage", DUMP_CUT_N++);
time_printf("Writing %s...\n", filename);
rval = GREEDY_write_sage_file(nrows, lfree_nrays, f, lfree_rays, beta,
filename);
abort_if(rval, "GREEDY_write_sage_file failed");
}
rval = create_cut(nrows, column_types, nrays, f, lfree_nrays, lfree_rays,
beta, extracted_rays, nz, variable_to_ray, indices, scale, cut);
abort_if(rval, "create_cut failed");
if_verbose_level print_cut(cut);
CLEANUP:
if (f) free(f);
if (variable_to_ray) free(variable_to_ray);
if (beta) free(beta);
if (indices) free(indices);
if (scale) free(scale);
if (scaled_rays) free(scaled_rays);
if (lfree_rays) free(lfree_rays);
return rval;
}
#endif // TEST_SOURCE

View File

@@ -0,0 +1,616 @@
/* Copyright (c) 2015 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>
#define TEST_SOURCE
extern "C" {
#include <multirow/util.h>
#include <infinity/greedy-2d.h>
#include "../src/greedy-2d.c"
}
#define BOUNDS_EPSILON 0.01
TEST(Greedy2DTest, test_generate_cut_1)
{
int rval = 0;
double bounds[100];
double f[] = {1 / 4.0, 3 / 4.0};
double rays[] = {-2 / 5.0, 5 / 7.0, 0.0, 1.0, 1.0, 1.0, 4 / 5.0, -2 / 3.0,
-1.0, 0.0};
rval = GREEDY_2D_generate_cut(rays, 5, f, bounds);
abort_if(rval, "GREEDY_2D_generate_cut failed");
EXPECT_NEAR(23 / 50.0, bounds[0], BOUNDS_EPSILON);
EXPECT_NEAR(23 / 42.0, bounds[1], BOUNDS_EPSILON);
EXPECT_NEAR(9 / 11.0, bounds[2], BOUNDS_EPSILON);
EXPECT_NEAR(9 / 11.0, bounds[3], BOUNDS_EPSILON);
EXPECT_NEAR(23 / 50.0, bounds[4], BOUNDS_EPSILON);
CLEANUP:
if (rval) FAIL();
}
TEST(Greedy2DTest, test_generate_cut_2)
{
int rval = 0;
double bounds[100];
double f[] = {1 / 2.0, 1 / 2.0};
double rays[] = {
-1.0, -1.0,
-1.0, 1.0,
1.0, 1.0,
1.0, 0.0,
1.0, -1.0
};
rval = GREEDY_2D_generate_cut(rays, 5, f, bounds);
abort_if(rval, "GREEDY_2D_generate_cut failed");
EXPECT_NEAR(0.5, bounds[0], BOUNDS_EPSILON);
EXPECT_NEAR(0.5, bounds[1], BOUNDS_EPSILON);
EXPECT_NEAR(0.5, bounds[2], BOUNDS_EPSILON);
EXPECT_EQ(GREEDY_BIG_E, bounds[3]);
EXPECT_NEAR(0.5, bounds[4], BOUNDS_EPSILON);
CLEANUP:
if (rval) FAIL();
}
TEST(Greedy2DTest, test_generate_cut_3)
{
int rval = 0;
double bounds[100];
double f[] = {5 / 22.0, 0.0};
double rays[] = {-1 / 22.0, 0.0, 0.0, 1 / 18.0, 1 / 22.0, 0.0};
rval = GREEDY_2D_generate_cut(rays, 3, f, bounds);
abort_if(rval, "GREEDY_2D_generate_cut failed");
EXPECT_NEAR(5.0, bounds[0], BOUNDS_EPSILON);
EXPECT_NEAR(17.0, bounds[2], BOUNDS_EPSILON);
EXPECT_EQ(GREEDY_BIG_E, bounds[1]);
CLEANUP:
if (rval) FAIL();
}
TEST(Greedy2DTest, scale_to_chull_test)
{
int rval = 0;
double rays[] = {
0, 1,
1, 1,
0.5, 0.25,
1, 0,
-1, -1,
-0.25, 0
};
double scale[6];
int nrays = 6;
rval = scale_to_chull(rays, nrays, scale);
abort_if(rval, "scale_to_chull failed");
EXPECT_NEAR(rays[0], 0.0, BOUNDS_EPSILON);
EXPECT_NEAR(rays[1], 1.0, BOUNDS_EPSILON);
EXPECT_NEAR(rays[2], 1.0, BOUNDS_EPSILON);
EXPECT_NEAR(rays[3], 1.0, BOUNDS_EPSILON);
EXPECT_NEAR(rays[4], 1.0, BOUNDS_EPSILON);
EXPECT_NEAR(rays[5], 0.5, BOUNDS_EPSILON);
EXPECT_NEAR(rays[6], 1.0, BOUNDS_EPSILON);
EXPECT_NEAR(rays[7], 0.0, BOUNDS_EPSILON);
EXPECT_NEAR(rays[8],-1.0, BOUNDS_EPSILON);
EXPECT_NEAR(rays[9],-1.0, BOUNDS_EPSILON);
EXPECT_NEAR(rays[10],-0.5, BOUNDS_EPSILON);
EXPECT_NEAR(rays[11], 0.0, BOUNDS_EPSILON);
EXPECT_NEAR(scale[0], 1.0, BOUNDS_EPSILON);
EXPECT_NEAR(scale[1], 1.0, BOUNDS_EPSILON);
EXPECT_NEAR(scale[2], 2.0, BOUNDS_EPSILON);
EXPECT_NEAR(scale[3], 1.0, BOUNDS_EPSILON);
EXPECT_NEAR(scale[4], 1.0, BOUNDS_EPSILON);
EXPECT_NEAR(scale[5], 2.0, BOUNDS_EPSILON);
CLEANUP:
if(rval) FAIL();
}
TEST(Greedy2DTest, scale_to_chull_test_2)
{
int rval = 0;
double rays[] = {
1, 1,
0.5, 0.25,
1, 0,
};
double scale[3];
int nrays = 3;
rval = scale_to_chull(rays, nrays, scale);
abort_if(rval, "scale_to_chull failed");
EXPECT_NEAR(rays[0], 1.0, BOUNDS_EPSILON);
EXPECT_NEAR(rays[1], 1.0, BOUNDS_EPSILON);
EXPECT_NEAR(rays[2], 1.0, BOUNDS_EPSILON);
EXPECT_NEAR(rays[3], 0.5, BOUNDS_EPSILON);
EXPECT_NEAR(rays[4], 1.0, BOUNDS_EPSILON);
EXPECT_NEAR(rays[5], 0.0, BOUNDS_EPSILON);
EXPECT_NEAR(scale[0], 1.0, BOUNDS_EPSILON);
EXPECT_NEAR(scale[1], 2.0, BOUNDS_EPSILON);
EXPECT_NEAR(scale[2], 1.0, BOUNDS_EPSILON);
CLEANUP:
if(rval) FAIL();
}
TEST(Greedy2DTest, find_containing_cone_test)
{
int rval = 0;
double rays[] = {-1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 1.0, -1.0, -1.0, -1.0};
double p1[] = {-1.0, 1.0};
double p2[] = {0.0, 1.0};
double p3[] = {1.0, 0.0};
double p4[] = {-1.0, 0.0};
int index1, index2;
double lambda1, lambda2;
rval = find_containing_cone(rays, 5, p1, &index1, &index2, &lambda1, &lambda2);
abort_if(rval, "find_containing_cone failed");
EXPECT_EQ(0, index1);
EXPECT_EQ(1, index2);
rval = find_containing_cone(rays, 5, p2, &index1, &index2, &lambda1, &lambda2);
abort_if(rval, "find_containing_cone failed");
EXPECT_EQ(0, index1);
EXPECT_EQ(1, index2);
rval = find_containing_cone(rays, 5, p3, &index1, &index2, &lambda1, &lambda2);
abort_if(rval, "find_containing_cone failed");
EXPECT_EQ(1, index1);
EXPECT_EQ(2, index2);
rval = find_containing_cone(rays, 5, p4, &index1, &index2, &lambda1, &lambda2);
abort_if(rval, "find_containing_cone failed");
EXPECT_EQ(4, index1);
EXPECT_EQ(0, index2);
CLEANUP:
if(rval) FAIL();
}
TEST(Greedy2DTest, find_containing_cone_test_2)
{
int rval = 0;
double rays[] = {0.0, 0.5, 1.0, 0.0, -0.5, 0.5};
double p[] = {0.5, -0.5};
int index1, index2;
double lambda1, lambda2;
rval = find_containing_cone(rays, 3, p, &index1, &index2, &lambda1, &lambda2);
abort_if(rval, "find_containing_cone failed");
EXPECT_EQ(-1, index1);
EXPECT_EQ(-1, index2);
CLEANUP:
if(rval) FAIL();
}
TEST(Greedy2DTest, find_containing_cone_test_3)
{
int rval = 0;
double rays[] = {
-1, -0.1,
1, -0.1,
1, -0.5,
-1, -0.5,
};
double p[] = { 0, -2 };
int index1, index2;
double lambda1, lambda2;
rval = find_containing_cone(rays, 4, p, &index1, &index2, &lambda1, &lambda2);
abort_if(rval, "find_containing_cone failed");
EXPECT_EQ(2, index1);
EXPECT_EQ(3, index2);
CLEANUP:
if(rval) FAIL();
}
//TEST(Greedy2DTest, test_generate_cut_4)
//{
// int rval = 0;
// double bounds[100];
// double f[] = {5 / 22.0, 10 / 19.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};
//
// rval = GREEDY_2D_generate_cut(rays, 6, f, bounds);
// abort_if(rval, "GREEDY_2D_generate_cut failed");
//
// EXPECT_NEAR(20.0, bounds[0], BOUNDS_EPSILON);
// EXPECT_NEAR(20.0, bounds[1], BOUNDS_EPSILON);
// EXPECT_NEAR(18.0, bounds[2], BOUNDS_EPSILON);
// EXPECT_NEAR(18.0, bounds[5], BOUNDS_EPSILON);
// EXPECT_EQ(GREEDY_BIG_E, bounds[3]);
// EXPECT_EQ(GREEDY_BIG_E, bounds[4]);
//
// CLEANUP:
// if (rval) FAIL();
//}
//
//TEST(Greedy2DTest, test_generate_cut_5)
//{
// int rval = 0;
// double bounds[100];
// double f[] = {0.22727272727272729291, 0.52631578947368418131};
// double rays[] = {0.00000000000000000000, -0.02631578947368420907,
// -0.04545454545454545581, -0.02631578947368420907,
// 0.00000000000000000000, 0.02631578947368420907,
// -0.04545454545454545581, 0.00000000000000000000,
// 0.04545454545454545581, 0.00000000000000000000,
// 0.04545454545454545581, 0.02631578947368420907};
//
// rval = GREEDY_2D_generate_cut(rays, 6, f, bounds);
// abort_if(rval, "GREEDY_2D_generate_cut failed");
//
// EXPECT_NEAR(20.0, bounds[0], BOUNDS_EPSILON);
// EXPECT_NEAR(20.0, bounds[1], BOUNDS_EPSILON);
// EXPECT_NEAR(18.0, bounds[2], BOUNDS_EPSILON);
// EXPECT_NEAR(18.0, bounds[5], BOUNDS_EPSILON);
// EXPECT_EQ(GREEDY_BIG_E, bounds[3]);
// EXPECT_EQ(GREEDY_BIG_E, bounds[4]);
//
// CLEANUP:
// if (rval) FAIL();
//}
//
//
//
//TEST(Greedy2DTest, get_peak_ray_test_1)
//{
// int rval = 0;
//
// double rays[] = {-2.0, 0.0, -1.0, 1.0, 1.0, 1.0, 2.0, 0.0, 1.0, -1.0, -1.0, -1.0 };
// int nrays = 6;
//
// double normal1[] = { 0.0, 1.0 };
// double normal2[] = { 1.0, 1.0 };
// double normal3[] = { 0.0, -1.0 };
// double normal4[] = {-1.0, -1.0 };
// int index;
//
// rval = get_peak_ray(rays, nrays, normal1, &index);
// abort_if(rval, "get_peak_ray failed");
// EXPECT_TRUE(index == 1 || index == 2);
//
// rval = get_peak_ray(rays, nrays, normal3, &index);
// abort_if(rval, "get_peak_ray failed");
// EXPECT_TRUE(index == 4 || index == 5);
//
// rval = get_peak_ray(rays, nrays, normal2, &index);
// abort_if(rval, "get_peak_ray failed");
// EXPECT_EQ(2, index);
//
// rval = get_peak_ray(rays, nrays, normal4, &index);
// abort_if(rval, "get_peak_ray failed");
// EXPECT_EQ(5, index);
//
// CLEANUP:
// if(rval) FAIL();
//}
//
//TEST(Greedy2DTest, get_peak_ray_test_2)
//{
// int rval = 0;
//
// double rays[] = { -1e100, 0, 0, 1, 1e100, 0, 1, -1, -1,-1 };
// int nrays = 5;
//
// double normal1[] = { 0.0, 1.0 };
// double normal2[] = { 1.0, 1.0 };
// double normal3[] = { 1.0, 0.0 };
// double normal4[] = { 0.0, -1.0 };
// double normal5[] = { -1.0, -1.0 };
// double normal6[] = { -1.0, 0.0 };
// int index;
//
// rval = get_peak_ray(rays, nrays, normal1, &index);
// abort_if(rval, "get_peak_ray failed");
// EXPECT_EQ(1, index);
//
// rval = get_peak_ray(rays, nrays, normal4, &index);
// abort_if(rval, "get_peak_ray failed");
// EXPECT_EQ(3, index);
//
// rval = get_peak_ray(rays, nrays, normal2, &index);
// abort_if(rval, "get_peak_ray failed");
// EXPECT_EQ(2, index);
//
// rval = get_peak_ray(rays, nrays, normal5, &index);
// abort_if(rval, "get_peak_ray failed");
// EXPECT_EQ(0, index);
//
// rval = get_peak_ray(rays, nrays, normal3, &index);
// abort_if(rval, "get_peak_ray failed");
// EXPECT_EQ(2, index);
//
// rval = get_peak_ray(rays, nrays, normal6, &index);
// abort_if(rval, "get_peak_ray failed");
// EXPECT_EQ(0, index);
//
// CLEANUP:
// if(rval) FAIL();
//}
//
//TEST(Greedy2DTest, get_peak_ray_test_3)
//{
// int rval = 0;
//
// double rays[] = { -1, 1, 0, 1, 1, 1};
// int nrays = 3;
//
// double normal1[] = { 0.0, -1.0 };
// int index;
//
// rval = get_peak_ray(rays, nrays, normal1, &index);
// EXPECT_EQ(ERR_NOT_FOUND, rval);
// rval = 0;
//
// CLEANUP:
// if(rval) FAIL();
//}
//
//TEST(Greedy2DTest, nearest_lattice_point_test_1)
//{
// int rval = 0;
//
// double z0a[] = {100, 1};
// double z0b[] = {-100, 1};
// double g[] = {-1, 0};
//
// double x1[] = {-1.34, 1};
// double x2[] = {-3, 1};
//
// double z1[2];
// double z2[2];
//
// rval = nearest_lattice_points(g, z0a, x1, z1, z2);
// abort_if(rval, "nearest_lattice_points failed");
// EXPECT_DOUBLE_EQ(-1, z1[0]);
// EXPECT_DOUBLE_EQ(1, z1[1]);
// EXPECT_DOUBLE_EQ(-2, z2[0]);
// EXPECT_DOUBLE_EQ(1, z2[1]);
//
// rval = nearest_lattice_points(g, z0b, x1, z1, z2);
// abort_if(rval, "nearest_lattice_points failed");
// EXPECT_DOUBLE_EQ(-1, z1[0]);
// EXPECT_DOUBLE_EQ(1, z1[1]);
// EXPECT_DOUBLE_EQ(-2, z2[0]);
// EXPECT_DOUBLE_EQ(1, z2[1]);
//
// rval = nearest_lattice_points(g, z0a, x2, z1, z2);
// abort_if(rval, "nearest_lattice_points failed");
// EXPECT_DOUBLE_EQ(-3, z1[0]);
// EXPECT_DOUBLE_EQ(1, z1[1]);
// EXPECT_DOUBLE_EQ(-3, z2[0]);
// EXPECT_DOUBLE_EQ(1, z2[1]);
//
// CLEANUP:
// if(rval) FAIL();
//}
//
//TEST(Greedy2DTest, nearest_lattice_point_test_2)
//{
// int rval = 0;
//
// double z0[] = {1, 1};
// double g[] = {1, 2};
// double x[] = {3.35, 5.7};
//
// double z1[2];
// double z2[2];
//
// rval = nearest_lattice_points(g, z0, x, z1, z2);
// abort_if(rval, "nearest_lattice_points failed");
// EXPECT_DOUBLE_EQ(3, z1[0]);
// EXPECT_DOUBLE_EQ(5, z1[1]);
//
// CLEANUP:
// if(rval) FAIL();
//}
//
//TEST(Greedy2DTest, find_normal_test)
//{
// int rval = 0;
//
// double d1[] = {1.0, 0.0};
// double d2[] = {1.0, 1.0};
//
// double x1[] = {1.0, 1.0};
// double x2[] = {1.0, -1.0};
//
// double n[2];
//
// rval = find_normal(d1, x1, n);
// abort_if(rval, "find_normal failed");
// EXPECT_DOUBLE_EQ(0, n[0]);
// EXPECT_DOUBLE_EQ(1, n[1]);
//
// rval = find_normal(d1, x2, n);
// abort_if(rval, "find_normal failed");
// EXPECT_DOUBLE_EQ(0, n[0]);
// EXPECT_DOUBLE_EQ(-1, n[1]);
//
// rval = find_normal(d2, x1, n);
// abort_if(rval, "find_normal failed");
// EXPECT_DOUBLE_EQ(0, n[0]);
// EXPECT_DOUBLE_EQ(0, n[1]);
//
// rval = find_normal(d2, x2, n);
// abort_if(rval, "find_normal failed");
// EXPECT_DOUBLE_EQ(1, n[0]);
// EXPECT_DOUBLE_EQ(-1, n[1]);
//
// CLEANUP:
// if(rval) FAIL();
//}
//
//TEST(Greedy2DTest, check_rays_parallel)
//{
// double r1[] = {1.0, 2.0};
// double r2[] = {2.0, 4.0};
// double r3[] = {-2.0, -4.0};
// double r4[] = {0.0, 0.0};
//
// int match;
// double scale;
//
// check_rays_parallel(r1, r2, &match, &scale);
// EXPECT_TRUE(match);
// EXPECT_DOUBLE_EQ(scale, 0.5);
//
// check_rays_parallel(r1, r1, &match, &scale);
// EXPECT_TRUE(match);
// EXPECT_DOUBLE_EQ(scale, 1.0);
//
// check_rays_parallel(r2, r3, &match, &scale);
// EXPECT_FALSE(match);
//
// check_rays_parallel(r1, r4, &match, &scale);
// EXPECT_FALSE(match);
//}
//
//TEST(Greedy2DTest, find_ray)
//{
// double rays[] = {1.0, 2.0, -1.0, 0.0, -5.0, -5.0};
// int nrays = 3;
//
// double r1[] = {1.0, 2.0};
// double r2[] = {-2.0, 0.0};
// double r3[] = {-1.0, -1.0};
// double r4[] = {7.0, 1.0};
// double r5[] = {-1.0, -2.0};
//
// int found, index;
// double scale;
//
// find_ray(rays, nrays, r1, &found, &scale, &index);
// EXPECT_TRUE(found);
// EXPECT_EQ(index, 0);
// EXPECT_DOUBLE_EQ(scale, 1.0);
//
// find_ray(rays, nrays, r2, &found, &scale, &index);
// EXPECT_TRUE(found);
// EXPECT_EQ(index, 1);
// EXPECT_DOUBLE_EQ(scale, 2.0);
//
// find_ray(rays, nrays, r3, &found, &scale, &index);
// EXPECT_TRUE(found);
// EXPECT_EQ(index, 2);
// EXPECT_DOUBLE_EQ(scale, 1 / 5.0);
//
// find_ray(rays, nrays, r4, &found, &scale, &index);
// EXPECT_FALSE(found);
//
// find_ray(rays, nrays, r5, &found, &scale, &index);
// EXPECT_FALSE(found);
//}
//
//TEST(Greedy2DTest, extract_rays_from_two_sparse_rows_test)
//{
// int rval = 0;
//
// char ctypes[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
// double pi1[] = {-3.0, 1.0, -2.0, -1.5, -3.0};
// int indices1[] = {2, 3, 6, 7, 9};
//
// double pi2[] = {1.0, -2.0, -3.0, -1.0};
// int indices2[] = {0, 2, 5, 7};
//
// struct Row row1 = {.nz = 5, .head = 3, .pi_zero = 0, .pi = pi1, .indices = indices1};
// struct Row row2 = {.nz = 4, .head = 0, .pi_zero = 0, .pi = pi2, .indices = indices2};
//
// int nrays;
// int nz;
//
// double rays[100];
// int indices[100];
// double ray_scale[100];
// int variable_to_ray[100];
//
// rval = extract_rays_from_two_sparse_rows(&row1, &row2, ctypes, rays, &nrays,
// variable_to_ray, ray_scale, indices, &nz);
// abort_if(rval, "extract_rays_from_two_sparse_rows failed");
//
// EXPECT_EQ(nrays, 3);
// EXPECT_EQ(nz, 5);
//
// EXPECT_DOUBLE_EQ(rays[0], 3.0);
// EXPECT_DOUBLE_EQ(rays[1], 2.0);
// EXPECT_DOUBLE_EQ(rays[2], 0.0);
// EXPECT_DOUBLE_EQ(rays[3], 3.0);
// EXPECT_DOUBLE_EQ(rays[4], 2.0);
// EXPECT_DOUBLE_EQ(rays[5], 0.0);
//
// EXPECT_EQ(indices[0], 2);
// EXPECT_EQ(indices[1], 5);
// EXPECT_EQ(indices[2], 6);
// EXPECT_EQ(indices[3], 7);
// EXPECT_EQ(indices[4], 9);
//
// EXPECT_EQ(variable_to_ray[0], 0);
// EXPECT_EQ(variable_to_ray[1], 1);
// EXPECT_EQ(variable_to_ray[2], 2);
// EXPECT_EQ(variable_to_ray[3], 0);
// EXPECT_EQ(variable_to_ray[4], 2);
//
// EXPECT_DOUBLE_EQ(ray_scale[0], 1.0);
// EXPECT_DOUBLE_EQ(ray_scale[1], 1.0);
// EXPECT_DOUBLE_EQ(ray_scale[2], 1.0);
// EXPECT_DOUBLE_EQ(ray_scale[3], 0.5);
// EXPECT_DOUBLE_EQ(ray_scale[4], 1.5);
//
// CLEANUP:
// if (rval) FAIL();
//}
//

View File

@@ -0,0 +1,457 @@
/* Copyright (c) 2015 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 <math.h>
#include <multirow/lp.h>
#include <multirow/util.h>
#include <infinity/greedy-nd.h>
}
int ENABLE_LIFTING = 0;
int MIN_N_ROWS = 2;
int MAX_N_ROWS = 2;
int DUMP_CUT = 0;
int DUMP_CUT_N = 0;
TEST(GreedyNDTest, find_violated_cone_test)
{
int rval = 0;
int nrows = 2;
int nrays = 4;
double f[] = { 0.5, 0.5 };
double rays[] =
{
-1.0, 1.0,
1.0, 1.0,
1.0, -1.0,
-1.0, -1.0
};
double x[] = { 1.0, 0.5 };
double beta[] = { INFINITY, INFINITY, INFINITY, INFINITY };
double sbar[nrays];
int rx[nrays];
int found;
rval = GREEDY_ND_find_violated_cone(nrows, nrays, f, rays, x, beta,
1.0, rx, sbar, &found);
abort_if(rval, "GREEDY_ND_find_violated_cone failed");
EXPECT_TRUE(found);
EXPECT_FALSE(rx[0]);
EXPECT_TRUE(rx[1]);
EXPECT_TRUE(rx[2]);
EXPECT_FALSE(rx[3]);
rval = GREEDY_ND_find_violated_cone(nrows, nrays, f, rays, x, beta,
0.5, rx, sbar, &found);
abort_if(rval, "GREEDY_ND_find_violated_cone failed");
EXPECT_FALSE(found);
CLEANUP:
if(rval) FAIL();
}
TEST(GreedyNDTest, find_tight_rays_test_1)
{
int rval = 0;
double f[] = { 0.5, 0.5 };
double rays[] =
{
1.0, 1.0,
1.0, -1.0,
-1.0, -1.0,
-1.0, 1.0,
0.0, 1.0,
1.0, 0.0
};
double beta[] = { INFINITY, INFINITY, INFINITY, INFINITY, INFINITY,
INFINITY };
double epsilon = 0.5;
double x[] = { 1.0, 1.0 };
int tx[6];
rval = GREEDY_ND_find_tight_rays(2, 6, f, rays, x, beta, epsilon, tx);
abort_if(rval, "GREEDY_ND_find_tight_rays failed");
EXPECT_TRUE(tx[0]);
EXPECT_FALSE(tx[1]);
EXPECT_FALSE(tx[2]);
EXPECT_FALSE(tx[3]);
EXPECT_FALSE(tx[4]);
EXPECT_FALSE(tx[5]);
CLEANUP:
if(rval) FAIL();
}
TEST(GreedyNDTest, find_tight_rays_test_2)
{
int rval = 0;
double f[] = { 0.5, 0.5 };
double rays[] =
{
1.0, 1.0,
1.0, -1.0,
-1.0, -1.0,
-1.0, 1.0,
0.0, 1.0,
1.0, 0.0
};
double beta[] = { 0.5, 0.5, 0.5, 0.5, INFINITY, INFINITY };
double epsilon = 1.0;
double x[] = { 1.0, 1.0 };
int tx[6];
rval = GREEDY_ND_find_tight_rays(2, 6, f, rays, x, beta, epsilon, tx);
abort_if(rval, "GREEDY_ND_find_tight_rays failed");
EXPECT_TRUE(tx[0]);
EXPECT_FALSE(tx[1]);
EXPECT_FALSE(tx[2]);
EXPECT_FALSE(tx[3]);
EXPECT_TRUE(tx[4]);
EXPECT_TRUE(tx[5]);
CLEANUP:
if(rval) FAIL();
}
TEST(GreedyNDTest, cone_bound_test_1)
{
int rval = 0;
double f[] = { 0.5, 0.5 };
double rays[] =
{
1.0, 1.0,
1.0, -1.0,
-1.0, -1.0,
-1.0, 1.0,
0.0, 1.0,
1.0, 0.0
};
double beta[] = { INFINITY, INFINITY, INFINITY, INFINITY, INFINITY,
INFINITY };
double x[] = { 1.0, 1.0 };
int rx1[] = { 1, 0, 0, 0, 0, 0 };
int rx2[] = { 0, 0, 0, 0, 1, 1 };
double epsilon;
rval = GREEDY_ND_cone_bound(2, 6, f, rays, rx1, x, beta, &epsilon);
abort_if(rval, "GREEDY_ND_cone_bound failed");
EXPECT_NEAR(0.5, epsilon, 1e-6);
rval = GREEDY_ND_cone_bound(2, 6, f, rays, rx2, x, beta, &epsilon);
abort_if(rval, "GREEDY_ND_cone_bound failed");
EXPECT_NEAR(1.0, epsilon, 1e-6);
CLEANUP:
if(rval) FAIL();
}
TEST(GreedyNDTest, cone_bound_test_2)
{
int rval = 0;
double f[] = { 0.0, 0.0 };
double rays[] =
{
0.0, 1.0,
1.0, 0.0
};
int rx[] = { 1, 1 };
double beta1[] = { 100, 100 };
double beta2[] = { 0.5, 100 };
double beta3[] = { 0.5, 1.0 };
double x1[] = { 0.5, 0.5 };
double x2[] = { 0.5, 0.25 };
double epsilon;
rval = GREEDY_ND_cone_bound(2, 2, f, rays, rx, x1, beta1, &epsilon);
abort_if(rval, "GREEDY_ND_cone_bound failed");
EXPECT_NEAR(1.0, epsilon, 1e-6);
rval = GREEDY_ND_cone_bound(2, 2, f, rays, rx, x1, beta2, &epsilon);
abort_if(rval, "GREEDY_ND_cone_bound failed");
EXPECT_EQ(INFINITY, epsilon);
rval = GREEDY_ND_cone_bound(2, 2, f, rays, rx, x2, beta2, &epsilon);
abort_if(rval, "GREEDY_ND_cone_bound failed");
EXPECT_NEAR(1.0, epsilon, 1e-6);
rval = GREEDY_ND_cone_bound(2, 2, f, rays, rx, x2, beta3, &epsilon);
abort_if(rval, "GREEDY_ND_cone_bound failed");
EXPECT_EQ(INFINITY, epsilon);
CLEANUP:
if(rval) FAIL();
}
TEST(GreedyNDTest, bound_test_1)
{
int rval = 0;
double f[] = { 0.5, 0.5 };
double rays[] =
{
1.0, 1.0,
1.0, -1.0,
-1.0, -1.0,
-1.0, 1.0,
0.0, 1.0,
1.0, 0.0
};
double beta1[] = { INFINITY, INFINITY, INFINITY, INFINITY, INFINITY, INFINITY };
double beta2[] = { 0.5, 0.5, 0.5, 0.5, INFINITY, INFINITY };
double beta3[] = { 0.5, 0.5, 0.5, 0.5, 1.0, 1.0 };
double x[] = { 1.0, 1.0 };
double epsilon;
int tx[6];
rval = GREEDY_ND_bound(2, 6, f, rays, x, beta1, &epsilon, tx);
abort_if(rval, "GREEDY_ND_bound failed");
EXPECT_NEAR(epsilon, 0.5, 1e-6);
EXPECT_TRUE(tx[0]);
EXPECT_FALSE(tx[1]);
EXPECT_FALSE(tx[2]);
EXPECT_FALSE(tx[3]);
EXPECT_FALSE(tx[4]);
EXPECT_FALSE(tx[5]);
rval = GREEDY_ND_bound(2, 6, f, rays, x, beta2, &epsilon, tx);
abort_if(rval, "GREEDY_ND_bound failed");
EXPECT_NEAR(epsilon, 1.0, 1e-6);
EXPECT_TRUE(tx[0]);
EXPECT_FALSE(tx[1]);
EXPECT_FALSE(tx[2]);
EXPECT_FALSE(tx[3]);
EXPECT_TRUE(tx[4]);
EXPECT_TRUE(tx[5]);
rval = GREEDY_ND_bound(2, 6, f, rays, x, beta3, &epsilon, tx);
abort_if(rval, "GREEDY_ND_bound failed");
EXPECT_EQ(epsilon, INFINITY);
EXPECT_FALSE(tx[0]);
EXPECT_FALSE(tx[1]);
EXPECT_FALSE(tx[2]);
EXPECT_FALSE(tx[3]);
EXPECT_FALSE(tx[4]);
EXPECT_FALSE(tx[5]);
CLEANUP:
if(rval) FAIL();
}
TEST(GreedyNDTest, psi_test)
{
int rval = 0;
double f[] = { 0.5, 0.5 };
double rays[] =
{
1.0, 1.0,
1.0, -1.0,
-1.0, -1.0,
-1.0, 1.0,
0.0, 1.0,
1.0, 0.0
};
double beta[] = { 0.5, 0.5, 0.5, 0.5, 1.0, 1.0 };
double q1[] = { 1.0, 1.0 };
double q2[] = { -2.0, 0.0 };
double value;
struct LP lp;
rval = LP_open(&lp);
abort_if(rval, "LP_open failed");
rval = GREEDY_create_psi_lp(2, 6, f, rays, beta, &lp);
abort_if(rval, "GREEDY_create_psi_lp failed");
rval = GREEDY_ND_psi(2, 6, f, rays, beta, q1, 1.0, &lp, &value);
abort_if(rval, "GREDDY_ND_psi failed");
EXPECT_NEAR(value, 2.0, 1e-6);
rval = GREEDY_ND_psi(2, 6, f, rays, beta, q2, 2.0, &lp, &value);
abort_if(rval, "GREDDY_ND_psi failed");
EXPECT_NEAR(value, 8.0, 1e-6);
CLEANUP:
LP_free(&lp);
if(rval) FAIL();
}
TEST(GreedyNDTest, psi_test_2)
{
int rval = 0;
double f[] = { 0.5, 0.5, 0.5 };
double rays[] =
{
-0.5, -0.5, -0.5,
-0.5, -0.5, 0.5,
-0.5, 0.5, -0.5,
-0.5, 0.5, 0.5,
0.5, -0.5, -0.5,
0.5, -0.5, 0.5,
0.5, 0.5, -0.5,
0.5, 0.5, 0.5,
};
double beta[] = { 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 };
double q1[] = { 0.5, 0.5, 0.5 };
double q2[] = { 1, 0, 0 };
double value;
struct LP lp;
rval = LP_open(&lp);
abort_if(rval, "LP_open failed");
rval = GREEDY_create_psi_lp(3, 8, f, rays, beta, &lp);
abort_if(rval, "GREEDY_create_psi_lp failed");
rval = GREEDY_ND_psi(3, 8, f, rays, beta, q1, 1.0, &lp, &value);
abort_if(rval, "GREDDY_ND_psi failed");
EXPECT_NEAR(value, 1.0, 1e-6);
rval = GREEDY_ND_psi(3, 8, f, rays, beta, q2, 1.0, &lp, &value);
abort_if(rval, "GREDDY_ND_psi failed");
EXPECT_NEAR(value, 2.0, 1e-6);
CLEANUP:
if(rval) FAIL();
}
TEST(GreedyNDTest, generate_cut_test_1)
{
int rval = 0;
double f[] = { 0.5, 0.5 };
double rays[] =
{
1.0, 1.0,
1.0, -1.0,
-1.0, -1.0,
-1.0, 1.0,
0.0, 1.0,
1.0, 0.0
};
double beta[6];
rval = GREEDY_ND_generate_cut(2, 6, f, rays, beta);
abort_if(rval, "GREEDY_ND_generate_cut failed");
EXPECT_NEAR(beta[0], 0.5, 1e-6);
EXPECT_NEAR(beta[1], 0.5, 1e-6);
EXPECT_NEAR(beta[2], 0.5, 1e-6);
EXPECT_NEAR(beta[3], 0.5, 1e-6);
EXPECT_NEAR(beta[4], 1.0, 1e-6);
EXPECT_NEAR(beta[5], 1.0, 1e-6);
CLEANUP:
if(rval) FAIL();
}
TEST(GreedyNDTest, generate_cut_test_2)
{
int rval = 0;
double f[] = { 0.75, 0.75, 0.75};
double rays[] =
{
1.0, 0.0, 0.0,
-1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, -1.0, 0.0,
0.0, 0.0, 1.0,
0.0, 0.0, -1.0
};
double beta[6];
rval = GREEDY_ND_generate_cut(3, 6, f, rays, beta);
abort_if(rval, "GREEDY_ND_generate_cut failed");
EXPECT_NEAR(beta[0], 0.75, 1e-6);
EXPECT_NEAR(beta[1], 2.25, 1e-6);
EXPECT_NEAR(beta[2], 0.75, 1e-6);
EXPECT_NEAR(beta[3], 2.25, 1e-6);
EXPECT_NEAR(beta[4], 0.75, 1e-6);
EXPECT_NEAR(beta[5], 2.25, 1e-6);
CLEANUP:
if(rval) FAIL();
}
TEST(GreedyNTest, scale_to_ahull_test)
{
int rval = 0;
double rays[] =
{
0.0, 0.0, 1.0,
0.0, 1.0, 0.0,
1.0, 0.0, 0.0,
-1.0, 0.0, 0.0
};
int rx[] = { 1, 1, 1 , 0 };
double beta[] = { INFINITY, INFINITY, INFINITY, INFINITY };
double epsilon = 1.0;
double d1[] = { 1.0, 1.0, 1.0 };
double d2[] = { 2.0, 2.0, 0.0 };
double d3[] = { -1.0, -1.0, -1.0 };
double alpha;
rval = GREEDY_ND_scale_to_ahull(3, 4, rays, rx, beta, epsilon, d1, &alpha);
abort_if(rval, "GREEDY_ND_scale_to_ahull failed");
EXPECT_DOUBLE_EQ(1 / 3.0, alpha);
rval = GREEDY_ND_scale_to_ahull(3, 4, rays, rx, beta, epsilon, d2, &alpha);
abort_if(rval, "GREEDY_ND_scale_to_ahull failed");
EXPECT_DOUBLE_EQ(0.25, alpha);
rval = GREEDY_ND_scale_to_ahull(3, 4, rays, rx, beta, epsilon, d3, &alpha);
abort_if(rval, "GREEDY_ND_scale_to_ahull failed");
EXPECT_EQ(INFINITY, alpha);
CLEANUP:
if(rval) FAIL();
}