New project structure
This commit is contained in:
20
infinity/library/CMakeLists.txt
Normal file
20
infinity/library/CMakeLists.txt
Normal 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)
|
||||
37
infinity/library/include/infinity/greedy-2d.h
Normal file
37
infinity/library/include/infinity/greedy-2d.h
Normal 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
|
||||
33
infinity/library/include/infinity/greedy-bsearch.h
Normal file
33
infinity/library/include/infinity/greedy-bsearch.h
Normal 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
|
||||
105
infinity/library/include/infinity/greedy-nd.h
Normal file
105
infinity/library/include/infinity/greedy-nd.h
Normal 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
|
||||
31
infinity/library/include/infinity/greedy.h
Normal file
31
infinity/library/include/infinity/greedy.h
Normal 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
|
||||
738
infinity/library/src/greedy-2d.c
Normal file
738
infinity/library/src/greedy-2d.c
Normal 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
|
||||
246
infinity/library/src/greedy-bsearch.c
Normal file
246
infinity/library/src/greedy-bsearch.c
Normal 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;
|
||||
}
|
||||
1331
infinity/library/src/greedy-nd.c
Normal file
1331
infinity/library/src/greedy-nd.c
Normal file
File diff suppressed because it is too large
Load Diff
478
infinity/library/src/greedy.c
Normal file
478
infinity/library/src/greedy.c
Normal 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
|
||||
616
infinity/library/tests/greedy-2d-test.cpp
Normal file
616
infinity/library/tests/greedy-2d-test.cpp
Normal 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();
|
||||
//}
|
||||
//
|
||||
457
infinity/library/tests/greedy-nd-test.cpp
Normal file
457
infinity/library/tests/greedy-nd-test.cpp
Normal 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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user