Revision 96344048632acd7871b0a92ac903fc07575517f4 authored by TolisChal on 07 December 2020, 16:23:16 UTC, committed by TolisChal on 07 December 2020, 16:23:16 UTC
2 parent s eb525ca + 77c446f
Raw File
boundary_oracles_test.cpp
// VolEsti (volume computation and sampling library)

// Copyright (c) 2012-2020 Vissarion Fisikopoulos
// Copyright (c) 2018-2020 Apostolos Chalkis
// Copyright (c) 2020-2020 Marios Papachristou

// Contributed and/or modified by Marios Papachristou, as part of Google Summer of Code 2020 program.

// Licensed under GNU LGPL.3, see LICENCE file

#ifndef DISABLE_NLP_ORACLES

#include <iostream>
#include <cmath>
#include <functional>
#include <vector>
#include <unistd.h>
#include <string>
#include <typeinfo>
#include <chrono>

#include "Eigen/Eigen"
#include "doctest.h"

#include "random.hpp"
#include "random/uniform_int.hpp"
#include "random/normal_distribution.hpp"
#include "random/uniform_real_distribution.hpp"
#include "random_walks/random_walks.hpp"
#include "volume/volume_sequence_of_balls.hpp"
#include "volume/volume_cooling_gaussians.hpp"
#include "volume/volume_cooling_balls.hpp"
#include "generators/known_polytope_generators.h"
#include "nlp_oracles/nlp_oracles.hpp"

template <typename NT, class Point, class bfunc>
void test_h_poly_oracles(std::vector<Point> coeffs, bfunc phi, bfunc grad_phi, NT t_des, int facet_des) {
  typedef boost::mt19937    RNGType;
  typedef HPolytope<Point> Hpolytope;
  typedef std::tuple<NT, Point, int> result;
  Hpolytope P;
  NT tol = 1e-4;

  P = generate_cube<Hpolytope>(2, false);
  NewtonRaphsonHPolyoracle<Hpolytope, bfunc> nr_oracle;
  IpoptHPolyoracle<Hpolytope, bfunc> ipopt_oracle;
  MPSolveHPolyoracle<Hpolytope, bfunc> mpsolve_oracle;

  result res = P.curve_intersect(0.01, 0, -1, coeffs, phi, grad_phi, nr_oracle);
  NT t = std::get<0>(res);
  int facet = std::get<2>(res);

  // CHECK(facet == facet_des);
  CHECK(std::abs(t - t_des) / t_des < tol);

  result res2 = P.curve_intersect(0.0, 0, -1, coeffs, phi, grad_phi, ipopt_oracle);

  t = std::get<0>(res2);
  facet = std::get<2>(res2);
  CHECK(std::abs(t - t_des) / t_des < tol);

  res2 = P.curve_intersect(0, 0, -1, coeffs, phi, grad_phi, mpsolve_oracle);

  t = std::get<0>(res2);
  // std::cout << "t is " << t << std::endl;
  facet = std::get<2>(res2);
  CHECK(std::abs(t - t_des) / t_des < tol);


}

template <typename NT, class Point, class bfunc>
void test_v_poly_oracles(std::vector<Point> coeffs, bfunc phi, bfunc grad_phi, NT t_des, int facet_des) {
  typedef boost::mt19937    RNGType;
  typedef VPolytope<Point> Vpolytope;
  typedef std::tuple<NT, Point, int> result;
  Vpolytope P;
  NT tol = 1e-4;

  P = generate_cube<Vpolytope>(2, true);
  IpoptVPolyoracle<Vpolytope, bfunc> ipopt_oracle;


  result res2 = P.curve_intersect(0.01, 0, -1, coeffs, phi, grad_phi, ipopt_oracle);
  NT t = std::get<0>(res2);

  std::cout << t << " " << t_des << std::endl;

  CHECK(std::abs(std::abs(t) - t_des) / t_des < tol);

}

template <typename NT>
void call_test_poly_oracles(char typ) {
  typedef Cartesian<NT>    Kernel;
  typedef typename Kernel::Point    Point;
  typedef std::vector<Point> pts;
  typedef PolynomialBasis<NT> bfunc;

  std::cout << "--- Testing intersection of 2D cube with p(t) = (t, t)" << std::endl;

  Point a0(2);
  Point a1(2);
  a1.set_coord(0, 1);
  a1.set_coord(1, 1);

  pts line_coeffs{a0, a1};

  bfunc poly_basis(FUNCTION);
  bfunc poly_basis_grad(DERIVATIVE);

  NT t_des_line = NT(1);
  int facet_des_line = 0;

  if (typ == 'H') {
    test_h_poly_oracles<NT, Point, bfunc>(line_coeffs, poly_basis, poly_basis_grad, t_des_line, facet_des_line);
  } else if (typ == 'V'){
    test_v_poly_oracles<NT, Point, bfunc>(line_coeffs, poly_basis, poly_basis_grad, t_des_line, facet_des_line);
  }

  std::cout << "--- Testing intersection of 2D cube with p(t) = (t, 2 * t^2)" << std::endl;

  Point b0(2);
  Point b1(2);
  Point b2(2);
  b1.set_coord(0, 1);
  b2.set_coord(1, 2);

  NT t_des_parabola = NT(1 / sqrt(2));
  int facet_des_parabola = 1;
  pts parabola_coeffs{b0, b1, b2};

  if (typ == 'H') {
    test_h_poly_oracles<NT, Point, bfunc>(parabola_coeffs, poly_basis, poly_basis_grad, t_des_parabola, facet_des_parabola);
  } else if (typ == 'V') {
    test_v_poly_oracles<NT, Point, bfunc>(parabola_coeffs, poly_basis, poly_basis_grad, t_des_parabola, facet_des_parabola);
  }

}

template <typename NT>
void call_benchmark_oracles() {
  typedef Cartesian<NT>    Kernel;
  typedef typename Kernel::Point    Point;
  typedef boost::mt19937    RNGType;
  typedef HPolytope<Point> Hpolytope;
  typedef std::tuple<NT, Point, int> result;
  typedef PolynomialBasis<NT> bfunc;
  Hpolytope P;
  NT tol = 1e-4;
  std::pair<int, int>dims = std::make_pair(2, 10);
  std::pair<int, int>orders = std::make_pair(2, 3);
  result res;
  long newton_correct = 0L, ipopt_correct = 0L, total = 0L;

  long newton_runtime = 0L;
  long ipopt_runtime = 0L;

  bfunc poly_basis(FUNCTION);
  bfunc poly_basis_grad(DERIVATIVE);

  std::vector<Point> coeffs;

  NewtonRaphsonHPolyoracle<Hpolytope, bfunc> nr_oracle;
  IpoptHPolyoracle<Hpolytope, bfunc> ipopt_oracle;

  for (int dim = dims.first; dim <= dims.second; dim++) {
    Point p;
    P = generate_cube<Hpolytope>(dim, false);

    for (int order = orders.first; order <= orders.second; order++) {
      p = Point(dim);
      p.set_coord(order, order);
      coeffs.push_back(p);

      auto start = std::chrono::high_resolution_clock::now();
      res = P.curve_intersect(0.01, 0, -1, coeffs, poly_basis, poly_basis_grad, nr_oracle);
      auto stop = std::chrono::high_resolution_clock::now();

      newton_runtime += (long) std::chrono::duration_cast<std::chrono::microseconds>(stop - start).count();

      start = std::chrono::high_resolution_clock::now();
      P.curve_intersect(0, 0, -1, coeffs, poly_basis, poly_basis_grad, ipopt_oracle);
      stop = std::chrono::high_resolution_clock::now();
      ipopt_runtime += (long) std::chrono::duration_cast<std::chrono::microseconds>(stop - start).count();

      std::cout << std::endl;

      total++;
    }

  }

  std::cout << "Newton-Raphson: " << newton_runtime << " us" << std::endl;
  std::cout << "Interior-points: " << ipopt_runtime << " us" << std::endl;
}


TEST_CASE("h_poly_oracles") {
  call_test_poly_oracles<double>('H');
}

// TEST_CASE("benchmark_oracles") {
//   call_benchmark_oracles<double>();
// }

// TEST_CASE("v_poly_oracles") {
//   call_test_poly_oracles<double>('V');
// }

#endif
back to top