mirror of https://github.com/CGAL/cgal
- in Quadratic_program model, default bounds can now be configured,
and there are some tests that cover this
This commit is contained in:
parent
7a80cfa1a3
commit
890c5d0fed
|
|
@ -1871,7 +1871,7 @@ QP_solver/examples/QP_solver/unboundedness_certificate.cpp -text
|
|||
QP_solver/maintainer -text
|
||||
QP_solver/test/QP_solver/create_test_solver_cin -text
|
||||
QP_solver/test/QP_solver/debug_bug.cpp -text
|
||||
QP_solver/test/QP_solver/test_empty_qp.cpp -text
|
||||
QP_solver/test/QP_solver/test_default_bounds.cpp -text
|
||||
QP_solver/test/QP_solver/test_random_qp.cpp -text
|
||||
QP_solver/test/QP_solver/test_solver.cout -text
|
||||
Qt_widget/demo/Qt_widget/hellosegment.vcproj eol=crlf
|
||||
|
|
|
|||
|
|
@ -52,13 +52,22 @@ the model \ccc{Quadratic_program_from_mps<NT>}.
|
|||
\ccCreationVariable{qp}
|
||||
|
||||
\ccConstructor{
|
||||
Quadratic_program(CGAL::Comparison_result default_r = CGAL::EQUAL);}
|
||||
Quadratic_program
|
||||
(CGAL::Comparison_result default_r = CGAL::EQUAL,
|
||||
bool default_fl = true,
|
||||
const NT& default_l = 0,
|
||||
bool default_fu = false,
|
||||
const NT& default_u = 0);}
|
||||
{constructs a quadratic program with no variables and no constraints, ready
|
||||
for data to be added. Unless
|
||||
bounds are explicitly set using one of the methods below, bounds will be
|
||||
$x\geq 0$. Unless relations are explicitly set, relations will be of type
|
||||
\ccc{default_r}. Numerical entries that are not explicitly set will
|
||||
default to $0$.}
|
||||
for data to be added. Unless relations are explicitly set, they will
|
||||
be of type \ccc{default_r}. Unless bounds are explicitly set, they
|
||||
will be as specified by \ccc{default_fl} (finite lower bound?),
|
||||
\ccc{default_l} (lower bound value if lower bound is finite),
|
||||
\ccc{default_fu} (finite upper bound?), and
|
||||
\ccc{default_l} (upper bound value if upper bound is finite). If all
|
||||
parameters take their default values, we thus get equality constraints
|
||||
and bounds $x\geq 0$ by default. Numerical entries that are not
|
||||
explicitly set will default to $0$.}
|
||||
|
||||
\ccOperations
|
||||
|
||||
|
|
@ -96,9 +105,10 @@ of \ccVar\ to \ccc{val}. An existing entry is overwritten.
|
|||
\ccMethod{void set_c0 (const NT& val);}{sets the entry $c_0$
|
||||
of \ccVar\ to \ccc{val}. An existing entry is overwritten.}
|
||||
|
||||
\ccMethod{void set_d (int i, int j, const NT& val);}{sets the entry
|
||||
$2D_{ij}$ of \ccVar\ to \ccc{val}. An existing entry is overwritten.
|
||||
\ccVar\ is enlarged if necessary to accomodate this entry.}
|
||||
\ccMethod{void set_d (int i, int j, const NT& val);}{sets the entries
|
||||
$2D_{ij}$ and $2D_{ji}$ of \ccVar\ to \ccc{val}. Existing entries are
|
||||
overwritten. \ccVar\ is enlarged if necessary to accomodate these entries.
|
||||
\ccPrecond \ccc{j <= i}}
|
||||
|
||||
|
||||
\ccSeeAlso
|
||||
|
|
|
|||
|
|
@ -97,9 +97,10 @@ of \ccVar\ to \ccc{val}. An existing entry is overwritten.
|
|||
\ccMethod{void set_c0 (const NT& val);}{sets the entry $c_0$
|
||||
of \ccVar\ to \ccc{val}. An existing entry is overwritten.}
|
||||
|
||||
\ccMethod{void set_d (int i, int j, const NT& val);}{sets the entry
|
||||
$2D_{ij}$ of \ccVar\ to \ccc{val}. An existing entry is overwritten.
|
||||
\ccVar\ is enlarged if necessary to accomodate this entry.}
|
||||
\ccMethod{void set_d (int i, int j, const NT& val);}{sets the entries
|
||||
$2D_{ij}$ and $2D_{ji}$ of \ccVar\ to \ccc{val}. Existing entries are
|
||||
overwritten. \ccVar\ is enlarged if necessary to accomodate these entries.
|
||||
\ccPrecond \ccc{j <= i}}
|
||||
|
||||
\ccSeeAlso
|
||||
\ccc{Quadratic_program<NT>}\\
|
||||
|
|
|
|||
|
|
@ -643,7 +643,7 @@ public:
|
|||
FL_iterator get_fl() const
|
||||
{
|
||||
CGAL_qpe_assertion(is_valid());
|
||||
return FL_iterator (&fl_vector, default_fl); // default bound: >= 0
|
||||
return FL_iterator (&fl_vector, default_fl);
|
||||
}
|
||||
L_iterator get_l() const
|
||||
{
|
||||
|
|
@ -688,10 +688,16 @@ public:
|
|||
}
|
||||
|
||||
// default constructor
|
||||
Quadratic_program (CGAL::Comparison_result relation = CGAL::EQUAL)
|
||||
Quadratic_program
|
||||
(CGAL::Comparison_result relation = CGAL::EQUAL,
|
||||
bool finite_lower = true,
|
||||
NT lower = 0,
|
||||
bool finite_upper = false,
|
||||
NT upper = 0)
|
||||
: n_(0), m_(0), c0_(0),
|
||||
default_r(relation), default_fl(true),
|
||||
default_l(0), default_fu(false), default_u(0), is_valid_(true)
|
||||
default_r(relation), default_fl(finite_lower),
|
||||
default_l(lower), default_fu(finite_upper),
|
||||
default_u(upper), is_valid_(true)
|
||||
{}
|
||||
// constructor from iterators
|
||||
template <typename A_it, typename B_it, typename R_it, typename FL_it,
|
||||
|
|
@ -741,14 +747,62 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
// helpers to determine bound status
|
||||
// checks whether all bounds in flu are as given by the parameter "finite"
|
||||
// default_flu is the default-value of the underlying map that is not
|
||||
// stored
|
||||
bool all_bounds_are
|
||||
(bool finite, const Sparse_f_vector& flu, bool default_flu) const
|
||||
{
|
||||
if (finite == default_flu)
|
||||
return flu.empty();
|
||||
else
|
||||
// are there exactly n non-default values "finite"?
|
||||
return flu.size() == (unsigned int)(n_);
|
||||
}
|
||||
|
||||
bool all_bounds_are_zero
|
||||
// checks whether all bounds in lu are 0. default_lu is the default-value
|
||||
// of the underlying map that is not stored
|
||||
(const Sparse_vector& lu, const NT& default_lu) const
|
||||
{
|
||||
if (CGAL::is_zero(default_lu))
|
||||
return lu.empty();
|
||||
else {
|
||||
// are there exactly n non-default values?
|
||||
if (lu.size() != (unsigned int)(n_)) return false;
|
||||
// ok, we have to test each of the non-default values against zero
|
||||
for (typename Sparse_vector::const_iterator
|
||||
j = lu.begin(); j != lu.end(); ++j)
|
||||
if (!CGAL::is_zero(j->second)) return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
bool is_nonnegative() const
|
||||
{
|
||||
CGAL_qpe_assertion(default_fl);
|
||||
CGAL_qpe_assertion(CGAL::is_zero(default_l));
|
||||
CGAL_qpe_assertion(!default_fu);
|
||||
// bounds must be at their defaults:
|
||||
// >= 0 inf
|
||||
return (fl_vector.empty() && l_vector.empty() && fu_vector.empty());
|
||||
return
|
||||
all_bounds_are (true, fl_vector, default_fl) &&
|
||||
all_bounds_are_zero (l_vector, default_l) &&
|
||||
all_bounds_are (false, fu_vector, default_fu);
|
||||
}
|
||||
|
||||
bool is_nonpositive() const
|
||||
{
|
||||
return
|
||||
all_bounds_are (false, fl_vector, default_fl) &&
|
||||
all_bounds_are_zero (u_vector, default_u) &&
|
||||
all_bounds_are (true, fu_vector, default_fu);
|
||||
}
|
||||
|
||||
bool is_free() const
|
||||
{
|
||||
return
|
||||
all_bounds_are (false, fl_vector, default_fl) &&
|
||||
all_bounds_are (false, fu_vector, default_fu);
|
||||
}
|
||||
|
||||
// set methods
|
||||
|
|
|
|||
|
|
@ -0,0 +1,161 @@
|
|||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <CGAL/basic.h>
|
||||
#include <CGAL/QP_models.h>
|
||||
#include <CGAL/QP_functions.h>
|
||||
|
||||
// choose exact integral type
|
||||
#ifndef CGAL_USE_GMP
|
||||
#include <CGAL/MP_Float.h>
|
||||
typedef CGAL::MP_Float ET;
|
||||
#else
|
||||
#include <CGAL/Gmpz.h>
|
||||
typedef CGAL::Gmpz ET;
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
for (bool fl = false; fl < true; ++fl)
|
||||
for (bool fu = false; fu < true; ++fu)
|
||||
for (int l = -2; l < 0; ++l)
|
||||
for (int u = 0; u < 2; ++u)
|
||||
for (int r = -1; r < 1; ++r) {
|
||||
// generate empty program with all possible
|
||||
// defaults, and test solver / bound status functions
|
||||
CGAL::Quadratic_program<int> qp
|
||||
(CGAL::Comparison_result(r), fl, l, fu, u);
|
||||
assert (qp.is_valid());
|
||||
|
||||
// test solver
|
||||
CGAL::Quadratic_program_solution<ET> s =
|
||||
CGAL::solve_quadratic_program (qp, ET());
|
||||
assert (CGAL::is_zero(s.objective_value()));
|
||||
assert (s.is_optimal());
|
||||
|
||||
// test bounds (program is empty, so everything should hold)
|
||||
assert (qp.is_nonnegative());
|
||||
assert (qp.is_nonpositive());
|
||||
assert (qp.is_free());
|
||||
|
||||
// now manipulate program
|
||||
qp.set_c(0, 1); // min x_0
|
||||
// l <= x_0 <= u
|
||||
// test solver
|
||||
s = CGAL::solve_quadratic_program (qp, ET());
|
||||
if (fl) {
|
||||
assert (s.is_optimal());
|
||||
assert (s.objective_value() == l);
|
||||
} else
|
||||
assert (s.is_unbounded());
|
||||
|
||||
// test bounds
|
||||
if (fl && fu) {
|
||||
assert (!qp.is_nonnegative());
|
||||
assert (!qp.is_nonpositive());
|
||||
assert (!qp.is_free());
|
||||
}
|
||||
if (fl && !fu) {
|
||||
if (l==0)
|
||||
assert (qp.is_nonnegative());
|
||||
else
|
||||
assert (!qp.is_nonnegative());
|
||||
assert (!qp.is_nonpositive());
|
||||
assert (!qp.is_free());
|
||||
}
|
||||
if (!fl && fu) {
|
||||
if (u==0)
|
||||
assert (qp.is_nonpositive());
|
||||
else
|
||||
assert (!qp.is_nonpositive());
|
||||
assert (!qp.is_nonnegative());
|
||||
assert (!qp.is_free());
|
||||
}
|
||||
if (!fl && !fu) {
|
||||
assert (qp.is_free());
|
||||
assert (!qp.is_nonnegative());
|
||||
assert (!qp.is_nonpositive());
|
||||
}
|
||||
|
||||
// manipulate program
|
||||
qp.set_l(0, true, 0); // 0 <= x_0 <= u
|
||||
|
||||
// test solver
|
||||
s = CGAL::solve_quadratic_program (qp, ET());
|
||||
assert (s.is_optimal());
|
||||
assert (CGAL::is_zero(s.objective_value()));
|
||||
|
||||
// test bounds
|
||||
if (!fu)
|
||||
assert (qp.is_nonnegative());
|
||||
else
|
||||
assert (!qp.is_nonnegative());
|
||||
assert (!qp.is_free());
|
||||
assert (!qp.is_nonpositive());
|
||||
|
||||
// manipulate program
|
||||
qp.set_l(0, false); // -infty <= x_0 <= u
|
||||
|
||||
// test solver
|
||||
s = CGAL::solve_quadratic_program (qp, ET());
|
||||
assert (s.is_unbounded());
|
||||
|
||||
// manipulate program
|
||||
qp.set_c(0, -1); // max x_0
|
||||
|
||||
// test solver
|
||||
s = CGAL::solve_quadratic_program (qp, ET());
|
||||
if (fu) {
|
||||
assert (s.is_optimal());
|
||||
assert (s.objective_value() == u);
|
||||
} else
|
||||
assert (s.is_unbounded());
|
||||
|
||||
// test bounds
|
||||
if (fu) {
|
||||
if (u==0)
|
||||
assert (qp.is_nonpositive());
|
||||
else
|
||||
assert (!qp.is_nonpositive());
|
||||
assert (!qp.is_free());
|
||||
} else {
|
||||
assert (qp.is_free());
|
||||
assert (!qp.is_nonpositive());
|
||||
}
|
||||
assert (!qp.is_nonnegative());
|
||||
|
||||
// manipulate program
|
||||
qp.set_c0(5);
|
||||
qp.set_u(0, true, 0); // -infty <= x_0 <= 0
|
||||
|
||||
// test solver
|
||||
s = CGAL::solve_quadratic_program (qp, ET());
|
||||
assert (s.is_optimal());
|
||||
assert (s.objective_value() == 5);
|
||||
|
||||
// test bounds
|
||||
assert (qp.is_nonpositive());
|
||||
assert (!qp.is_nonnegative());
|
||||
assert (!qp.is_free());
|
||||
|
||||
qp.set_u(0, false); // -infty <= x_0 <= infty
|
||||
s = CGAL::solve_quadratic_program (qp, ET());
|
||||
assert (s.is_unbounded());
|
||||
assert (qp.is_free());
|
||||
assert (!qp.is_nonnegative());
|
||||
assert (!qp.is_nonpositive());
|
||||
|
||||
// test default_r: insert constraint 0x ~ 1; this is
|
||||
// feasible iff <=
|
||||
qp.set_a(0,0,0);
|
||||
qp.set_b(0,1);
|
||||
|
||||
// test solver
|
||||
s = CGAL::solve_quadratic_program (qp, ET());
|
||||
if (r == -1)
|
||||
assert (s.is_unbounded());
|
||||
else
|
||||
assert (s.is_infeasible());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <CGAL/basic.h>
|
||||
#include <CGAL/QP_models.h>
|
||||
#include <CGAL/QP_functions.h>
|
||||
|
||||
// choose exact integral type
|
||||
#ifndef CGAL_USE_GMP
|
||||
#include <CGAL/MP_Float.h>
|
||||
typedef CGAL::MP_Float ET;
|
||||
#else
|
||||
#include <CGAL/Gmpz.h>
|
||||
typedef CGAL::Gmpz ET;
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
CGAL::Quadratic_program<int> qp; // no variables, no constraints
|
||||
assert (qp.is_valid());
|
||||
|
||||
CGAL::Quadratic_program_solution<ET> s =
|
||||
CGAL::solve_quadratic_program (qp, ET());
|
||||
|
||||
std::cout << "Solution = " << s.objective_value() << std::endl;
|
||||
std::cout << "Status = " << s.status() << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
Reference in New Issue