New project structure
This commit is contained in:
2
lifting/benchmark/CMakeLists.txt
Normal file
2
lifting/benchmark/CMakeLists.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
add_executable(lifting-benchmark.run src/main.c)
|
||||
target_link_libraries (lifting-benchmark.run LINK_PUBLIC lifting_static multirow_static)
|
||||
639
lifting/benchmark/src/main.c
Normal file
639
lifting/benchmark/src/main.c
Normal file
@@ -0,0 +1,639 @@
|
||||
/* 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 _XOPEN_SOURCE 500
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <getopt.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <multirow/util.h>
|
||||
#include <multirow/double.h>
|
||||
#include <multirow/lfree2d.h>
|
||||
#include <lifting/lifting.h>
|
||||
#include <lifting/lifting-mip.h>
|
||||
|
||||
char LOG_FILENAME[1000] = {0};
|
||||
char STATS_FILENAME[1000] = {0};
|
||||
char SETS_FILENAME[1000] = {0};
|
||||
char ANSWERS_FILENAME[1000] = {0};
|
||||
unsigned int SEED = 0;
|
||||
|
||||
#define ALGORITHM_BOUND 0
|
||||
#define ALGORITHM_NAIVE 1
|
||||
#define ALGORITHM_MIP 2
|
||||
|
||||
int SELECT_NAIVE_ALGORITHM = 0;
|
||||
int SELECT_BOUND_ALGORITHM = 0;
|
||||
int SELECT_MIP_ALGORITHM = 0;
|
||||
|
||||
int ENABLE_PREPROCESSING = 0;
|
||||
int ENABLE_SHEAR = 0;
|
||||
|
||||
int CHECK_ANSWERS = 0;
|
||||
int WRITE_ANSWERS = 0;
|
||||
|
||||
int USE_FIXED_BOUNDS = 0;
|
||||
int NAIVE_BIG_M = 0;
|
||||
int N_SAMPLES_PER_SET = 10;
|
||||
|
||||
int N_ANSWERS = 0;
|
||||
double ANSWERS[100000];
|
||||
|
||||
double PRE_M[100000];
|
||||
double CENTER[100000];
|
||||
|
||||
FILE *LOG_FILE;
|
||||
FILE *STATS_FILE;
|
||||
FILE *ANSWERS_FILE;
|
||||
|
||||
int BOUNDING_BOX_PADDING = 5;
|
||||
|
||||
static const struct option options_tab[] =
|
||||
{
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"sets", required_argument, 0, 'b'},
|
||||
{"log", required_argument, 0, 'l'},
|
||||
{"stats", required_argument, 0, 'o'},
|
||||
{"seed", required_argument, 0, 's'},
|
||||
{"fixed-bounds", required_argument, 0, 'f'},
|
||||
{"naive", no_argument, 0, 'n'},
|
||||
{"bound", no_argument, 0, 'u'},
|
||||
{"preprocess", no_argument, 0, 'p'},
|
||||
{"shear", no_argument, 0, 'e'},
|
||||
{"write-answers", required_argument, 0, 'w'},
|
||||
{"check-answers", required_argument, 0, 'c'},
|
||||
{"samples", required_argument, 0, 'a'},
|
||||
{"mip", no_argument, 0, 'm'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static void print_usage(char **argv)
|
||||
{
|
||||
printf("Usage: %s [OPTION]...\n", argv[0]);
|
||||
printf("Performs trivial lifting using different algorithms.\n\n");
|
||||
|
||||
printf("Parameters:\n");
|
||||
printf("%4s %-20s %s\n", "-l", "--log=FILE",
|
||||
"write log to the specified file");
|
||||
printf("%4s %-20s %s\n", "-b", "--sets=FILE",
|
||||
"file containing lattice-free sets");
|
||||
printf("%4s %-20s %s\n", "-o", "--stats=FILE",
|
||||
"write statistics to the specified file");
|
||||
printf("%4s %-20s %s\n", "-s", "--seed=NUM",
|
||||
"random seed");
|
||||
printf("%4s %-20s %s\n", "-f", "--fixed-bounds=NUM",
|
||||
"user fixed bounds for naive algorithm");
|
||||
printf("%4s %-20s %s\n", "-n", "--naive",
|
||||
"select naive algorithm");
|
||||
printf("%4s %-20s %s\n", "-m", "--mip",
|
||||
"select MIP algorithm");
|
||||
printf("%4s %-20s %s\n", "-u", "--bound",
|
||||
"select bound algorithm");
|
||||
printf("%4s %-20s %s\n", "-p", "--preprocess",
|
||||
"enable pre-processing step in bound algorithm");
|
||||
printf("%4s %-20s %s\n", "-e", "--shear",
|
||||
"apply shear transformation to sets");
|
||||
printf("%4s %-20s %s\n", "-w", "--write-answers=FILE",
|
||||
"write computed coefficients to given file");
|
||||
printf("%4s %-20s %s\n", "-c", "--check-answers=FILE",
|
||||
"check computed coefficients against given file");
|
||||
printf("%4s %-20s %s\n", "-a", "--samples=NUM",
|
||||
"use specified number of samples per set");
|
||||
}
|
||||
|
||||
void stats_printf(const char *fmt,
|
||||
...)
|
||||
{
|
||||
if(STATS_FILE)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vfprintf(STATS_FILE, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
fflush(STATS_FILE);
|
||||
}
|
||||
}
|
||||
|
||||
static int parse_args(int argc,
|
||||
char **argv)
|
||||
{
|
||||
int rval = 0;
|
||||
opterr = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
int c = 0;
|
||||
int option_index = 0;
|
||||
c = getopt_long(argc, argv, "hb:k:s:f:o:nupew:c:a:m", options_tab,
|
||||
&option_index);
|
||||
|
||||
if (c < 0) break;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case 'l':
|
||||
strcpy(LOG_FILENAME, optarg);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
{
|
||||
int count = sscanf(optarg, "%u", &SEED);
|
||||
abort_if(count != 1, "invalid seed");
|
||||
break;
|
||||
}
|
||||
|
||||
case 'a':
|
||||
{
|
||||
int count = sscanf(optarg, "%d", &N_SAMPLES_PER_SET);
|
||||
abort_if(count != 1, "invalid number of samples");
|
||||
abort_if(N_SAMPLES_PER_SET <= 0, "invalid number of samples");
|
||||
break;
|
||||
}
|
||||
|
||||
case 'f':
|
||||
{
|
||||
USE_FIXED_BOUNDS = 1;
|
||||
int count = sscanf(optarg, "%d", &NAIVE_BIG_M);
|
||||
abort_if(count != 1, "invalid fixed bound");
|
||||
break;
|
||||
}
|
||||
|
||||
case 'o':
|
||||
strcpy(STATS_FILENAME, optarg);
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
strcpy(SETS_FILENAME, optarg);
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
strcpy(ANSWERS_FILENAME, optarg);
|
||||
WRITE_ANSWERS = 1;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
strcpy(ANSWERS_FILENAME, optarg);
|
||||
CHECK_ANSWERS = 1;
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
SELECT_NAIVE_ALGORITHM = 1;
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
SELECT_MIP_ALGORITHM = 1;
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
SELECT_BOUND_ALGORITHM = 1;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
ENABLE_PREPROCESSING = 1;
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
ENABLE_SHEAR = 1;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
print_usage(argv);
|
||||
exit(0);
|
||||
|
||||
case ':':
|
||||
fprintf(stderr, "%s: option '-%c' requires an argument\n",
|
||||
argv[0], optopt);
|
||||
rval = 1;
|
||||
goto CLEANUP;
|
||||
|
||||
case '?':
|
||||
default:
|
||||
fprintf(stderr, "%s: option '-%c' is invalid\n", argv[0],
|
||||
optopt);
|
||||
rval = 1;
|
||||
goto CLEANUP;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if ((strlen(SETS_FILENAME) == 0))
|
||||
{
|
||||
fprintf(stderr, "You must specify a file containing the lattice-free "
|
||||
"sets.\n");
|
||||
rval = 1;
|
||||
}
|
||||
|
||||
if (SELECT_NAIVE_ALGORITHM + SELECT_BOUND_ALGORITHM + SELECT_MIP_ALGORITHM != 1)
|
||||
{
|
||||
fprintf(stderr, "You must select exactly one algorithm.\n");
|
||||
rval = 1;
|
||||
}
|
||||
|
||||
if (CHECK_ANSWERS + WRITE_ANSWERS > 1)
|
||||
{
|
||||
fprintf(stderr, "Cannot write and check answers at same time.\n");
|
||||
rval = 1;
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
if (rval)
|
||||
fprintf(stderr, "Try '%s --help' for more information.\n", argv[0]);
|
||||
return rval;
|
||||
}
|
||||
|
||||
void print_header(int argc,
|
||||
char *const *argv)
|
||||
{
|
||||
char hostname[3000];
|
||||
gethostname(hostname, 1024);
|
||||
|
||||
time_t now;
|
||||
time(&now);
|
||||
struct tm *ttm = localtime(&now);
|
||||
|
||||
time_printf("benchmark.run\n");
|
||||
time_printf("%s %04d-%02d-%02d %02d:%02d\n", hostname, ttm->tm_year + 1900,
|
||||
ttm->tm_mon + 1, ttm->tm_mday, ttm->tm_hour, ttm->tm_min);
|
||||
|
||||
time_printf("Compile-time parameters:\n");
|
||||
time_printf(" EPSILON: %e\n", EPSILON);
|
||||
|
||||
char cmdline[5000] = {0};
|
||||
for (int i = 0; i < argc; i++)
|
||||
sprintf(cmdline + strlen(cmdline), "%s ", argv[i]);
|
||||
|
||||
time_printf("Command line arguments:\n");
|
||||
time_printf(" %s\n", cmdline);
|
||||
}
|
||||
|
||||
int benchmark_set_sample(int algorithm,
|
||||
int set_idx,
|
||||
const struct LFreeSet2D *set,
|
||||
const double *rays,
|
||||
const double *pre_m,
|
||||
const double center,
|
||||
int *lb,
|
||||
int *ub,
|
||||
int current_sample,
|
||||
int *wrong_answer)
|
||||
{
|
||||
int rval = 0;
|
||||
|
||||
for (int i = 0; i < N_RAYS; i++)
|
||||
{
|
||||
double ray[2] = { rays[2 * i], rays[2 * i + 1] };
|
||||
double value;
|
||||
|
||||
if(ENABLE_PREPROCESSING)
|
||||
{
|
||||
double r0 = ray[0], r1 = ray[1];
|
||||
ray[0] = pre_m[0] * r0 + pre_m[2] * r1;
|
||||
ray[1] = pre_m[1] * r0 + pre_m[3] * r1;
|
||||
|
||||
ray[0] = ray[0] - floor(set->f[0] + ray[0]);
|
||||
ray[1] = ray[1] + floor(center + 0.5 - set->f[1] - ray[1]);
|
||||
}
|
||||
|
||||
log_debug(" Ray %d (%.6lf,%.6lf)...\n", i, ray[0], ray[1]);
|
||||
|
||||
switch (algorithm)
|
||||
{
|
||||
case ALGORITHM_BOUND:
|
||||
rval = LIFTING_2D_bound(set->n_halfspaces, set->halfspaces, ray,
|
||||
&value);
|
||||
abort_if(rval, "LIFTING_2D_bound failed");
|
||||
break;
|
||||
|
||||
case ALGORITHM_NAIVE:
|
||||
rval = LIFTING_2D_naive(set->n_halfspaces, set->halfspaces, ray,
|
||||
lb, ub, &value);
|
||||
abort_if(rval, "LIFTING_2D_naive failed");
|
||||
break;
|
||||
|
||||
case ALGORITHM_MIP:
|
||||
rval = LIFTING_2D_mip(set->n_halfspaces, set->halfspaces, ray,
|
||||
&value);
|
||||
abort_if(rval, "LIFTING_2D_mip failed");
|
||||
break;
|
||||
|
||||
default:
|
||||
abort_if(1, "Invalid algorithm");
|
||||
}
|
||||
|
||||
if(current_sample == 0)
|
||||
{
|
||||
if(WRITE_ANSWERS)
|
||||
{
|
||||
abort_iff(!DOUBLE_geq(value, 0),
|
||||
"value should be non-negative (%.8lf)", value);
|
||||
fprintf(ANSWERS_FILE, "%d %d %.20lf\n", set_idx, i, value);
|
||||
}
|
||||
|
||||
if(CHECK_ANSWERS)
|
||||
{
|
||||
int count;
|
||||
int expected_set_idx, expected_i;
|
||||
double expected_value;
|
||||
|
||||
while(1)
|
||||
{
|
||||
count = fscanf(ANSWERS_FILE, "%d %d %lf ",
|
||||
&expected_set_idx, &expected_i, &expected_value);
|
||||
|
||||
abort_if(count != 3, "error reading answer");
|
||||
if(set_idx == expected_set_idx && i == expected_i) break;
|
||||
}
|
||||
|
||||
double delta = fabs(value - expected_value);
|
||||
if(delta > 1e-3)
|
||||
{
|
||||
log_warn(" wrong answer (set=%d ray=%d answer=%.8lf"
|
||||
" expected=%.8lf delta=%.8lf)\n", set_idx,
|
||||
i, value, expected_value, delta);
|
||||
*wrong_answer = 1;
|
||||
|
||||
LFREE_2D_print_set(set);
|
||||
}
|
||||
}
|
||||
|
||||
log_verbose(" %4d %12.8lf\n", j, value);
|
||||
}
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
return rval;
|
||||
}
|
||||
|
||||
int benchmark_set(int algorithm,
|
||||
int set_idx,
|
||||
const struct LFreeSet2D *set,
|
||||
const double *rays,
|
||||
const double *pre_m,
|
||||
const double center,
|
||||
int *wrong_answer)
|
||||
{
|
||||
int rval = 0;
|
||||
int lb[2], ub[2];
|
||||
|
||||
if(algorithm == ALGORITHM_NAIVE)
|
||||
{
|
||||
if (USE_FIXED_BOUNDS)
|
||||
{
|
||||
ub[0] = ub[1] = NAIVE_BIG_M;
|
||||
lb[0] = lb[1] = -NAIVE_BIG_M;
|
||||
}
|
||||
else
|
||||
{
|
||||
rval = LFREE_2D_get_bounding_box(set, lb, ub);
|
||||
abort_if(rval, "LFREE_2D_get_bounding_box failed");
|
||||
|
||||
ub[0] += BOUNDING_BOX_PADDING;
|
||||
ub[1] += BOUNDING_BOX_PADDING;
|
||||
lb[0] -= BOUNDING_BOX_PADDING;
|
||||
lb[0] -= BOUNDING_BOX_PADDING;
|
||||
}
|
||||
|
||||
ub[0] = fmin(ub[0], MAX_BOX_SIZE);
|
||||
ub[1] = fmin(ub[1], MAX_BOX_SIZE);
|
||||
lb[0] = fmax(lb[0], -MAX_BOX_SIZE);
|
||||
lb[1] = fmax(lb[1], -MAX_BOX_SIZE);
|
||||
|
||||
if(ub[0] == MAX_BOX_SIZE || ub[1] == MAX_BOX_SIZE || lb[0] ==
|
||||
-MAX_BOX_SIZE || lb[1] == -MAX_BOX_SIZE)
|
||||
{
|
||||
log_info(" bounding box has been clipped\n");
|
||||
}
|
||||
}
|
||||
|
||||
for (int k = 0; k < N_SAMPLES_PER_SET; k ++)
|
||||
{
|
||||
rval = benchmark_set_sample(algorithm, set_idx, set, rays, pre_m,
|
||||
center, lb, ub, k, wrong_answer);
|
||||
abort_if(rval, "benchmark_set_sample failed");
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
return rval;
|
||||
}
|
||||
|
||||
int benchmark(int n_sets, struct LFreeSet2D *sets, double *rays,
|
||||
int algorithm)
|
||||
{
|
||||
int rval = 0;
|
||||
|
||||
log_info("Running benchmark...\n");
|
||||
|
||||
double total_initial_time = get_user_time();
|
||||
stats_printf("cpu_time:\n");
|
||||
|
||||
for (int j = 0; j < n_sets; j++)
|
||||
{
|
||||
log_debug("Set %d...\n", j);
|
||||
|
||||
double set_initial_time = get_user_time();
|
||||
|
||||
struct LFreeSet2D *set = &sets[j];
|
||||
double *pre_m = &PRE_M[j * 4];
|
||||
double center = CENTER[j];
|
||||
|
||||
rval = LFREE_2D_print_set(set);
|
||||
abort_if(rval, "LFREE_2D_print_set failed");
|
||||
|
||||
int wrong_answer = 0;
|
||||
|
||||
rval = benchmark_set(algorithm, j, set, rays, pre_m, center, &wrong_answer);
|
||||
abort_if(rval, "benchmark_set failed");
|
||||
|
||||
double set_duration = get_user_time() - set_initial_time;
|
||||
double avg = (set_duration / N_SAMPLES_PER_SET) * 1000;
|
||||
|
||||
if(wrong_answer) avg = 1000000;
|
||||
|
||||
stats_printf(" %d: %.8lf\n", j, avg);
|
||||
log_info(" %3d: %12.3lf ms\n", j, avg);
|
||||
}
|
||||
|
||||
double total_duration = get_user_time() - total_initial_time;
|
||||
|
||||
log_info(" %.3lf ms per set \n",
|
||||
total_duration / (n_sets * N_SAMPLES_PER_SET) * 1000);
|
||||
|
||||
if(algorithm == ALGORITHM_MIP)
|
||||
{
|
||||
log_info(" %.3lf s spent on LP_create\n", MIP_TIME_CREATE);
|
||||
log_info(" %.3lf s spent on LP_optimize\n", MIP_TIME_OPTIMIZE);
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
return rval;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int rval = 0;
|
||||
double *rays = 0;
|
||||
struct LFreeSet2D sets[MAX_N_SETS];
|
||||
|
||||
rval = parse_args(argc, argv);
|
||||
if (rval) return 1;
|
||||
|
||||
print_header(argc, argv);
|
||||
|
||||
if (LOG_FILENAME[0])
|
||||
{
|
||||
LOG_FILE = fopen(LOG_FILENAME, "w");
|
||||
abort_if(!LOG_FILE, "could not open log file");
|
||||
log_info("Writing log to file: %s\n", LOG_FILENAME);
|
||||
}
|
||||
|
||||
if (STATS_FILENAME[0])
|
||||
{
|
||||
STATS_FILE = fopen(STATS_FILENAME, "w");
|
||||
abort_if(!STATS_FILE, "could not open stats file");
|
||||
log_info("Writing stats to file: %s\n", STATS_FILENAME);
|
||||
}
|
||||
|
||||
if (WRITE_ANSWERS)
|
||||
{
|
||||
N_SAMPLES_PER_SET = 1;
|
||||
ANSWERS_FILE = fopen(ANSWERS_FILENAME, "w");
|
||||
abort_if(!ANSWERS_FILE, "could not open answers file");
|
||||
log_info("Writing answers to file: %s\n", ANSWERS_FILENAME);
|
||||
}
|
||||
|
||||
if (CHECK_ANSWERS)
|
||||
{
|
||||
ANSWERS_FILE = fopen(ANSWERS_FILENAME, "r");
|
||||
abort_if(!ANSWERS_FILE, "could not open answers file");
|
||||
log_info("Reading answers from file: %s\n", ANSWERS_FILENAME);
|
||||
}
|
||||
|
||||
if(SEED == 0)
|
||||
{
|
||||
struct timeval t1;
|
||||
gettimeofday(&t1, NULL);
|
||||
SEED = (unsigned int) (t1.tv_usec * t1.tv_sec) % 10000;
|
||||
}
|
||||
|
||||
log_info("Random seed: %u\n", SEED);
|
||||
srand(SEED);
|
||||
|
||||
log_info("Generating %d random rays...\n", N_RAYS);
|
||||
|
||||
rays = (double*) malloc(2 * N_RAYS * sizeof(double));
|
||||
abort_if(!rays, "could not allocate rays");
|
||||
|
||||
for (int i = 0; i < N_RAYS; i++)
|
||||
{
|
||||
double *ray = &rays[2 * i];
|
||||
ray[0] = DOUBLE_random(0.0, 1.0);
|
||||
ray[1] = DOUBLE_random(0.0, 1.0);
|
||||
}
|
||||
|
||||
int algorithm = ALGORITHM_BOUND;
|
||||
if(SELECT_MIP_ALGORITHM) algorithm = ALGORITHM_MIP;
|
||||
else if(SELECT_NAIVE_ALGORITHM) algorithm = ALGORITHM_NAIVE;
|
||||
|
||||
if(algorithm == ALGORITHM_NAIVE)
|
||||
{
|
||||
log_info("Enabling naive algorithm\n");
|
||||
|
||||
if(USE_FIXED_BOUNDS)
|
||||
log_info("Using fixed big M: %d\n", NAIVE_BIG_M);
|
||||
else
|
||||
log_info("Enabling bounding boxes\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
log_info("Enabling bound algorithm\n");
|
||||
}
|
||||
|
||||
log_info("Setting %d samples per set\n", N_SAMPLES_PER_SET);
|
||||
|
||||
if(ENABLE_PREPROCESSING)
|
||||
log_info("Enabling pre-processing\n");
|
||||
|
||||
log_info("Reading sets from file...\n");
|
||||
FILE *sets_file = fopen(SETS_FILENAME, "r");
|
||||
abort_iff(!sets_file, "could not read file %s", SETS_FILENAME);
|
||||
|
||||
int line = 0;
|
||||
int n_sets = 0;
|
||||
while(!feof(sets_file))
|
||||
{
|
||||
line++;
|
||||
struct LFreeSet2D *set = &sets[n_sets];
|
||||
LFREE_2D_init(set, 4, 4, 4);
|
||||
|
||||
rval = LFREE_2D_read_next(sets_file, set);
|
||||
abort_iff(rval, "LFREE_2D_read_next failed (line %d)", line);
|
||||
|
||||
if(ENABLE_SHEAR)
|
||||
{
|
||||
double m[4] = { 51.0, 5.0, 10.0, 1.0 };
|
||||
rval = LFREE_2D_transform_set(set, m);
|
||||
abort_iff(rval, "LFREE_2D_transform_set failed (line %d)", line);
|
||||
}
|
||||
|
||||
double dx = -floor(set->f[0]);
|
||||
double dy = -floor(set->f[1]);
|
||||
rval = LFREE_2D_translate_set(set, dx, dy);
|
||||
abort_iff(rval, "LFREE_2D_translate_set failed (line %d)", line);
|
||||
|
||||
if(ENABLE_PREPROCESSING)
|
||||
{
|
||||
double *pre_m = &PRE_M[n_sets * 4];
|
||||
double *center = &CENTER[n_sets];
|
||||
rval = LFREE_2D_preprocess(set, pre_m, center);
|
||||
abort_iff(rval, "LFREE_2D_preprocess failed (line %d)", line);
|
||||
}
|
||||
|
||||
rval = LFREE_2D_compute_halfspaces(set);
|
||||
abort_iff(rval, "LFREE_2D_compute_halfspaces failed (line %d)", line);
|
||||
|
||||
rval = LIFTING_2D_verify(set);
|
||||
if(rval)
|
||||
{
|
||||
log_warn(" skipping invalid set on line %d\n", line);
|
||||
continue;
|
||||
}
|
||||
|
||||
n_sets++;
|
||||
if(n_sets >= MAX_N_SETS) break;
|
||||
}
|
||||
|
||||
fclose(sets_file);
|
||||
log_info("Successfully read %d sets\n", n_sets);
|
||||
|
||||
rval = benchmark(n_sets, sets, rays, algorithm);
|
||||
abort_if(rval, "benchmark failed");
|
||||
|
||||
log_info("Done.\n");
|
||||
|
||||
CLEANUP:
|
||||
if (LOG_FILE) fclose(LOG_FILE);
|
||||
if (STATS_FILE) fclose(STATS_FILE);
|
||||
if (ANSWERS_FILE) fclose(ANSWERS_FILE);
|
||||
if (rays) free(rays);
|
||||
return rval;
|
||||
}
|
||||
17
lifting/library/CMakeLists.txt
Normal file
17
lifting/library/CMakeLists.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
include_directories(include)
|
||||
|
||||
set(COMMON_SOURCES
|
||||
src/lifting.c
|
||||
src/lifting-mip.c
|
||||
include/lifting/lifting-mip.h
|
||||
include/lifting/lifting.h)
|
||||
|
||||
set(TEST_SOURCES
|
||||
tests/lifting-test.cpp)
|
||||
|
||||
add_library(lifting_static ${COMMON_SOURCES})
|
||||
set_target_properties(lifting_static PROPERTIES OUTPUT_NAME lifting)
|
||||
target_include_directories (lifting_static PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
add_executable(lifting-test.run ${COMMON_SOURCES} ${TEST_SOURCES})
|
||||
target_link_libraries(lifting-test.run gtest_main multirow_static)
|
||||
32
lifting/library/include/lifting/lifting-mip.h
Normal file
32
lifting/library/include/lifting/lifting-mip.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/* Copyright (c) 2016 Laurent Poirrier
|
||||
*
|
||||
* 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 LIFTING_MIP_H
|
||||
#define LIFTING_MIP_H
|
||||
|
||||
extern double MIP_TIME_OPTIMIZE;
|
||||
extern double MIP_TIME_CREATE;
|
||||
|
||||
int LIFTING_2D_mip_init();
|
||||
|
||||
void LIFTING_2D_mip_cleanup();
|
||||
|
||||
int LIFTING_2D_mip(int n_halfspaces,
|
||||
const double *halfspaces,
|
||||
const double *ray,
|
||||
double *value);
|
||||
|
||||
#endif
|
||||
53
lifting/library/include/lifting/lifting.h
Normal file
53
lifting/library/include/lifting/lifting.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/* 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 LIFTING_H
|
||||
#define LIFTING_H
|
||||
|
||||
#include <multirow/lfree2d.h>
|
||||
|
||||
int LIFTING_2D_psi(int n_halfspaces,
|
||||
const double *halfspaces,
|
||||
const double *ray,
|
||||
double *value);
|
||||
|
||||
int LIFTING_2D_optimize_continuous(int n_halfspaces,
|
||||
const double *halfspaces,
|
||||
double alpha2,
|
||||
double *alpha1,
|
||||
double *value);
|
||||
|
||||
int LIFTING_2D_lift_fixed(int n_halfspaces,
|
||||
const double *halfspaces,
|
||||
const double *ray,
|
||||
double k1,
|
||||
double *opt);
|
||||
|
||||
int LIFTING_2D_naive(int n_halfspaces,
|
||||
const double *halfspaces,
|
||||
const double *ray,
|
||||
const int *lb,
|
||||
const int *ub,
|
||||
double *value);
|
||||
|
||||
int LIFTING_2D_bound(int n_halfspaces,
|
||||
const double *halfspaces,
|
||||
const double *ray,
|
||||
double *value);
|
||||
|
||||
int LIFTING_2D_verify(struct LFreeSet2D *set);
|
||||
|
||||
#endif //LIFTING_H
|
||||
162
lifting/library/src/lifting-mip.c
Normal file
162
lifting/library/src/lifting-mip.c
Normal file
@@ -0,0 +1,162 @@
|
||||
/* Copyright (c) 2016 Laurent Poirrier
|
||||
*
|
||||
* 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 <multirow/util.h>
|
||||
#include <multirow/lp.h>
|
||||
#include <lifting/lifting-mip.h>
|
||||
|
||||
double MIP_TIME_OPTIMIZE = 0;
|
||||
double MIP_TIME_CREATE = 0;
|
||||
|
||||
/**
|
||||
* Returns non-zero if the cplex_env part of struct LP is initialized.
|
||||
*
|
||||
* @param lp pointer to a struct LP
|
||||
*/
|
||||
int LP_is_open(struct LP *lp)
|
||||
{
|
||||
return (lp->cplex_env != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees the cplex_lp part of struct LP, leaving the environment open.
|
||||
*
|
||||
* @param lp pointer to a struct LP
|
||||
*/
|
||||
void LP_destroy(struct LP *lp)
|
||||
{
|
||||
if(!lp) return;
|
||||
if(!lp->cplex_env) return;
|
||||
|
||||
if(lp->cplex_lp)
|
||||
CPXfreeprob(lp->cplex_env, &(lp->cplex_lp));
|
||||
|
||||
lp->cplex_lp = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Static data for LIFTING_2D_mip().
|
||||
*
|
||||
* Warning: Because of this, LIFTING_2D_mip() is not thread safe.
|
||||
*/
|
||||
static struct LP LIFTING_2D_mip_lp = {0, 0};
|
||||
|
||||
/**
|
||||
* Opens the cplex environment of the struct LP used by LIFTING_2D_mip().
|
||||
*
|
||||
* This is called automatically by LIFTING_2D_mip().
|
||||
*/
|
||||
int LIFTING_2D_mip_init()
|
||||
{
|
||||
struct LP *lp = &LIFTING_2D_mip_lp;
|
||||
|
||||
if(!LP_is_open(lp))
|
||||
{
|
||||
if(LP_open(lp)) return (-1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the cplex environment of the struct LP used by LIFTING_2D_mip().
|
||||
*
|
||||
* This function should be called by the user of LIFTING_2D_mip(), if
|
||||
* cleaning up the environment is desired.
|
||||
*/
|
||||
void LIFTING_2D_mip_cleanup()
|
||||
{
|
||||
struct LP *lp = &LIFTING_2D_mip_lp;
|
||||
|
||||
LP_free(lp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Computes the lifting coefficient of a ray by formulating the lifting
|
||||
* problem as a MIP.
|
||||
*
|
||||
* @param[in] n_halfspaces number of facets of the lattice-free set used
|
||||
* @param[in] halfspaces description of the lattice-free set used
|
||||
* @param[in] ray ray to lift
|
||||
* @param[out] value lifting coefficient
|
||||
*/
|
||||
int LIFTING_2D_mip(int n_halfspaces,
|
||||
const double *halfspaces,
|
||||
const double *ray,
|
||||
double *value)
|
||||
{
|
||||
struct LP *lp = &LIFTING_2D_mip_lp;
|
||||
int rval = 0;
|
||||
|
||||
double initial_time = get_user_time();
|
||||
|
||||
rval = LIFTING_2D_mip_init();
|
||||
abort_if(rval, "LIFTING_2D_mip_init failed");
|
||||
|
||||
rval = LP_create(lp, "lifting2d");
|
||||
abort_if(rval, "LP_create failed");
|
||||
|
||||
rval = LP_new_col(lp, 1.0, 0.0, MILP_INFINITY, 'C');
|
||||
rval |= LP_new_col(lp, 0.0, -MILP_INFINITY, MILP_INFINITY, 'I');
|
||||
rval |= LP_new_col(lp, 0.0, -MILP_INFINITY, MILP_INFINITY, 'I');
|
||||
abort_if(rval, "LP_new_col failed");
|
||||
|
||||
double rhs;
|
||||
char sense = 'G';
|
||||
int beg = 0;
|
||||
int ind[3] = {0, 1, 2};
|
||||
double val[3];
|
||||
|
||||
val[0] = 1.0;
|
||||
|
||||
for(int i = 0; i < n_halfspaces; i++)
|
||||
{
|
||||
double a0 = halfspaces[i * 2 + 0];
|
||||
double a1 = halfspaces[i * 2 + 1];
|
||||
|
||||
rhs = a0 * ray[0] + a1 * ray[1];
|
||||
|
||||
val[1] = -a0;
|
||||
val[2] = -a1;
|
||||
|
||||
rval |= LP_add_rows(lp, 1, 3, &rhs, &sense, &beg, ind, val);
|
||||
}
|
||||
|
||||
MIP_TIME_CREATE += get_user_time() - initial_time;
|
||||
|
||||
abort_if(rval, "LP_add_rows failed");
|
||||
|
||||
int infeasible;
|
||||
|
||||
initial_time = get_user_time();
|
||||
|
||||
rval = LP_optimize(lp, &infeasible);
|
||||
abort_if(rval, "LP_optimize failed");
|
||||
abort_if(infeasible, "LIFTING_2D_mip infeasible");
|
||||
|
||||
MIP_TIME_OPTIMIZE += get_user_time() - initial_time;
|
||||
|
||||
double obj;
|
||||
|
||||
rval = LP_get_obj_val(lp, &obj);
|
||||
abort_if(rval, "LP_get_obj_val failed");
|
||||
|
||||
*value = obj;
|
||||
|
||||
CLEANUP:
|
||||
LP_destroy(lp);
|
||||
return (rval);
|
||||
}
|
||||
286
lifting/library/src/lifting.c
Normal file
286
lifting/library/src/lifting.c
Normal file
@@ -0,0 +1,286 @@
|
||||
/* 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 _XOPEN_SOURCE 700
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <multirow/double.h>
|
||||
#include <multirow/util.h>
|
||||
#include <multirow/lp.h>
|
||||
#include <multirow/lfree2d.h>
|
||||
#include <lifting/lifting.h>
|
||||
|
||||
/**
|
||||
* Verifies if the set is well formed.
|
||||
*/
|
||||
int LIFTING_2D_verify(struct LFreeSet2D *set)
|
||||
{
|
||||
int rval = 0;
|
||||
|
||||
abort_if(set->n_halfspaces == 0, "Halfspaces not found");
|
||||
|
||||
for(int i = 0; i < set->n_lattice_points; i++)
|
||||
{
|
||||
double *t = &set->lattice_points[2 * i];
|
||||
double r[2] = {t[0] - set->f[0],
|
||||
t[1] - set->f[1]};
|
||||
|
||||
double value;
|
||||
|
||||
rval = LIFTING_2D_psi(set->n_halfspaces, set->halfspaces, r, &value);
|
||||
abort_if(rval, "LIFTING_2D_psi failed");
|
||||
|
||||
double delta = fabs(value - 1);
|
||||
if(delta > 0.0001)
|
||||
{
|
||||
log_debug("Lattice point (%.2lf, %.2lf) is "
|
||||
"not on the boundary (delta=%.6lf)", t[0], t[1], delta);
|
||||
rval = 1;
|
||||
goto CLEANUP;
|
||||
}
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
return rval;
|
||||
}
|
||||
|
||||
int LIFTING_2D_psi(int n_halfspaces,
|
||||
const double *halfspaces,
|
||||
const double *ray,
|
||||
double *value)
|
||||
{
|
||||
int rval = 0;
|
||||
|
||||
*value = -INFINITY;
|
||||
|
||||
for(int i = 0; i < n_halfspaces; i++)
|
||||
{
|
||||
const double *h = &halfspaces[2 * i];
|
||||
double v = ray[0] * h[0] + ray[1] * h[1];
|
||||
*value = DOUBLE_max(v, *value);
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
return rval;
|
||||
}
|
||||
|
||||
int LIFTING_2D_optimize_continuous(int n_halfspaces,
|
||||
const double *halfspaces,
|
||||
double alpha2,
|
||||
double *alpha1,
|
||||
double *value)
|
||||
{
|
||||
int rval = 0;
|
||||
|
||||
*value = -INFINITY;
|
||||
|
||||
for(int r = 0; r < n_halfspaces; r++)
|
||||
{
|
||||
for(int s = r+1; s < n_halfspaces; s++)
|
||||
{
|
||||
const double *ar = &halfspaces[r * 2];
|
||||
const double *as = &halfspaces[s * 2];
|
||||
|
||||
double xr = ar[0];
|
||||
double xs = as[0];
|
||||
if(DOUBLE_eq(xr, xs)) continue;
|
||||
|
||||
double br = - xs / (xr - xs);
|
||||
double bs = xr / (xr - xs);
|
||||
if(!DOUBLE_geq(br, 0)) continue;
|
||||
if(!DOUBLE_geq(bs, 0)) continue;
|
||||
|
||||
double yr = ar[1] * alpha2;
|
||||
double ys = as[1] * alpha2;
|
||||
|
||||
double obj = yr * br + ys * bs;
|
||||
|
||||
if(DOUBLE_geq(obj, *value))
|
||||
{
|
||||
*value = obj;
|
||||
|
||||
if(DOUBLE_neq(xr, 0))
|
||||
*alpha1 = - (yr - obj) / xr;
|
||||
else
|
||||
*alpha1 = - (ys - obj) / xs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
return rval;
|
||||
}
|
||||
|
||||
int LIFTING_2D_lift_fixed(int n_halfspaces,
|
||||
const double *halfspaces,
|
||||
const double *ray,
|
||||
double k1,
|
||||
double *opt)
|
||||
{
|
||||
int rval = 0;
|
||||
|
||||
double k0;
|
||||
double value;
|
||||
|
||||
rval = LIFTING_2D_optimize_continuous(n_halfspaces, halfspaces,
|
||||
ray[1] + k1, &k0, &value);
|
||||
abort_if(rval, "LIFTING_2D_optimize_continuous failed");
|
||||
|
||||
double delta = k0 - ray[0];
|
||||
|
||||
double r_ceil[2] = { ray[0] + ceil(delta), ray[1] + k1 };
|
||||
double r_floor[2] = { ray[0] + floor(delta), ray[1] + k1 };
|
||||
|
||||
log_debug(" delta=%.6lf value=%.6lf\n", delta, value);
|
||||
log_debug(" r_ceil=%12.6lf %12.6lf\n", r_ceil[0], r_ceil[1]);
|
||||
log_debug(" r_floor=%12.6lf %12.6lf\n", r_floor[0], r_floor[1]);
|
||||
|
||||
double value_ceil, value_floor;
|
||||
|
||||
rval = LIFTING_2D_psi(n_halfspaces, halfspaces, r_ceil, &value_ceil);
|
||||
abort_if(rval, "LIFTING_2D_psi failed");
|
||||
|
||||
rval = LIFTING_2D_psi(n_halfspaces, halfspaces, r_floor, &value_floor);
|
||||
abort_if(rval, "LIFTING_2D_psi failed");
|
||||
|
||||
*opt = min(value_ceil, value_floor);
|
||||
|
||||
CLEANUP:
|
||||
return rval;
|
||||
}
|
||||
|
||||
int LIFTING_2D_naive(int n_halfspaces,
|
||||
const double *halfspaces,
|
||||
const double *ray,
|
||||
const int *lb,
|
||||
const int *ub,
|
||||
double *value)
|
||||
{
|
||||
int rval = 0;
|
||||
|
||||
*value = INFINITY;
|
||||
int best_k0 = 0;
|
||||
int best_k1 = 0;
|
||||
|
||||
int margin = 10;
|
||||
|
||||
for(int k0 = lb[0] - margin; k0 <= ub[0] + margin; k0++)
|
||||
{
|
||||
for(int k1 = lb[1] - margin; k1 <= ub[1] + margin; k1++)
|
||||
{
|
||||
double q[2] = { ray[0] + k0, ray[1] + k1 };
|
||||
double value_q;
|
||||
|
||||
rval = LIFTING_2D_psi(n_halfspaces, halfspaces, q, &value_q);
|
||||
abort_if(rval, "LIFTING_2D_ps failed");
|
||||
|
||||
if(value_q < *value)
|
||||
{
|
||||
best_k0 = k0;
|
||||
best_k1 = k1;
|
||||
*value = value_q;
|
||||
log_debug(" k=%6d %6d value=%12.6lf\n", k0, k1, *value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// log_debug(" best_k=(%d %d) value=%.6lf\n", best_k0, best_k1, *value);
|
||||
|
||||
CLEANUP:
|
||||
return rval;
|
||||
}
|
||||
|
||||
int LIFTING_2D_bound(int n_halfspaces,
|
||||
const double *halfspaces,
|
||||
const double *ray,
|
||||
double *value)
|
||||
{
|
||||
int rval = 0;
|
||||
|
||||
double eta_star, eta_plus, eta_minus;
|
||||
double xi_plus, xi_minus;
|
||||
double m_plus, m_minus;
|
||||
double ignored;
|
||||
int k1 = 1;
|
||||
|
||||
rval = LIFTING_2D_lift_fixed(n_halfspaces, halfspaces, ray, 0, &eta_star);
|
||||
abort_if(rval, "LIFTING_2D_lift_fixed failed");
|
||||
|
||||
rval = LIFTING_2D_optimize_continuous(n_halfspaces, halfspaces, 1, &ignored,
|
||||
&xi_plus);
|
||||
abort_if(rval, "LIFTING_2D_optimize_continuous failed");
|
||||
|
||||
rval = LIFTING_2D_optimize_continuous(n_halfspaces, halfspaces, -1,
|
||||
&ignored, &xi_minus);
|
||||
abort_if(rval, "LIFTING_2D_optimize_continuous failed");
|
||||
|
||||
m_plus = m_minus = INFINITY;
|
||||
|
||||
log_debug("Level 0:\n");
|
||||
log_debug(" eta star = %.6lf\n", eta_star);
|
||||
log_debug(" next slack plus = %.6lf\n", k1 + ray[1] - m_plus);
|
||||
log_debug(" next slack minus = %.6lf\n", k1 - ray[1] - m_minus);
|
||||
log_debug(" xi plus = %.6lf\n", xi_plus);
|
||||
log_debug(" xi minus = %.6lf\n", xi_minus);
|
||||
|
||||
while((k1 <= fabs(ray[1])) || (k1 + ray[1] <= m_plus) || (k1 - ray[1] <= m_minus))
|
||||
{
|
||||
log_debug("Level %d:\n", k1);
|
||||
|
||||
double h_plus, h_minus;
|
||||
|
||||
rval = LIFTING_2D_optimize_continuous(n_halfspaces, halfspaces, ray[1]
|
||||
+ k1, &ignored, &h_plus);
|
||||
abort_if(rval, "LIFTING_2D_optimize_continuous failed");
|
||||
|
||||
rval = LIFTING_2D_optimize_continuous(n_halfspaces, halfspaces, ray[1]
|
||||
- k1, &ignored, &h_minus);
|
||||
abort_if(rval, "LIFTING_2D_optimize_continuous failed");
|
||||
|
||||
rval = LIFTING_2D_lift_fixed(n_halfspaces, halfspaces, ray, k1,
|
||||
&eta_plus);
|
||||
abort_if(rval, "LIFTING_2D_lift_fixed failed");
|
||||
|
||||
rval = LIFTING_2D_lift_fixed(n_halfspaces, halfspaces, ray, -k1,
|
||||
&eta_minus);
|
||||
abort_if(rval, "LIFTING_2D_lift_fixed failed");
|
||||
|
||||
eta_star = fmin(eta_star, fmin(eta_plus, eta_minus));
|
||||
|
||||
m_plus = ceil(eta_star / xi_plus);
|
||||
m_minus = ceil(eta_star / xi_minus);
|
||||
|
||||
log_debug(" eta plus = %.6lf\n", eta_plus);
|
||||
log_debug(" eta minus = %.6lf\n", eta_minus);
|
||||
log_debug(" eta star = %.6lf\n", eta_star);
|
||||
log_debug(" h minus = %.6lf\n", h_minus);
|
||||
log_debug(" h plus = %.6lf\n", h_plus);
|
||||
|
||||
k1++;
|
||||
|
||||
log_debug(" next slack plus = %.6lf\n", k1 + ray[1] - m_plus);
|
||||
log_debug(" next slack minus = %.6lf\n", k1 - ray[1] - m_minus);
|
||||
}
|
||||
|
||||
log_debug("Done\n");
|
||||
|
||||
*value = eta_star;
|
||||
|
||||
CLEANUP:
|
||||
return rval;
|
||||
}
|
||||
1
lifting/library/tests/fixtures/quads.txt
vendored
Normal file
1
lifting/library/tests/fixtures/quads.txt
vendored
Normal file
@@ -0,0 +1 @@
|
||||
0.5 0.5 4 -0.5 0.5 0.5 1.5 1.5 0.5 0.5 -0.5 4 0 0 0 1 1 1 1 0
|
||||
2
lifting/library/tests/fixtures/triangles.txt
vendored
Normal file
2
lifting/library/tests/fixtures/triangles.txt
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
0.7875 1.7875 3 1 2 0.4875 2.0875 -0.0625 -16.0625 3 1 2 0 -14 0 -15
|
||||
0.5 0.5 3 0 0 2 0 0 2 3 0 1 1 0 1 1
|
||||
715
lifting/library/tests/lifting-test.cpp
Normal file
715
lifting/library/tests/lifting-test.cpp
Normal file
@@ -0,0 +1,715 @@
|
||||
/* 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 <multirow/util.h>
|
||||
#include <multirow/double.h>
|
||||
#include <multirow/lfree2d.h>
|
||||
#include <lifting/lifting.h>
|
||||
#include <lifting/lifting-mip.h>
|
||||
#include <math.h>
|
||||
}
|
||||
|
||||
#define E 1e-6
|
||||
|
||||
TEST(Lifting2DTest, lift_fixed_test_2)
|
||||
{
|
||||
int rval = 0;
|
||||
|
||||
double opt;
|
||||
|
||||
int n_halfspaces = 3;
|
||||
double halfspaces[] = {
|
||||
-1.12796209, -2.25592417,
|
||||
2.38125329, 11.19606810,
|
||||
7.35264174, 6.22467965,
|
||||
};
|
||||
|
||||
double r[] = { 0.48231629, 0.70551355 };
|
||||
|
||||
rval = LIFTING_2D_lift_fixed(n_halfspaces, halfspaces, r, -1, &opt);
|
||||
abort_if(rval, "LIFTING_lift_fixed failed");
|
||||
EXPECT_NEAR(opt, 1.24826670, E);
|
||||
|
||||
CLEANUP:
|
||||
if(rval) FAIL();
|
||||
}
|
||||
|
||||
TEST(Lifting2DTest, psi_test)
|
||||
{
|
||||
int rval = 0;
|
||||
|
||||
int n_halfspaces = 5;
|
||||
double halfspaces[] = {
|
||||
-1 / 2.0, 0,
|
||||
-1 / 2.0, -1 / 2.0,
|
||||
-1 / 4.0, 1 / 2.0,
|
||||
-1 / 6.0, -5 / 6.0,
|
||||
5 / 16.0, 1 / 8.0
|
||||
};
|
||||
|
||||
double r1[] = { 0, 0 };
|
||||
double r2[] = { 2, 3 };
|
||||
double r3[] = { 1 / 3.0, 1 / 2.0 };
|
||||
double r4[] = { -4.0, 0 };
|
||||
double r5[] = { 1, -1/2.0 };
|
||||
double r6[] = { -1/2.0, 1/2.0 };
|
||||
double r7[] = { 1/2.0, 1/2.0 };
|
||||
double value;
|
||||
|
||||
rval = LIFTING_2D_psi(n_halfspaces, halfspaces, r1, &value);
|
||||
abort_if(rval, "LIFTING_2D_psi failed");
|
||||
EXPECT_NEAR(value, 0.0, E);
|
||||
|
||||
rval = LIFTING_2D_psi(n_halfspaces, halfspaces, r2, &value);
|
||||
abort_if(rval, "LIFTING_2D_psi failed");
|
||||
EXPECT_NEAR(value, 1.0, E);
|
||||
|
||||
rval = LIFTING_2D_psi(n_halfspaces, halfspaces, r3, &value);
|
||||
abort_if(rval, "LIFTING_2D_psi failed");
|
||||
EXPECT_NEAR(value, 1 / 6.0, E);
|
||||
|
||||
rval = LIFTING_2D_psi(n_halfspaces, halfspaces, r4, &value);
|
||||
abort_if(rval, "LIFTING_2D_psi failed");
|
||||
EXPECT_NEAR(value, 2.0, E);
|
||||
|
||||
rval = LIFTING_2D_psi(n_halfspaces, halfspaces, r5, &value);
|
||||
abort_if(rval, "LIFTING_2D_psi failed");
|
||||
EXPECT_NEAR(value, 1 / 4.0, E);
|
||||
|
||||
rval = LIFTING_2D_psi(n_halfspaces, halfspaces, r6, &value);
|
||||
abort_if(rval, "LIFTING_2D_psi failed");
|
||||
EXPECT_NEAR(value, 0.375, E);
|
||||
|
||||
rval = LIFTING_2D_psi(n_halfspaces, halfspaces, r7, &value);
|
||||
abort_if(rval, "LIFTING_2D_psi failed");
|
||||
EXPECT_NEAR(value, 7 / 32.0, E);
|
||||
|
||||
CLEANUP:
|
||||
if(rval) FAIL();
|
||||
}
|
||||
|
||||
TEST(Lifting2DTest, psi_test_2)
|
||||
{
|
||||
int rval = 0;
|
||||
|
||||
LFreeSet2D set;
|
||||
|
||||
set.f[0] = 0;
|
||||
set.f[1] = 0.359;
|
||||
|
||||
double vertices[] = {
|
||||
-1.700870, -0.796700,
|
||||
0.068700, 0.032200,
|
||||
1.106900, 1.111100,
|
||||
-0.131990, 0.986800,
|
||||
};
|
||||
|
||||
double lattice_points[] = {
|
||||
0.000000, 0.000000,
|
||||
1.000000, 1.000000,
|
||||
0.000000, 1.000000,
|
||||
-1.000000, 0.000000,
|
||||
};
|
||||
|
||||
|
||||
int ub[] = { 10, 10 };
|
||||
int lb[] = { -12, -12 };
|
||||
|
||||
double r0[] = { 0.37, 0.19 };
|
||||
double value;
|
||||
|
||||
rval = LFREE_2D_init(&set, 100, 100, 100);
|
||||
abort_if(rval, "LFREE_2D_init failed");
|
||||
|
||||
set.n_vertices = 4;
|
||||
set.vertices = vertices;
|
||||
|
||||
set.n_lattice_points = 4;
|
||||
set.lattice_points = lattice_points;
|
||||
|
||||
rval = LFREE_2D_compute_halfspaces(&set);
|
||||
abort_if(rval, "LFREE_2D_compute_halfspaces failed");
|
||||
|
||||
rval = LFREE_2D_print_set(&set);
|
||||
abort_if(rval, "LFREE_2D_print_set failed");
|
||||
|
||||
rval = LIFTING_2D_naive(set.n_halfspaces, set.halfspaces, r0, lb, ub, &value);
|
||||
abort_if(rval, "LIFTING_2D_psi failed");
|
||||
|
||||
EXPECT_NEAR(value, 0.48846868, E);
|
||||
|
||||
CLEANUP:
|
||||
if(rval) FAIL();
|
||||
}
|
||||
|
||||
TEST(Lifting2DTest, naive_test_1)
|
||||
{
|
||||
int rval = 0;
|
||||
|
||||
int n_halfspaces = 5;
|
||||
double halfspaces[] = {
|
||||
-1 / 2.0, 0,
|
||||
-1 / 2.0, -1 / 2.0,
|
||||
-1 / 4.0, 1 / 2.0,
|
||||
-1 / 6.0, -5 / 6.0,
|
||||
5 / 16.0, 1 / 8.0
|
||||
};
|
||||
|
||||
double r1[] = { 1/2.0, 1/2.0 };
|
||||
double r2[] = { 0, 1/2.0 };
|
||||
double r3[] = { 1/3.0, 2/3.0 };
|
||||
double r4[] = { 2/5.0, 3/7.0 };
|
||||
int lb[] = { -10, -10 };
|
||||
int ub[] = { 10, 10 };
|
||||
|
||||
double value;
|
||||
|
||||
rval = LIFTING_2D_naive(n_halfspaces, halfspaces, r1, lb, ub, &value);
|
||||
abort_if(rval, "LIFTING_2D_naive failed");
|
||||
EXPECT_NEAR(value, 0.21875, E);
|
||||
|
||||
rval = LIFTING_2D_naive(n_halfspaces, halfspaces, r2, lb, ub, &value);
|
||||
abort_if(rval, "LIFTING_2D_naive failed");
|
||||
EXPECT_NEAR(value, 0.25, E);
|
||||
|
||||
rval = LIFTING_2D_naive(n_halfspaces, halfspaces, r3, lb, ub, &value);
|
||||
abort_if(rval, "LIFTING_2D_naive failed");
|
||||
EXPECT_NEAR(value, 0.222222, E);
|
||||
|
||||
rval = LIFTING_2D_naive(n_halfspaces, halfspaces, r4, lb, ub, &value);
|
||||
abort_if(rval, "LIFTING_2D_naive failed");
|
||||
EXPECT_NEAR(value, 0.178571, E);
|
||||
|
||||
CLEANUP:
|
||||
if(rval) FAIL();
|
||||
}
|
||||
|
||||
TEST(Lifting2DTest, naive_test_2)
|
||||
{
|
||||
int rval = 0;
|
||||
|
||||
int n_halfspaces = 3;
|
||||
double halfspaces[] = {
|
||||
-1.12796209, -2.25592417,
|
||||
2.38125329, 11.19606810,
|
||||
7.35264174, 6.22467965,
|
||||
};
|
||||
|
||||
double r[] = { 0.48231629, 0.70551355 };
|
||||
int lb[] = { -50, -50 };
|
||||
int ub[] = { 50, 50 };
|
||||
|
||||
double value;
|
||||
|
||||
rval = LIFTING_2D_naive(n_halfspaces, halfspaces, r, lb, ub, &value);
|
||||
abort_if(rval, "LIFTING_2D_naive failed");
|
||||
EXPECT_NEAR(value, 1.24826671, E);
|
||||
|
||||
CLEANUP:
|
||||
if(rval) FAIL();
|
||||
}
|
||||
|
||||
TEST(Lifting2DTest, bound_test_1)
|
||||
{
|
||||
int rval = 0;
|
||||
|
||||
int n_halfspaces = 5;
|
||||
double halfspaces[] = {
|
||||
-1 / 2.0, 0,
|
||||
-1 / 2.0, -1 / 2.0,
|
||||
-1 / 4.0, 1 / 2.0,
|
||||
-1 / 6.0, -5 / 6.0,
|
||||
5 / 16.0, 1 / 8.0
|
||||
};
|
||||
|
||||
double r1[] = { 1/2.0, 1/2.0 };
|
||||
double r2[] = { 0, 1/2.0 };
|
||||
double r3[] = { 1/3.0, 2/3.0 };
|
||||
double r4[] = { 2/5.0, 3/7.0 };
|
||||
|
||||
double value;
|
||||
|
||||
rval = LIFTING_2D_bound(n_halfspaces, halfspaces, r1, &value);
|
||||
abort_if(rval, "LIFTING_2D_bound failed");
|
||||
EXPECT_NEAR(value, 0.21875, E);
|
||||
|
||||
rval = LIFTING_2D_bound(n_halfspaces, halfspaces, r2, &value);
|
||||
abort_if(rval, "LIFTING_2D_bound failed");
|
||||
EXPECT_NEAR(value, 0.25, E);
|
||||
|
||||
rval = LIFTING_2D_bound(n_halfspaces, halfspaces, r3, &value);
|
||||
abort_if(rval, "LIFTING_2D_bound failed");
|
||||
EXPECT_NEAR(value, 0.222222, E);
|
||||
|
||||
rval = LIFTING_2D_bound(n_halfspaces, halfspaces, r4, &value);
|
||||
abort_if(rval, "LIFTING_2D_bound failed");
|
||||
EXPECT_NEAR(value, 0.178571, E);
|
||||
|
||||
CLEANUP:
|
||||
if(rval) FAIL();
|
||||
}
|
||||
|
||||
TEST(Lifting2DTest, bound_test_2)
|
||||
{
|
||||
int rval = 0;
|
||||
|
||||
int n_halfspaces = 3;
|
||||
double halfspaces[] = {
|
||||
-1.12796209, -2.25592417,
|
||||
2.38125329, 11.19606810,
|
||||
7.35264174, 6.22467965,
|
||||
};
|
||||
|
||||
double r[] = { 0.48231629, 0.70551355 };
|
||||
|
||||
double value;
|
||||
|
||||
rval = LIFTING_2D_bound(n_halfspaces, halfspaces, r, &value);
|
||||
abort_if(rval, "LIFTING_2D_bound failed");
|
||||
EXPECT_NEAR(value, 1.24826671, E);
|
||||
|
||||
CLEANUP:
|
||||
if(rval) FAIL();
|
||||
}
|
||||
|
||||
TEST(Lifting2DTest, mip_test_1)
|
||||
{
|
||||
int rval = 0;
|
||||
|
||||
int n_halfspaces = 5;
|
||||
double halfspaces[] = {
|
||||
-1 / 2.0, 0,
|
||||
-1 / 2.0, -1 / 2.0,
|
||||
-1 / 4.0, 1 / 2.0,
|
||||
-1 / 6.0, -5 / 6.0,
|
||||
5 / 16.0, 1 / 8.0
|
||||
};
|
||||
|
||||
double r1[] = { 1/2.0, 1/2.0 };
|
||||
double r2[] = { 0, 1/2.0 };
|
||||
double r3[] = { 1/3.0, 2/3.0 };
|
||||
double r4[] = { 2/5.0, 3/7.0 };
|
||||
|
||||
double value;
|
||||
|
||||
rval = LIFTING_2D_mip(n_halfspaces, halfspaces, r1, &value);
|
||||
abort_if(rval, "LIFTING_2D_mip failed");
|
||||
EXPECT_NEAR(value, 0.21875, E);
|
||||
|
||||
rval = LIFTING_2D_mip(n_halfspaces, halfspaces, r2, &value);
|
||||
abort_if(rval, "LIFTING_2D_mip failed");
|
||||
EXPECT_NEAR(value, 0.25, E);
|
||||
|
||||
rval = LIFTING_2D_mip(n_halfspaces, halfspaces, r3, &value);
|
||||
abort_if(rval, "LIFTING_2D_mip failed");
|
||||
EXPECT_NEAR(value, 0.222222, E);
|
||||
|
||||
rval = LIFTING_2D_mip(n_halfspaces, halfspaces, r4, &value);
|
||||
abort_if(rval, "LIFTING_2D_mip failed");
|
||||
EXPECT_NEAR(value, 0.178571, E);
|
||||
|
||||
CLEANUP:
|
||||
if(rval) FAIL();
|
||||
}
|
||||
|
||||
TEST(Lifting2DTest, verify_test_1)
|
||||
{
|
||||
int rval = 0;
|
||||
|
||||
double vertices[] = {
|
||||
0.361588, -0.411851,
|
||||
2.550110, 1.000000,
|
||||
1.009740, 1.000000,
|
||||
-0.836467, 0.952742,
|
||||
};
|
||||
|
||||
double lattice_points[] = {
|
||||
1.000000, 0.000000,
|
||||
2.000000, 1.000000,
|
||||
1.000000, 1.000000,
|
||||
0.000000, 0.000000,
|
||||
};
|
||||
|
||||
LFreeSet2D set;
|
||||
|
||||
rval = LFREE_2D_init(&set, 4, 4, 4);
|
||||
abort_if(rval, "LFREE_2D_init failed");
|
||||
|
||||
set.n_vertices = 4;
|
||||
set.vertices = vertices;
|
||||
|
||||
set.n_lattice_points = 4;
|
||||
set.lattice_points = lattice_points;
|
||||
|
||||
set.f[0] = 0.918857;
|
||||
set.f[1] = 0.952742;
|
||||
|
||||
rval = LFREE_2D_compute_halfspaces(&set);
|
||||
abort_if(rval, "LFREE_2D_compute_halfspaces failed");
|
||||
|
||||
rval = LIFTING_2D_verify(&set);
|
||||
EXPECT_EQ(rval, 1);
|
||||
rval = 0;
|
||||
|
||||
CLEANUP:
|
||||
if(rval) FAIL();
|
||||
}
|
||||
|
||||
TEST(LFreeSetTest, read_next_test)
|
||||
{
|
||||
int rval = 0;
|
||||
|
||||
FILE *triangles = fopen("../lifting/library/tests/fixtures/triangles.txt", "r");
|
||||
abort_if(!triangles, "could not read triangles.txt");
|
||||
|
||||
LFreeSet2D set;
|
||||
LFREE_2D_init(&set, 100, 100, 100);
|
||||
|
||||
rval = LFREE_2D_read_next(triangles, &set);
|
||||
abort_if(rval, "LFREE_2D_read_next failed");
|
||||
|
||||
EXPECT_NEAR(set.f[0], 0.7875, E);
|
||||
EXPECT_NEAR(set.f[1], 1.7875, E);
|
||||
|
||||
EXPECT_NEAR(set.vertices[0], 1, E);
|
||||
EXPECT_NEAR(set.vertices[1], 2, E);
|
||||
|
||||
EXPECT_NEAR(set.vertices[2], 0.4875, E);
|
||||
EXPECT_NEAR(set.vertices[3], 2.0875, E);
|
||||
|
||||
EXPECT_NEAR(set.vertices[4], -0.0625, E);
|
||||
EXPECT_NEAR(set.vertices[5], -16.0625, E);
|
||||
|
||||
EXPECT_NEAR(set.lattice_points[0], 1, E);
|
||||
EXPECT_NEAR(set.lattice_points[1], 2, E);
|
||||
|
||||
EXPECT_NEAR(set.lattice_points[2], 0, E);
|
||||
EXPECT_NEAR(set.lattice_points[3], -14, E);
|
||||
|
||||
EXPECT_NEAR(set.lattice_points[4], 0, E);
|
||||
EXPECT_NEAR(set.lattice_points[5], -15, E);
|
||||
|
||||
rval = LFREE_2D_compute_halfspaces(&set);
|
||||
abort_if(rval, "LFREE_2D_compute_halfspaces failed");
|
||||
|
||||
EXPECT_NEAR(set.halfspaces[0], 0.686274, E);
|
||||
EXPECT_NEAR(set.halfspaces[1], 4.019607, E);
|
||||
|
||||
EXPECT_NEAR(set.halfspaces[2], -3.235294, E);
|
||||
EXPECT_NEAR(set.halfspaces[3], 0.098039, E);
|
||||
|
||||
EXPECT_NEAR(set.halfspaces[4], 5.0, E);
|
||||
EXPECT_NEAR(set.halfspaces[5], -0.294117, E);
|
||||
|
||||
CLEANUP:
|
||||
if(rval) FAIL();
|
||||
}
|
||||
|
||||
TEST(LFreeSetTest, read_next_quadrilateral_test)
|
||||
{
|
||||
int rval = 0;
|
||||
|
||||
FILE *file = fopen("../lifting/library/tests/fixtures/quads.txt", "r");
|
||||
abort_if(!file, "could not read quads.txt");
|
||||
|
||||
LFreeSet2D set;
|
||||
LFREE_2D_init(&set, 100, 100, 100);
|
||||
|
||||
rval = LFREE_2D_read_next(file, &set);
|
||||
abort_if(rval, "LFREE_2D_read_next failed");
|
||||
|
||||
EXPECT_NEAR(set.f[0], 0.5, E);
|
||||
EXPECT_NEAR(set.f[1], 0.5, E);
|
||||
|
||||
EXPECT_NEAR(set.vertices[0], -0.5, E);
|
||||
EXPECT_NEAR(set.vertices[1], 0.5, E);
|
||||
|
||||
EXPECT_NEAR(set.vertices[2], 0.5, E);
|
||||
EXPECT_NEAR(set.vertices[3], 1.5, E);
|
||||
|
||||
EXPECT_NEAR(set.vertices[4], 1.5, E);
|
||||
EXPECT_NEAR(set.vertices[5], 0.5, E);
|
||||
|
||||
EXPECT_NEAR(set.vertices[6], 0.5, E);
|
||||
EXPECT_NEAR(set.vertices[7], -0.5, E);
|
||||
|
||||
EXPECT_NEAR(set.lattice_points[0], 0, E);
|
||||
EXPECT_NEAR(set.lattice_points[1], 0, E);
|
||||
|
||||
EXPECT_NEAR(set.lattice_points[2], 0, E);
|
||||
EXPECT_NEAR(set.lattice_points[3], 1, E);
|
||||
|
||||
EXPECT_NEAR(set.lattice_points[4], 1, E);
|
||||
EXPECT_NEAR(set.lattice_points[5], 1, E);
|
||||
|
||||
EXPECT_NEAR(set.lattice_points[6], 1, E);
|
||||
EXPECT_NEAR(set.lattice_points[7], 0, E);
|
||||
|
||||
rval = LFREE_2D_compute_halfspaces(&set);
|
||||
abort_if(rval, "LFREE_2D_compute_halfspaces failed");
|
||||
|
||||
EXPECT_NEAR(set.halfspaces[0], -1, E);
|
||||
EXPECT_NEAR(set.halfspaces[1], 1, E);
|
||||
|
||||
EXPECT_NEAR(set.halfspaces[2], 1, E);
|
||||
EXPECT_NEAR(set.halfspaces[3], 1, E);
|
||||
|
||||
EXPECT_NEAR(set.halfspaces[4], 1, E);
|
||||
EXPECT_NEAR(set.halfspaces[5], -1, E);
|
||||
|
||||
EXPECT_NEAR(set.halfspaces[6], -1, E);
|
||||
EXPECT_NEAR(set.halfspaces[7], -1, E);
|
||||
|
||||
CLEANUP:
|
||||
if(rval) FAIL();
|
||||
}
|
||||
|
||||
//TEST(LFreeSetTest, get_bounding_box_test)
|
||||
//{
|
||||
// int rval = 0;
|
||||
//
|
||||
// FILE *triangles = fopen("../tests/fixtures/triangles.txt", "r");
|
||||
// abort_if(!triangles, "could not read triangles.txt");
|
||||
//
|
||||
// LFreeSet2D set;
|
||||
// LFREE_2D_init(&set, 100, 100, 100);
|
||||
//
|
||||
// int ub[2], lb[2];
|
||||
//
|
||||
// rval = LFREE_2D_read_next(triangles, &set);
|
||||
// abort_if(rval, "LFREE_2D_read_next failed");
|
||||
//
|
||||
// rval = LFREE_2D_get_bounding_box(&set, lb, ub);
|
||||
// abort_if(rval, "LFREE_2D_get_bounding_box failed");
|
||||
//
|
||||
// EXPECT_NEAR(lb[0], -1.0, E);
|
||||
// EXPECT_NEAR(ub[0], 1.0, E);
|
||||
//
|
||||
// EXPECT_NEAR(lb[1], -18.0, E);
|
||||
// EXPECT_NEAR(ub[1], 2, E);
|
||||
//
|
||||
//CLEANUP:
|
||||
// if(rval) FAIL();
|
||||
//}
|
||||
|
||||
TEST(LFreeSetTest, preprocess_test)
|
||||
{
|
||||
int rval = 0;
|
||||
|
||||
double vertices[] = {
|
||||
100/11.0 ,167/33.0,
|
||||
10/11.0 , 97/33.0,
|
||||
20/11.0 , 39/11.0
|
||||
};
|
||||
|
||||
double lattice_points[] = {
|
||||
1, 3,
|
||||
4, 4,
|
||||
5, 4
|
||||
};
|
||||
|
||||
double pre_m[4];
|
||||
double center;
|
||||
|
||||
struct LFreeSet2D set;
|
||||
set.f[0] = 9 / 2.0;
|
||||
set.f[1] = 4.0;
|
||||
|
||||
set.n_vertices = 3;
|
||||
set.vertices = vertices;
|
||||
|
||||
set.n_lattice_points = 3;
|
||||
set.lattice_points = lattice_points;
|
||||
|
||||
rval = LFREE_2D_preprocess(&set, pre_m, ¢er);
|
||||
abort_if(rval, "LFREE_2D_preprocess failed");
|
||||
|
||||
EXPECT_NEAR(set.f[0], 1 / 2.0, E);
|
||||
EXPECT_NEAR(set.f[1], 1 / 2.0, E);
|
||||
|
||||
EXPECT_NEAR(set.vertices[0], 21 / 11.0, E);
|
||||
EXPECT_NEAR(set.vertices[1], 5 / 33.0, E);
|
||||
|
||||
EXPECT_NEAR(set.vertices[2], 1 / 11.0, E);
|
||||
EXPECT_NEAR(set.vertices[3], -5 / 33.0, E);
|
||||
|
||||
EXPECT_NEAR(set.vertices[4], -9 / 11.0, E);
|
||||
EXPECT_NEAR(set.vertices[5], 15 / 11.0, E);
|
||||
|
||||
EXPECT_NEAR(center, 20 / 33.0, E);
|
||||
|
||||
CLEANUP:
|
||||
if(rval) FAIL();
|
||||
|
||||
}TEST(LFreeSetTest, preprocess_test_3)
|
||||
{
|
||||
int rval = 0;
|
||||
|
||||
double vertices[] = {
|
||||
1.0, -4.0,
|
||||
1.0, 2.0,
|
||||
-0.2, 0.8
|
||||
};
|
||||
|
||||
double lattice_points[] = {
|
||||
1, 0,
|
||||
0, 1,
|
||||
0, 0
|
||||
};
|
||||
|
||||
double pre_m[4];
|
||||
double center;
|
||||
|
||||
struct LFreeSet2D set;
|
||||
set.f[0] = 1 / 2.0;
|
||||
set.f[1] = 1 / 2.0;
|
||||
|
||||
set.n_vertices = 3;
|
||||
set.vertices = vertices;
|
||||
|
||||
set.n_lattice_points = 3;
|
||||
set.lattice_points = lattice_points;
|
||||
|
||||
rval = LFREE_2D_preprocess(&set, pre_m, ¢er);
|
||||
abort_if(rval, "LFREE_2D_preprocess failed");
|
||||
|
||||
EXPECT_NEAR(set.vertices[0], -4, E);
|
||||
EXPECT_NEAR(set.vertices[1], 1, E);
|
||||
|
||||
EXPECT_NEAR(set.vertices[2], 2, E);
|
||||
EXPECT_NEAR(set.vertices[3], 1, E);
|
||||
|
||||
EXPECT_NEAR(set.vertices[4], 0.8, E);
|
||||
EXPECT_NEAR(set.vertices[5], -0.2, E);
|
||||
|
||||
EXPECT_NEAR(center, 0.4, E);
|
||||
|
||||
CLEANUP:
|
||||
if(rval) FAIL();
|
||||
}
|
||||
|
||||
TEST(LFreeSetTest, preprocess_test_2)
|
||||
{
|
||||
int rval = 0;
|
||||
|
||||
double vertices[] = {
|
||||
22, 69/7.0,
|
||||
-3, -11/7.0,
|
||||
-8, -26/7.0
|
||||
};
|
||||
|
||||
double lattice_points[] = {
|
||||
-4, -2,
|
||||
-2, -1,
|
||||
7, 3
|
||||
};
|
||||
|
||||
double r[] = { 2/3.0, 2/6.0 };
|
||||
double r0, r1;
|
||||
double value;
|
||||
|
||||
double pre_m[4];
|
||||
|
||||
struct LFreeSet2D set;
|
||||
set.f[0] = 2 / 3.0;
|
||||
set.f[1] = 1 / 6.0;
|
||||
|
||||
rval = LFREE_2D_init(&set, 10, 10, 10);
|
||||
abort_if(rval, "LFREE_2D_init failed");
|
||||
|
||||
set.n_vertices = 3;
|
||||
set.vertices = vertices;
|
||||
|
||||
set.n_lattice_points = 3;
|
||||
set.lattice_points = lattice_points;
|
||||
|
||||
rval = LFREE_2D_print_set(&set);
|
||||
abort_if(rval, "LFREE_2D_print_set failed");
|
||||
|
||||
rval = LFREE_2D_compute_halfspaces(&set);
|
||||
abort_if(rval, "LFREE_2D_compute_halfspaces failed");
|
||||
|
||||
rval = LIFTING_2D_bound(set.n_halfspaces, set.halfspaces, r, &value);
|
||||
abort_if(rval, "LIFTING_2D_bound failed");
|
||||
|
||||
log_debug("%.6lf\n", value);
|
||||
|
||||
CLEANUP:
|
||||
if(rval) FAIL();
|
||||
}
|
||||
|
||||
|
||||
TEST(LFreeSetTest, preprocess_test_4)
|
||||
{
|
||||
int rval = 0;
|
||||
|
||||
double vertices[] = {
|
||||
-5/2.0, -1,
|
||||
17/4.0, 2,
|
||||
7/2.0, 2,
|
||||
-13/4.0, -1
|
||||
};
|
||||
|
||||
double lattice_points[] = {
|
||||
2, 1,
|
||||
-3, -1,
|
||||
-1, 0,
|
||||
4, 2
|
||||
};
|
||||
|
||||
double pre_m[4];
|
||||
double center;
|
||||
|
||||
struct LFreeSet2D set;
|
||||
set.f[0] = 1 / 2.0;
|
||||
set.f[1] = 1 / 2.0;
|
||||
|
||||
set.n_vertices = 4;
|
||||
set.vertices = vertices;
|
||||
|
||||
set.n_lattice_points = 4;
|
||||
set.lattice_points = lattice_points;
|
||||
|
||||
rval = LFREE_2D_preprocess(&set, pre_m, ¢er);
|
||||
abort_if(rval, "LFREE_2D_preprocess failed");
|
||||
|
||||
LFREE_2D_print_set(&set);
|
||||
|
||||
EXPECT_NEAR(set.vertices[0], -1, E);
|
||||
EXPECT_NEAR(set.vertices[1], 1/2.0, E);
|
||||
|
||||
EXPECT_NEAR(set.vertices[2], 1/2.0, E);
|
||||
EXPECT_NEAR(set.vertices[3], -1/4.0, E);
|
||||
|
||||
EXPECT_NEAR(set.vertices[4], 2, E);
|
||||
EXPECT_NEAR(set.vertices[5], 1/2.0, E);
|
||||
|
||||
EXPECT_NEAR(set.vertices[6], 1/2.0, E);
|
||||
EXPECT_NEAR(set.vertices[7], 5/4.0, E);
|
||||
|
||||
EXPECT_NEAR(pre_m[0], -2, E);
|
||||
EXPECT_NEAR(pre_m[1], -1, E);
|
||||
EXPECT_NEAR(pre_m[2], 5, E);
|
||||
EXPECT_NEAR(pre_m[3], 2, E);
|
||||
|
||||
EXPECT_NEAR(center, 0.5, E);
|
||||
|
||||
CLEANUP:
|
||||
if(rval) FAIL();
|
||||
}
|
||||
Reference in New Issue
Block a user