mirror of https://github.com/CGAL/cgal
- forgot to commit that file (previous log message applies)
This commit is contained in:
parent
6552d6b08b
commit
1e46b5e6d1
|
|
@ -26,11 +26,244 @@
|
|||
#include <CGAL/function_objects.h>
|
||||
|
||||
#include <CGAL/QP_solver.h>
|
||||
#include <CGAL/QP_models.h>
|
||||
#include <CGAL/QP_solver/iterator.h>
|
||||
#include <CGAL/QP_solver/QP_partial_filtered_pricing.h>
|
||||
#include <CGAL/QP_solver/QP_partial_exact_pricing.h>
|
||||
|
||||
CGAL_BEGIN_NAMESPACE
|
||||
|
||||
// To determine the polytope distance, we set up the following QP:
|
||||
//
|
||||
// We let v-w be nonnegative vectors such that
|
||||
// v-w = p-q, where p and q are the points that realize the
|
||||
// optimal distance. That way, we obtain a nonnegative QP
|
||||
//
|
||||
//
|
||||
//min (v-w)^T(w-v)
|
||||
// v-w - \sum x_i p_i + \sum y_j q_j = 0
|
||||
// \sum x_i = 1
|
||||
// \sum y_j = 1
|
||||
// v, w, x, y >= 0
|
||||
|
||||
namespace PD_detail {
|
||||
// The functors necessary to realize access to A
|
||||
//
|
||||
// A has the form
|
||||
// I -I -P Q
|
||||
// 0 0 1 0
|
||||
// 0 0 0 1
|
||||
// where I and -I are blocks of size d*d, and the 0's and 1's are
|
||||
// rows vectors of 0's and 1's
|
||||
//
|
||||
// we have one functor for a fixed column, and one functor for the
|
||||
// whole matrix
|
||||
|
||||
// functor for a fixed column of A
|
||||
template <class NT, class Iterator>
|
||||
class A_column : public std::unary_function <int, NT>
|
||||
{
|
||||
public:
|
||||
typedef NT result_type;
|
||||
A_column()
|
||||
{}
|
||||
|
||||
A_column (int j, int d, bool in_p, Iterator it)
|
||||
: j_ (j), d_ (d), in_p_ (in_p), it_ (it), nt_0_ (0), nt_1_ (1)
|
||||
{}
|
||||
|
||||
result_type operator() (int i) const
|
||||
{
|
||||
if (j_ < d_) {
|
||||
// column for v
|
||||
return (i == j_ ? nt_1_ : nt_0_);
|
||||
}
|
||||
if (j_ < 2*d_) {
|
||||
// column for w
|
||||
return (i == j_-d_ ? -nt_1_ : nt_0_);
|
||||
}
|
||||
// point column
|
||||
if (in_p_) {
|
||||
// column for P
|
||||
if (i < d_) return -(*(it_ + i));
|
||||
if (i == d_) return *(it_ + d_); // homogenizing coordinate
|
||||
return nt_0_;
|
||||
} else {
|
||||
// column for Q
|
||||
if (i < d_) return (*(it_ + i));
|
||||
if (i == d_+1) return *(it_ + d_); // homogenizing coordinate
|
||||
return nt_0_;
|
||||
}
|
||||
CGAL_optimisation_assertion(false); // never get here
|
||||
return nt_0_;
|
||||
}
|
||||
|
||||
private:
|
||||
int j_; // column number
|
||||
int d_; // dimension
|
||||
bool in_p_; // point in P ?
|
||||
Iterator it_; // the iterator through the column's point
|
||||
NT nt_0_;
|
||||
NT nt_1_;
|
||||
};
|
||||
|
||||
// functor for matrix A
|
||||
template <class NT, class Access_coordinate_begin_d,
|
||||
class Point_iterator >
|
||||
class A_matrix : public std::unary_function
|
||||
<int, CGAL::Transform_diff_const_iterator
|
||||
<int, A_column
|
||||
<NT, typename Access_coordinate_begin_d::Coordinate_iterator> > >
|
||||
{
|
||||
typedef A_column
|
||||
<NT, typename Access_coordinate_begin_d::Coordinate_iterator> A_column;
|
||||
public:
|
||||
typedef CGAL::Transform_diff_const_iterator
|
||||
<int, A_column> result_type;
|
||||
|
||||
A_matrix ()
|
||||
{}
|
||||
|
||||
A_matrix (int d,
|
||||
Access_coordinate_begin_d da_coord,
|
||||
Point_iterator P,
|
||||
int r,
|
||||
Point_iterator Q)
|
||||
: d_ (d), da_coord_ (da_coord), P_ (P), r_ (r), Q_ (Q)
|
||||
{}
|
||||
|
||||
result_type operator () (int j) const
|
||||
{
|
||||
if (j < 2*d_) {
|
||||
// column of v or w
|
||||
return result_type
|
||||
(0, A_column (j, d_, false /*dummy*/,
|
||||
da_coord_ (*P_) /*dummy*/));
|
||||
}
|
||||
if (j < 2*d_+r_) {
|
||||
// column of P
|
||||
return result_type
|
||||
(0, A_column (j , d_, true, da_coord_ (*(P_+j-2*d_))));
|
||||
}
|
||||
// column of Q
|
||||
return result_type
|
||||
(0, A_column (j, d_, false, da_coord_ (*(Q_+j-2*d_-r_))));
|
||||
}
|
||||
|
||||
private:
|
||||
int d_; // dimension
|
||||
Access_coordinate_begin_d da_coord_; // data accessor
|
||||
Point_iterator P_; // point set P
|
||||
int r_; // size of point set P
|
||||
Point_iterator Q_; // point set Q
|
||||
};
|
||||
|
||||
// The functor necessary to realize access to b
|
||||
// b has the form
|
||||
// 0
|
||||
// 0
|
||||
// 1 (row d)
|
||||
// 1 (row d+1)
|
||||
|
||||
template <class NT>
|
||||
class B_vector : public std::unary_function<int, NT>
|
||||
{
|
||||
public:
|
||||
typedef NT result_type;
|
||||
B_vector()
|
||||
{}
|
||||
|
||||
B_vector (int d)
|
||||
: d_ (d), nt_0_ (0), nt_1_ (1)
|
||||
{}
|
||||
|
||||
result_type operator() (int i) const
|
||||
{
|
||||
return ( (i == d_ || i == d_+1) ? nt_1_ : nt_0_);
|
||||
}
|
||||
|
||||
private:
|
||||
int d_;
|
||||
NT nt_0_;
|
||||
NT nt_1_;
|
||||
};
|
||||
|
||||
|
||||
// The functors necessary to realize access to D
|
||||
//
|
||||
// D has the form
|
||||
// I -I 0
|
||||
// -I I 0
|
||||
// 0 0 0
|
||||
// where all I and -I are blocks of size d*d
|
||||
//
|
||||
// we have one functor for a fixed row, and one functor for the
|
||||
// whole matrix
|
||||
|
||||
// functor for a fixed row of D
|
||||
template <class NT>
|
||||
class D_row : public std::unary_function <int, NT>
|
||||
{
|
||||
public:
|
||||
typedef NT result_type;
|
||||
D_row ()
|
||||
{}
|
||||
D_row (int i, int d)
|
||||
: i_ (i), d_ (d), nt_0_ (0), nt_1_ (1)
|
||||
{}
|
||||
|
||||
result_type operator () (int j) const
|
||||
{
|
||||
if (j < d_) {
|
||||
// I ( 1 iff i = j)
|
||||
// -I (-1 iff i = j + d)
|
||||
// 0
|
||||
if (i_ == j) return nt_1_;
|
||||
if (i_ == j + d_) return -nt_1_;
|
||||
return nt_0_;
|
||||
}
|
||||
if (j < 2*d_) {
|
||||
// -I (-1 iff i = j - d)
|
||||
// I ( 1 iff i = j)
|
||||
// 0
|
||||
if (i_ == j - d_) return -nt_1_;
|
||||
if (i_ == j) return nt_1_;
|
||||
return nt_0_;
|
||||
}
|
||||
// 0
|
||||
// 0
|
||||
// 0
|
||||
return nt_0_;
|
||||
}
|
||||
private:
|
||||
int i_; // row number
|
||||
int d_; // dimension
|
||||
NT nt_0_;
|
||||
NT nt_1_;
|
||||
};
|
||||
|
||||
// functor for matrix D
|
||||
template <class NT>
|
||||
class D_matrix : public std::unary_function
|
||||
<int, CGAL::Transform_diff_const_iterator<int, D_row<NT> > >
|
||||
{
|
||||
public:
|
||||
typedef CGAL::Transform_diff_const_iterator<int, D_row<NT> > result_type;
|
||||
D_matrix ()
|
||||
{}
|
||||
D_matrix (int d)
|
||||
: d_ (d)
|
||||
{}
|
||||
|
||||
result_type operator()(int i) const
|
||||
{
|
||||
return result_type (0, D_row<NT>(i, d_));
|
||||
}
|
||||
|
||||
private:
|
||||
int d_; // dimension
|
||||
};
|
||||
|
||||
// A functor whose operator(int i) provides access to the i-th element
|
||||
// of a random access iterator.
|
||||
template < typename RndAccIt, typename ArgType >
|
||||
|
|
@ -45,36 +278,7 @@ public:
|
|||
private:
|
||||
RndAccIt a;
|
||||
};
|
||||
|
||||
// Class declarations
|
||||
// ==================
|
||||
template < class Traits_ >
|
||||
class Polytope_distance_d;
|
||||
|
||||
template < class ET_, class NT_, class Point, class Point_iterator,
|
||||
class Access_coord, class Access_dim >
|
||||
struct QP_rep_poly_dist_d;
|
||||
|
||||
template < class NT >
|
||||
struct QP_rep_row_of_a {
|
||||
typedef std::vector<NT> argument_type;
|
||||
typedef typename argument_type::const_iterator result_type;
|
||||
|
||||
result_type
|
||||
operator ( ) ( const argument_type& v) const { return v.begin(); }
|
||||
};
|
||||
|
||||
template < class Point, class Point_iterator >
|
||||
struct QP_rep_signed_point_iterator;
|
||||
|
||||
template < class NT, class ET, class Point,
|
||||
class Access_coord, class Access_dim >
|
||||
class QP_rep_signed_inner_product;
|
||||
|
||||
template < class NT, class ET, class Point, class Point_iterator,
|
||||
class Access_coord, class Access_dim >
|
||||
struct QP_rep_row_of_d;
|
||||
|
||||
}
|
||||
|
||||
// Class interfaces
|
||||
// ================
|
||||
|
|
@ -106,27 +310,17 @@ class Polytope_distance_d {
|
|||
typedef typename Traits::NT NT;
|
||||
|
||||
private:
|
||||
// QP solver
|
||||
typedef CGAL::QP_rep_poly_dist_d<
|
||||
ET, NT, Point, typename std::vector<Point>::const_iterator,
|
||||
Access_coordinates_begin_d, Access_dimension_d >
|
||||
QP_rep;
|
||||
typedef CGAL::QP_solver< QP_rep > Solver;
|
||||
typedef typename Solver::Pricing_strategy
|
||||
Pricing_strategy;
|
||||
// private types
|
||||
typedef std::vector<Point> Point_vector;
|
||||
typedef std::vector<ET> ET_vector;
|
||||
|
||||
typedef std::vector<int> Index_vector;
|
||||
|
||||
typedef CGAL::Access_by_index<typename std::vector<Point>::const_iterator,
|
||||
int> Point_by_index;
|
||||
typedef PD_detail::Access_by_index
|
||||
<typename std::vector<Point>::const_iterator, int> Point_by_index;
|
||||
|
||||
typedef std::vector<NT> NT_vector;
|
||||
typedef std::vector<NT_vector> NT_matrix;
|
||||
|
||||
|
||||
typedef std::vector<int> Index_vector;
|
||||
public:
|
||||
// public types
|
||||
typedef typename Point_vector::const_iterator
|
||||
|
|
@ -142,10 +336,41 @@ class Polytope_distance_d {
|
|||
typedef typename ET_vector::const_iterator
|
||||
Coordinate_iterator;
|
||||
|
||||
private:
|
||||
|
||||
// QP solver iterator types
|
||||
typedef PD_detail::A_matrix <NT, Access_coordinates_begin_d,
|
||||
Point_iterator> A_matrix;
|
||||
typedef CGAL::Transform_diff_const_iterator<int, A_matrix> A_iterator;
|
||||
|
||||
typedef PD_detail::B_vector <NT> B_vector;
|
||||
typedef CGAL::Transform_diff_const_iterator<int, B_vector> B_iterator;
|
||||
|
||||
typedef CGAL::Const_oneset_iterator<CGAL::Comparison_result> R_iterator;
|
||||
typedef CGAL::Const_oneset_iterator<NT> C_iterator;
|
||||
|
||||
typedef PD_detail::D_matrix <NT> D_matrix;
|
||||
typedef CGAL::Transform_diff_const_iterator<int, D_matrix> D_iterator;
|
||||
|
||||
// Program type
|
||||
typedef CGAL::Nonnegative_quadratic_program_from_iterators
|
||||
<A_iterator, B_iterator, R_iterator, D_iterator, C_iterator> QP;
|
||||
|
||||
// Tags
|
||||
typedef QP_solver_impl::QP_tags <Tag_false, Tag_true> QP_tags;
|
||||
|
||||
// Solver types
|
||||
typedef CGAL::QP_solver <QP, ET, QP_tags > Solver;
|
||||
|
||||
typedef typename Solver::Pricing_strategy Pricing_strategy;
|
||||
|
||||
public:
|
||||
|
||||
// creation
|
||||
Polytope_distance_d( const Traits& traits = Traits())
|
||||
: tco( traits), d( -1), solver(0), strategy(0) {}
|
||||
: nt_0(0), nt_1(1),
|
||||
tco( traits), da_coord (tco.access_coordinates_begin_d_object()),
|
||||
d( -1), solver(0), strategy(0) {}
|
||||
|
||||
template < class InputIterator1, class InputIterator2 >
|
||||
Polytope_distance_d( InputIterator1 p_first,
|
||||
|
|
@ -153,7 +378,9 @@ class Polytope_distance_d {
|
|||
InputIterator2 q_first,
|
||||
InputIterator2 q_last,
|
||||
const Traits& traits = Traits())
|
||||
: tco( traits), solver(0), strategy(0)
|
||||
: nt_0(0), nt_1(1),
|
||||
tco( traits), da_coord (tco.access_coordinates_begin_d_object()),
|
||||
solver(0), strategy(0)
|
||||
{
|
||||
set( p_first, p_last, q_first, q_last);
|
||||
}
|
||||
|
|
@ -182,7 +409,8 @@ class Polytope_distance_d {
|
|||
// access to support points
|
||||
int
|
||||
number_of_support_points( ) const
|
||||
{ return is_finite() ? solver->number_of_basic_variables() : 0; }
|
||||
{ return is_finite() ?
|
||||
p_support_indices.size()+q_support_indices.size() : 0; }
|
||||
|
||||
int number_of_support_points_p() const { return p_support_indices.size();}
|
||||
int number_of_support_points_q() const { return q_support_indices.size();}
|
||||
|
|
@ -254,14 +482,16 @@ class Polytope_distance_d {
|
|||
Point
|
||||
realizing_point_p( ) const
|
||||
{ CGAL_optimisation_precondition( is_finite());
|
||||
return tco.construct_point_d_object()( ambient_dimension(),
|
||||
return tco.construct_point_d_object()
|
||||
( ambient_dimension(),
|
||||
realizing_point_p_coordinates_begin(),
|
||||
realizing_point_p_coordinates_end ()); }
|
||||
|
||||
Point
|
||||
realizing_point_q( ) const
|
||||
{ CGAL_optimisation_precondition( is_finite());
|
||||
return tco.construct_point_d_object()( ambient_dimension(),
|
||||
return tco.construct_point_d_object()
|
||||
( ambient_dimension(),
|
||||
realizing_point_q_coordinates_begin(),
|
||||
realizing_point_q_coordinates_end ()); }
|
||||
|
||||
|
|
@ -284,99 +514,124 @@ class Polytope_distance_d {
|
|||
void
|
||||
set( InputIterator1 p_first, InputIterator1 p_last,
|
||||
InputIterator2 q_first, InputIterator2 q_last)
|
||||
{ if ( p_points.size() > 0)
|
||||
{
|
||||
if ( p_points.size() > 0)
|
||||
p_points.erase( p_points.begin(), p_points.end());
|
||||
if ( q_points.size() > 0)
|
||||
q_points.erase( q_points.begin(), q_points.end());
|
||||
std::copy( p_first, p_last, std::back_inserter( p_points));
|
||||
std::copy( q_first, q_last, std::back_inserter( q_points));
|
||||
set_dimension();
|
||||
CGAL_optimisation_precondition_msg(
|
||||
check_dimension( p_points.begin(), p_points.end())
|
||||
CGAL_optimisation_precondition_msg
|
||||
(check_dimension( p_points.begin(), p_points.end())
|
||||
&& check_dimension( q_points.begin(), q_points.end()),
|
||||
"Not all points have the same dimension.");
|
||||
compute_distance(); }
|
||||
|
||||
compute_distance();
|
||||
}
|
||||
|
||||
template < class InputIterator >
|
||||
void
|
||||
set_p( InputIterator p_first, InputIterator p_last)
|
||||
{ if ( p_points.size() > 0)
|
||||
{
|
||||
if ( p_points.size() > 0)
|
||||
p_points.erase( p_points.begin(), p_points.end());
|
||||
std::copy( p_first, p_last, std::back_inserter( p_points));
|
||||
set_dimension();
|
||||
CGAL_optimisation_precondition_msg(
|
||||
check_dimension( p_points.begin(), p_points.end()),
|
||||
CGAL_optimisation_precondition_msg
|
||||
(check_dimension( p_points.begin(), p_points.end()),
|
||||
"Not all points have the same dimension.");
|
||||
compute_distance(); }
|
||||
|
||||
compute_distance();
|
||||
}
|
||||
|
||||
template < class InputIterator >
|
||||
void
|
||||
set_q( InputIterator q_first, InputIterator q_last)
|
||||
{ if ( q_points.size() > 0)
|
||||
{
|
||||
if ( q_points.size() > 0)
|
||||
q_points.erase( q_points.begin(), q_points.end());
|
||||
std::copy( q_first, q_last, std::back_inserter( q_points));
|
||||
set_dimension();
|
||||
CGAL_optimisation_precondition_msg(
|
||||
check_dimension( q_points.begin(), q_points.end()),
|
||||
CGAL_optimisation_precondition_msg
|
||||
(check_dimension( q_points.begin(), q_points.end()),
|
||||
"Not all points have the same dimension.");
|
||||
compute_distance(); }
|
||||
|
||||
compute_distance();
|
||||
}
|
||||
|
||||
void
|
||||
insert_p( const Point& p)
|
||||
{ CGAL_optimisation_precondition( ( ! is_finite()) ||
|
||||
{
|
||||
CGAL_optimisation_precondition
|
||||
( ( ! is_finite()) ||
|
||||
( tco.access_dimension_d_object()( p) == d));
|
||||
p_points.push_back( p);
|
||||
compute_distance(); }
|
||||
set_dimension(); // it might no longer be -1
|
||||
compute_distance();
|
||||
}
|
||||
|
||||
void
|
||||
insert_q( const Point& q)
|
||||
{ CGAL_optimisation_precondition( ( ! is_finite()) ||
|
||||
{
|
||||
CGAL_optimisation_precondition
|
||||
( ( ! is_finite()) ||
|
||||
( tco.access_dimension_d_object()( q) == d));
|
||||
q_points.push_back( q);
|
||||
compute_distance(); }
|
||||
set_dimension(); // it might no longer be -1
|
||||
compute_distance();
|
||||
}
|
||||
|
||||
template < class InputIterator1, class InputIterator2 >
|
||||
void
|
||||
insert( InputIterator1 p_first, InputIterator1 p_last,
|
||||
InputIterator2 q_first, InputIterator2 q_last)
|
||||
{ CGAL_optimisation_precondition_code( int old_r = p_points.size());
|
||||
CGAL_optimisation_precondition_code( int old_s = q_points.size());
|
||||
{
|
||||
int old_r = p_points.size();
|
||||
int old_s = q_points.size();
|
||||
p_points.insert( p_points.end(), p_first, p_last);
|
||||
q_points.insert( q_points.end(), q_first, q_last);
|
||||
set_dimension();
|
||||
CGAL_optimisation_precondition_msg(
|
||||
check_dimension( p_points.begin()+old_r, p_points.end())
|
||||
CGAL_optimisation_precondition_msg
|
||||
(check_dimension( p_points.begin()+old_r, p_points.end())
|
||||
&& check_dimension( q_points.begin()+old_s, q_points.end()),
|
||||
"Not all points have the same dimension.");
|
||||
compute_distance(); }
|
||||
compute_distance();
|
||||
}
|
||||
|
||||
template < class InputIterator >
|
||||
void
|
||||
insert_p( InputIterator p_first, InputIterator p_last)
|
||||
{ CGAL_optimisation_precondition_code( int old_r = p_points.size());
|
||||
{
|
||||
int old_r = p_points.size();
|
||||
p_points.insert( p_points.end(), p_first, p_last);
|
||||
set_dimension();
|
||||
CGAL_optimisation_precondition_msg(
|
||||
check_dimension( p_points.begin()+old_r, p_points.end()),
|
||||
CGAL_optimisation_precondition_msg
|
||||
(check_dimension( p_points.begin()+old_r, p_points.end()),
|
||||
"Not all points have the same dimension.");
|
||||
compute_distance(); }
|
||||
compute_distance();
|
||||
}
|
||||
|
||||
template < class InputIterator >
|
||||
void
|
||||
insert_q( InputIterator q_first, InputIterator q_last)
|
||||
{ CGAL_optimisation_precondition_code( int old_s = q_points.size());
|
||||
{
|
||||
int old_s = q_points.size();
|
||||
q_points.insert( q_points.end(), q_first, q_last);
|
||||
set_dimension();
|
||||
CGAL_optimisation_precondition_msg(
|
||||
check_dimension( q_points.begin()+old_s, q_points.end()),
|
||||
CGAL_optimisation_precondition_msg
|
||||
(check_dimension( q_points.begin()+old_s, q_points.end()),
|
||||
"Not all points have the same dimension.");
|
||||
compute_distance(); }
|
||||
compute_distance();
|
||||
}
|
||||
|
||||
void
|
||||
clear( )
|
||||
{ p_points.erase( p_points.begin(), p_points.end());
|
||||
{
|
||||
p_points.erase( p_points.begin(), p_points.end());
|
||||
q_points.erase( q_points.begin(), q_points.end());
|
||||
compute_distance(); }
|
||||
compute_distance();
|
||||
}
|
||||
|
||||
// validity check
|
||||
bool is_valid( bool verbose = false, int level = 0) const;
|
||||
|
|
@ -386,7 +641,11 @@ class Polytope_distance_d {
|
|||
|
||||
|
||||
private:
|
||||
NT nt_0;
|
||||
NT nt_1;
|
||||
|
||||
Traits tco; // traits class object
|
||||
Access_coordinates_begin_d da_coord; // data accessor object
|
||||
|
||||
Point_vector p_points; // points of P
|
||||
Point_vector q_points; // points of Q
|
||||
|
|
@ -401,25 +660,26 @@ private:
|
|||
Index_vector p_support_indices;
|
||||
Index_vector q_support_indices;
|
||||
|
||||
NT_matrix a_matrix; // matrix `A' of QP
|
||||
|
||||
private:
|
||||
// set dimension of input points
|
||||
void
|
||||
set_dimension( )
|
||||
{ d = ( p_points.size() > 0 ?
|
||||
{
|
||||
d = ( p_points.size() > 0 ?
|
||||
tco.access_dimension_d_object()( p_points[ 0]) :
|
||||
q_points.size() > 0 ?
|
||||
tco.access_dimension_d_object()( q_points[ 0]) :
|
||||
-1); }
|
||||
-1);
|
||||
}
|
||||
|
||||
// check dimension of input points
|
||||
template < class InputIterator >
|
||||
bool
|
||||
check_dimension( InputIterator first, InputIterator last)
|
||||
{ return ( std::find_if( first, last,
|
||||
CGAL::compose1_1( std::bind2nd(
|
||||
std::not_equal_to<int>(), d),
|
||||
{ return ( std::find_if
|
||||
( first, last,
|
||||
CGAL::compose1_1
|
||||
( std::bind2nd(std::not_equal_to<int>(), d),
|
||||
tco.access_dimension_d_object()))
|
||||
== last); }
|
||||
|
||||
|
|
@ -434,65 +694,50 @@ private:
|
|||
q_support_indices.end());
|
||||
if ( ( p_points.size() == 0) || ( q_points.size() == 0)) return;
|
||||
|
||||
// set up and solve QP
|
||||
int i, j;
|
||||
NT nt_0 = 0, nt_1 = 1;
|
||||
|
||||
// matrix A
|
||||
a_matrix.erase( a_matrix.begin(), a_matrix.end());
|
||||
a_matrix.insert( a_matrix.end(),
|
||||
number_of_points(), NT_vector( 2, nt_0));
|
||||
for ( j = 0; j < number_of_points_p(); ++j) a_matrix[ j][ 0] = nt_1;
|
||||
for ( ; j < number_of_points (); ++j) a_matrix[ j][ 1] = nt_1;
|
||||
|
||||
// set-up
|
||||
typedef QP_rep_signed_point_iterator< Point, Point_iterator >
|
||||
Signed_point_iterator;
|
||||
Signed_point_iterator
|
||||
signed_pts_it(p_points.begin(), p_points.size(), q_points.begin());
|
||||
QP_rep_row_of_d< NT, ET, Point, Signed_point_iterator,
|
||||
Access_coordinates_begin_d, Access_dimension_d >
|
||||
row_of_d( signed_pts_it,
|
||||
tco.access_coordinates_begin_d_object(),
|
||||
tco.access_dimension_d_object());
|
||||
|
||||
typedef typename QP_rep::A_iterator A_it;
|
||||
typedef typename QP_rep::B_iterator B_it;
|
||||
typedef typename QP_rep::C_iterator C_it;
|
||||
typedef typename C_it::value_type C_entry;
|
||||
typedef typename QP_rep::D_iterator D_it;
|
||||
typedef typename QP_rep::Row_type_iterator Row_it;
|
||||
// construct program
|
||||
unsigned int n = 2 * d + p_points.size() + q_points.size();
|
||||
unsigned int m = d + 2;
|
||||
CGAL_optimisation_precondition (p_points.size() > 0);
|
||||
QP qp (n, m,
|
||||
A_iterator
|
||||
(0, A_matrix (d, da_coord, p_points.begin(), p_points.size(),
|
||||
q_points.begin())),
|
||||
B_iterator (0, B_vector (d)),
|
||||
R_iterator (CGAL::EQUAL),
|
||||
D_iterator (0, D_matrix (d)),
|
||||
C_iterator (nt_0));
|
||||
|
||||
delete strategy;
|
||||
strategy = pricing_strategy(NT());
|
||||
solver = new Solver(number_of_points(), 2,
|
||||
A_it( a_matrix.begin()), B_it( 1), C_it( 0),
|
||||
C_entry( 0), D_it( signed_pts_it, row_of_d),
|
||||
Row_it(QP_rep::EQUAL), strategy);
|
||||
|
||||
delete solver;
|
||||
solver = new Solver(qp, strategy);
|
||||
CGAL_optimisation_assertion(solver->is_valid());
|
||||
CGAL_optimisation_assertion(solver->status() == QP_OPTIMAL);
|
||||
// compute support and realizing points
|
||||
ET et_0 = 0;
|
||||
int r = number_of_points_p();
|
||||
int r = p_points.size();
|
||||
p_coords.resize( ambient_dimension()+1);
|
||||
q_coords.resize( ambient_dimension()+1);
|
||||
std::fill( p_coords.begin(), p_coords.end(), et_0);
|
||||
std::fill( q_coords.begin(), q_coords.end(), et_0);
|
||||
for ( i = 0; i < solver->number_of_basic_variables(); ++i) {
|
||||
for (int i = 0; i < solver->number_of_basic_original_variables(); ++i) {
|
||||
ET value = solver->basic_original_variables_numerator_begin()[ i];
|
||||
int index = solver->basic_original_variables_index_begin()[ i];
|
||||
if ( index < r) {
|
||||
int index = solver->basic_original_variable_indices_begin()[ i];
|
||||
if (index < 2*d) continue; // v or w variable
|
||||
if (index < 2*d + r) {
|
||||
// a point of p
|
||||
for ( int j = 0; j < d; ++j) {
|
||||
p_coords[ j]
|
||||
+= value * tco.access_coordinates_begin_d_object()(
|
||||
p_points[ index ])[ j];
|
||||
+= value * ET(da_coord (p_points[ index-2*d ])[ j]);
|
||||
}
|
||||
p_support_indices.push_back( index);
|
||||
p_support_indices.push_back( index-2*d);
|
||||
} else {
|
||||
// a point of q
|
||||
for ( int j = 0; j < d; ++j) {
|
||||
q_coords[ j]
|
||||
+= value * tco.access_coordinates_begin_d_object()(
|
||||
q_points[ index-r])[ j];
|
||||
+= value * ET(da_coord (q_points[ index-2*d-r])[ j]);
|
||||
}
|
||||
q_support_indices.push_back( index-r);
|
||||
q_support_indices.push_back( index-2*d-r);
|
||||
}
|
||||
}
|
||||
p_coords[ d] = q_coords[ d] = solver->variables_common_denominator();
|
||||
|
|
@ -500,201 +745,15 @@ private:
|
|||
|
||||
template < class NT >
|
||||
Pricing_strategy *pricing_strategy( NT) {
|
||||
return new QP_partial_filtered_pricing<QP_rep>;
|
||||
return new QP_partial_filtered_pricing<QP, ET, QP_tags>;
|
||||
}
|
||||
|
||||
Pricing_strategy *pricing_strategy( ET) {
|
||||
return new QP_partial_exact_pricing<QP_rep>;
|
||||
return new QP_partial_exact_pricing<QP, ET, QP_tags>;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template < class Point, class PointIterator >
|
||||
struct QP_rep_signed_point_iterator {
|
||||
public:
|
||||
typedef std::pair<Point,CGAL::Sign> value_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef value_type* pointer;
|
||||
typedef value_type& reference;
|
||||
typedef std::random_access_iterator_tag iterator_category;
|
||||
|
||||
typedef QP_rep_signed_point_iterator<Point,PointIterator> Self;
|
||||
typedef value_type Val;
|
||||
typedef difference_type Dist;
|
||||
typedef pointer Ptr;
|
||||
|
||||
// forward operations
|
||||
QP_rep_signed_point_iterator() {}
|
||||
QP_rep_signed_point_iterator(const PointIterator& it_p, Dist n_p,
|
||||
const PointIterator& it_q)
|
||||
: p_it( it_p), q_it( it_q), n( n_p), curr( 0) { }
|
||||
|
||||
bool operator == ( const Self& it) const { return (curr == it.curr);}
|
||||
bool operator != ( const Self& it) const { return (curr != it.curr);}
|
||||
|
||||
Val operator * ( ) const
|
||||
{ return ( curr < n) ? std::make_pair( *p_it, CGAL::POSITIVE)
|
||||
: std::make_pair( *q_it, CGAL::NEGATIVE); }
|
||||
|
||||
Self& operator ++ ( )
|
||||
{ if ( ++curr <= n) ++p_it; else ++q_it; return *this; }
|
||||
Self operator ++ ( int)
|
||||
{ Self tmp = *this; operator++(); return tmp; }
|
||||
|
||||
// bidirectional operations
|
||||
Self& operator -- ( )
|
||||
{ if ( --curr < n) --p_it; else --q_it; return *this; }
|
||||
Self operator -- ( int)
|
||||
{ Self tmp = *this; operator--(); return tmp; }
|
||||
|
||||
// random access operations
|
||||
Self& operator += ( Dist i)
|
||||
{
|
||||
if ( curr+i <= n) {
|
||||
curr += i;
|
||||
p_it += i;
|
||||
} else {
|
||||
if ( curr < n) p_it += n-curr;
|
||||
curr += i;
|
||||
q_it += curr-n;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
Self& operator -= ( Dist i)
|
||||
{
|
||||
if ( curr-i < n) {
|
||||
if ( curr > n) q_it -= curr-n;
|
||||
curr -= i;
|
||||
p_it -= n-curr;
|
||||
} else {
|
||||
curr -= i;
|
||||
q_it -= i;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
Self operator + ( Dist i) const { Self tmp = *this; return tmp+=i; }
|
||||
Self operator - ( Dist i) const { Self tmp = *this; return tmp-=i; }
|
||||
|
||||
Dist operator - ( const Self& it) const { return curr - it.curr; }
|
||||
|
||||
Val operator [] ( int i) const
|
||||
{ return ( curr+i < n)
|
||||
? std::make_pair( p_it[ i ], CGAL::POSITIVE)
|
||||
: std::make_pair( q_it[ i-n], CGAL::NEGATIVE); }
|
||||
|
||||
bool operator < ( const Self& it) const { return ( curr < it.curr); }
|
||||
bool operator > ( const Self& it) const { return ( curr > it.curr); }
|
||||
bool operator <= ( const Self& it) const { return ( curr <= it.curr); }
|
||||
bool operator >= ( const Self& it) const { return ( curr >= it.curr); }
|
||||
|
||||
private:
|
||||
PointIterator p_it;
|
||||
PointIterator q_it;
|
||||
Dist n;
|
||||
Dist curr;
|
||||
};
|
||||
|
||||
// this class should compute the EXACT inner product, otherwise,
|
||||
// the matrix D passed to the QP_solver through D_iterator has
|
||||
// roundoffs and may in the worst case not be positive-definite
|
||||
// the problem is that if the D-values are exact and the A-values,
|
||||
// say, are inexact, then the QP-solver runs into formal troubles
|
||||
// --> a fix is not easy right now
|
||||
template < class NT, class ET, class Point,
|
||||
class Access_coord, class Access_dim >
|
||||
class QP_rep_signed_inner_product {
|
||||
Point p_i;
|
||||
CGAL::Sign s_i;
|
||||
Access_coord da_coord;
|
||||
Access_dim da_dim;
|
||||
public:
|
||||
typedef std::pair<Point,CGAL::Sign> argument_type;
|
||||
typedef NT result_type;
|
||||
|
||||
QP_rep_signed_inner_product( ) { }
|
||||
QP_rep_signed_inner_product( const argument_type& p_signed,
|
||||
const Access_coord& ac,
|
||||
const Access_dim& ad)
|
||||
: p_i( p_signed.first), s_i( p_signed.second),
|
||||
da_coord( ac), da_dim( ad) { }
|
||||
|
||||
NT operator( ) ( const argument_type& p_signed) const
|
||||
{ NT ip = std::inner_product( da_coord( p_i),
|
||||
da_coord( p_i)+da_dim( p_i),
|
||||
da_coord( p_signed.first), NT( 0),
|
||||
std::plus<NT>(),
|
||||
std::multiplies<NT>());
|
||||
return ( s_i*p_signed.second == CGAL::POSITIVE) ? ip : -ip; }
|
||||
};
|
||||
|
||||
template < class NT, class ET, class Point, class Signed_point_iterator,
|
||||
class Access_coord, class Access_dim >
|
||||
class QP_rep_row_of_d {
|
||||
Signed_point_iterator signed_pts_it;
|
||||
Access_coord da_coord;
|
||||
Access_dim da_dim;
|
||||
public:
|
||||
typedef CGAL::QP_rep_signed_inner_product<
|
||||
NT, ET, Point, Access_coord, Access_dim >
|
||||
Signed_inner_product;
|
||||
typedef CGAL::Join_input_iterator_1<
|
||||
Signed_point_iterator, Signed_inner_product >
|
||||
Row_of_d;
|
||||
|
||||
typedef std::pair<Point,CGAL::Sign>
|
||||
argument_type;
|
||||
typedef Row_of_d result_type;
|
||||
|
||||
QP_rep_row_of_d( ) { }
|
||||
QP_rep_row_of_d( const Signed_point_iterator& it,
|
||||
const Access_coord& ac,
|
||||
const Access_dim& ad)
|
||||
: signed_pts_it( it), da_coord( ac), da_dim( ad) { }
|
||||
|
||||
Row_of_d operator( ) ( const argument_type& p_signed) const
|
||||
{ return Row_of_d( signed_pts_it,
|
||||
Signed_inner_product( p_signed, da_coord, da_dim));}
|
||||
};
|
||||
|
||||
template < class ET_, class NT_, class Point, class Point_iterator,
|
||||
class Access_coord, class Access_dim >
|
||||
struct QP_rep_poly_dist_d {
|
||||
// (possibly inexact) number type for the pricing:
|
||||
typedef NT_ NT;
|
||||
|
||||
// helper types:
|
||||
typedef std::vector< std::vector<NT> > NT_matrix;
|
||||
typedef CGAL::QP_rep_signed_point_iterator< Point, Point_iterator>
|
||||
Signed_point_iterator;
|
||||
|
||||
// stuff required by concept QPSolverTraits:
|
||||
typedef ET_ ET;
|
||||
typedef CGAL::Join_input_iterator_1<
|
||||
typename NT_matrix::const_iterator,
|
||||
QP_rep_row_of_a<NT> > A_iterator;
|
||||
typedef CGAL::Const_oneset_iterator<NT> B_iterator;
|
||||
typedef CGAL::Const_oneset_iterator<NT> C_iterator;
|
||||
typedef CGAL::Join_input_iterator_1<
|
||||
Signed_point_iterator,
|
||||
QP_rep_row_of_d< NT, ET, Point, Signed_point_iterator,
|
||||
Access_coord, Access_dim > > D_iterator;
|
||||
|
||||
typedef Const_oneset_iterator<bool> FU_iterator;
|
||||
typedef Const_oneset_iterator<bool> FL_iterator;
|
||||
typedef Const_oneset_iterator<NT> U_iterator;
|
||||
typedef Const_oneset_iterator<NT> L_iterator;
|
||||
|
||||
enum Row_type { LESS_EQUAL = -1, EQUAL, GREATER_EQUAL};
|
||||
typedef Const_oneset_iterator<Row_type> Row_type_iterator;
|
||||
|
||||
typedef Tag_false Is_linear;
|
||||
typedef Tag_true Is_symmetric;
|
||||
typedef Tag_true Has_equalities_only_and_full_rank;
|
||||
typedef Tag_true Is_in_standard_form;
|
||||
};
|
||||
|
||||
// Function declarations
|
||||
// =====================
|
||||
// I/O operators
|
||||
|
|
@ -730,19 +789,28 @@ is_valid( bool verbose, int level) const
|
|||
<< '+' << number_of_support_points_q() << endl;
|
||||
|
||||
if ( is_finite()) {
|
||||
// check QP solver
|
||||
CGAL_optimisation_assertion(solver);
|
||||
if (!solver->is_valid())
|
||||
return CGAL::_optimisation_is_valid_fail(
|
||||
verr,
|
||||
"underlying QP_solver is in invalid state");
|
||||
|
||||
// compute normal vector
|
||||
ET_vector normal( d), diff( d);
|
||||
ET et_0 = 0, den = solver->variables_common_denominator();
|
||||
ET et_0 = 0, den = p_coords[d];
|
||||
CGAL_optimisation_assertion (den > et_0);
|
||||
CGAL_optimisation_assertion (den == q_coords[d]);
|
||||
int i, j;
|
||||
for ( j = 0; j < d; ++j) normal[ j] = p_coords[ j] - q_coords[ j];
|
||||
|
||||
// check correctness of computed squared distance
|
||||
verr << " checking squared_distance..." << flush;
|
||||
ET sqr_dist_num (0);
|
||||
for ( j = 0; j < d; ++j)
|
||||
sqr_dist_num += normal[ j] * normal[ j];
|
||||
ET sqr_dist_den =
|
||||
p_coords[ d] * p_coords[ d];
|
||||
if (sqr_dist_num * squared_distance_denominator() !=
|
||||
sqr_dist_den * squared_distance_numerator())
|
||||
return CGAL::_optimisation_is_valid_fail
|
||||
( verr, "realizing points don't have correct squared distance");
|
||||
|
||||
|
||||
// check P
|
||||
// -------
|
||||
verr << " checking P..." << flush;
|
||||
|
|
@ -750,13 +818,15 @@ is_valid( bool verbose, int level) const
|
|||
// check point set
|
||||
for ( i = 0; i < number_of_points_p(); ++i) {
|
||||
for ( j = 0; j < d; ++j) {
|
||||
diff[ j] = p_coords[ j] - den
|
||||
* tco.access_coordinates_begin_d_object()( p_points[ i])[ j];
|
||||
// compute (a positive multiple of) p^* - p_i
|
||||
diff[ j] =
|
||||
ET(da_coord(p_points[ i])[d]) * p_coords[ j] -
|
||||
den * ET(da_coord( p_points[ i])[ j]);
|
||||
}
|
||||
if ( std::inner_product( diff.begin(), diff.end(),
|
||||
normal.begin(), et_0) > et_0)
|
||||
return CGAL::_optimisation_is_valid_fail( verr,
|
||||
"polytope P is not separated by its hyperplane");
|
||||
return CGAL::_optimisation_is_valid_fail
|
||||
( verr, "polytope P is not separated by its hyperplane");
|
||||
}
|
||||
|
||||
verr << "passed." << endl;
|
||||
|
|
@ -768,13 +838,15 @@ is_valid( bool verbose, int level) const
|
|||
// check point set
|
||||
for ( i = 0; i < number_of_points_q(); ++i) {
|
||||
for ( j = 0; j < d; ++j) {
|
||||
diff[ j] = q_coords[ j] - den
|
||||
* tco.access_coordinates_begin_d_object()( q_points[ i])[ j];
|
||||
// compute (a positive multiple of) q^* - q_i
|
||||
diff[ j] =
|
||||
ET(da_coord(q_points[ i])[d]) * q_coords[ j] -
|
||||
den * ET(da_coord( q_points[ i])[ j]);
|
||||
}
|
||||
if ( std::inner_product( diff.begin(), diff.end(),
|
||||
normal.begin(), et_0) < et_0)
|
||||
return CGAL::_optimisation_is_valid_fail( verr,
|
||||
"polytope Q is not separated by its hyperplane");
|
||||
return CGAL::_optimisation_is_valid_fail
|
||||
( verr, "polytope Q is not separated by its hyperplane");
|
||||
}
|
||||
|
||||
verr << "passed." << endl;
|
||||
|
|
|
|||
Loading…
Reference in New Issue