cgal/QP_solver/include/CGAL/QP_models.h

960 lines
30 KiB
C++

// Copyright (c) 1997-2001 ETH Zurich (Switzerland).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org); you may redistribute it under
// the terms of the Q Public License version 1.0.
// See the file LICENSE.QPL distributed with CGAL.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL: svn+ssh://gaertner@scm.gforge.inria.fr/svn/cgal/trunk/QP_solver/include/CGAL/QP_models.h $
// $Id: QP_models.h 33922 2006-09-05 12:32:25Z gaertner $
//
//
// Author(s) : Bernd Gaertner <gaertner@inf.ethz.ch>
#ifndef CGAL_QP_MODELS_H
#define CGAL_QP_MODELS_H
#include <CGAL/basic.h>
#include <CGAL/iterator.h>
#include <vector>
#include <iomanip>
#include <istream>
#include <sstream>
#define QP_MODEL_ITERATOR_TYPES \
typedef typename Base::A_iterator A_iterator;\
typedef typename Base::B_iterator B_iterator;\
typedef typename Base::R_iterator R_iterator;\
typedef typename Base::FL_iterator FL_iterator;\
typedef typename Base::L_iterator L_iterator;\
typedef typename Base::FU_iterator FU_iterator;\
typedef typename Base::U_iterator U_iterator;\
typedef typename Base::D_iterator D_iterator; \
typedef typename Base::C_iterator C_iterator; \
typedef typename Base::value_type value_type;
// end QP_MODEL_ITERATOR_TYPES
CGAL_BEGIN_NAMESPACE
// default iterator types to be used in LP / Nonnegative models
template <class Iterator>
class QP_Default {
private:
typedef typename std::iterator_traits<Iterator>::value_type value_type;
public:
typedef Const_oneset_iterator<value_type>
It_1d; // 1-dimensional random access iterator for a constant value
typedef Const_oneset_iterator<Const_oneset_iterator<value_type> >
It_2d; // 2-dimensional random access iterator for a constant value
};
// models of QuadraticProgram
// ==========================
// QP_from_iterators
// -----------------
template <
typename A_it, // for constraint matrix A (columnwise)
typename B_it, // for right-hand side b
typename R_it, // for relations (value type Comparison)
typename FL_it, // for finiteness of lower bounds (value type bool)
typename L_it, // for lower bounds
typename FU_it, // for finiteness of upper bounds (value type bool)
typename U_it, // for upper bounds
typename D_it, // for quadratic matrix D (rowwise)
typename C_it > // for objective function c
class QP_from_iterators
{
public:
// types
typedef A_it A_iterator;
typedef B_it B_iterator;
typedef R_it R_iterator;
typedef FL_it FL_iterator;
typedef L_it L_iterator;
typedef FU_it FU_iterator;
typedef U_it U_iterator;
typedef D_it D_iterator;
typedef C_it C_iterator;
typedef typename std::iterator_traits<C_iterator>::value_type value_type;
private:
// data
const int n_;
const int m_;
const A_iterator a_it;
const B_iterator b_it;
const R_iterator r_it;
const FL_iterator fl_it;
const L_iterator l_it;
const FU_iterator fu_it;
const U_iterator u_it;
const D_iterator d_it;
const C_iterator c_it;
const value_type c_0; // constant term in objective function
public:
// construction
QP_from_iterators (
int n, int m, // number of variables / constraints
const A_iterator& a,
const B_iterator& b,
const R_iterator& r,
const FL_iterator& fl,
const L_iterator& l,
const FU_iterator& fu,
const U_iterator& u,
const D_iterator& d,
const C_iterator& c,
const value_type& c0 = value_type(0)
)
: n_ (n), m_ (m), a_it (a), b_it (b), r_it (r), fl_it (fl), l_it (l),
fu_it (fu), u_it (u), d_it (d), c_it (c), c_0 (c0)
{}
// access
int n() const {return n_;}
int m() const {return m_;}
const A_iterator& a() const {return a_it;}
const B_iterator& b() const {return b_it;}
const R_iterator& r() const {return r_it;}
const FL_iterator& fl() const {return fl_it;}
const L_iterator& l() const {return l_it;}
const FU_iterator& fu() const {return fu_it;}
const U_iterator& u() const {return u_it;}
const D_iterator& d() const {return d_it;}
const C_iterator& c() const {return c_it;}
const value_type& c0() const {return c_0;}
};
// global function make_QP_from_iterators
// --------------------------------------
template <
typename A_it, // for constraint matrix A (columnwise)
typename B_it, // for right-hand side b
typename R_it, // for relations (value type Comparison)
typename FL_it, // for finiteness of lower bounds (value type bool)
typename L_it, // for lower bounds
typename FU_it, // for finiteness of upper bounds (value type bool)
typename U_it, // for upper bounds
typename D_it, // for quadratic matrix D (rowwise)
typename C_it > // for objective function c
QP_from_iterators<A_it, B_it, R_it, FL_it, L_it, FU_it, U_it, D_it, C_it>
make_QP_from_iterators (
int n, int m,
const A_it& a,
const B_it& b,
const R_it& r,
const FL_it& fl,
const L_it& l,
const FU_it& fu,
const U_it& u,
const D_it& d,
const C_it& c,
typename std::iterator_traits<C_it>::value_type c0)
{
return QP_from_iterators
<A_it, B_it, R_it, FL_it, L_it, FU_it, U_it, D_it, C_it>
(n, m, a, b, r, fl, l, fu, u, d, c, c0);
}
// QP_from_pointers
// ----------------
template <typename NT>
class QP_from_pointers :
public QP_from_iterators <NT**, NT*, CGAL::Comparison_result*,
bool*, NT*, bool*, NT*, NT**, NT*>
{
private:
typedef QP_from_iterators <NT**, NT*, CGAL::Comparison_result*,
bool*, NT*, bool*, NT*, NT**, NT*> Base;
public:
QP_MODEL_ITERATOR_TYPES;
QP_from_pointers (
int n, int m, // number of variables / constraints
const A_iterator& a,
const B_iterator& b,
const R_iterator& r,
const FL_iterator& fl,
const L_iterator& l,
const FU_iterator& fu,
const U_iterator& u,
const D_iterator& d,
const C_iterator& c,
const value_type& c0 = value_type(0)
)
: Base (n, m, a, b, r, fl, l, fu, u, d, c, c0)
{}
};
// LP_from_iterators
// -----------------
template <
typename A_it, // for constraint matrix A (columnwise)
typename B_it, // for right-hand side b
typename R_it, // for relations (value type Comparison)
typename FL_it, // for finiteness of lower bounds (value type bool)
typename L_it, // for lower bounds
typename FU_it, // for finiteness of upper bounds (value type bool)
typename U_it, // for upper bounds
typename C_it > // for objective function c
class LP_from_iterators :
public QP_from_iterators <A_it, B_it, R_it, FL_it, L_it, FU_it, U_it,
typename QP_Default<A_it>::It_2d, C_it>
{
private:
typedef QP_from_iterators <A_it, B_it, R_it, FL_it, L_it, FU_it, U_it,
typename QP_Default<B_it>::It_2d, C_it> Base;
typedef typename QP_Default<B_it>::It_2d Const_D_iterator;
public:
QP_MODEL_ITERATOR_TYPES;
LP_from_iterators (
int n, int m, // number of variables / constraints
const A_iterator& a,
const B_iterator& b,
const R_iterator& r,
const FL_iterator& fl,
const L_iterator& l,
const FU_iterator& fu,
const U_iterator& u,
const C_iterator& c,
const value_type& c0 = value_type(0)
)
: Base (n, m, a, b, r, fl, l, fu, u,
Const_D_iterator(value_type(0)), c, c0)
{}
};
// LP_from_pointers
// ----------------
template <typename NT>
class LP_from_pointers :
public LP_from_iterators <NT**, NT*, CGAL::Comparison_result*, bool*,
NT*, bool*, NT*, NT*>
{
private:
typedef LP_from_iterators <NT**, NT*, CGAL::Comparison_result*, bool*,
NT*, bool*, NT*, NT*> Base;
public:
QP_MODEL_ITERATOR_TYPES;
LP_from_pointers (
int n, int m, // number of variables / constraints
const A_iterator& a,
const B_iterator& b,
const R_iterator& r,
const FL_iterator& fl,
const L_iterator& l,
const FU_iterator& fu,
const U_iterator& u,
const C_iterator& c,
const value_type& c0 = value_type(0)
)
: Base (n, m, a, b, r, fl, l, fu, u, c, c0)
{}
};
// Nonnegative_QP_from_iterators
// -----------------------------
template <
typename A_it, // for constraint matrix A (columnwise)
typename B_it, // for right-hand side b
typename R_it, // for relations (value type Comparison)
typename D_it, // for quadratic matrix D (rowwise)
typename C_it > // for objective function c
class Nonnegative_QP_from_iterators :
public QP_from_iterators <A_it, B_it, R_it,
typename QP_Default<bool*>::It_1d,
typename QP_Default<B_it>::It_1d,
typename QP_Default<bool*>::It_1d,
typename QP_Default<B_it>::It_1d,
D_it, C_it>
{
private:
typedef QP_from_iterators <A_it, B_it, R_it,
typename QP_Default<bool*>::It_1d,
typename QP_Default<B_it>::It_1d,
typename QP_Default<bool*>::It_1d,
typename QP_Default<B_it>::It_1d,
D_it, C_it> Base;
typedef typename QP_Default<bool*>::It_1d Const_FLU_iterator;
typedef typename QP_Default<B_it>::It_1d Const_LU_iterator;
public:
QP_MODEL_ITERATOR_TYPES;
Nonnegative_QP_from_iterators (
int n, int m, // number of variables / constraints
const A_iterator& a,
const B_iterator& b,
const R_iterator& r,
const D_iterator& d,
const C_iterator& c,
const value_type& c0 = value_type(0)
)
: Base (n, m, a, b, r,
Const_FLU_iterator(true), Const_LU_iterator(value_type(0)),
Const_FLU_iterator(false), Const_LU_iterator(value_type(0)),
d, c, c0)
{}
};
// Nonnegative_QP_from_pointers
// ----------------------------
template <typename NT>
class Nonnegative_QP_from_pointers :
public Nonnegative_QP_from_iterators <NT**, NT*, CGAL::Comparison_result*,
NT**, NT*>
{
private:
typedef Nonnegative_QP_from_iterators <NT**, NT*, CGAL::Comparison_result*,
NT**, NT*> Base;
public:
QP_MODEL_ITERATOR_TYPES;
Nonnegative_QP_from_pointers (
int n, int m, // number of variables / constraints
const A_iterator& a,
const B_iterator& b,
const R_iterator& r,
const D_iterator& d,
const C_iterator& c,
const value_type& c0 = value_type(0)
)
: Base (n, m, a, b, r, d, c, c0)
{}
};
// Nonnegative_LP_from_iterators
// -----------------------------
template <
typename A_it, // for constraint matrix A (columnwise)
typename B_it, // for right-hand side b
typename R_it, // for relations (value type Comparison)
typename C_it > // for objective function c
class Nonnegative_LP_from_iterators :
public QP_from_iterators <A_it, B_it, R_it,
typename QP_Default<bool*>::It_1d,
typename QP_Default<B_it>::It_1d,
typename QP_Default<bool*>::It_1d,
typename QP_Default<B_it>::It_1d,
typename QP_Default<B_it>::It_2d, C_it>
{
private:
typedef QP_from_iterators <A_it, B_it, R_it,
typename QP_Default<bool*>::It_1d,
typename QP_Default<B_it>::It_1d,
typename QP_Default<bool*>::It_1d,
typename QP_Default<B_it>::It_1d,
typename QP_Default<B_it>::It_2d, C_it> Base;
typedef typename QP_Default<bool*>::It_1d Const_FLU_iterator;
typedef typename QP_Default<B_it>::It_1d Const_LU_iterator;
typedef typename QP_Default<B_it>::It_2d Const_D_iterator;
public:
QP_MODEL_ITERATOR_TYPES;
Nonnegative_LP_from_iterators (
int n, int m, // number of variables / constraints
const A_iterator& a,
const B_iterator& b,
const R_iterator& r,
const C_iterator& c,
const value_type& c0 = value_type(0)
)
: Base (n, m, a, b, r,
Const_FLU_iterator(true), Const_LU_iterator(value_type(0)),
Const_FLU_iterator(false), Const_LU_iterator(value_type(0)),
Const_D_iterator(value_type(0)), c, c0)
{}
};
// Nonnegative_LP_from_pointers
// ----------------------------
template <typename NT>
class Nonnegative_LP_from_pointers :
public Nonnegative_LP_from_iterators <NT**, NT*, CGAL::Comparison_result*,
NT*>
{
private:
typedef Nonnegative_LP_from_iterators <NT**, NT*, CGAL::Comparison_result*,
NT*> Base;
public:
QP_MODEL_ITERATOR_TYPES;
Nonnegative_LP_from_pointers (
int n, int m, // number of variables / constraints
const A_iterator& a,
const B_iterator& b,
const R_iterator& r,
const C_iterator& c,
const value_type& c0 = value_type(0)
)
: Base (a, b, r, c, c0)
{}
};
// QP_from_mps
// -----------
namespace QP_from_mps_detail {
template<typename V>
struct Begin
: public std::unary_function< V, typename V::const_iterator >
{
typedef typename V::const_iterator result_type;
result_type operator () ( const V& v) const { return v.begin(); }
};
} // QP_from_mps_detail
template<typename IT_, // The input number type: the numbers in the
// MPS stream are expected to be of this type
// and are read using IT_'s operator>>.
// Warning: IT_ must support EXACT division by
// 2 (so x/2 must be exactly representable in
// IT_). The reason is that the QMATRIX
// section of the MPS format stores the matrix
// 2*D and the QP-solver needs D, so we need
// to divide by 2. Note: If the MPS stream is
// known to only contain a DMATRIX section,
// this warning can be neglected because in a
// DMATRIX section, D is stored (and not 2*D).
// (See also method D_format_type().)
typename Use_sparse_representation_for_D_=Tag_false,
// Use a sparse representation for D. Note:
// must be Tag_false currently (Tag_true not
// yet implemented).
typename Use_sparse_representation_for_A_=Tag_false>
// Use a sparse representation for A. Note:
// must be Tag_false currently (Tag_true not
// yet implemented).
class QP_from_mps {
public:
typedef IT_ IT;
public: // undocumented types, should be considered private:
typedef std::vector<IT> Vector;
typedef std::vector<Vector> Matrix;
typedef QP_from_mps_detail::Begin<Vector> Beginner;
typedef CGAL::Join_input_iterator_1<typename Matrix::const_iterator,
Beginner > Vector_iterator;
typedef typename Vector::const_iterator Entry_iterator;
typedef std::vector<bool> F_vector;
typedef F_vector::const_iterator F_vector_iterator;
typedef std::vector<CGAL::Comparison_result> Row_type_vector;
public:
// iterators over the input matrices and vectors:
typedef Vector_iterator A_iterator;
typedef Entry_iterator B_iterator;
typedef Entry_iterator C_iterator;
typedef Vector_iterator D_iterator;
typedef Const_oneset_iterator< Const_oneset_iterator<IT> >
Zero_D_iterator;
typedef F_vector_iterator FU_iterator;
typedef F_vector_iterator FL_iterator;
typedef Entry_iterator U_iterator;
typedef Entry_iterator L_iterator;
typedef IT value_type;
typedef typename Row_type_vector::const_iterator R_iterator;
typedef Use_sparse_representation_for_D_ Use_sparse_representation_for_D;
typedef Use_sparse_representation_for_A_ Use_sparse_representation_for_A;
private:
typedef std::pair<std::string,unsigned int> String_int_pair;
typedef std::map<std::string,unsigned int> Index_map;
private:
const int verbosity_;
std::istream& from;
std::string error_msg;
bool is_format_okay_;
bool is_linear_;
const bool use_CPLEX_convention;
IT c_0; // constant term in objective function
Vector b_, c_; // vectors b and c
Matrix A_, D_; // matrices A and D
std::string D_section; // name of the section from which D was read
Row_type_vector row_types_; // equality type for each row
Vector u_, l_; // upper and lower bounds
F_vector fu_, fl_; // whether the lower/upper bound is finite or not
// cached data:
bool is_symmetric_cached, is_symmetric_;
bool has_equalities_only_and_full_rank_cached,
has_equalities_only_and_full_rank_;
bool is_in_standard_form_cached, is_in_standard_form_;
// data from MPS file:
std::string name; // from the NAME section
std::string comment_; // first comment in the file, if any
std::string obj; // name of the objective "constraint"
Index_map row_names;
Index_map duplicated_row_names; // to handle RANGES section
Index_map var_names;
std::vector<std::string> var_by_index; // name of i-th column
std::vector<std::string> row_by_index; // name of i-th row
// variables used in token() (see below):
bool use_put_back_token;
std::string put_back_token;
public: // unofficial helper routines used in master_mps_to_derivatives.C;
// these should be considered private for CGAL end-users:
const Matrix& A_matrix() { return A_; }
const Vector& b_vector() { return b_; }
const Row_type_vector& row_types_vector() { return row_types_; }
private: // helpers to deal with sparse/dense representation:
void initialize_D(unsigned int dimension,const Tag_true) // sparse case
{
CGAL_qpe_assertion_msg(false, "not implemented yet");
}
void initialize_D(unsigned int dimension,const Tag_false) // dense case
{
for (unsigned int i=0; i<dimension; ++i)
D_.push_back(Vector(dimension,IT(0)));
}
void set_entry_in_D(unsigned int i,unsigned int j,const IT& val,
const Tag_true) // sparse case
{
CGAL_qpe_assertion_msg(false, "not implemented yet");
}
void set_entry_in_D(unsigned int i,unsigned int j,const IT& val,
const Tag_false) // dense case
{
D_[i][j] = val;
}
private: // private helpers:
// Replaces the first occurrence of '%' in msg by replacement.
std::string replace1(const std::string& msg,const std::string& replacement)
{
std::string result(msg);
const std::string::size_type pos = result.find('%');
CGAL_qpe_assertion(pos < result.size());
result.replace(pos,1,replacement);
return result;
}
bool err(const char* msg) {
error_msg = msg;
return false;
}
bool err1(const char* msg,
const std::string& parameter1) {
error_msg = replace1(msg,parameter1);
return false;
}
bool err2(const char* msg,
const std::string& parameter1,
const std::string& parameter2) {
error_msg = replace1(replace1(msg,parameter1),parameter2);
return false;
}
void warn(const std::string& msg) {
std::cerr << "MPS parser warning: " << msg << '.' << std::endl;
}
void warn1(const std::string& msg,const std::string& parameter1) {
warn(replace1(msg,parameter1));
}
private: // parsing routines:
// (Note: returns true iff a line-break was eaten.)
bool whitespace()
{
// support for put_token_back():
if (use_put_back_token)
return false;
bool lineBreakFound = false;
char c;
bool in_comment = false; // true iff we are within a comment
const bool remember_comment = comment_.size() == 0;
while (from.get(c))
if (in_comment) {
if (c!='\r' && c!='\n') {
if (remember_comment)
comment_.push_back(c);
} else
in_comment = false;
} else { // not in comment?
if (!isspace(c)) {
if (c!='$' && c!='*') {
from.putback(c);
break;
}
in_comment = true;
lineBreakFound = true;
} else {
if (c=='\r' || c=='\n')
lineBreakFound = true;
}
}
return lineBreakFound;
}
std::string token() {
if (use_put_back_token) {
use_put_back_token = false;
return put_back_token;
}
whitespace();
std::string token;
char c;
while (from.get(c)) {
if (isspace(c)) {
from.putback(c);
break;
}
token.push_back(c);
}
return token;
}
void put_token_back(const std::string& token) {
CGAL_qpe_assertion(!use_put_back_token);
use_put_back_token = true;
put_back_token = token;
}
// here is a general template for halving a number; we must
// have a specialization for Gmpz that performs exact division
// (and therefore fails if the result is incorrect)
template<typename NumberType>
void halve(NumberType& entry) {
entry /= 2;
}
void halve(CGAL::Gmpz& entry) {
entry = CGAL::exact_division(entry,2);
}
// here is the general template, and the C-file contains
// implementations of a specialization for Gmpq
template<typename NumberType>
bool number(NumberType& entry) {
whitespace();
from >> entry;
return from.good();
}
bool number(CGAL::Gmpq& entry) {
// accept rational or floating-point format
std::string s = token() + " "; // routines below can't deal with EOF
std::istringstream from1(s), from2(s);
return
number_from_quotient (entry, from1) ||
number_from_float (entry, from2);
}
bool number_from_quotient(CGAL::Gmpq& entry, std::istringstream& from);
bool number_from_float(CGAL::Gmpq& entry, std::istringstream& from);
bool name_section();
bool rows_section();
bool columns_section();
bool rhs_section();
bool ranges_section();
bool bounds_section();
bool qmatrix_section();
private:
D_iterator D(const Tag_true);
D_iterator D(const Tag_false);
public: // methods:
// Create a quadratic program instance from a stream.
//
// If use_CPLEX_convention is true and you set the upper bound of a
// variable to exactly zero and do not give a lower bound then the
// lower bound will be set to zero as well. If use_CPLEX_convention
// and you set the upper bound of a variable to exactly zero and do
// not specify a lower bound then the lower bound will be set to
// -infinity.
QP_from_mps(std::istream& in,bool use_CPLEX_convention=true,
int verbosity=0);
// Returns true if and only if the instance has been properly
// constructed (i.e., if the QP could be loaded from the MPS
// stream).
bool is_valid() const;
// Returns the verbosity level with which the instance was
// constructed.
int verbosity() const
{
return verbosity_;
}
// If is_valid() returns false, this routine returns an error
// string describing the problem that was encountered.
//
// Precondition: !is_valid()
const std::string& error();
// Returns the first comment that was read from the MPS stream.
const std::string& comment();
// Returns the number of variables in the QP.
//
// Precondition: is_valid()
unsigned int n() const
{
CGAL_qpe_assertion(is_valid());
return var_names.size();
}
// Returns the number of constraints in the QP.
//
// Precondition: is_valid()
unsigned int m() const
{
CGAL_qpe_assertion(is_valid());
return b_.size(); // row_names doesn't work as RANGES may duplicate rows
}
// Returns the problem's name (as specified in the MPS-file).
//
// Precondition: is_valid()
const std::string& problem_name()
{
CGAL_qpe_assertion(is_valid());
return name;
}
// Returns the name (as present in the MPS-file) of the i-th variable.
// Note: this routine has linear complexity.
const std::string& name_of_variable(unsigned int i)
{
CGAL_qpe_assertion(0<=i && i<n());
return var_by_index[i];
// for (Index_map::const_iterator it = var_names.begin();
// it != var_names.end();
// ++it)
// if ((*it).second == i)
// return (*it).first;
// CGAL_qpe_assertion(false); // should never get here; following
// // only to fix compiler warnings
// static std::string dummy;
// return dummy;
}
// Returns the section name of the MPS stream in which the D matrix
// (if any present) was read.
//
// Note: The MPS file was originally defined for LP's only, and so
// there was no way to store the D matrix of a QP. Several
// extensions exists, including:
//
// - CPLEX extension: here, not D but the matrix 2*D is stored in a
// so-called "QMATRIX" section. When the parser encounters such a
// section it has to divide the read entries by 2 in order to be
// able to return (see D_iterator) the matrix D. For this, IT
// must support division by 2.
// - QP-solver extension: we also support reading D from a section
// called "DMATRIX" which is defined exactly like CPLEX's QMATRIX
// section with the only difference that we do in fact store D and
// not 2*D.
//
// Precondition: !is_linear
const std::string& D_format_type()
{
CGAL_qpe_assertion(!is_linear());
return D_section;
}
// Initializes the internal D matrix to the zero matrix so that D()
// will return an iterator over a zero matrix. Normally, there
// should not be any need to call this routine; it is used by the
// QP_solver testsuite to solve an LP as a QP, and for this we need
// a zero D matrix.
//
// Note: If Use_sparse_representation_for_D_ is Tag_false, this
// routine allocates a zero (n x n)-matrix (where n is
// number_of_variables()). If you known in advance that you need a
// zero D matrix, you might want to use zero_D() (see below).
//
// Precondition: is_linear()
void make_zero_D()
{
CGAL_qpe_assertion(is_linear());
initialize_D(var_names.size(),Use_sparse_representation_for_D());
}
// Returns an iterator over the matrix A (as needs to be
// passed to the constructor of class QP_solver).
//
// Precondition: is_valid()
A_iterator a() const
{
CGAL_qpe_assertion(is_valid());
return Vector_iterator(A_.begin(),Beginner());
}
// Returns an iterator over the vector b (as needs to be
// passed to the constructor of class QP_solver).
//
// Precondition: is_valid()
B_iterator b() const
{
CGAL_qpe_assertion(is_valid());
return b_.begin();
}
// Returns an iterator over the vector c (as needs to be
// passed to the constructor of class QP_solver).
//
// Precondition: is_valid()
C_iterator c() const
{
CGAL_qpe_assertion(is_valid());
return c_.begin();
}
// Returns the constant term of the objective function (as
// needs to be passed to the constructor of class QP_solver).
// Precondition: is_valid()
IT c0() const
{
CGAL_qpe_assertion(is_valid());
return c_0;
}
// Returns an iterator over the matrix D (as needs to be
// passed to the constructor of class QP_solver).
//
// Precondition: is_valid()
D_iterator d() const
{
CGAL_qpe_assertion(is_valid());
return Vector_iterator(D_.begin(),Beginner());
}
// Returns an iterator over a matrix D that is zero (as needs to be
// passed to the constructor of class QP_solver if you for instance
// want to solve an LP as a QP with a zero D-matrix for test
// purposes).
//
// Precondition: is_valid()
Zero_D_iterator zero_D()
{
CGAL_qpe_assertion(is_valid());
return Zero_D_iterator(Const_oneset_iterator<IT>(0));
}
// Returns an iterator (of value-type Row_type) over the constraint
// types (as needs to be passed to the constructor of class
// QP_solver).
//
// Precondition: is_valid()
R_iterator r() const
{
CGAL_qpe_assertion(is_valid());
return row_types_.begin();
}
// Returns an iterator of Booleans specifying for each variable
// whether it has a finite lower bound or not (such an iterator
// needs to be passed to the constructor of class QP_solver).
//
// Precondition: is_valid()
FL_iterator fl() const {
CGAL_qpe_assertion(is_valid());
return fl_.begin();
}
// Returns an iterator of Booleans specifying for each variable
// whether it has a finite upper bound or not (such an iterator
// needs to be passed to the constructor of class QP_solver).
//
// Precondition: is_valid()
FU_iterator fu() const {
CGAL_qpe_assertion(is_valid());
return fu_.begin();
}
// Returns an iterator of IT's specifying for each variable what its
// lower bound is (provided it is finite); such an iterator needs to
// be passed to the constructor of class QP_solver.
//
// Precondition: is_valid()
U_iterator u() const {
CGAL_qpe_assertion(is_valid());
return u_.begin();
}
// Returns an iterator of IT's specifying for each variable what its
// upper bound is (provided it is finite); such an iterator needs to
// be passed to the constructor of class QP_solver.
//
// Precondition: is_valid()
L_iterator l() const {
CGAL_qpe_assertion(is_valid());
return l_.begin();
}
// Returns true iff the MPS stream could be successfully parsed and
// the loaded QP instance has a symmetric D matrix (if it has a D
// matrix at all).
bool is_symmetric();
// Returns true iff the MPS stream could be successfully parsed and
// the loaded QP instance has a D matrix that is zero (i.e., iff the
// QP is actually an LP).
bool is_linear()
{
return is_format_okay_ && is_linear_;
}
// Returns true iff the MPS stream could be successfully parsed and
// the loaded QP instance is in standard form.
bool is_in_standard_form()
{
if (!is_format_okay_)
return false;
if (!is_in_standard_form_cached) {
for (unsigned int i=0; i<var_names.size(); ++i)
if (fl_[i] == false || l_[i] != 0 ||
fu_[i] == true) {
is_in_standard_form_ = false;
return is_in_standard_form_;
}
is_in_standard_form_ = true;
}
return is_in_standard_form_;
}
};
template<typename IT_,
typename Use_sparse_representation_for_D_,
typename Use_sparse_representation_for_A_>
std::ostream& operator<<(std::ostream& o,
QP_from_mps<IT_,
Use_sparse_representation_for_D_,
Use_sparse_representation_for_A_>& qp);
CGAL_END_NAMESPACE
#include <CGAL/QP_solver/QP_models_impl.h>
#endif // CGAL_QP_MODELS_H