From a2712eb42952407b0856e06bc9ecbeab33a12c9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bernd=20G=C3=A4rtner?= Date: Wed, 11 Apr 2007 15:48:19 +0000 Subject: [PATCH] - various refactorings: - mps reader is now derived from a model that allows to set up and manipulate a program entrywise - old copying models removed - free models removed (they are utterly useless) - a() -> get_a() etc. - the solver can now solve problems with no variables :-) - manual: - added maker pages - adapted to above changes --- .gitattributes | 15 +- .../QP_solver_ref/Free_linear_program.tex | 51 - .../Free_linear_program_from_iterators.tex | 50 - .../Free_linear_program_from_pointers.tex | 41 - .../QP_solver_ref/Free_quadratic_program.tex | 54 - .../Free_quadratic_program_from_iterators.tex | 53 - .../Free_quadratic_program_from_pointers.tex | 43 - .../QP_solver_ref/LinearProgramInterface.tex | 41 +- .../doc_tex/QP_solver_ref/Linear_program.tex | 81 +- .../Linear_program_from_iterators.tex | 5 +- .../QP_solver_ref/Linear_program_from_mps.tex | 65 +- .../Linear_program_from_pointers.tex | 8 +- QP_solver/doc_tex/QP_solver_ref/MPSFormat.tex | 25 +- .../NonnegativeLinearProgramInterface.tex | 36 +- .../NonnegativeQuadraticProgramInterface.tex | 30 +- .../Nonnegative_linear_program.tex | 62 +- ...negative_linear_program_from_iterators.tex | 8 +- .../Nonnegative_linear_program_from_mps.tex | 84 + ...nnegative_linear_program_from_pointers.tex | 10 +- .../Nonnegative_quadratic_program.tex | 66 +- ...ative_quadratic_program_from_iterators.tex | 6 +- ...Nonnegative_quadratic_program_from_mps.tex | 90 + ...gative_quadratic_program_from_pointers.tex | 8 +- .../QuadraticProgramInterface.tex | 39 +- .../QP_solver_ref/Quadratic_program.tex | 84 +- .../Quadratic_program_from_iterators.tex | 3 +- .../Quadratic_program_from_mps.tex | 69 +- .../Quadratic_program_from_pointers.tex | 7 +- .../Sparse_linear_program_from_mps.tex | 73 - .../Sparse_quadratic_program_from_mps.tex | 79 - QP_solver/doc_tex/QP_solver_ref/intro.tex | 63 +- QP_solver/doc_tex/QP_solver_ref/main.tex | 15 +- .../make_linear_program_from_iterators.tex | 36 + ...negative_linear_program_from_iterators.tex | 30 + ...ative_quadratic_program_from_iterators.tex | 31 + .../make_quadratic_program_from_iterators.tex | 38 + .../QP_solver_ref/print_linear_program.tex | 4 +- .../print_nonnegative_linear_program.tex | 4 +- .../print_nonnegative_quadratic_program.tex | 4 +- .../QP_solver_ref/print_quadratic_program.tex | 4 +- .../QP_solver_ref/solve_linear_program.tex | 3 +- .../solve_nonnegative_linear_program.tex | 3 +- .../solve_nonnegative_quadratic_program.tex | 3 +- .../QP_solver_ref/solve_quadratic_program.tex | 3 +- .../examples/QP_solver/double_qp_solver.cpp | 10 +- QP_solver/include/CGAL/QP_functions.h | 2 + QP_solver/include/CGAL/QP_models.h | 2396 ++++++++--------- QP_solver/include/CGAL/QP_solution.h | 66 +- QP_solver/include/CGAL/QP_solver.h | 18 +- .../include/CGAL/QP_solver/Initialization.h | 28 +- .../include/CGAL/QP_solver/QP_basis_inverse.h | 56 +- .../CGAL/QP_solver/QP_basis_inverse_impl.h | 42 +- .../CGAL/QP_solver/QP_functions_impl.h | 88 +- .../include/CGAL/QP_solver/QP_models_impl.h | 682 ----- .../CGAL/QP_solver/QP_partial_exact_pricing.h | 2 +- .../CGAL/QP_solver/QP_pricing_strategy.h | 8 +- .../include/CGAL/QP_solver/QP_solver_impl.h | 10 +- .../QP_solver_nonstandardform_impl.h | 8 +- .../CGAL/QP_solver/QP_solver_validity_impl.h | 6 +- QP_solver/include/CGAL/QP_solver/iterator.h | 8 +- .../QP_solver/master_mps_to_derivatives.cpp | 133 +- QP_solver/test/QP_solver/test_MPS.cpp | 10 +- QP_solver/test/QP_solver/test_empty_qp.cpp | 29 + QP_solver/test/QP_solver/test_solver.cpp | 174 +- 64 files changed, 2211 insertions(+), 3092 deletions(-) delete mode 100644 QP_solver/doc_tex/QP_solver_ref/Free_linear_program.tex delete mode 100644 QP_solver/doc_tex/QP_solver_ref/Free_linear_program_from_iterators.tex delete mode 100644 QP_solver/doc_tex/QP_solver_ref/Free_linear_program_from_pointers.tex delete mode 100644 QP_solver/doc_tex/QP_solver_ref/Free_quadratic_program.tex delete mode 100644 QP_solver/doc_tex/QP_solver_ref/Free_quadratic_program_from_iterators.tex delete mode 100644 QP_solver/doc_tex/QP_solver_ref/Free_quadratic_program_from_pointers.tex create mode 100644 QP_solver/doc_tex/QP_solver_ref/Nonnegative_linear_program_from_mps.tex create mode 100644 QP_solver/doc_tex/QP_solver_ref/Nonnegative_quadratic_program_from_mps.tex delete mode 100644 QP_solver/doc_tex/QP_solver_ref/Sparse_linear_program_from_mps.tex delete mode 100644 QP_solver/doc_tex/QP_solver_ref/Sparse_quadratic_program_from_mps.tex create mode 100644 QP_solver/doc_tex/QP_solver_ref/make_linear_program_from_iterators.tex create mode 100644 QP_solver/doc_tex/QP_solver_ref/make_nonnegative_linear_program_from_iterators.tex create mode 100644 QP_solver/doc_tex/QP_solver_ref/make_nonnegative_quadratic_program_from_iterators.tex create mode 100644 QP_solver/doc_tex/QP_solver_ref/make_quadratic_program_from_iterators.tex delete mode 100644 QP_solver/include/CGAL/QP_solver/QP_models_impl.h create mode 100644 QP_solver/test/QP_solver/test_empty_qp.cpp diff --git a/.gitattributes b/.gitattributes index b0b944d0e11..1c6a172f888 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1834,12 +1834,6 @@ QP_solver/doc_tex/QP_solver/first_qp.eps -text svneol=unset#application/postscri QP_solver/doc_tex/QP_solver/first_qp.fig -text svneol=unset#application/octet-stream QP_solver/doc_tex/QP_solver/first_qp.gif -text svneol=unset#image/gif QP_solver/doc_tex/QP_solver/first_qp.pdf -text svneol=unset#application/pdf -QP_solver/doc_tex/QP_solver_ref/Free_linear_program.tex -text -QP_solver/doc_tex/QP_solver_ref/Free_linear_program_from_iterators.tex -text -QP_solver/doc_tex/QP_solver_ref/Free_linear_program_from_pointers.tex -text -QP_solver/doc_tex/QP_solver_ref/Free_quadratic_program.tex -text -QP_solver/doc_tex/QP_solver_ref/Free_quadratic_program_from_iterators.tex -text -QP_solver/doc_tex/QP_solver_ref/Free_quadratic_program_from_pointers.tex -text QP_solver/doc_tex/QP_solver_ref/Linear_program.tex -text QP_solver/doc_tex/QP_solver_ref/Linear_program_from_iterators.tex -text QP_solver/doc_tex/QP_solver_ref/Linear_program_from_mps.tex -text @@ -1847,15 +1841,19 @@ QP_solver/doc_tex/QP_solver_ref/Linear_program_from_pointers.tex -text QP_solver/doc_tex/QP_solver_ref/MPSFormat.tex -text QP_solver/doc_tex/QP_solver_ref/Nonnegative_linear_program.tex -text QP_solver/doc_tex/QP_solver_ref/Nonnegative_linear_program_from_iterators.tex -text +QP_solver/doc_tex/QP_solver_ref/Nonnegative_linear_program_from_mps.tex -text QP_solver/doc_tex/QP_solver_ref/Nonnegative_linear_program_from_pointers.tex -text QP_solver/doc_tex/QP_solver_ref/Nonnegative_quadratic_program.tex -text QP_solver/doc_tex/QP_solver_ref/Nonnegative_quadratic_program_from_iterators.tex -text +QP_solver/doc_tex/QP_solver_ref/Nonnegative_quadratic_program_from_mps.tex -text QP_solver/doc_tex/QP_solver_ref/Nonnegative_quadratic_program_from_pointers.tex -text QP_solver/doc_tex/QP_solver_ref/Quadratic_program.tex -text QP_solver/doc_tex/QP_solver_ref/Quadratic_program_from_mps.tex -text QP_solver/doc_tex/QP_solver_ref/Quadratic_program_from_pointers.tex -text -QP_solver/doc_tex/QP_solver_ref/Sparse_linear_program_from_mps.tex -text -QP_solver/doc_tex/QP_solver_ref/Sparse_quadratic_program_from_mps.tex -text +QP_solver/doc_tex/QP_solver_ref/make_linear_program_from_iterators.tex -text +QP_solver/doc_tex/QP_solver_ref/make_nonnegative_linear_program_from_iterators.tex -text +QP_solver/doc_tex/QP_solver_ref/make_nonnegative_quadratic_program_from_iterators.tex -text +QP_solver/doc_tex/QP_solver_ref/make_quadratic_program_from_iterators.tex -text QP_solver/doc_tex/QP_solver_ref/print_linear_program.tex -text QP_solver/doc_tex/QP_solver_ref/print_nonnegative_linear_program.tex -text QP_solver/doc_tex/QP_solver_ref/print_nonnegative_quadratic_program.tex -text @@ -1876,6 +1874,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_random_qp.cpp -text QP_solver/test/QP_solver/test_solver.cout -text Qt_widget/demo/Qt_widget/hellosegment.vcproj eol=crlf diff --git a/QP_solver/doc_tex/QP_solver_ref/Free_linear_program.tex b/QP_solver/doc_tex/QP_solver_ref/Free_linear_program.tex deleted file mode 100644 index 7ca2fc73d25..00000000000 --- a/QP_solver/doc_tex/QP_solver_ref/Free_linear_program.tex +++ /dev/null @@ -1,51 +0,0 @@ -\begin{ccRefClass}{Free_linear_program} - -\ccInclude{CGAL/QP_models.h} - -\ccDefinition -An object of class \ccRefName\ describes a linear program of the form -%% -\begin{eqnarray*} -\mbox{(QP)}& \mbox{minimize} & c^{T}x+c_0 \\ -&\mbox{subject to} & Ax\qprel b -\end{eqnarray*} -%% -in $n$ real variables $x=(x_0,\ldots,x_{n-1})$. The term ``free'' refers -to the fact that there are no explicit bounds on the variables. -Here, -\begin{itemize} -\item $A$ is an $m\times n$ matrix (the constraint matrix), -\item $b$ is an $m$-dimensional vector (the right-hand side), -\item $\qprel$ is an $m$-dimensional vector of relations -from $\{\leq, =, \geq\}$, -\item $c$ is an $n$-dimensional vector (the linear objective - function), and -\item $c_0$ is a constant. -\end{itemize} - -This class copies the program data from given iterator ranges; -if you only need to wrap existing iterators, you may use the classes -\ccc{Free_linear_program_from_iterators} and \ccc{Free_linear_program_from_pointers}). - -\ccIsModel -\ccc{LinearProgramInterface} - -\ccCreation -\ccIndexClassCreation -\ccCreationVariable{qp} - -\ccConstructor{template - Free_linear_program(int n, int m, - const A_it& a, - const B_it& b, - const R_it& r, - const C_it& c, - const std::iterator_traitsvalue_type& c0 = 0 - )}{constructs \ccVar\ from given input iterators and the constant \ccc{c0}. The passed iterators are merely stored, no copying of the program data takes place. } - -\ccSeeAlso -\ccc{Free_linear_program_from_iterators}\\ -\ccc{Free_linear_program_from_pointers} - - -\end{ccRefClass} diff --git a/QP_solver/doc_tex/QP_solver_ref/Free_linear_program_from_iterators.tex b/QP_solver/doc_tex/QP_solver_ref/Free_linear_program_from_iterators.tex deleted file mode 100644 index 9dc4df964c1..00000000000 --- a/QP_solver/doc_tex/QP_solver_ref/Free_linear_program_from_iterators.tex +++ /dev/null @@ -1,50 +0,0 @@ -\begin{ccRefClass}{Free_linear_program_from_iterators} - -\ccInclude{CGAL/QP_models.h} - -\ccDefinition -An object of class \ccRefName\ describes a linear program of the form -%% -\begin{eqnarray*} -\mbox{(QP)}& \mbox{minimize} & c^{T}x+c_0 \\ -&\mbox{subject to} & Ax\qprel b -\end{eqnarray*} -%% -in $n$ real variables $x=(x_0,\ldots,x_{n-1})$. The term ``free'' refers -to the fact that there are no explicit bounds on the variables. -Here, -\begin{itemize} -\item $A$ is an $m\times n$ matrix (the constraint matrix), -\item $b$ is an $m$-dimensional vector (the right-hand side), -\item $\qprel$ is an $m$-dimensional vector of relations -from $\{\leq, =, \geq\}$, -\item $c$ is an $n$-dimensional vector (the linear objective - function), and -\item $c_0$ is a constant. -\end{itemize} - -This class is simply a wrapper for existing iterators, and it does not -copy the program data (if you need a copy, you may use the class -\ccc{Free_linear_program}). - -\ccIsModel -\ccc{LinearProgramInterface} - - -\ccCreation -\ccIndexClassCreation -\ccCreationVariable{lp} - -\ccConstructor{Free_linear_program_from_iterators(int n, int m, - const A_it& a, - const B_it& b, - const R_it& r, - const C_it& c, - const std::iterator_traitsvalue_type& c0 = 0 - )}{constructs \ccVar\ from given random-access iterators and the constant \ccc{c0}. The passed iterators are merely stored, no copying of the program data takes place. } - -\ccSeeAlso -\ccc{Free_linear_program_from_pointers}\\ -\ccc{Free_linear_program} - -\end{ccRefClass} diff --git a/QP_solver/doc_tex/QP_solver_ref/Free_linear_program_from_pointers.tex b/QP_solver/doc_tex/QP_solver_ref/Free_linear_program_from_pointers.tex deleted file mode 100644 index 98d13f41aea..00000000000 --- a/QP_solver/doc_tex/QP_solver_ref/Free_linear_program_from_pointers.tex +++ /dev/null @@ -1,41 +0,0 @@ -\begin{ccRefClass}{Free_linear_program_from_pointers} - -\ccInclude{CGAL/QP_models.h} - -\ccDefinition -An object of class \ccRefName\ describes a linear program of the form -%% -\begin{eqnarray*} -\mbox{(QP)}& \mbox{minimize} & c^{T}x+c_0 \\ -&\mbox{subject to} & Ax\qprel b -\end{eqnarray*} -%% -in $n$ real variables $x=(x_0,\ldots,x_{n-1})$. The term ``free'' refers -to the fact that there are no explicit bounds on the variables. -Here, -\begin{itemize} -\item $A$ is an $m\times n$ matrix (the constraint matrix), -\item $b$ is an $m$-dimensional vector (the right-hand side), -\item $\qprel$ is an $m$-dimensional vector of relations -from $\{\leq, =, \geq\}$, -\item $c$ is an $n$-dimensional vector (the linear objective - function), and -\item $c_0$ is a constant. -\end{itemize} - -This class specializes the class -\ccc{Free_linear_program_from_iterators} for the case where all iterators are of type -\ccc{NT**} (for -$A$) and \ccc{NT*} otherwise, for some number type \ccc{NT}. -The class is simply a wrapper for -existing pointers, and it does not copy the program data (if you need -a copy, you may use the class \ccc{Free_linear_program}). - -\ccIsModel -\ccc{LinearProgramInterface} - -\ccSeeAlso -\ccc{Free_linear_program_from_iterators}\\ -\ccc{Free_linear_program} - -\end{ccRefClass} diff --git a/QP_solver/doc_tex/QP_solver_ref/Free_quadratic_program.tex b/QP_solver/doc_tex/QP_solver_ref/Free_quadratic_program.tex deleted file mode 100644 index 2672191f872..00000000000 --- a/QP_solver/doc_tex/QP_solver_ref/Free_quadratic_program.tex +++ /dev/null @@ -1,54 +0,0 @@ -\begin{ccRefClass}{Free_quadratic_program} - -\ccInclude{CGAL/QP_models.h} - -\ccDefinition -An object of class \ccRefName\ describes a convex quadratic program of the form -%% -\begin{eqnarray*} -\mbox{(QP)}& \mbox{minimize} & x^{T}Dx+c^{T}x+c_0 \\ -&\mbox{subject to} & Ax\qprel b -\end{eqnarray*} -%% -in $n$ real variables $x=(x_0,\ldots,x_{n-1})$. The term ``free'' refers -to the fact that there are no explicit bounds on the variables. -Here, -\begin{itemize} -\item $A$ is an $m\times n$ matrix (the constraint matrix), -\item $b$ is an $m$-dimensional vector (the right-hand side), -\item $\qprel$ is an $m$-dimensional vector of relations -from $\{\leq, =, \geq\}$, -\item $D$ is a symmetric positive-semidefinite $n\times n$ matrix (the - quadratic objective function), -\item $c$ is an $n$-dimensional vector (the linear objective - function), and -\item $c_0$ is a constant. -\end{itemize} - -This class copies the program data from given iterator ranges; -if you only need to wrap existing iterators, you may use the classes -\ccc{Free_quadratic_program_from_iterators} and \ccc{Free_quadratic_program_from_pointers}). - -\ccIsModel -\ccc{QuadraticProgramInterface} - -\ccCreation -\ccIndexClassCreation -\ccCreationVariable{qp} - -\ccConstructor{template - Free_quadratic_program(int n, int m, - const A_it& a, - const B_it& b, - const R_it& r, - const D_it& d, - const C_it& c, - const std::iterator_traitsvalue_type& c0 = 0 - )}{constructs \ccVar\ from given input iterators and the constant \ccc{c0}. The passed iterators are merely stored, no copying of the program data takes place. } - -\ccSeeAlso -\ccc{Free_quadratic_program_from_iterators}\\ -\ccc{Free_quadratic_program_from_pointers} - - -\end{ccRefClass} diff --git a/QP_solver/doc_tex/QP_solver_ref/Free_quadratic_program_from_iterators.tex b/QP_solver/doc_tex/QP_solver_ref/Free_quadratic_program_from_iterators.tex deleted file mode 100644 index d3864338028..00000000000 --- a/QP_solver/doc_tex/QP_solver_ref/Free_quadratic_program_from_iterators.tex +++ /dev/null @@ -1,53 +0,0 @@ -\begin{ccRefClass}{Free_quadratic_program_from_iterators} - -\ccInclude{CGAL/QP_models.h} - -\ccDefinition -An object of class \ccRefName\ describes a convex quadratic program of the form -%% -\begin{eqnarray*} -\mbox{(QP)}& \mbox{minimize} & x^{T}Dx+c^{T}x+c_0 \\ -&\mbox{subject to} & Ax\qprel b -\end{eqnarray*} -%% -in $n$ real variables $x=(x_0,\ldots,x_{n-1})$. The term ``free'' refers -to the fact that there are no explicit bounds on the variables. -Here, -\begin{itemize} -\item $A$ is an $m\times n$ matrix (the constraint matrix), -\item $b$ is an $m$-dimensional vector (the right-hand side), -\item $\qprel$ is an $m$-dimensional vector of relations -from $\{\leq, =, \geq\}$, -\item $D$ is a symmetric positive-semidefinite $n\times n$ matrix (the - quadratic objective function), -\item $c$ is an $n$-dimensional vector (the linear objective - function), and -\item $c_0$ is a constant. -\end{itemize} - -This class is simply a wrapper for existing iterators, and it does not -copy the program data (if you need a copy, you may use the class -\ccc{Free_quadratic_program}). - -\ccIsModel -\ccc{QuadraticProgramInterface} - - -\ccCreation -\ccIndexClassCreation -\ccCreationVariable{qp} - -\ccConstructor{Free_quadratic_program_from_iterators(int n, int m, - const A_it& a, - const B_it& b, - const R_it& r, - const D_it& d, - const C_it& c, - const std::iterator_traitsvalue_type& c0 = 0 - )}{constructs \ccVar\ from given random-access iterators and the constant \ccc{c0}. The passed iterators are merely stored, no copying of the program data takes place. } - -\ccSeeAlso -\ccc{Free_quadratic_program_from_pointers}\\ -\ccc{Free_quadratic_program} - -\end{ccRefClass} diff --git a/QP_solver/doc_tex/QP_solver_ref/Free_quadratic_program_from_pointers.tex b/QP_solver/doc_tex/QP_solver_ref/Free_quadratic_program_from_pointers.tex deleted file mode 100644 index e09668ca11b..00000000000 --- a/QP_solver/doc_tex/QP_solver_ref/Free_quadratic_program_from_pointers.tex +++ /dev/null @@ -1,43 +0,0 @@ -\begin{ccRefClass}{Free_quadratic_program_from_pointers} - -\ccInclude{CGAL/QP_models.h} - -\ccDefinition -An object of class \ccRefName\ describes a convex quadratic program of the form -%% -\begin{eqnarray*} -\mbox{(QP)}& \mbox{minimize} & x^{T}Dx+c^{T}x+c_0 \\ -&\mbox{subject to} & Ax\qprel b -\end{eqnarray*} -%% -in $n$ real variables $x=(x_0,\ldots,x_{n-1})$. The term ``free'' refers -to the fact that there are no explicit bounds on the variables. -Here, -\begin{itemize} -\item $A$ is an $m\times n$ matrix (the constraint matrix), -\item $b$ is an $m$-dimensional vector (the right-hand side), -\item $\qprel$ is an $m$-dimensional vector of relations -from $\{\leq, =, \geq\}$, -\item $D$ is a symmetric positive-semidefinite $n\times n$ matrix (the - quadratic objective function), -\item $c$ is an $n$-dimensional vector (the linear objective - function), and -\item $c_0$ is a constant. -\end{itemize} - -This class specializes the class -\ccc{Free_quadratic_program_from_iterators} for the case where all iterators are of type -\ccc{NT**} (for -$A$ and $D$) and \ccc{NT*} otherwise, for some number type \ccc{NT}. -The class is simply a wrapper for -existing pointers, and it does not copy the program data (if you need -a copy, you may use the class \ccc{Free_quadratic_program}). - -\ccIsModel -\ccc{QuadraticProgramInterface} - -\ccSeeAlso -\ccc{Free_quadratic_program_from_iterators}\\ -\ccc{Free_quadratic_program} - -\end{ccRefClass} diff --git a/QP_solver/doc_tex/QP_solver_ref/LinearProgramInterface.tex b/QP_solver/doc_tex/QP_solver_ref/LinearProgramInterface.tex index b6e4fc40629..80370efd83a 100644 --- a/QP_solver/doc_tex/QP_solver_ref/LinearProgramInterface.tex +++ b/QP_solver/doc_tex/QP_solver_ref/LinearProgramInterface.tex @@ -4,7 +4,7 @@ A model of \ccRefName\ describes a linear program of the form %% \begin{eqnarray*} -\mbox{(QP)}& \mbox{minimize} & c^{T}x+c_0 \\ +\mbox{(LP)}& \mbox{minimize} & c^{T}x+c_0 \\ &\mbox{subject to} & Ax\qprel b, \\ & & l \leq x \leq u \end{eqnarray*} @@ -25,13 +25,14 @@ $x$, \item $c_0$ is a constant. \end{itemize} +The description is given by appropriate \emph{random-access} +iterators over the program data, see below. The program therefore +comes in \emph{dense} representation which includes zero entries. + \ccHasModels +\ccc{CGAL::Linear_program}\\ \ccc{CGAL::Linear_program_from_iterators}\\ \ccc{CGAL::Linear_program_from_pointers}\\ -\ccc{CGAL::Linear_program}\\ -\ccc{CGAL::Free_linear_program_from_iterators}\\ -\ccc{CGAL::Free_linear_program_from_pointers}\\ -\ccc{CGAL::Free_linear_program}\\ \ccc{CGAL::Linear_program_from_mps}\\ \ccTypes @@ -69,54 +70,56 @@ $x$, \ccCreationVariable{qp} -\ccMethod{int n() const;}{returns the number $n$ of variables (number +\ccMethod{int get_n() const;}{returns the number $n$ of variables (number of columns of $A$) in \ccVar.} -\ccMethod{int m() const;}{returns the number $m$ of constraints +\ccMethod{int get_m() const;}{returns the number $m$ of constraints (number of rows of $A$) in \ccVar.} -\ccMethod{const A_iterator& a() const;}{returns an iterator over the columns +\ccMethod{A_iterator get_a() const;}{returns an iterator over the columns of $A$. For $j=0,\ldots,n-1$, $\ccc{*(a()+j)}$ is a random access iterator for column $j$.} -\ccMethod{const B_iterator& b() const;}{returns an iterator over the entries +\ccMethod{B_iterator get_b() const;}{returns an iterator over the entries of $b$.} -\ccMethod{const R_iterator& r() const;}{returns an iterator over the entries +\ccMethod{R_iterator get_r() const;}{returns an iterator over the entries of $\qprel$. The value \ccc{CGAL::SMALLER} stands for $\leq$, \ccc{CGAL::EQUAL} stands for $=$, and \ccc{CGAL::LARGER} stands for $\geq$.} -\ccMethod{const FL_iterator& fl() const;}{returns an iterator over the +\ccMethod{FL_iterator get_fl() const;}{returns an iterator over the existence of the lower bounds $l_j, j=0,\ldots,n-1$. If $\ccVar.\ccc{fl()}[j]=true$, the variable $x_j$ has a lower bound, otherwise it has no lower bound.} -\ccMethod{const L_iterator& l() const;}{returns an iterator for the +\ccMethod{L_iterator get_l() const;}{returns an iterator for the entries of $l$. If $\ccVar.\ccc{fl()}[j]=\ccc{false}$, the value $\ccVar.\ccc{l()}[j]$ is not accessed.} -\ccMethod{const FU_iterator& fu() const;}{returns an iterator over the +\ccMethod{FU_iterator get_fu() const;}{returns an iterator over the existence of the upper bounds $u_j, j=0,\ldots,n-1$. If $\ccVar.\ccc{fu()}[j]=true$, the variable $x_j$ has an upper bound, otherwise it has no upper bound.} -\ccMethod{const U_iterator& u() const;}{returns an iterator over the +\ccMethod{U_iterator get_u() const;}{returns an iterator over the entries of $u$. If $\ccVar.\ccc{fu()}[j]=\ccc{false}$, the value $\ccVar.\ccc{u()}[j]$ is not accessed.} -\ccMethod{const C_iterator& c() const;}{returns an iterator over the entries +\ccMethod{C_iterator get_c() const;}{returns an iterator over the entries of $c$.} -\ccMethod{const std::iterator_traits::value_type& c0() const;}{returns the constant - term $c_0$ of the objective function.} +\ccMethod{std::iterator_traits::value_type c0() const;} +{returns the constant term $c_0$ of the objective function.} \ccRequirements The value types of all iterator types (nested iterator types, -respectively, for \ccc{A_iterator} and \ccc{D_iterator}) must be +respectively, for \ccc{A_iterator}) must be convertible to some common \ccc{IntegralDomain} \ccc{ET}. \ccSeeAlso - +\ccc{QuadraticProgramInterface}\\ +\ccc{NonnegativeQuadraticProgramInterface}\\ +\ccc{NonnegativeLinearProgramInterface} \end{ccRefConcept} diff --git a/QP_solver/doc_tex/QP_solver_ref/Linear_program.tex b/QP_solver/doc_tex/QP_solver_ref/Linear_program.tex index 5463233b1aa..393a58f7fb5 100644 --- a/QP_solver/doc_tex/QP_solver_ref/Linear_program.tex +++ b/QP_solver/doc_tex/QP_solver_ref/Linear_program.tex @@ -6,7 +6,7 @@ An object of class \ccRefName\ describes a linear program of the form %% \begin{eqnarray*} -\mbox{(QP)}& \mbox{minimize} & c^{T}x+c_0 \\ +\mbox{(LP)}& \mbox{minimize} & c^{T}x+c_0 \\ &\mbox{subject to} & Ax\qprel b, \\ & & l \leq x \leq u \end{eqnarray*} @@ -27,40 +27,71 @@ $x$, \item $c_0$ is a constant. \end{itemize} -This class copies the program data from given iterator ranges; this -is useful if the iterators that you have are not random-access. -The time taken to copy the data is $\Theta(nm+n^2)$, though, even if -the program description is very sparse. Usually, -you only need to wrap existing (random-access) -iterators, and then you may use the classes -\ccc{Linear_program_from_iterators} and \ccc{Linear_program_from_pointers}). +This class allows you to build your program entry by entry, using +the set-methods below. If you only need to wrap existing (random-access) +iterators, then you may use the classes +\ccc{Linear_program_from_iterators} and \ccc{Linear_program_from_pointers}). If you want +to read a linear program in \ccc{MPSFormat} from a file, please use +the model \ccc{Linear_program_from_mps}. \ccIsModel \ccc{LinearProgramInterface} +\ccTypes + +\ccNestedType{NT}{The number type of the program entries.} + \ccCreation \ccIndexClassCreation \ccCreationVariable{lp} -The following constructor is a template, so you can provide input -iterators of any types. +\ccConstructor{ +Linear_program(CGAL::Comparison_result default_r = CGAL::EQUAL);} +{constructs a linear 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$.} -\ccConstructor{template - Linear_program(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 C_it& c, - const std::iterator_traitsvalue_type& c0 = 0 - )}{constructs \ccVar\ from given input iterators and the constant \ccc{c0}.} +\ccOperations + +\ccCreationVariable{lp} + +\ccMethod{bool is_linear() const;}{returns \ccc{true}.} + +\ccMethod{bool is_nonnegative() const;}{returns \ccc{true} iff +the bounds of \ccVar\ are $x\geq 0$.} + +\ccMethod{void set_a (int j, int i, const NT& val);}{sets the entry $A_{ij}$ +in column $j$ and row $i$ of the constraint matrix $A$ of \ccVar\ to +\ccc{val}. An existing entry is overwritten. \ccVar\ is enlarged if +necessary to accomodate this entry.} + +\ccMethod{void set_b (int i, const NT& val);}{sets the entry $b_i$ +of \ccVar\ to \ccc{val}. An existing entry is overwritten. +\ccVar\ is enlarged if necessary to accomodate this entry.} + +\ccMethod{void set_l (int j, bool is_finite, const NT& val = NT(0));} +{if \ccc{is_finite}, this sets the entry $l_j$ of \ccVar\ to \ccc{val}, +otherwise it sets $l_j$ to $-\infty$. An existing entry is overwritten. +\ccVar\ is enlarged if necessary to accomodate this entry.} + +\ccMethod{void set_u (int j, bool is_finite, const NT& val = NT(0));} +{if \ccc{is_finite}, this sets the entry $u_j$ of \ccVar\ to \ccc{val}, +otherwise it sets $u_j$ to $\infty$. An existing entry is overwritten. +\ccVar\ is enlarged if necessary to accomodate this entry.} + +\ccMethod{void set_c (int j, const NT& val);}{sets the entry $c_j$ +of \ccVar\ to \ccc{val}. An existing entry is overwritten. +\ccVar\ is enlarged if necessary to accomodate this entry.} + +\ccMethod{void set_c0 (const NT& val);}{sets the entry $c_0$ +of \ccVar\ to \ccc{val}. An existing entry is overwritten.} \ccSeeAlso -\ccc{Linear_program_from_iterators}\\ -\ccc{Linear_program_from_pointers} - +\ccc{Linear_program_from_iterators}\\ +\ccc{Linear_program_from_pointers}\\ +\ccc{Linear_program_from_mps} \end{ccRefClass} diff --git a/QP_solver/doc_tex/QP_solver_ref/Linear_program_from_iterators.tex b/QP_solver/doc_tex/QP_solver_ref/Linear_program_from_iterators.tex index d6d7fc7cde4..cd673787b76 100644 --- a/QP_solver/doc_tex/QP_solver_ref/Linear_program_from_iterators.tex +++ b/QP_solver/doc_tex/QP_solver_ref/Linear_program_from_iterators.tex @@ -6,7 +6,7 @@ An object of class \ccRefName\ describes a linear program of the form %% \begin{eqnarray*} -\mbox{(QP)}& \mbox{minimize} & c^{T}x+c_0 \\ +\mbox{(LP)}& \mbox{minimize} & c^{T}x+c_0 \\ &\mbox{subject to} & Ax\qprel b, \\ & & l \leq x \leq u \end{eqnarray*} @@ -52,7 +52,8 @@ copy the program data (if you need a copy, you may use the class )}{constructs \ccVar\ from given random-access iterators and the constant \ccc{c0}. The passed iterators are merely stored, no copying of the program data takes place. } \ccSeeAlso +\ccc{Linear_program}\\ \ccc{Linear_program_from_pointers}\\ -\ccc{Linear_program} +\ccc{Linear_program_from_mps} \end{ccRefClass} diff --git a/QP_solver/doc_tex/QP_solver_ref/Linear_program_from_mps.tex b/QP_solver/doc_tex/QP_solver_ref/Linear_program_from_mps.tex index 7a4397caf0b..3074ad2b49b 100644 --- a/QP_solver/doc_tex/QP_solver_ref/Linear_program_from_mps.tex +++ b/QP_solver/doc_tex/QP_solver_ref/Linear_program_from_mps.tex @@ -6,7 +6,7 @@ An object of class \ccRefName\ describes a linear program of the form %% \begin{eqnarray*} -\mbox{(QP)}& \mbox{minimize} & c^{T}x+c_0 \\ +\mbox{(LP)}& \mbox{minimize} & c^{T}x+c_0 \\ &\mbox{subject to} & Ax\qprel b, \\ & & l \leq x \leq u \end{eqnarray*} @@ -30,45 +30,68 @@ $x$, The program data are read from an input stream in \ccc{MPSFormat}. This is a commonly used format for encoding linear and quadratic programs that is understood by many solvers. All values are expected to be readable -into type \ccc{NT}. - -\textbf{Note:} The space required to store the program is $\Theta(nm + -n^2)$, even if these matrix $A$ is very sparse. This might be -prohibitive. In this case, you may use the model -\ccc{Sparse_linear_program_from_mps} whose space requirements -are bounded by the number of nonzero entries in the program -description. In this latter model, access to the iterators in -\ccc{LinearProgramInterface} will be a little slower, though. - -As a rule of thumb, however, if there is a need for the sparse model, -then \cgal's linear programming solver will probably not be able to -solve it anyway. +into type \ccc{NT}. The constructed program can be further manipulated +by using the set-methods below. \ccIsModel \ccc{LinearProgramInterface} +\ccTypes +\ccNestedType{NT}{The number type of the program entries.} + \ccCreation \ccIndexClassCreation \ccCreationVariable{lp} -\ccConstructor{Sparse_linear_program_from_mps(std::istream& in)} {reads \ccVar\ from the input stream \ccc{in}.} +\ccConstructor{Linear_program_from_mps(std::istream& in)} +{reads \ccVar\ from the input stream \ccc{in}.} \ccOperations \ccMethod{bool is_valid() const;}{returns \ccc{true} if and only if an MPS-encoded linear program could be extracted from the input stream.} -\ccMethod{const std::string& name_of_variable (int i) const;} {returns the name of the $i$-th variable.\ccPrecond \ccVar\ccc{.is_valid()}} +\ccMethod{const std::string& get_name_of_variable (int j) const;} +{returns the name of the $j$-th variable.} -\ccMethod{bool is_nonnegative() const;}{returns \ccc{true} if and only if the linear program read into \ccVar\ is a nonnegative program -\ccPrecond \ccVar\ccc{.is_valid()}.} +\ccMethod{bool is_linear() const;}{returns \ccc{true}.} -\ccMethod{const std::string& error() const;}{returns an error message explaining why the input is not in MPS format \ccPrecond \ccc{!} \ccVar\ccc{.is_valid()}} +\ccMethod{bool is_nonnegative() const;}{returns \ccc{true} if and only +if the linear program read into \ccVar\ is a nonnegative program.} + +\ccMethod{const std::string& get_error() const;}{if !\ccVar\ccc{.is_valid()}, +this method returns an error message explaining why the input does not +conform to the \ccc{MPSFormat}.} + +\ccMethod{void set_a (int j, int i, const NT& val);}{sets the entry $A_{ij}$ +in column $j$ and row $i$ of the constraint matrix $A$ of \ccVar\ to +\ccc{val}. An existing entry is overwritten. \ccVar\ is enlarged if +necessary to accomodate this entry.} + +\ccMethod{void set_b (int i, const NT& val);}{sets the entry $b_i$ +of \ccVar\ to \ccc{val}. An existing entry is overwritten. +\ccVar\ is enlarged if necessary to accomodate this entry.} + +\ccMethod{void set_l (int j, bool is_finite, const NT& val = NT(0));} +{if \ccc{is_finite}, this sets the entry $l_j$ of \ccVar\ to \ccc{val}, +otherwise it sets $l_j$ to $-\infty$. An existing entry is overwritten. +\ccVar\ is enlarged if necessary to accomodate this entry.} + +\ccMethod{void set_u (int j, bool is_finite, const NT& val = NT(0));} +{if \ccc{is_finite}, this sets the entry $u_j$ of \ccVar\ to \ccc{val}, +otherwise it sets $u_j$ to $\infty$. An existing entry is overwritten. +\ccVar\ is enlarged if necessary to accomodate this entry.} + +\ccMethod{void set_c (int j, const NT& val);}{sets the entry $c_j$ +of \ccVar\ to \ccc{val}. An existing entry is overwritten. +\ccVar\ is enlarged if necessary to accomodate this entry.} + +\ccMethod{void set_c0 (const NT& val);}{sets the entry $c_0$ +of \ccVar\ to \ccc{val}. An existing entry is overwritten.} \ccSeeAlso -\ccc{Sparse_linear_program_from_mps}\\ \ccc{Linear_program}\\ -\ccc{Linear_program_from_iterators}\\ +\ccc{Linear_program_from_iterators}\\ \ccc{Linear_program_from_pointers} diff --git a/QP_solver/doc_tex/QP_solver_ref/Linear_program_from_pointers.tex b/QP_solver/doc_tex/QP_solver_ref/Linear_program_from_pointers.tex index 2babe5e2909..fb9da99f553 100644 --- a/QP_solver/doc_tex/QP_solver_ref/Linear_program_from_pointers.tex +++ b/QP_solver/doc_tex/QP_solver_ref/Linear_program_from_pointers.tex @@ -6,7 +6,7 @@ An object of class \ccRefName\ describes a linear program of the form %% \begin{eqnarray*} -\mbox{(QP)}& \mbox{minimize} & c^{T}x+c_0 \\ +\mbox{(LP)}& \mbox{minimize} & c^{T}x+c_0 \\ &\mbox{subject to} & Ax\qprel b, \\ & & l \leq x \leq u \end{eqnarray*} @@ -37,8 +37,12 @@ a copy, you may use the class \ccc{Linear_program}). \ccIsModel \ccc{LinearProgramInterface} +\ccTypes +\ccNestedType{NT}{The number type of the program entries.} + \ccSeeAlso +\ccc{Linear_program}\\ \ccc{Linear_program_from_iterators}\\ -\ccc{Linear_program} +\ccc{Linear_program_from_mps} \end{ccRefClass} diff --git a/QP_solver/doc_tex/QP_solver_ref/MPSFormat.tex b/QP_solver/doc_tex/QP_solver_ref/MPSFormat.tex index ae7cc4f81eb..6a2e41809e8 100644 --- a/QP_solver/doc_tex/QP_solver_ref/MPSFormat.tex +++ b/QP_solver/doc_tex/QP_solver_ref/MPSFormat.tex @@ -75,8 +75,9 @@ of one or two sequences of three tokens $j i val$, where $j$ is the name of a variable (here, we have variables \texttt{x0,x1}), $i$ is the name of a constraint or the objective function, and $val$ is the value $A_{ij}$ (if $i$ names a constraint), or $c_j$ (if $i$ names the -linear objective function). Values that are not specified in this -section default to $0$. +linear objective function). Values for pairs $(i,j)$ that are not +specified in this section default to $0$. Otherwise, for every pair +$(i,j)$, the \emph{last} specified value determines $A_{ij}$ or $c_j$. \section*{RHS section} This (mandatory) section encodes the right-hand side vector $b$ and @@ -86,10 +87,13 @@ encode several right-hand sides $b$ by using several such identifiers, but we ignore all lines having an identifier different from that of the first line. -The second token $i$ in every line names a constraint or the linear -objective function, and the third token $val$ is the value $b_i$ (if +The right-hand side identifier is succeeded by one or two sequences +of tokens $i val$, where $i$ names a constraint or the linear +objective function, and $val$ specifies the value $b_i$ (if $i$ names a constraint), or $-c_0$ (if $i$ names the linear objective function). Values that are not specified in this section default to $0$. +Otherwise, for every $i$, the \emph{last} specified value determines +$b_{i}$ or $-c_0$. \section*{BOUNDS section} This (optional) section encodes the lower and upper bound vectors $l$ @@ -114,7 +118,7 @@ they are processed in order of appearance. \begin{tabular}{l|l} bound type & resulting bound \\ \hline -FX & $x_j \leq val$ (lower bound remains unchanged) \\ +FX & $x_j = val$ ($x_j$ becomes a fixed variable) \\ LO & $x_j \geq val$ (upper bound remains unchanged) \\ UP & $x_j \leq val$ (lower bound remains unchanged, except if $val<0$; then, a zero lower bound is reset to $-\infty$)\\ @@ -133,16 +137,17 @@ or \texttt{QUADOBJ}), or $D_{ij}$ (in case of \texttt{DMATRIX}). In case of \texttt{QMATRIX} and \texttt{DMATRIX}, \emph{all} nonzero entries must be specified: if there is a line $i j val$, then there must also be a line $j i val$, since $D$ is required to be symmetric. -In case of \texttt{QUADOBJ}, only the entries of $2D$ on or below the -diagonal must be specified, and the entries above the diagonal are -deduced from symmetry. +In case of \texttt{QUADOBJ}, only the entries of $2D$ on or below the +diagonal must be specified, entries above the diagonal are deduced from +symmetry. It is not allowed to specify two or more \emph{different} +nonzero values for an unordered pair $\{i,j\}$. -If this seftion is missing or does not contain nonzero values, the +If this section is missing or does not contain nonzero values, the program is a model of the concept \ccc{LinearProgramInterface}. \section*{Miscellaneous} Our MPS format also supports an (optional) \texttt{RANGES} section, -but we won't explain this here. +but we don't explain this here. \end{ccRefConcept} diff --git a/QP_solver/doc_tex/QP_solver_ref/NonnegativeLinearProgramInterface.tex b/QP_solver/doc_tex/QP_solver_ref/NonnegativeLinearProgramInterface.tex index 3e3fe34e905..231c808bd35 100644 --- a/QP_solver/doc_tex/QP_solver_ref/NonnegativeLinearProgramInterface.tex +++ b/QP_solver/doc_tex/QP_solver_ref/NonnegativeLinearProgramInterface.tex @@ -4,9 +4,9 @@ A model of \ccRefName\ describes a linear program of the form %% \begin{eqnarray*} -\mbox{(QP)}& \mbox{minimize} & c^{T}x+c_0 \\ +\mbox{(LP)}& \mbox{minimize} & c^{T}x+c_0 \\ &\mbox{subject to} & Ax\qprel b, \\ -& & x\geq \mathbf{0} +& & x\geq 0 \end{eqnarray*} %% in $n$ real variables $x=(x_0,\ldots,x_{n-1})$. @@ -21,11 +21,15 @@ from $\{\leq, =, \geq\}$, \item $c_0$ is a constant. \end{itemize} +The description is given by appropriate \emph{random-access} +iterators over the program data, see below. The program therefore +comes in \emph{dense} representation which includes zero entries. + \ccHasModels +\ccc{CGAL::Nonnegative_linear_program}\\ \ccc{CGAL::Nonnegative_linear_program_from_iterators}\\ \ccc{CGAL::Nonnegative_linear_program_from_pointers}\\ -\ccc{CGAL::Nonnegative_linear_program}\\ -\ccc{CGAL::Linear_program_from_mps}\\ +\ccc{CGAL::Nonnegative_linear_program_from_mps}\\ \ccTypes @@ -48,36 +52,38 @@ from $\{\leq, =, \geq\}$, \ccCreationVariable{qp} -\ccMethod{int n() const;}{returns the number $n$ of variables (number +\ccMethod{int get_n() const;}{returns the number $n$ of variables (number of columns of $A$) in \ccVar.} -\ccMethod{int m() const;}{returns the number $m$ of constraints +\ccMethod{int get_m() const;}{returns the number $m$ of constraints (number of rows of $A$) in \ccVar.} -\ccMethod{const A_iterator& a() const;}{returns an iterator over the columns +\ccMethod{A_iterator get_a() const;}{returns an iterator over the columns of $A$. For $j=0,\ldots,n-1$, $\ccc{*(a()+j)}$ is a random access iterator for column $j$.} -\ccMethod{const B_iterator& b() const;}{returns an iterator over the entries +\ccMethod{B_iterator get_b() const;}{returns an iterator over the entries of $b$.} -\ccMethod{const R_iterator& r() const;}{returns an iterator over the entries +\ccMethod{R_iterator get_r() const;}{returns an iterator over the entries of $\qprel$. The value \ccc{CGAL::SMALLER} stands for $\leq$, \ccc{CGAL::EQUAL} stands for $=$, and \ccc{CGAL::LARGER} stands for $\geq$.} -\ccMethod{const C_iterator& c() const;}{returns an iterator over the entries +\ccMethod{C_iterator get_c() const;}{returns an iterator over the entries of $c$.} -\ccMethod{const std::iterator_traits::value_type& c0() const;}{returns the constant - term $c_0$ of the objective function.} +\ccMethod{std::iterator_traits::value_type get_c0() const;} +{returns the constant term $c_0$ of the objective function.} \ccRequirements The value types of all iterator types (nested iterator types, -respectively, for \ccc{A_iterator} and \ccc{D_iterator}) must be -convertible to some common \ccc{IntegralDomain} \ccc{ET}. +respectively, for \ccc{A_iterator}) must be convertible to some common +\ccc{IntegralDomain} \ccc{ET}. \ccSeeAlso - +\ccc{QuadraticProgramInterface}\\ +\ccc{LinearProgramInterface}\\ +\ccc{NonnegativeQuadraticProgramInterface} \end{ccRefConcept} diff --git a/QP_solver/doc_tex/QP_solver_ref/NonnegativeQuadraticProgramInterface.tex b/QP_solver/doc_tex/QP_solver_ref/NonnegativeQuadraticProgramInterface.tex index 97d332d242a..9c751f33015 100644 --- a/QP_solver/doc_tex/QP_solver_ref/NonnegativeQuadraticProgramInterface.tex +++ b/QP_solver/doc_tex/QP_solver_ref/NonnegativeQuadraticProgramInterface.tex @@ -6,7 +6,7 @@ A model of \ccRefName\ describes a convex quadratic program of the form \begin{eqnarray*} \mbox{(QP)}& \mbox{minimize} & x^{T}Dx+c^{T}x+c_0 \\ &\mbox{subject to} & Ax\qprel b, \\ -& & x\geq \mathbf{0} +& & x\geq 0 \end{eqnarray*} %% in $n$ real variables $x=(x_0,\ldots,x_{n-1})$. @@ -23,11 +23,15 @@ from $\{\leq, =, \geq\}$, \item $c_0$ is a constant. \end{itemize} +The description is given by appropriate \emph{random-access} +iterators over the program data, see below. The program therefore +comes in \emph{dense} representation which includes zero entries. + \ccHasModels +\ccc{CGAL::Nonnegative_quadratic_program}\\ \ccc{CGAL::Nonnegative_quadratic_program_from_iterators}\\ \ccc{CGAL::Nonnegative_quadratic_program_from_pointers}\\ -\ccc{CGAL::Nonnegative_quadratic_program}\\ -\ccc{CGAL::Quadratic_program_from_mps}\\ +\ccc{CGAL::Nonnegative_quadratic_program_from_mps}\\ \ccTypes @@ -56,32 +60,32 @@ from $\{\leq, =, \geq\}$, \ccCreationVariable{qp} -\ccMethod{int n() const;}{returns the number $n$ of variables (number +\ccMethod{int get_n() const;}{returns the number $n$ of variables (number of columns of $A$) in \ccVar.} -\ccMethod{int m() const;}{returns the number $m$ of constraints +\ccMethod{int get_m() const;}{returns the number $m$ of constraints (number of rows of $A$) in \ccVar.} -\ccMethod{const A_iterator& a() const;}{returns an iterator over the columns +\ccMethod{A_iterator get_a() const;}{returns an iterator over the columns of $A$. For $j=0,\ldots,n-1$, $\ccc{*(a()+j)}$ is a random access iterator for column $j$.} -\ccMethod{const B_iterator& b() const;}{returns an iterator over the entries +\ccMethod{B_iterator get_b() const;}{returns an iterator over the entries of $b$.} -\ccMethod{const R_iterator& r() const;}{returns an iterator over the entries +\ccMethod{R_iterator get_r() const;}{returns an iterator over the entries of $\qprel$. The value \ccc{CGAL::SMALLER} stands for $\leq$, \ccc{CGAL::EQUAL} stands for $=$, and \ccc{CGAL::LARGER} stands for $\geq$.} -\ccMethod{const D_iterator& d() const;}{returns an iterator for the rows of +\ccMethod{D_iterator get_d() const;}{returns an iterator for the rows of $2D$. For $i=0,\ldots,n-1$, $\ccc{*(d()+i)}$ is a random access iterator for the entries in row $i$ below or on the diagonal.} -\ccMethod{const C_iterator& c() const;}{returns an iterator over the entries +\ccMethod{C_iterator get_c() const;}{returns an iterator over the entries of $c$.} -\ccMethod{const std::iterator_traits::value_type& c0() const;}{returns the constant +\ccMethod{std::iterator_traits::value_type c0() const;}{returns the constant term $c_0$ of the objective function.} \ccRequirements @@ -91,5 +95,7 @@ respectively, for \ccc{A_iterator} and \ccc{D_iterator}) must be convertible to some common \ccc{IntegralDomain} \ccc{ET}. \ccSeeAlso - +\ccc{QuadraticProgramInterface}\\ +\ccc{LinearProgramInterface}\\ +\ccc{NonnegativeLinearProgramInterface} \end{ccRefConcept} diff --git a/QP_solver/doc_tex/QP_solver_ref/Nonnegative_linear_program.tex b/QP_solver/doc_tex/QP_solver_ref/Nonnegative_linear_program.tex index fbe17ea02dd..f07a58ff4d9 100644 --- a/QP_solver/doc_tex/QP_solver_ref/Nonnegative_linear_program.tex +++ b/QP_solver/doc_tex/QP_solver_ref/Nonnegative_linear_program.tex @@ -6,9 +6,9 @@ An object of class \ccRefName\ describes a linear program of the form %% \begin{eqnarray*} -\mbox{(QP)}& \mbox{minimize} & c^{T}x+c_0 \\ +\mbox{(LP)}& \mbox{minimize} & c^{T}x+c_0 \\ &\mbox{subject to} & Ax\qprel b, \\ -& & x \geq \mathbf{0} +& & x \geq 0 \end{eqnarray*} %% in $n$ real variables $x=(x_0,\ldots,x_{n-1})$. @@ -23,31 +23,59 @@ from $\{\leq, =, \geq\}$, \item $c_0$ is a constant. \end{itemize} -This class copies the program data from given iterator ranges; -if you only need to wrap existing iterators, you may use the classes -\ccc{Nonnegative_linear_program_from_iterators} and \ccc{Nonnegative_linear_program_from_pointers}). +This class allows you to build your program entry by entry, using +the set-methods below. If you only need to wrap existing (random-access) +iterators, then you may use the classes +\ccc{Nonnegative_linear_program_from_iterators} and \ccc{Nonnegative_linear_program_from_pointers}). +If you want to read a nonnegative linear program in \ccc{MPSFormat} from a +file, please use the model \ccc{Nonnegative_linear_program_from_mps}. \ccIsModel \ccc{NonnegativeLinearProgramInterface} +\ccTypes + +\ccNestedType{NT}{The number type of the program entries.} + \ccCreation \ccIndexClassCreation \ccCreationVariable{lp} -The following constructor is a template, so you can provide input -iterators of any types. +\ccConstructor{ +Nonnegative_linear_program(CGAL::Comparison_result default_r = CGAL::EQUAL);} +{constructs a nonnegative +linear program with no variables and no constraints, ready +for data to be added. Unless relations are explicitly set, +relations will be of type \ccc{default_r}. +Numerical entries that are not explicitly set will default to $0$.} -\ccConstructor{template - Nonnegative_linear_program(int n, int m, - const A_it& a, - const B_it& b, - const R_it& r, - const C_it& c, - const std::iterator_traitsvalue_type& c0 = 0 - )}{constructs \ccVar\ from given input iterators and the constant \ccc{c0}. The passed iterators are merely stored, no copying of the program data takes place. } +\ccOperations + +\ccCreationVariable{lp} + +\ccMethod{bool is_linear() const;}{returns \ccc{true}.} + +\ccMethod{bool is_nonnegative() const;}{returns \ccc{true}.} + +\ccMethod{void set_a (int j, int i, const NT& val);}{sets the entry $A_{ij}$ +in column $j$ and row $i$ of the constraint matrix $A$ of \ccVar\ to +\ccc{val}. An existing entry is overwritten. \ccVar\ is enlarged if +necessary to accomodate this entry.} + +\ccMethod{void set_b (int i, const NT& val);}{sets the entry $b_i$ +of \ccVar\ to \ccc{val}. An existing entry is overwritten. +\ccVar\ is enlarged if necessary to accomodate this entry.} + +\ccMethod{void set_c (int j, const NT& val);}{sets the entry $c_j$ +of \ccVar\ to \ccc{val}. An existing entry is overwritten. +\ccVar\ is enlarged if necessary to accomodate this entry.} + +\ccMethod{void set_c0 (const NT& val);}{sets the entry $c_0$ +of \ccVar\ to \ccc{val}. An existing entry is overwritten.} \ccSeeAlso -\ccc{Nonnegative_linear_program_from_iterators}\\ -\ccc{Nonnegative_linear_program_from_pointers} +\ccc{Nonnegative_linear_program_from_iterators}\\ +\ccc{Nonnegative_linear_program_from_pointers}\\ +\ccc{Nonnegative_linear_program_from_mps} \end{ccRefClass} diff --git a/QP_solver/doc_tex/QP_solver_ref/Nonnegative_linear_program_from_iterators.tex b/QP_solver/doc_tex/QP_solver_ref/Nonnegative_linear_program_from_iterators.tex index 95e50e2c2ef..dbd0377320d 100644 --- a/QP_solver/doc_tex/QP_solver_ref/Nonnegative_linear_program_from_iterators.tex +++ b/QP_solver/doc_tex/QP_solver_ref/Nonnegative_linear_program_from_iterators.tex @@ -6,9 +6,9 @@ An object of class \ccRefName\ describes a linear program of the form %% \begin{eqnarray*} -\mbox{(QP)}& \mbox{minimize} & c^{T}x+c_0 \\ +\mbox{(LP)}& \mbox{minimize} & c^{T}x+c_0 \\ &\mbox{subject to} & Ax\qprel b, \\ -& & x \geq \mathbf{0} +& & x \geq 0 \end{eqnarray*} %% in $n$ real variables $x=(x_0,\ldots,x_{n-1})$. @@ -44,7 +44,7 @@ copy the program data (if you need a copy, you may use the class )}{constructs \ccVar\ from given random-access iterators and the constant \ccc{c0}. The passed iterators are merely stored, no copying of the program data takes place. } \ccSeeAlso +\ccc{Nonnegative_linear_program}\\ \ccc{Nonnegative_linear_program_from_pointers}\\ -\ccc{Nonnegative_linear_program} - +\ccc{Nonnegative_linear_program_from_mps} \end{ccRefClass} diff --git a/QP_solver/doc_tex/QP_solver_ref/Nonnegative_linear_program_from_mps.tex b/QP_solver/doc_tex/QP_solver_ref/Nonnegative_linear_program_from_mps.tex new file mode 100644 index 00000000000..7bfe278a474 --- /dev/null +++ b/QP_solver/doc_tex/QP_solver_ref/Nonnegative_linear_program_from_mps.tex @@ -0,0 +1,84 @@ +\begin{ccRefClass}{Nonnegative_linear_program_from_mps} + +\ccInclude{CGAL/QP_models.h} + +\ccDefinition +An object of class \ccRefName\ describes a linear program of the form +%% +\begin{eqnarray*} +\mbox{(LP)}& \mbox{minimize} & c^{T}x+c_0 \\ +&\mbox{subject to} & Ax\qprel b, \\ +& & x \geq 0 +\end{eqnarray*} +%% +in $n$ real variables $x=(x_0,\ldots,x_{n-1})$. +Here, +\begin{itemize} +\item $A$ is an $m\times n$ matrix (the constraint matrix), +\item $b$ is an $m$-dimensional vector (the right-hand side), +\item $\qprel$ is an $m$-dimensional vector of relations +from $\{\leq, =, \geq\}$, +\item $c$ is an $n$-dimensional vector (the linear objective + function), and +\item $c_0$ is a constant. +\end{itemize} + +The program data are read from an input stream in \ccc{MPSFormat}. This is +a commonly used format for encoding linear and quadratic programs that +is understood by many solvers. All values are expected to be readable +into type \ccc{NT}. The constructed program can be further manipulated +by using the set-methods below. + +\ccIsModel +\ccc{NonnegativeLinearProgramInterface} + +\ccTypes +\ccNestedType{NT}{The number type of the program entries.} + +\ccCreation +\ccIndexClassCreation +\ccCreationVariable{lp} + +\ccConstructor{Nonnegative_linear_program_from_mps(std::istream& in)} +{reads \ccVar\ from the input stream \ccc{in}.} + +\ccOperations + +\ccMethod{bool is_valid() const;}{returns \ccc{true} if and only if an +MPS-encoded nonnegative linear program could be extracted from the input +stream.} + +\ccMethod{const std::string& get_name_of_variable (int j) const;} +{returns the name of the $j$-th variable.} + +\ccMethod{bool is_linear() const;}{returns \ccc{true}.} + +\ccMethod{bool is_nonnegative() const;}{returns \ccc{true}.} + +\ccMethod{const std::string& get_error() const;}{if !\ccVar\ccc{.is_valid()}, +this method returns an error message explaining why the input does not +conform to the \ccc{MPSFormat}.} + +\ccMethod{void set_a (int j, int i, const NT& val);}{sets the entry $A_{ij}$ +in column $j$ and row $i$ of the constraint matrix $A$ of \ccVar\ to +\ccc{val}. An existing entry is overwritten. \ccVar\ is enlarged if +necessary to accomodate this entry.} + +\ccMethod{void set_b (int i, const NT& val);}{sets the entry $b_i$ +of \ccVar\ to \ccc{val}. An existing entry is overwritten. +\ccVar\ is enlarged if necessary to accomodate this entry.} + +\ccMethod{void set_c (int j, const NT& val);}{sets the entry $c_j$ +of \ccVar\ to \ccc{val}. An existing entry is overwritten. +\ccVar\ is enlarged if necessary to accomodate this entry.} + +\ccMethod{void set_c0 (const NT& val);}{sets the entry $c_0$ +of \ccVar\ to \ccc{val}. An existing entry is overwritten.} + +\ccSeeAlso +\ccc{Nonnegative_linear_program}\\ +\ccc{Nonnegative_linear_program_from_iterators}\\ +\ccc{Nonnegative_linear_program_from_pointers} + + +\end{ccRefClass} diff --git a/QP_solver/doc_tex/QP_solver_ref/Nonnegative_linear_program_from_pointers.tex b/QP_solver/doc_tex/QP_solver_ref/Nonnegative_linear_program_from_pointers.tex index 96a8873893e..0d6359325e4 100644 --- a/QP_solver/doc_tex/QP_solver_ref/Nonnegative_linear_program_from_pointers.tex +++ b/QP_solver/doc_tex/QP_solver_ref/Nonnegative_linear_program_from_pointers.tex @@ -6,9 +6,9 @@ An object of class \ccRefName\ describes a linear program of the form %% \begin{eqnarray*} -\mbox{(QP)}& \mbox{minimize} & c^{T}x+c_0 \\ +\mbox{(LP)}& \mbox{minimize} & c^{T}x+c_0 \\ &\mbox{subject to} & Ax\qprel b, \\ -& & x \geq \mathbf{0} +& & x \geq 0 \end{eqnarray*} %% in $n$ real variables $x=(x_0,\ldots,x_{n-1})$. @@ -34,8 +34,12 @@ a copy, you may use the class \ccc{Nonnegative_linear_program}). \ccIsModel \ccc{NonnegativeLinearProgramInterface} +\ccTypes +\ccNestedType{NT}{The number type of the program entries.} + \ccSeeAlso +\ccc{Nonnegative_linear_program}\\ \ccc{Nonnegative_linear_program_from_iterators}\\ -\ccc{Nonnegative_linear_program} +\ccc{Nonnegative_linear_program_from_mps} \end{ccRefClass} diff --git a/QP_solver/doc_tex/QP_solver_ref/Nonnegative_quadratic_program.tex b/QP_solver/doc_tex/QP_solver_ref/Nonnegative_quadratic_program.tex index 6d41fda6a4e..640810965b7 100644 --- a/QP_solver/doc_tex/QP_solver_ref/Nonnegative_quadratic_program.tex +++ b/QP_solver/doc_tex/QP_solver_ref/Nonnegative_quadratic_program.tex @@ -8,7 +8,7 @@ An object of class \ccRefName\ describes a convex quadratic program of the form \begin{eqnarray*} \mbox{(QP)}& \mbox{minimize} & x^{T}Dx+c^{T}x+c_0 \\ &\mbox{subject to} & Ax\qprel b, \\ -& & x \geq \mathbf{0} +& & x \geq 0 \end{eqnarray*} %% in $n$ real variables $x=(x_0,\ldots,x_{n-1})$. @@ -25,33 +25,65 @@ from $\{\leq, =, \geq\}$, \item $c_0$ is a constant. \end{itemize} -This class copies the program data from given iterator ranges; -if you only need to wrap existing iterators, you may use the classes -\ccc{Nonnegative_quadratic_program_from_iterators} and \ccc{Nonnegative_quadratic_program_from_pointers}). +This class allows you to build your program entry by entry, using +the set-methods below. If you only need to wrap existing (random-access) +iterators, then you may use the classes +\ccc{Nonnegative_quadratic_program_from_iterators} and \ccc{Nonnegative_quadratic_program_from_pointers}). If you want +to read a quadratic program in \ccc{MPSFormat} from a file, please use +the model \ccc{Nonnegative_quadratic_program_from_mps}. \ccIsModel \ccc{NonnegativeQuadraticProgramInterface} +\ccTypes + +\ccNestedType{NT}{The number type of the program entries.} + \ccCreation \ccIndexClassCreation \ccCreationVariable{qp} -The following constructor is a template, so you can provide input -iterators of any types. +\ccConstructor{ + Nonnegative_quadratic_program(CGAL::Comparison_result default_r = +CGAL::EQUAL);} +{constructs a nonnegative quadratic program with no variables and no +constraints, ready for data to be added. Unless relations are explicitly set, +relations will be of type \ccc{default_r}. Numerical entries that are not +explicitly set will default to $0$.} + +\ccOperations + +\ccCreationVariable{qp} + +\ccMethod{bool is_linear() const;}{returns \ccc{true} iff the +objective function matrix of \ccVar\ satisfies $D=0$.} + +\ccMethod{bool is_nonnegative() const;}{returns \ccc{true}.} + +\ccMethod{void set_a (int j, int i, const NT& val);}{sets the entry $A_{ij}$ +in column $j$ and row $i$ of the constraint matrix $A$ of \ccVar\ to +\ccc{val}. An existing entry is overwritten. \ccVar\ is enlarged if +necessary to accomodate this entry.} + +\ccMethod{void set_b (int i, const NT& val);}{sets the entry $b_i$ +of \ccVar\ to \ccc{val}. An existing entry is overwritten. +\ccVar\ is enlarged if necessary to accomodate this entry.} + +\ccMethod{void set_c (int j, const NT& val);}{sets the entry $c_j$ +of \ccVar\ to \ccc{val}. An existing entry is overwritten. +\ccVar\ is enlarged if necessary to accomodate this entry.} + +\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.} -\ccConstructor{template - Nonnegative_quadratic_program(int n, int m, - const A_it& a, - const B_it& b, - const R_it& r, - const D_it& d, - const C_it& c, - const std::iterator_traitsvalue_type& c0 = 0 - )}{constructs \ccVar\ from given input iterators and the constant \ccc{c0}. } \ccSeeAlso \ccc{Nonnegative_quadratic_program_from_iterators}\\ -\ccc{Nonnegative_quadratic_program_from_pointers} - +\ccc{Nonnegative_quadratic_program_from_pointers}\\ +\ccc{Nonnegative_quadratic_program_from_mps} \end{ccRefClass} diff --git a/QP_solver/doc_tex/QP_solver_ref/Nonnegative_quadratic_program_from_iterators.tex b/QP_solver/doc_tex/QP_solver_ref/Nonnegative_quadratic_program_from_iterators.tex index 44d09f01c90..7f50be85380 100644 --- a/QP_solver/doc_tex/QP_solver_ref/Nonnegative_quadratic_program_from_iterators.tex +++ b/QP_solver/doc_tex/QP_solver_ref/Nonnegative_quadratic_program_from_iterators.tex @@ -8,7 +8,7 @@ An object of class \ccRefName\ describes a convex quadratic program of the form \begin{eqnarray*} \mbox{(QP)}& \mbox{minimize} & x^{T}Dx+c^{T}x+c_0 \\ &\mbox{subject to} & Ax\qprel b, \\ -& & x \geq \mathbf{0} +& & x \geq 0 \end{eqnarray*} %% in $n$ real variables $x=(x_0,\ldots,x_{n-1})$. @@ -47,7 +47,7 @@ copy the program data (if you need a copy, you may use the class )}{constructs \ccVar\ from given random-access iterators and the constant \ccc{c0}. The passed iterators are merely stored, no copying of the program data takes place. } \ccSeeAlso +\ccc{Nonnegative_quadratic_program}\\ \ccc{Nonnegative_quadratic_program_from_pointers}\\ -\ccc{Nonnegative_quadratic_program} - +\ccc{Nonnegative_quadratic_program_from_mps} \end{ccRefClass} diff --git a/QP_solver/doc_tex/QP_solver_ref/Nonnegative_quadratic_program_from_mps.tex b/QP_solver/doc_tex/QP_solver_ref/Nonnegative_quadratic_program_from_mps.tex new file mode 100644 index 00000000000..8ef92593c6d --- /dev/null +++ b/QP_solver/doc_tex/QP_solver_ref/Nonnegative_quadratic_program_from_mps.tex @@ -0,0 +1,90 @@ +\begin{ccRefClass}{Nonnegative_quadratic_program_from_mps} + +\ccInclude{CGAL/QP_models.h} + +\ccDefinition +An object of class \ccRefName\ describes a convex quadratic program of the form +%% +\begin{eqnarray*} +\mbox{(QP)}& \mbox{minimize} & x^{T}Dx+c^{T}x+c_0 \\ +&\mbox{subject to} & Ax\qprel b, \\ +& & x \geq 0 +\end{eqnarray*} +%% +in $n$ real variables $x=(x_0,\ldots,x_{n-1})$. +Here, +\begin{itemize} +\item $A$ is an $m\times n$ matrix (the constraint matrix), +\item $b$ is an $m$-dimensional vector (the right-hand side), +\item $\qprel$ is an $m$-dimensional vector of relations +from $\{\leq, =, \geq\}$, +\item $D$ is a symmetric positive-semidefinite $n\times n$ matrix (the + quadratic objective function), +\item $c$ is an $n$-dimensional vector (the linear objective + function), and +\item $c_0$ is a constant. +\end{itemize} + +The program data are read from an input stream in \ccc{MPSFormat}. This is +a commonly used format for encoding linear and quadratic programs that +is understood by many solvers. All values are expected to be readable +into type \ccc{NT}. The constructed program can be further manipulated +by using the set-methods below. + +\ccIsModel +\ccc{NonnegativeQuadraticProgramInterface} + +\ccTypes +\ccNestedType{NT}{The number type of the program entries.} + +\ccCreation +\ccIndexClassCreation +\ccCreationVariable{qp} + +\ccConstructor{Nonnegative_quadratic_program_from_mps(std::istream& in)} +{reads \ccVar\ from the input stream \ccc{in}.} + +\ccOperations + +\ccMethod{bool is_valid() const;}{returns \ccc{true} if and only if an +MPS-encoded nonnegative +quadratic program could be extracted from the input stream.} + +\ccMethod{const std::string& get_name_of_variable (int j) const;} +{returns the name of the $j$-th variable.} + +\ccMethod{bool is_linear() const;}{returns \ccc{true} if and only if the quadratic program read into \ccVar\ is a linear program.} + +\ccMethod{bool is_nonnegative() const;}{returns \ccc{true}.} + +\ccMethod{const std::string& get_error() const;}{if !\ccVar\ccc{.is_valid()}, +this method returns an error message explaining why the input does not +conform to the \ccc{MPSFormat}.} + +\ccMethod{void set_a (int j, int i, const NT& val);}{sets the entry $A_{ij}$ +in column $j$ and row $i$ of the constraint matrix $A$ of \ccVar\ to +\ccc{val}. An existing entry is overwritten. \ccVar\ is enlarged if +necessary to accomodate this entry.} + +\ccMethod{void set_b (int i, const NT& val);}{sets the entry $b_i$ +of \ccVar\ to \ccc{val}. An existing entry is overwritten. +\ccVar\ is enlarged if necessary to accomodate this entry.} + +\ccMethod{void set_c (int j, const NT& val);}{sets the entry $c_j$ +of \ccVar\ to \ccc{val}. An existing entry is overwritten. +\ccVar\ is enlarged if necessary to accomodate this entry.} + +\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.} + +\ccSeeAlso +\ccc{Nonnegative_quadratic_program}\\ +\ccc{Nonnegative_quadratic_program_from_iterators}\\ +\ccc{Nonnegative_quadratic_program_from_pointers} + + +\end{ccRefClass} diff --git a/QP_solver/doc_tex/QP_solver_ref/Nonnegative_quadratic_program_from_pointers.tex b/QP_solver/doc_tex/QP_solver_ref/Nonnegative_quadratic_program_from_pointers.tex index f70639cfc22..d9807f005c9 100644 --- a/QP_solver/doc_tex/QP_solver_ref/Nonnegative_quadratic_program_from_pointers.tex +++ b/QP_solver/doc_tex/QP_solver_ref/Nonnegative_quadratic_program_from_pointers.tex @@ -8,7 +8,7 @@ An object of class \ccRefName\ describes a convex quadratic program of the form \begin{eqnarray*} \mbox{(QP)}& \mbox{minimize} & x^{T}Dx+c^{T}x+c_0 \\ &\mbox{subject to} & Ax\qprel b, \\ -& & x \geq \mathbf{0} +& & x \geq 0 \end{eqnarray*} %% in $n$ real variables $x=(x_0,\ldots,x_{n-1})$. @@ -35,8 +35,12 @@ a copy, you may use the class \ccc{Nonnegative_quadratic_program}). \ccIsModel \ccc{NonnegativeQuadraticProgramInterface} +\ccTypes +\ccNestedType{NT}{The number type of the program entries.} + \ccSeeAlso +\ccc{Nonnegative_quadratic_program}\\ \ccc{Nonnegative_quadratic_program_from_iterators}\\ -\ccc{Nonnegative_quadratic_program} +\ccc{Nonnegative_quadratic_program_from_mps} \end{ccRefClass} diff --git a/QP_solver/doc_tex/QP_solver_ref/QuadraticProgramInterface.tex b/QP_solver/doc_tex/QP_solver_ref/QuadraticProgramInterface.tex index 77e1a4b91a0..be9e72b33dc 100644 --- a/QP_solver/doc_tex/QP_solver_ref/QuadraticProgramInterface.tex +++ b/QP_solver/doc_tex/QP_solver_ref/QuadraticProgramInterface.tex @@ -27,13 +27,14 @@ $x$, \item $c_0$ is a constant. \end{itemize} +The description is given by appropriate \emph{random-access} +iterators over the program data, see below. The program therefore +comes in \emph{dense} representation which includes zero entries. + \ccHasModels +\ccc{CGAL::Quadratic_program}\\ \ccc{CGAL::Quadratic_program_from_iterators}\\ \ccc{CGAL::Quadratic_program_from_pointers}\\ -\ccc{CGAL::Quadratic_program}\\ -\ccc{CGAL::Free_quadratic_program_from_iterators}\\ -\ccc{CGAL::Free_quadratic_program_from_pointers}\\ -\ccc{CGAL::Free_quadratic_program}\\ \ccc{CGAL::Quadratic_program_from_mps}\\ \ccTypes @@ -77,51 +78,51 @@ $x$, \ccCreationVariable{qp} -\ccMethod{int n() const;}{returns the number $n$ of variables (number +\ccMethod{int get_n() const;}{returns the number $n$ of variables (number of columns of $A$) in \ccVar.} -\ccMethod{int m() const;}{returns the number $m$ of constraints +\ccMethod{int get_m() const;}{returns the number $m$ of constraints (number of rows of $A$) in \ccVar.} -\ccMethod{const A_iterator& a() const;}{returns an iterator over the columns +\ccMethod{A_iterator get_a() const;}{returns an iterator over the columns of $A$. For $j=0,\ldots,n-1$, $\ccc{*(a()+j)}$ is a random access iterator for column $j$.} -\ccMethod{const B_iterator& b() const;}{returns an iterator over the entries +\ccMethod{B_iterator get_b() const;}{returns an iterator over the entries of $b$.} -\ccMethod{const R_iterator& r() const;}{returns an iterator over the entries +\ccMethod{R_iterator get_r() const;}{returns an iterator over the entries of $\qprel$. The value \ccc{CGAL::SMALLER} stands for $\leq$, \ccc{CGAL::EQUAL} stands for $=$, and \ccc{CGAL::LARGER} stands for $\geq$.} -\ccMethod{const FL_iterator& fl() const;}{returns an iterator over the +\ccMethod{FL_iterator get_fl() const;}{returns an iterator over the existence of the lower bounds $l_j, j=0,\ldots,n-1$. If $\ccVar.\ccc{fl()}[j]=true$, the variable $x_j$ has a lower bound, otherwise it has no lower bound.} -\ccMethod{const L_iterator& l() const;}{returns an iterator for the +\ccMethod{L_iterator get_l() const;}{returns an iterator for the entries of $l$. If $\ccVar.\ccc{fl()}[j]=\ccc{false}$, the value $\ccVar.\ccc{l()}[j]$ is not accessed.} -\ccMethod{const FU_iterator& fu() const;}{returns an iterator over the +\ccMethod{FU_iterator get_fu() const;}{returns an iterator over the existence of the upper bounds $u_j, j=0,\ldots,n-1$. If $\ccVar.\ccc{fu()}[j]=true$, the variable $x_j$ has an upper bound, otherwise it has no upper bound.} -\ccMethod{const U_iterator& u() const;}{returns an iterator over the +\ccMethod{U_iterator get_u() const;}{returns an iterator over the entries of $u$. If $\ccVar.\ccc{fu()}[j]=\ccc{false}$, the value $\ccVar.\ccc{u()}[j]$ is not accessed.} -\ccMethod{const D_iterator& d() const;}{returns an iterator for the rows of +\ccMethod{D_iterator get_d() const;}{returns an iterator for the rows of $2D$. For $i=0,\ldots,n-1$, $\ccc{*(d()+i)}$ is a random access iterator for the entries in row $i$ below or on the diagonal.} -\ccMethod{const C_iterator& c() const;}{returns an iterator over the entries +\ccMethod{C_iterator get_c() const;}{returns an iterator over the entries of $c$.} -\ccMethod{const std::iterator_traits::value_type& c0() const;}{returns the constant - term $c_0$ of the objective function.} +\ccMethod{std::iterator_traits::value_type c0() const;} +{returns the constant term $c_0$ of the objective function.} \ccRequirements @@ -130,5 +131,7 @@ respectively, for \ccc{A_iterator} and \ccc{D_iterator}) must be convertible to some common \ccc{IntegralDomain} \ccc{ET}. \ccSeeAlso - +\ccc{NonnegativeQuadraticProgramInterface}\\ +\ccc{LinearProgramInterface}\\ +\ccc{NonnegativeLinearProgramInterface} \end{ccRefConcept} diff --git a/QP_solver/doc_tex/QP_solver_ref/Quadratic_program.tex b/QP_solver/doc_tex/QP_solver_ref/Quadratic_program.tex index cd83cb70d0f..b1cd8076764 100644 --- a/QP_solver/doc_tex/QP_solver_ref/Quadratic_program.tex +++ b/QP_solver/doc_tex/QP_solver_ref/Quadratic_program.tex @@ -29,41 +29,77 @@ $x$, \item $c_0$ is a constant. \end{itemize} -This class copies the program data from given iterator ranges;this -is useful if the iterators that you have are not random-access. -The time taken to copy the data is $\Theta(nm+n^2)$, though, even if the -program description is very sparse. Usually, -you only need to wrap existing (random-access) -iterators, and then you may use the classes -\ccc{Quadratic_program_from_iterators} and \ccc{Quadratic_program_from_pointers}). +This class allows you to build your program entry by entry, using +the set-methods below. If you only need to wrap existing (random-access) +iterators, then you may use the classes +\ccc{Quadratic_program_from_iterators} and \ccc{Quadratic_program_from_pointers}). If you want +to read a quadratic program in \ccc{MPSFormat} from a file, please use +the model \ccc{Quadratic_program_from_mps}. \ccIsModel \ccc{QuadraticProgramInterface} +\ccTypes + +\ccNestedType{NT}{The number type of the program entries.} + \ccCreation \ccIndexClassCreation \ccCreationVariable{qp} -The following constructor is a template, so you can provide input -iterators of any types. +\ccConstructor{ + Quadratic_program(CGAL::Comparison_result default_r = CGAL::EQUAL);} +{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$.} + +\ccOperations + +\ccCreationVariable{qp} + +\ccMethod{bool is_linear() const;}{returns \ccc{true} iff the +objective function matrix of \ccVar\ satisfies $D=0$.} + +\ccMethod{bool is_nonnegative() const;}{returns \ccc{true} iff +the bounds of \ccVar\ are $x\geq 0$.} + +\ccMethod{void set_a (int j, int i, const NT& val);}{sets the entry $A_{ij}$ +in column $j$ and row $i$ of the constraint matrix $A$ of \ccVar\ to +\ccc{val}. An existing entry is overwritten. \ccVar\ is enlarged if +necessary to accomodate this entry.} + +\ccMethod{void set_b (int i, const NT& val);}{sets the entry $b_i$ +of \ccVar\ to \ccc{val}. An existing entry is overwritten. +\ccVar\ is enlarged if necessary to accomodate this entry.} + +\ccMethod{void set_l (int j, bool is_finite, const NT& val = NT(0));} +{if \ccc{is_finite}, this sets the entry $l_j$ of \ccVar\ to \ccc{val}, +otherwise it sets $l_j$ to $-\infty$. An existing entry is overwritten. +\ccVar\ is enlarged if necessary to accomodate this entry.} + +\ccMethod{void set_u (int j, bool is_finite, const NT& val = NT(0));} +{if \ccc{is_finite}, this sets the entry $u_j$ of \ccVar\ to \ccc{val}, +otherwise it sets $u_j$ to $\infty$. An existing entry is overwritten. +\ccVar\ is enlarged if necessary to accomodate this entry.} + +\ccMethod{void set_c (int j, const NT& val);}{sets the entry $c_j$ +of \ccVar\ to \ccc{val}. An existing entry is overwritten. +\ccVar\ is enlarged if necessary to accomodate this entry.} + +\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.} -\ccConstructor{template - Quadratic_program(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, - const std::iterator_traitsvalue_type& c0 = 0 - )}{constructs \ccVar\ from given input iterators and the constant \ccc{c0}.} \ccSeeAlso \ccc{Quadratic_program_from_iterators}\\ -\ccc{Quadratic_program_from_pointers} - +\ccc{Quadratic_program_from_pointers}\\ +\ccc{Quadratic_program_from_mps} \end{ccRefClass} diff --git a/QP_solver/doc_tex/QP_solver_ref/Quadratic_program_from_iterators.tex b/QP_solver/doc_tex/QP_solver_ref/Quadratic_program_from_iterators.tex index 34c0262ed97..109fa5f7688 100644 --- a/QP_solver/doc_tex/QP_solver_ref/Quadratic_program_from_iterators.tex +++ b/QP_solver/doc_tex/QP_solver_ref/Quadratic_program_from_iterators.tex @@ -55,7 +55,8 @@ copy the program data (if you need a copy, you may use the class )}{constructs \ccVar\ from given random-access iterators and the constant \ccc{c0}. The passed iterators are merely stored, no copying of the program data takes place. } \ccSeeAlso +\ccc{Quadratic_program}\\ \ccc{Quadratic_program_from_pointers}\\ -\ccc{Quadratic_program} +\ccc{Quadratic_program_from_mps} \end{ccRefClass} diff --git a/QP_solver/doc_tex/QP_solver_ref/Quadratic_program_from_mps.tex b/QP_solver/doc_tex/QP_solver_ref/Quadratic_program_from_mps.tex index 81f084ee14b..bafd6cd3ec9 100644 --- a/QP_solver/doc_tex/QP_solver_ref/Quadratic_program_from_mps.tex +++ b/QP_solver/doc_tex/QP_solver_ref/Quadratic_program_from_mps.tex @@ -32,48 +32,69 @@ $x$, The program data are read from an input stream in \ccc{MPSFormat}. This is a commonly used format for encoding linear and quadratic programs that is understood by many solvers. All values are expected to be readable -into type \ccc{NT}. - -\textbf{Note:} -The space required to store the matrices -$A$ and $D$ is $\Theta(nm + n^2)$, even if these matrices are very sparse. This -might be prohibitive (for example, if there are many variables, but only -few of them are involved in the quadratic objective function). In this -case, you may use the model \ccc{Sparse_quadratic_program_from_mps} -whose space requirements are bounded by the number of nonzero entries -in the program description. In this latter model, access to the iterators -in \ccc{QuadraticProgramInterface} will be a little slower, though. - -As a rule of thumb, however, if there is a need for the sparse model -\emph{because both $m$ and $n$ are large}, then \cgal's quadratic -programming solver will probably not be able to solve it anyway. +into type \ccc{NT}. The constructed program can be further manipulated +by using the set-methods below. \ccIsModel \ccc{QuadraticProgramInterface} +\ccTypes +\ccNestedType{NT}{The number type of the program entries.} + \ccCreation \ccIndexClassCreation \ccCreationVariable{qp} -\ccConstructor{Quadratic_program_from_mps(std::istream& in)} {reads \ccVar\ fromthe input stream \ccc{in}.} +\ccConstructor{Quadratic_program_from_mps(std::istream& in)} +{reads \ccVar\ from the input stream \ccc{in}.} \ccOperations \ccMethod{bool is_valid() const;}{returns \ccc{true} if and only if an -MPS-encoded program could be extracted from the input stream.} +MPS-encoded quadratic program could be extracted from the input stream.} -\ccMethod{const std::string& name_of_variable (int i) const;} {returns the name of the $i$-th variable.\ccPrecond \ccVar\ccc{.is_valid()}} +\ccMethod{const std::string& get_name_of_variable (int j) const;} +{returns the name of the $j$-th variable.} -\ccMethod{bool is_linear() const;}{returns \ccc{true} if and only if the quadratic program read into \ccVar\ is a linear program. -\ccPrecond \ccVar\ccc{.is_valid()}} +\ccMethod{bool is_linear() const;}{returns \ccc{true} if and only if the quadratic program read into \ccVar\ is a linear program.} -\ccMethod{bool is_nonnegative() const;}{returns \ccc{true} if and only if the quadratic program read into \ccVar\ is a nonnegative program -\ccPrecond \ccVar\ccc{.is_valid()}.} +\ccMethod{bool is_nonnegative() const;}{returns \ccc{true} if and only if the quadratic program read into \ccVar\ is a nonnegative program.} -\ccMethod{const std::string& error() const;}{returns an error message explaining why the input is not in MPS format \ccPrecond \ccc{!} \ccVar\ccc{.is_valid()}} +\ccMethod{const std::string& get_error() const;}{if !\ccVar\ccc{.is_valid()}, +this method returns an error message explaining why the input does not +conform to the \ccc{MPSFormat}.} + +\ccMethod{void set_a (int j, int i, const NT& val);}{sets the entry $A_{ij}$ +in column $j$ and row $i$ of the constraint matrix $A$ of \ccVar\ to +\ccc{val}. An existing entry is overwritten. \ccVar\ is enlarged if +necessary to accomodate this entry.} + +\ccMethod{void set_b (int i, const NT& val);}{sets the entry $b_i$ +of \ccVar\ to \ccc{val}. An existing entry is overwritten. +\ccVar\ is enlarged if necessary to accomodate this entry.} + +\ccMethod{void set_l (int j, bool is_finite, const NT& val = NT(0));} +{if \ccc{is_finite}, this sets the entry $l_j$ of \ccVar\ to \ccc{val}, +otherwise it sets $l_j$ to $-\infty$. An existing entry is overwritten. +\ccVar\ is enlarged if necessary to accomodate this entry.} + +\ccMethod{void set_u (int j, bool is_finite, const NT& val = NT(0));} +{if \ccc{is_finite}, this sets the entry $u_j$ of \ccVar\ to \ccc{val}, +otherwise it sets $u_j$ to $\infty$. An existing entry is overwritten. +\ccVar\ is enlarged if necessary to accomodate this entry.} + +\ccMethod{void set_c (int j, const NT& val);}{sets the entry $c_j$ +of \ccVar\ to \ccc{val}. An existing entry is overwritten. +\ccVar\ is enlarged if necessary to accomodate this entry.} + +\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.} \ccSeeAlso -\ccc{Sparse_quadratic_program_from_mps}\\ \ccc{Quadratic_program}\\ \ccc{Quadratic_program_from_iterators}\\ \ccc{Quadratic_program_from_pointers} diff --git a/QP_solver/doc_tex/QP_solver_ref/Quadratic_program_from_pointers.tex b/QP_solver/doc_tex/QP_solver_ref/Quadratic_program_from_pointers.tex index 7adca3203ab..7f71a41d5ec 100644 --- a/QP_solver/doc_tex/QP_solver_ref/Quadratic_program_from_pointers.tex +++ b/QP_solver/doc_tex/QP_solver_ref/Quadratic_program_from_pointers.tex @@ -39,8 +39,13 @@ a copy, you may use the class \ccc{Quadratic_program}). \ccIsModel \ccc{QuadraticProgramInterface} +\ccTypes +\ccNestedType{NT}{The number type of the program entries.} + \ccSeeAlso +\ccc{Quadratic_program}\\ \ccc{Quadratic_program_from_iterators}\\ -\ccc{Quadratic_program} +\ccc{Quadratic_program_from_mps} + \end{ccRefClass} diff --git a/QP_solver/doc_tex/QP_solver_ref/Sparse_linear_program_from_mps.tex b/QP_solver/doc_tex/QP_solver_ref/Sparse_linear_program_from_mps.tex deleted file mode 100644 index 52de2f13685..00000000000 --- a/QP_solver/doc_tex/QP_solver_ref/Sparse_linear_program_from_mps.tex +++ /dev/null @@ -1,73 +0,0 @@ -\begin{ccRefClass}{Sparse_linear_program_from_mps} - -\ccInclude{CGAL/QP_models.h} - -\ccDefinition -An object of class \ccRefName\ describes a linear program of the form -%% -\begin{eqnarray*} -\mbox{(QP)}& \mbox{minimize} & c^{T}x+c_0 \\ -&\mbox{subject to} & Ax\qprel b, \\ -& & l \leq x \leq u -\end{eqnarray*} -%% -in $n$ real variables $x=(x_0,\ldots,x_{n-1})$. -Here, -\begin{itemize} -\item $A$ is an $m\times n$ matrix (the constraint matrix), -\item $b$ is an $m$-dimensional vector (the right-hand side), -\item $\qprel$ is an $m$-dimensional vector of relations -from $\{\leq, =, \geq\}$, -\item $l$ is an $n$-dimensional vector of lower -bounds for $x$, -\item $u$ is an $n$-dimensional vector of upper bounds for -$x$, -\item $c$ is an $n$-dimensional vector (the linear objective - function), and -\item $c_0$ is a constant. -\end{itemize} - -The program data are read from an input stream in \ccc{MPSFormat}. This is -a commonly used format for encoding linear and quadratic programs that -is understood by many solvers. All values are expected to be readable -into type \ccc{NT}. - -\textbf{Note:} -The space requirements are bounded by the number of nonzero entries -in the program description. However, if you can afford space -$\Theta(nm)$, the model \ccc{Linear_program_from_mps} -might be preferrable, since in the latter model, access to the -iterators in \ccc{LinearProgramInterface} will be faster. - -As a rule of thumb, if there is a need for this sparse model, -then \cgal's linear programming solver will probably not be able to -solve it anyway. -\ccIsModel -\ccc{LinearProgramInterface} - -\ccCreation -\ccIndexClassCreation -\ccCreationVariable{lp} - -\ccConstructor{Sparse_linear_program_from_mps(std::istream& in)} {reads \ccVar\ from the input stream \ccc{in}.} - -\ccOperations - -\ccMethod{bool is_valid() const;}{returns \ccc{true} if and only if an -MPS-encoded linear program could be extracted from the input stream.} - -\ccMethod{const std::string& name_of_variable (int i) const;} {returns the name of the $i$-th variable.\ccPrecond \ccVar\ccc{.is_valid()}} - -\ccMethod{bool is_nonnegative() const;}{returns \ccc{true} if and only if the linear program read into \ccVar\ is a nonnegative program -\ccPrecond \ccVar\ccc{.is_valid()}.} - -\ccMethod{const std::string& error() const;}{returns an error message explaining why the input is not in MPS format \ccPrecond \ccc{!} \ccVar\ccc{.is_valid()}} - -\ccSeeAlso -\ccc{Linear_program_from_mps}\\ -\ccc{Linear_program}\\ -\ccc{Linear_program_from_iterators}\\ -\ccc{Linear_program_from_pointers} - - -\end{ccRefClass} diff --git a/QP_solver/doc_tex/QP_solver_ref/Sparse_quadratic_program_from_mps.tex b/QP_solver/doc_tex/QP_solver_ref/Sparse_quadratic_program_from_mps.tex deleted file mode 100644 index dda294a4576..00000000000 --- a/QP_solver/doc_tex/QP_solver_ref/Sparse_quadratic_program_from_mps.tex +++ /dev/null @@ -1,79 +0,0 @@ -\begin{ccRefClass}{Sparse_quadratic_program_from_mps} - -\ccInclude{CGAL/QP_models.h} - -\ccDefinition -An object of class \ccRefName\ describes a convex quadratic program of the form -%% -\begin{eqnarray*} -\mbox{(QP)}& \mbox{minimize} & x^{T}Dx+c^{T}x+c_0 \\ -&\mbox{subject to} & Ax\qprel b, \\ -& & l \leq x \leq u -\end{eqnarray*} -%% -in $n$ real variables $x=(x_0,\ldots,x_{n-1})$. -Here, -\begin{itemize} -\item $A$ is an $m\times n$ matrix (the constraint matrix), -\item $b$ is an $m$-dimensional vector (the right-hand side), -\item $\qprel$ is an $m$-dimensional vector of relations -from $\{\leq, =, \geq\}$, -\item $l$ is an $n$-dimensional vector of lower -bounds for $x$, -\item $u$ is an $n$-dimensional vector of upper bounds for -$x$, -\item $D$ is a symmetric positive-semidefinite $n\times n$ matrix (the - quadratic objective function), -\item $c$ is an $n$-dimensional vector (the linear objective - function), and -\item $c_0$ is a constant. -\end{itemize} - -The program data are read from an input stream in \ccc{MPSFormat}. This is -a commonly used format for encoding linear and quadratic programs that -is understood by many solvers. All values are expected to be readable -into type \ccc{NT}. - -\textbf{Note:} -The space requirements are bounded by the number of nonzero entries -in the program description. However, if you can afford space -$\Theta(nm + n^2)$, the model \ccc{Quadratic_program_from_mps} -might be preferrable, since in the latter model, access to the iterators -in \ccc{QuadraticProgramInterface} will be faster. - -As a rule of thumb, if there is a need for the sparse model -\emph{because both $m$ and $n$ are large}, then \cgal's quadratic -programming solver will probably not be able to solve it anyway. - -\ccIsModel -\ccc{QuadraticProgramInterface} - -\ccCreation -\ccIndexClassCreation -\ccCreationVariable{qp} - -\ccConstructor{Sparse_quadratic_program_from_mps(std::istream& in)} {reads \ccVar\ from the input stream \ccc{in}.} - -\ccOperations - -\ccMethod{bool is_valid() const;}{returns \ccc{true} if and only if an -MPS-encoded program could be extracted from the input stream.} - -\ccMethod{const std::string& name_of_variable (int i) const;} {returns the name of the $i$-th variable.\ccPrecond \ccVar\ccc{.is_valid()}} - -\ccMethod{bool is_linear() const;}{returns \ccc{true} if and only if the quadratic program read into \ccVar\ is a linear program. -\ccPrecond \ccVar\ccc{.is_valid()}} - -\ccMethod{bool is_nonnegative() const;}{returns \ccc{true} if and only if the quadratic program read into \ccVar\ is a nonnegative program -\ccPrecond \ccVar\ccc{.is_valid()}.} - -\ccMethod{const std::string& error() const;}{returns an error message explaining why the input is not in MPS format \ccPrecond \ccc{!} \ccVar\ccc{.is_valid()}} - -\ccSeeAlso -\ccc{Quadratic_program_from_mps}\\ -\ccc{Quadratic_program}\\ -\ccc{Quadratic_program_from_iterators}\\ -\ccc{Quadratic_program_from_pointers} - - -\end{ccRefClass} diff --git a/QP_solver/doc_tex/QP_solver_ref/intro.tex b/QP_solver/doc_tex/QP_solver_ref/intro.tex index 9d088ff2a64..b665ff09cac 100644 --- a/QP_solver/doc_tex/QP_solver_ref/intro.tex +++ b/QP_solver/doc_tex/QP_solver_ref/intro.tex @@ -11,9 +11,9 @@ $\quad$ (for quadratic programs with variable bounds $l\leq x \leq u$) \\ \ccRefConceptPage{LinearProgramInterface} \\ $\quad$(for linear programs with variable bounds $l\leq x \leq u$)\\ \ccRefConceptPage{NonnegativeQuadraticProgramInterface}\\ -$\quad$ (for quadratic programs with variable bounds $x\geq\mathbf{0}$) \\ +$\quad$ (for quadratic programs with variable bounds $x\geq 0$) \\ \ccRefConceptPage{NonnegativeLinearProgramInterface}\\ -$\quad$ (for linear programs with variable bounds $x\geq\mathbf{0}$) +$\quad$ (for linear programs with variable bounds $x\geq 0$) \ccRefConceptPage{MPSFormat}\\ $\quad$ (the format used for reading and writing linear and quadratic @@ -34,74 +34,67 @@ Here are the models that conform to the concept \ccc{QuadraticProgramInterface}. \ccc{Quadratic_program}\\ -$\quad$ (for quadratic programs that copy data from iterator ranges) \\ +$\quad$ (for quadratic programs that own their data and are built entry-wise; probably the most useful model)\\ \ccc{Quadratic_program_from_iterators}\\ $\quad$ (for quadratic programs that wrap given iterators, without copying data) \\ \ccc{Quadratic_program_from_pointers}\\ $\quad$ (for quadratic programs that wrap given pointers, without copying data) \\ -\ccc{Free_quadratic_program}\\ -$\quad$ (for quadratic programs with no variable bounds, copied from iterator ranges)\\ -\ccc{Free_quadratic_program_from_iterators}\\ -$\quad$ (for quadratic programs with no variable bounds, wrapping given iterators)\\ -\ccc{Free_quadratic_program_from_pointers}\\ -$\quad$ (for quadratic programs with no variable bounds, wrapping given pointers)\\ \ccc{Quadratic_program_from_mps}\\ -$\quad$ (for quadratic programs copied from an input stream in -\ccc{MPSFormat})\\ -\ccc{Sparse_quadratic_program_from_mps}\\ -$\quad$ (for sparse quadratic programs copied from an input stream in -\ccc{MPSFormat}) - +$\quad$ (for quadratic programs read from an input stream in +\ccc{MPSFormat}; the constructed program can be manipulate entry-wise) These are the models for \ccc{LinearProgramInterface}. \ccc{Linear_program}\\ -$\quad$ (for linear programs that copy data from iterator ranges) \\ +$\quad$ (for linear programs that own their data and are built entry-wise; probably the most useful model)\\ \ccc{Linear_program_from_iterators}\\ $\quad$ (for linear programs that wrap given iterators, without copying data) \\ \ccc{Linear_program_from_pointers}\\ $\quad$ (for linear programs that wrap given pointers, without copying data) \\ -\ccc{Free_linear_program}\\ -$\quad$ (for linear programs with no variable bounds, copied from iterator ranges)\\ -\ccc{Free_linear_program_from_iterators}\\ -$\quad$ (for linear programs with no variable bounds, wrapping given -iterators)\\ -\ccc{Free_linear_program_from_pointers}\\ -$\quad$ (for linear programs with no variable bounds, wrapping given -pointers)\\ \ccc{Linear_program_from_mps}\\ -$\quad$ (for linear programs copied from an input stream in -\ccc{MPSFormat})\\ -\ccc{Sparse_linear_program_from_mps}\\ -$\quad$ (for sparse linear programs copied from an input stream in -\ccc{MPSFormat}) +$\quad$ (for linear programs read from an input stream in +\ccc{MPSFormat}; the constructed program can be manipulate entry-wise) For \ccc{NonnegativeQuadraticProgramInterface}, we offer these -three models. +four models. \ccc{Nonnegative_quadratic_program}\\ -$\quad$ (for nonnegative quadratic programs, copied from iterator ranges)\\ +$\quad$ (for nonnegative quadratic programs that own their data and are built entry-wise; probably the most useful model)\\ \ccc{Nonnegative_quadratic_program_from_iterators}\\ $\quad$ (for nonnegative quadratic programs, wrapping given iterators)\\ \ccc{Nonnegative_quadratic_program_from_pointers}\\ -$\quad$ (for nonnegative quadratic programs, wrapping given pointers) +$\quad$ (for nonnegative quadratic programs, wrapping given pointers)\\ +\ccc{Nonnegative_quadratic_program_from_mps}\\ +$\quad$ (for nonnegative quadratic programs read from an input stream in +\ccc{MPSFormat}; the constructed program can be manipulate entry-wise) -And finally, the three models for \ccc{NonnegativeLinearProgramInterface}. +And finally, the four models for \ccc{NonnegativeLinearProgramInterface}. \ccc{Nonnegative_linear_program}\\ -$\quad$ (for nonnegative linear programs, copied from iterator ranges)\\ +$\quad$ (for nonnegative linear programs that own their data and are built entry-wise; probably the most useful model)\\ \ccc{Nonnegative_linear_program_from_iterators}\\ $\quad$ (for nonnegative linear programs, wrapping given iterators)\\ \ccc{Nonnegative_linear_program_from_pointers}\\ $\quad$ (for nonnegative linear programs, wrapping given pointers)\\ - +\ccc{Nonnegative_linear_program_from_mps}\\ +$\quad$ (for nonnegative linear programs read from an input stream in +\ccc{MPSFormat}; the constructed programt can be manipulate entry-wise) \ccHeading{Functions} +In case you want to construct a program from complicated iterators +(whose types you don't know, or simply don't want to bother with), +we provide four makers. + +\ccc{make_quadratic_program_from_iterators}\\ +\ccc{make_linear_program_from_iterators}\\ +\ccc{make_nonnegative_quadratic_program_from_iterators}\\ +\ccc{make_nonnegative_linear_program_from_iterators} + There are four functions to solve a program, one for each program concept. diff --git a/QP_solver/doc_tex/QP_solver_ref/main.tex b/QP_solver/doc_tex/QP_solver_ref/main.tex index f36013de0c4..8e5cb4f2204 100644 --- a/QP_solver/doc_tex/QP_solver_ref/main.tex +++ b/QP_solver/doc_tex/QP_solver_ref/main.tex @@ -15,28 +15,27 @@ \input{QP_solver_ref/Quadratic_program} \input{QP_solver_ref/Quadratic_program_from_iterators} \input{QP_solver_ref/Quadratic_program_from_pointers} -\input{QP_solver_ref/Free_quadratic_program} -\input{QP_solver_ref/Free_quadratic_program_from_iterators} -\input{QP_solver_ref/Free_quadratic_program_from_pointers} \input{QP_solver_ref/Quadratic_program_from_mps} -\input{QP_solver_ref/Sparse_quadratic_program_from_mps} \input{QP_solver_ref/Linear_program} \input{QP_solver_ref/Linear_program_from_iterators} \input{QP_solver_ref/Linear_program_from_pointers} -\input{QP_solver_ref/Free_linear_program} -\input{QP_solver_ref/Free_linear_program_from_iterators} -\input{QP_solver_ref/Free_linear_program_from_pointers} \input{QP_solver_ref/Linear_program_from_mps} -\input{QP_solver_ref/Sparse_linear_program_from_mps} \input{QP_solver_ref/Nonnegative_quadratic_program} \input{QP_solver_ref/Nonnegative_quadratic_program_from_iterators} \input{QP_solver_ref/Nonnegative_quadratic_program_from_pointers} +\input{QP_solver_ref/Nonnegative_quadratic_program_from_mps} \input{QP_solver_ref/Nonnegative_linear_program} \input{QP_solver_ref/Nonnegative_linear_program_from_iterators} \input{QP_solver_ref/Nonnegative_linear_program_from_pointers} +\input{QP_solver_ref/Nonnegative_linear_program_from_mps} + +\input{QP_solver_ref/make_quadratic_program_from_iterators.tex} +\input{QP_solver_ref/make_linear_program_from_iterators.tex} +\input{QP_solver_ref/make_nonnegative_quadratic_program_from_iterators.tex} +\input{QP_solver_ref/make_nonnegative_linear_program_from_iterators.tex} \input{QP_solver_ref/solve_quadratic_program.tex} \input{QP_solver_ref/solve_linear_program.tex} diff --git a/QP_solver/doc_tex/QP_solver_ref/make_linear_program_from_iterators.tex b/QP_solver/doc_tex/QP_solver_ref/make_linear_program_from_iterators.tex new file mode 100644 index 00000000000..62cd8d2ef2f --- /dev/null +++ b/QP_solver/doc_tex/QP_solver_ref/make_linear_program_from_iterators.tex @@ -0,0 +1,36 @@ +\begin{ccRefFunction}{make_linear_program_from_iterators} + +\ccInclude{CGAL/QP_models.h} + +This template function creates an instance of +\ccc{Linear_program_from_iterators} from given iterators. This function can be useful if the types of these +iterators are too complicated (or of too little interest for you) +to write them down explicitly. + +\ccFunction{template < + typename A_it, + typename B_it, + typename R_it, + typename FL_it, + typename L_it, + typename FU_it, + typename U_it, + typename C_it > +Linear_program_from_iterators +make_linear_program_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 C_it& c, + typename std::iterator_traits::value_type c0 = + typename std::iterator_traits::value_type(0));} +{returns an instance of \ccc{Linear_program_from_iterators}, constructed from the given iterators.} + +\ccSeeAlso +\ccc{Linear_program_from_iterators} +\end{ccRefFunction} diff --git a/QP_solver/doc_tex/QP_solver_ref/make_nonnegative_linear_program_from_iterators.tex b/QP_solver/doc_tex/QP_solver_ref/make_nonnegative_linear_program_from_iterators.tex new file mode 100644 index 00000000000..b2ed65aa1be --- /dev/null +++ b/QP_solver/doc_tex/QP_solver_ref/make_nonnegative_linear_program_from_iterators.tex @@ -0,0 +1,30 @@ +\begin{ccRefFunction}{make_nonnegative_linear_program_from_iterators} + +\ccInclude{CGAL/QP_models.h} + +This template function creates an instance of +\ccc{Nonnegative_linear_program_from_iterators} +from given iterators. This function can be useful if the types of these +iterators are too complicated (or of too little interest for you) +to write them down explicitly. + +\ccFunction{template < + typename A_it, + typename B_it, + typename R_it, + typename C_it > +Nonnegative_linear_program_from_iterators + +make_nonnegative_linear_program_from_iterators ( + int n, int m, + const A_it& a, + const B_it& b, + const R_it& r, + const C_it& c, + typename std::iterator_traits::value_type c0 = + typename std::iterator_traits::value_type(0));} +{returns an instance of \ccc{Nonnegative_linear_program_from_iterators}, constructed from the given iterators.} + +\ccSeeAlso +\ccc{Nonnegative_linear_program_from_iterators} +\end{ccRefFunction} diff --git a/QP_solver/doc_tex/QP_solver_ref/make_nonnegative_quadratic_program_from_iterators.tex b/QP_solver/doc_tex/QP_solver_ref/make_nonnegative_quadratic_program_from_iterators.tex new file mode 100644 index 00000000000..10c63a1c367 --- /dev/null +++ b/QP_solver/doc_tex/QP_solver_ref/make_nonnegative_quadratic_program_from_iterators.tex @@ -0,0 +1,31 @@ +\begin{ccRefFunction}{make_nonnegative_quadratic_program_from_iterators} + +\ccInclude{CGAL/QP_models.h} + +This template function creates an instance of +\ccc{Nonnegative_quadratic_program_from_iterators} from given iterators. This function can be useful if the types of these +iterators are too complicated (or of too little interest for you) +to write them down explicitly. + +\ccFunction{template < + typename A_it, + typename B_it, + typename R_it, + typename D_it, + typename C_it > +Nonnegative_quadratic_program_from_iterators + +make_nonnegative_quadratic_program_from_iterators ( + int n, int m, + const A_it& a, + const B_it& b, + const R_it& r, + const D_it& d, + const C_it& c, + typename std::iterator_traits::value_type c0 = + typename std::iterator_traits::value_type(0));} +{returns an instance of \ccc{Nonnegative_quadratic_program_from_iterators}, constructed from the given iterators.} + +\ccSeeAlso +\ccc{Nonnegative_quadratic_program_from_iterators} +\end{ccRefFunction} diff --git a/QP_solver/doc_tex/QP_solver_ref/make_quadratic_program_from_iterators.tex b/QP_solver/doc_tex/QP_solver_ref/make_quadratic_program_from_iterators.tex new file mode 100644 index 00000000000..f1c48b44c0c --- /dev/null +++ b/QP_solver/doc_tex/QP_solver_ref/make_quadratic_program_from_iterators.tex @@ -0,0 +1,38 @@ +\begin{ccRefFunction}{make_quadratic_program_from_iterators} + +\ccInclude{CGAL/QP_models.h} + +This template function creates an instance of +\ccc{Quadratic_program_from_iterators} from given iterators. This function can be useful if the types of these +iterators are too complicated (or of too little interest for you) +to write them down explicitly. + +\ccFunction{template < + typename A_it, + typename B_it, + typename R_it, + typename FL_it, + typename L_it, + typename FU_it, + typename U_it, + typename D_it, + typename C_it > +Quadratic_program_from_iterators +make_quadratic_program_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::value_type c0 = + typename std::iterator_traits::value_type(0));} +{returns an instance of \ccc{Quadratic_program_from_iterators}, constructed from the given iterators.} + +\ccSeeAlso +\ccc{Quadratic_program_from_iterators} +\end{ccRefFunction} diff --git a/QP_solver/doc_tex/QP_solver_ref/print_linear_program.tex b/QP_solver/doc_tex/QP_solver_ref/print_linear_program.tex index 74a3f9da4b4..9dd7054046b 100644 --- a/QP_solver/doc_tex/QP_solver_ref/print_linear_program.tex +++ b/QP_solver/doc_tex/QP_solver_ref/print_linear_program.tex @@ -2,7 +2,9 @@ \ccInclude{CGAL/QP_functions.h} -This function writes a linear program to an output stream. +This function writes a linear program to an output stream (in +\ccc{MPSFormat}). The time +complexity is $\Theta (mn)$, even if the program is very sparse. \ccFunction{template void print_linear_program diff --git a/QP_solver/doc_tex/QP_solver_ref/print_nonnegative_linear_program.tex b/QP_solver/doc_tex/QP_solver_ref/print_nonnegative_linear_program.tex index a714a468cf8..bf2faedb68e 100644 --- a/QP_solver/doc_tex/QP_solver_ref/print_nonnegative_linear_program.tex +++ b/QP_solver/doc_tex/QP_solver_ref/print_nonnegative_linear_program.tex @@ -2,7 +2,9 @@ \ccInclude{CGAL/QP_functions.h} -This function writes a nonnegative linear program to an output stream. +This function writes a nonnegative linear program to an output stream +(in \ccc{MPSFormat}). The time +complexity is $\Theta (mn)$, even if the program is very sparse. \ccFunction{template void print_nonnegative_linear_program diff --git a/QP_solver/doc_tex/QP_solver_ref/print_nonnegative_quadratic_program.tex b/QP_solver/doc_tex/QP_solver_ref/print_nonnegative_quadratic_program.tex index feb11c82b27..bfd6912c8b1 100644 --- a/QP_solver/doc_tex/QP_solver_ref/print_nonnegative_quadratic_program.tex +++ b/QP_solver/doc_tex/QP_solver_ref/print_nonnegative_quadratic_program.tex @@ -2,7 +2,9 @@ \ccInclude{CGAL/QP_functions.h} -This function writes a nonnegative quadratic program to an output stream. +This function writes a nonnegative quadratic program +to an output stream (in \ccc{MPSFormat}). The time +complexity is $\Theta (n^2 + mn)$, even if the program is very sparse. \ccFunction{template void print_nonnegative_quadratic_program diff --git a/QP_solver/doc_tex/QP_solver_ref/print_quadratic_program.tex b/QP_solver/doc_tex/QP_solver_ref/print_quadratic_program.tex index 62ed0eccb59..b0ec66c86d6 100644 --- a/QP_solver/doc_tex/QP_solver_ref/print_quadratic_program.tex +++ b/QP_solver/doc_tex/QP_solver_ref/print_quadratic_program.tex @@ -2,7 +2,9 @@ \ccInclude{CGAL/QP_functions.h} -This function writes a quadratic program to an output stream. +This function writes a quadratic program to an output stream (in +\ccc{MPSFormat}). The time complexity is $\Theta (n^2 + mn)$, even +if the program is very sparse. \ccFunction{template void print_quadratic_program diff --git a/QP_solver/doc_tex/QP_solver_ref/solve_linear_program.tex b/QP_solver/doc_tex/QP_solver_ref/solve_linear_program.tex index d85971a5fc9..0caeb512746 100644 --- a/QP_solver/doc_tex/QP_solver_ref/solve_linear_program.tex +++ b/QP_solver/doc_tex/QP_solver_ref/solve_linear_program.tex @@ -21,6 +21,5 @@ be an exact type, and all entries of \ccc{lp} are convertible to runtime-checks to ensure consistency during the solution process. However, these checks slow down the computations by a considerable factor. For maximum efficiency, it is advisable to define the macros -\texttt{CGAL\_QP\_NO\_ASSERTIONS} or (still better) -\texttt{NDEBUG}. +\texttt{CGAL\_QP\_NO\_ASSERTIONS} or \texttt{NDEBUG}. \end{ccRefFunction} diff --git a/QP_solver/doc_tex/QP_solver_ref/solve_nonnegative_linear_program.tex b/QP_solver/doc_tex/QP_solver_ref/solve_nonnegative_linear_program.tex index 443b0084bfd..9111e93b308 100644 --- a/QP_solver/doc_tex/QP_solver_ref/solve_nonnegative_linear_program.tex +++ b/QP_solver/doc_tex/QP_solver_ref/solve_nonnegative_linear_program.tex @@ -21,6 +21,5 @@ be an exact type, and all entries of \ccc{lp} are convertible to runtime-checks to ensure consistency during the solution process. However, these checks slow down the computations by a considerable factor. For maximum efficiency, it is advisable to define the macros -\texttt{CGAL\_QP\_NO\_ASSERTIONS} or (still better) -\texttt{NDEBUG}. +\texttt{CGAL\_QP\_NO\_ASSERTIONS} or \texttt{NDEBUG}. \end{ccRefFunction} diff --git a/QP_solver/doc_tex/QP_solver_ref/solve_nonnegative_quadratic_program.tex b/QP_solver/doc_tex/QP_solver_ref/solve_nonnegative_quadratic_program.tex index b22d12c4366..5e85854003f 100644 --- a/QP_solver/doc_tex/QP_solver_ref/solve_nonnegative_quadratic_program.tex +++ b/QP_solver/doc_tex/QP_solver_ref/solve_nonnegative_quadratic_program.tex @@ -21,6 +21,5 @@ be an exact type, and all entries of \ccc{qp} are convertible to runtime-checks to ensure consistency during the solution process. However, these checks slow down the computations by a considerable factor. For maximum efficiency, it is advisable to define the macros -\texttt{CGAL\_QP\_NO\_ASSERTIONS} or (still better) -\texttt{NDEBUG}. +\texttt{CGAL\_QP\_NO\_ASSERTIONS} or \texttt{NDEBUG}. \end{ccRefFunction} diff --git a/QP_solver/doc_tex/QP_solver_ref/solve_quadratic_program.tex b/QP_solver/doc_tex/QP_solver_ref/solve_quadratic_program.tex index 0fbfc91bfc1..666f63a56b6 100644 --- a/QP_solver/doc_tex/QP_solver_ref/solve_quadratic_program.tex +++ b/QP_solver/doc_tex/QP_solver_ref/solve_quadratic_program.tex @@ -21,6 +21,5 @@ be an exact type, and all entries of \ccc{qp} are convertible to runtime-checks to ensure consistency during the solution process. However, these checks slow down the computations by a considerable factor. For maximum efficiency, it is advisable to define the macros -\texttt{CGAL\_QP\_NO\_ASSERTIONS} or (still better) -\texttt{NDEBUG}. +\texttt{CGAL\_QP\_NO\_ASSERTIONS} or \texttt{NDEBUG}. \end{ccRefFunction} diff --git a/QP_solver/examples/QP_solver/double_qp_solver.cpp b/QP_solver/examples/QP_solver/double_qp_solver.cpp index a5ee9d3091d..69da7447b61 100644 --- a/QP_solver/examples/QP_solver/double_qp_solver.cpp +++ b/QP_solver/examples/QP_solver/double_qp_solver.cpp @@ -43,7 +43,7 @@ int main(const int argNr,const char **args) { using std::endl; // get desired level of additional logging output: - const int verbosity = argNr < 2? 1 : std::atoi(args[1]); + //const int verbosity = argNr < 2? 1 : std::atoi(args[1]); // construct QP instance: typedef double IT; @@ -55,11 +55,11 @@ int main(const int argNr,const char **args) { #endif typedef CGAL::Quadratic_program_from_mps QP; - QP qp(std::cin,true,verbosity); + QP qp(std::cin); // check for format errors in MPS f\ile: if (!qp.is_valid()) { cout << "Input is not a valid MPS file." << endl - << "Error: " << qp.error() << endl; + << "Error: " << qp.get_error() << endl; std::exit(2); } @@ -75,8 +75,8 @@ int main(const int argNr,const char **args) { cout << "Variable values:" << endl; Solution::Variable_value_iterator vit = s.variable_values_begin() ; - for (int i=0; i < qp.n(); ++vit, ++i) - cout << " " << qp.name_of_variable(i) << " = " + for (int i=0; i < qp.get_n(); ++vit, ++i) + cout << " " << qp.get_name_of_variable(i) << " = " << CGAL::to_double(*vit) << endl; cout << "Basic variables (index, value):" << endl; diff --git a/QP_solver/include/CGAL/QP_functions.h b/QP_solver/include/CGAL/QP_functions.h index 84718f7eb6d..99fc105c486 100644 --- a/QP_solver/include/CGAL/QP_functions.h +++ b/QP_solver/include/CGAL/QP_functions.h @@ -44,10 +44,12 @@ namespace QP_functions_detail { Is_linear is_linear, Is_nonnegative is_nonnegative); + // internal routine: // test whether the system is of the form A x == b (equations only) template bool is_in_equational_form (const R& r); + // internal routine: // test whether the row vectors of A that correpsond to equations // are linearly independent; this is done using type ET. The value // type of LinearInequalitySystem must be convertible to ET diff --git a/QP_solver/include/CGAL/QP_models.h b/QP_solver/include/CGAL/QP_models.h index 60f470f8f6e..8f933d0f392 100644 --- a/QP_solver/include/CGAL/QP_models.h +++ b/QP_solver/include/CGAL/QP_models.h @@ -35,25 +35,19 @@ // - Quadratic_program_from_iterators // - Quadratic_program_from_pointers // - Quadratic_program +// - Quadratic_program_from_mps // - Nonngative_quadratic_program_from_iterators // - Nonengative_quadratic_program_from_pointers -// - Nonengative_quadratic_program_ -// - Free_quadratic_program_from_iterators -// - Free_quadratic_program_from_pointers -// - Free_quadratic_program +// - Nonengative_quadratic_program +// - Nonengative_quadratic_program_from_mps // - Linear_program_from_iterators // - Linear_program_from_pointers // - Linear_program +// - Linear_program_from_mps // - Nonngative_linear_program_from_iterators // - Nonengative_linear_program_from_pointers // - Nonengative_linear_program -// - Free_linear_program_from_iterators -// - Free_linear_program_from_pointers -// - Free_linear_program -// - Quadratic_program_from_mps -// - Linear_program_from_mps -// - Sparse_quadratic_program_from_mps -// - Sparse_linear_program_from_mps +// - Nonengative_linear_program_from_mps // for convenience, every model is actually a model of the // concept QuadraticProgramInterface: @@ -69,79 +63,6 @@ typedef typename Base::C_iterator C_iterator;\ typedef typename Base::C_entry C_entry -// macros to ease coding of copying models -// invariant: a pointer is either 0, or it points to valid memory -#define QP_MODEL_MAKE_ABRC \ - if (this->n_ > 0) this->a_it = new NT*[this->n_];\ - for (int j=0; jn_; ++j)\ - if (this->m_ > 0)\ - this->a_it[j] = new NT[this->m_];\ - else\ - this->a_it[j] = 0;\ - if (this->m_ > 0) this->b_it = new NT[this->m_];\ - if (this->m_ > 0) this->r_it = new CGAL::Comparison_result[this->m_];\ - if (this->n_ > 0) this->c_it = new NT[this->n_] - -#define QP_MODEL_SET_ABRC \ - for (int j=0; jn_; ++j)\ - CGAL::copy_n (*(a+j), this->m_, this->a_it[j]);\ - CGAL::copy_n (b, this->m_, this->b_it);\ - CGAL::copy_n (r, this->m_, this->r_it);\ - CGAL::copy_n (c, this->n_, this->c_it) - -#define QP_MODEL_SET_ABRC_FROM_P \ - for (int j=0; jn_; ++j)\ - CGAL::copy_n (*(p.a()+j), this->m_, this->a_it[j]);\ - CGAL::copy_n (p.b(), this->m_, this->b_it);\ - CGAL::copy_n (p.r(), this->m_, this->r_it);\ - CGAL::copy_n (p.c(), this->n_, this->c_it) - -#define QP_MODEL_DELETE_ABRC \ - delete[] this->c_it;\ - delete[] this->r_it;\ - delete[] this->b_it;\ - for (int j=0; jn_; ++j) delete[] this->a_it[j];\ - delete[] this->a_it - -#define QP_MODEL_MAKE_BOUNDS \ - if (this->n_ > 0) this->fl_it = new bool[this->n_];\ - if (this->n_ > 0) this->l_it = new NT[this->n_];\ - if (this->n_ > 0) this->fu_it = new bool[this->n_];\ - if (this->n_ > 0) this->u_it = new NT[this->n_]; - -#define QP_MODEL_SET_BOUNDS \ - CGAL::copy_n (fl, this->n_, this->fl_it);\ - CGAL::copy_n (l, this->n_, this->l_it);\ - CGAL::copy_n (fu, this->n_, this->fu_it);\ - CGAL::copy_n (u, this->n_, this->u_it) - -#define QP_MODEL_SET_BOUNDS_FROM_P \ - CGAL::copy_n (p.fl(), this->n_, this->fl_it);\ - CGAL::copy_n (p.l(), this->n_, this->l_it);\ - CGAL::copy_n (p.fu(), this->n_, this->fu_it);\ - CGAL::copy_n (p.u(), this->n_, this->u_it) - -#define QP_MODEL_DELETE_BOUNDS \ - delete[] this->u_it;\ - delete[] this->fu_it;\ - delete[] this->l_it;\ - delete[] this->fl_it - -#define QP_MODEL_MAKE_D \ - if (this->n_ > 0) this->d_it = new NT*[this->n_];\ - for (int j=0; jn_; ++j) this->d_it[j] = new NT[j+1]; - -#define QP_MODEL_SET_D \ - for (int j=0; jn_; ++j) CGAL::copy_n (*(d+j), j+1, this->d_it[j]) - -#define QP_MODEL_SET_D_FROM_P \ - for (int j=0; jn_; ++j) CGAL::copy_n (*(p.d()+j), j+1, this->d_it[j]) - -#define QP_MODEL_DELETE_D \ - for (int j=0; jn_; ++j) delete[] this->d_it[j];\ - delete[] this->d_it - - CGAL_BEGIN_NAMESPACE // default iterator types to used to make linear / nonnegative models @@ -217,18 +138,18 @@ public: {} // access - int n() const {return n_;} - int m() const {return m_;} - A_iterator a() const {return a_it;} - B_iterator b() const {return b_it;} - R_iterator r() const {return r_it;} - FL_iterator fl() const {return fl_it;} - L_iterator l() const {return l_it;} - FU_iterator fu() const {return fu_it;} - U_iterator u() const {return u_it;} - D_iterator d() const {return d_it;} - C_iterator c() const {return c_it;} - C_entry c0() const {return c_0;} + int get_n() const {return n_;} + int get_m() const {return m_;} + A_iterator get_a() const {return a_it;} + B_iterator get_b() const {return b_it;} + R_iterator get_r() const {return r_it;} + FL_iterator get_fl() const {return fl_it;} + L_iterator get_l() const {return l_it;} + FU_iterator get_fu() const {return fu_it;} + U_iterator get_u() const {return u_it;} + D_iterator get_d() const {return d_it;} + C_iterator get_c() const {return c_it;} + C_entry get_c0() const {return c_0;} }; // corresponding global function make_quadratic_program_from_iterators @@ -265,12 +186,14 @@ make_quadratic_program_from_iterators ( // Quadratic_program_from_pointers // ------------------------------- -template +template class Quadratic_program_from_pointers : public Quadratic_program_from_iterators - + { +public: + typedef NT_ NT; private: typedef Quadratic_program_from_iterators -class Quadratic_program : - public Quadratic_program_from_pointers -{ -private: - typedef Quadratic_program_from_pointers Base; -public: - QP_MODEL_ITERATOR_TYPES; - template - Quadratic_program - ( - int n, int m, // number of variables / constraints - 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, - const C_entry& c0 = C_entry(0)) - : Base (n, m, 0, 0, 0, 0, 0, 0, 0, 0, 0, c0) - { - QP_MODEL_MAKE_ABRC; - QP_MODEL_SET_ABRC; - QP_MODEL_MAKE_BOUNDS; - QP_MODEL_SET_BOUNDS; - QP_MODEL_MAKE_D; - QP_MODEL_SET_D; - } - - Quadratic_program () - : Base (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) - {} - - Quadratic_program (const Quadratic_program& p) - : Base (p.n(), p.m(), 0, 0, 0, 0, 0, 0, 0, 0, 0, p.c0()) - { - QP_MODEL_MAKE_ABRC; - QP_MODEL_SET_ABRC_FROM_P; - QP_MODEL_MAKE_BOUNDS; - QP_MODEL_SET_BOUNDS_FROM_P; - QP_MODEL_MAKE_D; - QP_MODEL_SET_D_FROM_P; - } - - Quadratic_program& operator= (const Quadratic_program& p) - { - if (this != &p) { - // cleanup - QP_MODEL_DELETE_D; - QP_MODEL_DELETE_BOUNDS; - QP_MODEL_DELETE_ABRC; - // reset - this->n_ = p.n(); - this->m_ = p.m(); - this->c_0 = p.c0(); - QP_MODEL_MAKE_ABRC; - QP_MODEL_SET_ABRC_FROM_P; - QP_MODEL_MAKE_BOUNDS; - QP_MODEL_SET_BOUNDS_FROM_P; - QP_MODEL_MAKE_D; - QP_MODEL_SET_D_FROM_P; - } - return *this; - } - - ~Quadratic_program () - { - QP_MODEL_DELETE_D; - QP_MODEL_DELETE_BOUNDS; - QP_MODEL_DELETE_ABRC; - } -}; - // Linear_program_from_iterators // ----------------------------- template < @@ -446,11 +289,13 @@ make_linear_program_from_iterators ( // Linear_program_from_pointers // ---------------------------- -template +template class Linear_program_from_pointers : public Linear_program_from_iterators - + { +public: + typedef NT_ NT; private: typedef Linear_program_from_iterators Base; @@ -472,77 +317,6 @@ public: {} }; -// Linear_program (copies the data) -// -------------------------------- -template -class Linear_program : - public Linear_program_from_pointers -{ -private: - typedef Linear_program_from_pointers Base; -public: - QP_MODEL_ITERATOR_TYPES; - template - Linear_program - ( - int n, int m, // number of variables / constraints - 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 C_it& c, - const C_entry& c0 = C_entry(0)) - : Base (n, m, 0, 0, 0, 0, 0, 0, 0, 0, c0) - { - QP_MODEL_MAKE_ABRC; - QP_MODEL_SET_ABRC; - QP_MODEL_MAKE_BOUNDS; - QP_MODEL_SET_BOUNDS; - } - - Linear_program () - : Base (0, 0, 0, 0, 0, 0, 0, 0, 0, 0) - {} - - Linear_program (const Linear_program& p) - : Base (p.n(), p.m(), 0, 0, 0, 0, 0, 0, 0, 0, p.c0()) - { - QP_MODEL_MAKE_ABRC; - QP_MODEL_SET_ABRC_FROM_P; - QP_MODEL_MAKE_BOUNDS; - QP_MODEL_SET_BOUNDS_FROM_P; - } - - Linear_program& operator= (const Linear_program& p) - { - if (this != &p) { - // cleanup - QP_MODEL_DELETE_BOUNDS; - QP_MODEL_DELETE_ABRC; - // reset - this->n_ = p.n(); - this->m_ = p.m(); - this->c_0 = p.c0(); - QP_MODEL_MAKE_ABRC; - QP_MODEL_SET_ABRC_FROM_P; - QP_MODEL_MAKE_BOUNDS; - QP_MODEL_SET_BOUNDS_FROM_P; - } - return *this; - } - - ~Linear_program () - { - QP_MODEL_DELETE_BOUNDS; - QP_MODEL_DELETE_ABRC; - } -}; - - // Nonnegative_quadratic_program_from_iterators // -------------------------------------------- template < @@ -614,11 +388,13 @@ make_nonnegative_quadratic_program_from_iterators ( // Nonnegative_Quadratic_program_from_pointers // ------------------------------------------- -template +template class Nonnegative_quadratic_program_from_pointers : public Nonnegative_quadratic_program_from_iterators - + { +public: + typedef NT_ NT; private: typedef Nonnegative_quadratic_program_from_iterators Base; @@ -637,235 +413,9 @@ public: {} }; -// Nonnegative_quadratic_program (copies the data) -// ---------------------------------------------- -template -class Nonnegative_quadratic_program : - public Nonnegative_quadratic_program_from_pointers -{ -private: - typedef Nonnegative_quadratic_program_from_pointers Base; -public: - QP_MODEL_ITERATOR_TYPES; - template - Nonnegative_quadratic_program - ( - int n, int m, // number of variables / constraints - const A_it& a, - const B_it& b, - const R_it& r, - const D_it& d, - const C_it& c, - const C_entry& c0 = C_entry(0)) - : Base (n, m, 0, 0, 0, 0, 0, c0) - { - QP_MODEL_MAKE_ABRC; - QP_MODEL_SET_ABRC; - QP_MODEL_MAKE_D; - QP_MODEL_SET_D; - } - - Nonnegative_quadratic_program () - : Base (0, 0, 0, 0, 0, 0, 0) - {} - - Nonnegative_quadratic_program (const Nonnegative_quadratic_program& p) - : Base (p.n(), p.m(), 0, 0, 0, 0, 0, p.c0()) - { - QP_MODEL_MAKE_ABRC; - QP_MODEL_SET_ABRC_FROM_P; - QP_MODEL_MAKE_D; - QP_MODEL_SET_D_FROM_P; - } - - Nonnegative_quadratic_program& operator= - (const Nonnegative_quadratic_program& p) - { - if (this != &p) { - // cleanup - QP_MODEL_DELETE_D; - QP_MODEL_DELETE_ABRC; - // reset - this->n_ = p.n(); - this->m_ = p.m(); - this->c_0 = p.c0(); - QP_MODEL_MAKE_ABRC; - QP_MODEL_SET_ABRC_FROM_P; - QP_MODEL_MAKE_D; - QP_MODEL_SET_D_FROM_P; - } - return *this; - } - - ~Nonnegative_quadratic_program () - { - QP_MODEL_DELETE_D; - QP_MODEL_DELETE_ABRC; - } -}; -// Free_quadratic_program_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 Free_quadratic_program_from_iterators : - public Quadratic_program_from_iterators ::It_1d, - typename QP_model_default_iterators::It_1d, - typename QP_model_default_iterators::It_1d, - typename QP_model_default_iterators::It_1d, - D_it, C_it> -{ -private: - typedef Quadratic_program_from_iterators ::It_1d, - typename QP_model_default_iterators::It_1d, - typename QP_model_default_iterators::It_1d, - typename QP_model_default_iterators::It_1d, - D_it, C_it> Base; - typedef typename QP_model_default_iterators::It_1d Const_FLU_iterator; - typedef typename QP_model_default_iterators::It_1d Const_LU_iterator; -public: - QP_MODEL_ITERATOR_TYPES; - Free_quadratic_program_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 C_entry& c0 = C_entry(0) - ) - : Base (n, m, a, b, r, - Const_FLU_iterator(false), Const_LU_iterator(C_entry(0)), - Const_FLU_iterator(false), Const_LU_iterator(C_entry(0)), - d, c, c0) - {} -}; -// corresponding global function -// make_free_quadratic_program_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 -Free_quadratic_program_from_iterators - -make_free_quadratic_program_from_iterators ( - int n, int m, - const A_it& a, - const B_it& b, - const R_it& r, - const D_it& d, - const C_it& c, - typename std::iterator_traits::value_type c0 = - typename std::iterator_traits::value_type(0)) -{ - return Free_quadratic_program_from_iterators - - (n, m, a, b, r, d, c, c0); -} -// Free_Quadratic_program_from_pointers -// ------------------------------------------- -template -class Free_quadratic_program_from_pointers : - public Free_quadratic_program_from_iterators - -{ -private: - typedef Free_quadratic_program_from_iterators - Base; -public: - QP_MODEL_ITERATOR_TYPES; - Free_quadratic_program_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 C_entry& c0 = C_entry(0) - ) - : Base (n, m, a, b, r, d, c, c0) - {} -}; - -// Free_quadratic_program (copies the data) -// --------------------------------------- -template -class Free_quadratic_program : - public Free_quadratic_program_from_pointers -{ -private: - typedef Free_quadratic_program_from_pointers Base; -public: - QP_MODEL_ITERATOR_TYPES; - template - Free_quadratic_program - ( - int n, int m, // number of variables / constraints - const A_it& a, - const B_it& b, - const R_it& r, - const D_it& d, - const C_it& c, - const C_entry& c0 = C_entry(0)) - : Base (n, m, 0, 0, 0, 0, 0, c0) - { - QP_MODEL_MAKE_ABRC; - QP_MODEL_SET_ABRC; - QP_MODEL_MAKE_D; - QP_MODEL_SET_D; - } - - Free_quadratic_program () - : Base (0, 0, 0, 0, 0, 0, 0) - {} - - Free_quadratic_program (const Free_quadratic_program& p) - : Base (p.n(), p.m(), 0, 0, 0, 0, 0, p.c0()) - { - QP_MODEL_MAKE_ABRC; - QP_MODEL_SET_ABRC_FROM_P; - QP_MODEL_MAKE_D; - QP_MODEL_SET_D_FROM_P; - } - - Free_quadratic_program& operator= (const Free_quadratic_program& p) - { - if (this != &p) { - // cleanup - QP_MODEL_DELETE_D; - QP_MODEL_DELETE_ABRC; - // reset - this->n_ = p.n(); - this->m_ = p.m(); - this->c_0 = p.c0(); - QP_MODEL_MAKE_ABRC; - QP_MODEL_SET_ABRC_FROM_P; - QP_MODEL_MAKE_D; - QP_MODEL_SET_D_FROM_P; - } - return *this; - } - - ~Free_quadratic_program () - { - QP_MODEL_DELETE_D; - QP_MODEL_DELETE_ABRC; - } -}; - // Nonnegative_linear_program_from_iterators // ----------------------------------------- template < @@ -934,11 +484,13 @@ make_nonnegative_linear_program_from_iterators ( // Nonnegative_linear_program_from_pointers // ---------------------------------------- -template +template class Nonnegative_linear_program_from_pointers : public Nonnegative_linear_program_from_iterators - + { +public: + typedef NT_ NT; private: typedef Nonnegative_linear_program_from_iterators Base; @@ -956,216 +508,8 @@ public: {} }; -// Nonnegative_linear_program (copies the data) -// -------------------------------------------- -template -class Nonnegative_linear_program : - public Nonnegative_linear_program_from_pointers -{ -private: - typedef Nonnegative_linear_program_from_pointers Base; -public: - QP_MODEL_ITERATOR_TYPES; - template - Nonnegative_linear_program - ( - int n, int m, // number of variables / constraints - const A_it& a, - const B_it& b, - const R_it& r, - const C_it& c, - const C_entry& c0 = C_entry(0)) - : Base (n, m, 0, 0, 0, 0, c0) - { - QP_MODEL_MAKE_ABRC; - QP_MODEL_SET_ABRC; - } - - Nonnegative_linear_program () - : Base (0, 0, 0, 0, 0, 0) - {} - - Nonnegative_linear_program (const Nonnegative_linear_program& p) - : Base (p.n(), p.m(), 0, 0, 0, 0, p.c0()) - { - QP_MODEL_MAKE_ABRC; - QP_MODEL_SET_ABRC_FROM_P; - } - - Nonnegative_linear_program& operator= (const Nonnegative_linear_program& p) - { - if (this != &p) { - // cleanup - QP_MODEL_DELETE_ABRC; - // reset - this->n_ = p.n(); - this->m_ = p.m(); - this->c_0 = p.c0(); - QP_MODEL_MAKE_ABRC; - QP_MODEL_SET_ABRC_FROM_P; - } - return *this; - } - - ~Nonnegative_linear_program () - { - QP_MODEL_DELETE_ABRC; - } -}; - - -// Free_linear_program_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 Free_linear_program_from_iterators : - public Quadratic_program_from_iterators ::It_1d, - typename QP_model_default_iterators::It_1d, - typename QP_model_default_iterators::It_1d, - typename QP_model_default_iterators::It_1d, - typename QP_model_default_iterators::It_2d, C_it> -{ -private: - typedef Quadratic_program_from_iterators ::It_1d, - typename QP_model_default_iterators::It_1d, - typename QP_model_default_iterators::It_1d, - typename QP_model_default_iterators::It_1d, - typename QP_model_default_iterators::It_2d, C_it> Base; - typedef typename QP_model_default_iterators::It_1d Const_FLU_iterator; - typedef typename QP_model_default_iterators::It_1d Const_LU_iterator; - typedef typename QP_model_default_iterators::It_2d Const_D_iterator; -public: - QP_MODEL_ITERATOR_TYPES; - Free_linear_program_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 C_entry& c0 = C_entry(0) - ) - : Base (n, m, a, b, r, - Const_FLU_iterator(false), Const_LU_iterator(C_entry(0)), - Const_FLU_iterator(false), Const_LU_iterator(C_entry(0)), - Const_D_iterator(C_entry(0)), c, c0) - {} -}; - -// corresponding global function -// make_free_linear_program_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 -Nonnegative_linear_program_from_iterators - -make_free_linear_program_from_iterators ( - int n, int m, - const A_it& a, - const B_it& b, - const R_it& r, - const C_it& c, - typename std::iterator_traits::value_type c0 = - typename std::iterator_traits::value_type(0)) -{ - return Free_linear_program_from_iterators - - (n, m, a, b, r, c, c0); -} - -// Free_linear_program_from_pointers -// --------------------------------- -template -class Free_linear_program_from_pointers : - public Free_linear_program_from_iterators - -{ -private: - typedef Free_linear_program_from_iterators - Base; -public: - QP_MODEL_ITERATOR_TYPES; - Free_linear_program_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 C_entry& c0 = C_entry(0) - ) - : Base (n, m, a, b, r, c, c0) - {} -}; - -// Free_linear_program (copies the data) -// ------------------------------------- -template -class Free_linear_program : - public Free_linear_program_from_pointers -{ -private: - typedef Free_linear_program_from_pointers Base; -public: - QP_MODEL_ITERATOR_TYPES; - template - Free_linear_program - ( - int n, int m, // number of variables / constraints - const A_it& a, - const B_it& b, - const R_it& r, - const C_it& c, - const C_entry& c0 = C_entry(0)) - : Base (n, m, 0, 0, 0, 0, c0) - { - QP_MODEL_MAKE_ABRC; - QP_MODEL_SET_ABRC; - } - - Free_linear_program () - : Base (0, 0, 0, 0, 0, 0) - {} - - Free_linear_program (const Free_linear_program& p) - : Base (p.n(), p.m(), 0, 0, 0, 0, p.c0()) - { - QP_MODEL_MAKE_ABRC; - QP_MODEL_SET_ABRC_FROM_P; - } - - Free_linear_program& operator= (const Free_linear_program& p) - { - if (this != &p) { - // cleanup - QP_MODEL_DELETE_ABRC; - // reset - this->n_ = p.n(); - this->m_ = p.m(); - this->c_0 = p.c0(); - QP_MODEL_MAKE_ABRC; - QP_MODEL_SET_ABRC_FROM_P; - } - return *this; - } - - ~Free_linear_program () - { - QP_MODEL_DELETE_ABRC; - } -}; - -// QP_from_mps -// -------------------------- -namespace QP_from_mps_detail { - - // functor to get the appropriate begin-iterator of a container +namespace QP_model_detail { + // maps a container to its begin-iterator, as specified by HowToBegin template struct Begin : public std::unary_function< Container, Iterator > @@ -1176,165 +520,507 @@ namespace QP_from_mps_detail { return HowToBegin()(v); } }; +} - // the general representation template - template - struct Rep_selector {}; - - // sparse representation; uses a map and "fake" random access iterator - template - struct Rep_selector - { - typedef std::map Container; - typedef CGAL::Fake_random_access_const_iterator Iterator; - struct HowToBegin { - Iterator operator() (const Container& v) const - { return Iterator(&v, IT(0));} - }; - typedef Begin Beginner; - }; - - // dense representation; uses vector and its const-iterator - template - struct Rep_selector - { - typedef std::vector Container; - typedef typename Container::const_iterator Iterator; - struct HowToBegin { - Iterator operator() (const Container& v) const - { return v.begin();} - }; - typedef Begin Beginner; - }; - - template - struct D_selector {}; - - template - struct D_selector // linear case - { - typedef typename QP_model_default_iterators::It_2d D_iterator; - }; - - template - struct D_selector // quadratic case - { - typedef CGAL::Join_input_iterator_1 - D_iterator; - }; - -} // QP_from_mps_detail - -template>. - // 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 Is_linear_, - // this checks that there is no DMATRIX - // section, and it avoids allocation of - // an (n x n) matrix in the non-sparse - // case - typename Sparse_D_=Tag_false, - // Use a sparse representation for D. - typename Sparse_A_=Tag_false> - // Use a sparse representation for A. -class QP_from_mps { +// Quadratic_program_base +// ---------------------- +// sparse representation, entries can be set one by one, overriding +// defaults; during construction, we can provide flags that tell us +// whether we want to set up a linear/nonnegative program +template +class Quadratic_program_base +{ public: - typedef IT_ IT; - typedef Is_linear_ Is_linear; - typedef Sparse_D_ Sparse_D; - typedef Sparse_A_ Sparse_A; - - // choose representation for columns of A-matrix - typedef typename QP_from_mps_detail::Rep_selector - ::Container A_col; - typedef typename QP_from_mps_detail::Rep_selector - ::Iterator A_col_iterator; - - // choose representation for rows of D-matrix - typedef typename QP_from_mps_detail::Rep_selector - ::Container D_row; - typedef typename QP_from_mps_detail::Rep_selector - ::Iterator D_row_iterator; - - // choose Beginners (maps col/row containers to their begin iterators) - typedef typename QP_from_mps_detail::Rep_selector - ::Beginner A_Beginner; - typedef typename QP_from_mps_detail::Rep_selector - ::Beginner D_Beginner; - - // matrices A and D itself are vectors of columns resp. rows - typedef std::vector A_Matrix; - typedef std::vector D_Matrix; - - // containers for the other QP data - typedef std::vector Vector; // b, c, l, u - typedef std::vector F_vector; // fl, fu - typedef std::vector R_vector; // r - - // QP_model types - typedef CGAL::Join_input_iterator_1 - A_iterator; - typedef typename Vector::const_iterator B_iterator; - typedef typename R_vector::const_iterator R_iterator; - typedef typename F_vector::const_iterator FL_iterator; - typedef typename F_vector::const_iterator FU_iterator; - typedef typename Vector::const_iterator L_iterator; - typedef typename Vector::const_iterator U_iterator; - - // select D_iterator, depending on Is_linear - typedef typename QP_from_mps_detail::D_selector - ::D_iterator - D_iterator; - // typedef CGAL::Join_input_iterator_1 -// -// D_iterator; - typedef typename Vector::const_iterator C_iterator; - typedef typename std::iterator_traits::value_type C_entry; + typedef NT_ NT; private: - typedef std::pair String_int_pair; - typedef std::map Index_map; - typedef std::map Map; + // Sparse_vectors + typedef std::map + Sparse_vector; + typedef std::map + Sparse_r_vector; + typedef std::map + Sparse_f_vector; -private: - const bool has_linear_tag; - const int verbosity_; - std::istream& from; - std::string error_msg; - bool is_format_okay_; - bool is_linear_; - const bool use_CPLEX_convention; - const IT it0; + // Sparse_matrix + typedef std::vector + Sparse_matrix; - // actual problem data to be read from MPS file - A_Matrix A_; - D_Matrix D_; - Vector b_; - R_vector row_types_; - F_vector fl_, fu_; - Vector l_, u_; - Vector c_; - IT c_0; - - std::string D_section; // name of the section from which D was read + // Sparse_vector_iterators + typedef CGAL::Fake_random_access_const_iterator + Sparse_vector_iterator; + typedef CGAL::Fake_random_access_const_iterator + Sparse_r_vector_iterator; + typedef CGAL::Fake_random_access_const_iterator + Sparse_f_vector_iterator; + + // Sparse_matrix_iterator + struct HowToBegin + { + Sparse_vector_iterator operator() (const Sparse_vector& v) const + { return Sparse_vector_iterator(&v, NT(0));} + }; + + typedef QP_model_detail::Begin + Beginner; + typedef CGAL::Join_input_iterator_1 + + Sparse_matrix_iterator; - // cached data: - bool is_nonnegative_cached, is_nonnegative_; + // program data; we maintain the invariant that only the + // non-default elements are stored; this means that entries + // may get removed again, and n_, m_ might be larger than + // absolutely needed; we also maintain the invariants that + // a_matrix and d_matrix always have n_ elements + + // type settings + bool linear_; + bool nonnegative_; + + int n_; + int m_; + Sparse_matrix a_matrix; + Sparse_vector b_vector; + Sparse_r_vector r_vector; + Sparse_f_vector fl_vector; + Sparse_vector l_vector; + Sparse_f_vector fu_vector; + Sparse_vector u_vector; + Sparse_vector c_vector; + Sparse_matrix d_matrix; + NT c0_; + + // default settings + CGAL::Comparison_result default_r; // from constructor + bool default_fl; // true + NT default_l; // 0 + bool default_fu; // false + NT default_u; // dummy +protected: + mutable bool is_valid_; +private: + mutable std::string error_msg; + + // methods + // enlarges a_matrix, d_matrix to size s, under the + // precondition that the previous sizes were smaller + void grow_a_d (int s) + { + CGAL_qpe_assertion( a_matrix.size() == d_matrix.size() ); + CGAL_qpe_assertion( a_matrix.size() < (unsigned int)s); + for (int k = a_matrix.size(); k < s; ++k) { + a_matrix.push_back(Sparse_vector()); + d_matrix.push_back(Sparse_vector()); + } + } + +public: + // interface types + typedef Sparse_matrix_iterator A_iterator; + typedef Sparse_vector_iterator B_iterator; + typedef Sparse_r_vector_iterator R_iterator; + typedef Sparse_f_vector_iterator FL_iterator; + typedef Sparse_vector_iterator L_iterator; + typedef Sparse_f_vector_iterator FU_iterator; + typedef Sparse_vector_iterator U_iterator; + typedef Sparse_vector_iterator C_iterator; + typedef Sparse_matrix_iterator D_iterator; + typedef NT C_entry; + + // concept methods + int get_n() const + { + CGAL_qpe_assertion(is_valid()); + return n_; + } + int get_m() const + { + CGAL_qpe_assertion(is_valid()); + return m_; + } + A_iterator get_a() const + { + CGAL_qpe_assertion(is_valid()); + return A_iterator (a_matrix.begin(), Beginner()); + } + B_iterator get_b() const + { + CGAL_qpe_assertion(is_valid()); + return B_iterator (&b_vector, NT(0)); + } + R_iterator get_r() const + { + CGAL_qpe_assertion(is_valid()); + return R_iterator (&r_vector, default_r); + } + FL_iterator get_fl() const + { + CGAL_qpe_assertion(is_valid()); + return FL_iterator (&fl_vector, default_fl); // default bound: >= 0 + } + L_iterator get_l() const + { + CGAL_qpe_assertion(is_valid()); + return L_iterator (&l_vector, default_l); + } + FU_iterator get_fu() const + { + CGAL_qpe_assertion(is_valid()); + return FU_iterator (&fu_vector, default_fu); + } + U_iterator get_u() const + { + CGAL_qpe_assertion(is_valid()); + return U_iterator (&u_vector, default_u); + } + C_iterator get_c() const + { + CGAL_qpe_assertion(is_valid()); + return C_iterator (&c_vector, NT(0)); + } + D_iterator get_d() const + { + CGAL_qpe_assertion(is_valid()); + return D_iterator (d_matrix.begin(), Beginner()); + } + C_entry get_c0() const + { + CGAL_qpe_assertion(is_valid()); + return c0_; + } + + bool is_valid() const + { + if (is_valid_) { + // check for type validity + if (linear_ && !is_linear()) + err ("program is not linear"); + if (nonnegative_ && !is_nonnegative()) + err ("program is not nonnegative"); + } + return is_valid_; + } + + const std::string& get_error() const + { + CGAL_qpe_assertion(!is_valid_); + return error_msg; + } + + // default constructor + Quadratic_program_base (bool linear, + bool nonnegative, + CGAL::Comparison_result relation = CGAL::EQUAL) + : linear_(linear), nonnegative_(nonnegative), n_(0), m_(0), c0_(0), + default_r(relation), default_fl(true), + default_l(0), default_fu(false), default_u(0), is_valid_(true) + {} + // constructor from iterators + template + Quadratic_program_base + ( + int n, int m, // number of variables / constraints + 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, + const typename std::iterator_traits::value_type& c0 = 0) + : linear_(false), nonnegative_(false), n_(0), m_(0), c0_(0), + default_r(CGAL::EQUAL), default_fl(true), + default_l(0), default_fu(false), default_u(0), is_valid_(true) + { + // now copy, using the set methods + for (int j=0; j= 0 inf + return (fl_vector.empty() && l_vector.empty() && fu_vector.empty()); + } + + // set methods + void set_a (int j, int i, const NT& val) + { + CGAL_qpe_assertion (j >= 0); + CGAL_qpe_assertion (i >= 0); + if (j >= n_) { + n_ = j+1; + grow_a_d(n_); + } + if (i >= m_) m_ = i+1; + if (CGAL::is_zero(val)) + a_matrix[j].erase(i); + else + a_matrix[j][i] = val; + } + + void set_b (int i, const NT& val) + { + CGAL_qpe_assertion (i >= 0); + if (i >= m_) m_ = i+1; + if (CGAL::is_zero(val)) + b_vector.erase(i); + else + b_vector[i] = val; + } + + void set_r (int i, CGAL::Comparison_result val) + { + CGAL_qpe_assertion (i >= 0); + if (i >= m_) m_ = i+1; + if (val == default_r) + r_vector.erase(i); + else + r_vector[i] = val; + } + + void set_l (int j, bool is_finite, const NT& val = NT(0)) + { + CGAL_qpe_assertion(!nonnegative_); + CGAL_qpe_assertion (j >= 0); + if (j >= n_) { + n_ = j+1; + grow_a_d(n_); + } + if (is_finite == default_fl) + fl_vector.erase(j); + else + fl_vector[j] = is_finite; + if (val == default_l) + l_vector.erase(j); + else + l_vector[j] = val; + } + + void set_u (int j, bool is_finite, const NT& val = NT(0)) + { + CGAL_qpe_assertion(!nonnegative_); + CGAL_qpe_assertion (j >= 0); + if (j >= n_) { + n_ = j+1; + grow_a_d(n_); + } + if (is_finite == default_fu) + fu_vector.erase(j); + else + fu_vector[j] = is_finite; + if (val == default_u) + u_vector.erase(j); + else + u_vector[j] = val; + } + + void set_c (int j, const NT& val) + { + CGAL_qpe_assertion (j >= 0); + if (j >= n_) { + n_ = j+1; + grow_a_d(n_); + } + if (CGAL::is_zero(val)) + c_vector.erase(j); + else + c_vector[j] = val; + } + + void set_c0 (const NT& val) + { + c0_ = val; + } + + void set_d (int i, int j, const NT& val) + { + CGAL_qpe_assertion(!linear_); + CGAL_qpe_assertion (i >= 0); + CGAL_qpe_assertion (j >= 0); + CGAL_qpe_assertion (j <= i); // lower-diagonal entry + if (i >= n_) { + n_ = i+1; + grow_a_d(n_); + } + if (CGAL::is_zero(val)) + d_matrix[i].erase(j); + else + d_matrix[i][j] = val; + } + +protected: + // helpers for errors/warnings + std::string replace1 + (const std::string& msg,const std::string& replacement) const + { + 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) const { + error_msg = msg; + is_valid_ = false; + return false; + } + + bool err1(const char* msg, + const std::string& parameter1) const { + error_msg = replace1(msg,parameter1); + is_valid_ = false; + return false; + } + + bool err2(const char* msg, + const std::string& parameter1, + const std::string& parameter2) const { + error_msg = replace1(replace1(msg,parameter1),parameter2); + is_valid_ = false; + return false; + } + + bool err3(const char* msg, + const std::string& parameter1, + const std::string& parameter2, + const std::string& parameter3) const { + error_msg = + replace1(replace1(replace1(msg,parameter1),parameter2),parameter3); + is_valid_ = false; + return false; + } + + void warn(const std::string& msg) { + std::cerr << "Warning: " << msg << '.' << std::endl; + } + + void warn1(const std::string& msg,const std::string& parameter1) { + warn(replace1(msg,parameter1)); + } + + +}; + +// Quadratic_program_from_mps_base +// ------------------------------- +// for reading a QP from a stream in MPS format + +template +class Quadratic_program_from_mps_base : + public Quadratic_program_base +{ +public: + typedef NT_ NT; +private: + typedef Quadratic_program_base Base; +public: + QP_MODEL_ITERATOR_TYPES; +private: + // types + typedef std::map Index_map; + typedef std::pair String_int_pair; +public: + // constructor + Quadratic_program_from_mps_base + (std::istream& in, bool linear, bool nonnegative) + : Base(linear, nonnegative), from(in), nt0(0), use_put_back_token(false) + { + // read NAME section: + if (!name_section()) + return; + + // read ROWS section: + if (!rows_section()) + return; + + // read COLUMNS section: + if (!columns_section()) + return; + + // read RHS section: + if (!rhs_section()) + return; + + // check for (optional) RANGES section: + if (!ranges_section()) + return; + + // read optional BOUNDS section: + if (!bounds_section()) + return; + + // read optional QMATRIX section: + if (!qmatrix_section()) + return; + + // check for ENDATA: + const std::string end = token(); + if (end != "ENDATA") { + this->err1("ENDDATA expected but found '%'",end); + return; + } + } + + // returns the first comment that was read from the MPS stream + const std::string& get_comment() const + { + return comment_; + } + + // returns name of the problem + const std::string& get_problem_name() const + { + return name; + } + + const std::string& get_name_of_variable(int i) + { + CGAL_qpe_assertion(this->is_valid_); + CGAL_qpe_assertion(0<=i && iget_n()); + return var_by_index[i]; + } +private: + // data + // ---- + std::istream& from; // input stream + NT nt0; + + std::string D_section; // name of the section from which D was read + std::string name; // name of the problem + std::string comment_; // first comment in the input, if any + std::string obj; // name of the objective "constraint" - // further data gathered 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; @@ -1345,166 +1031,7 @@ private: bool use_put_back_token; std::string put_back_token; -public: - // unofficial helpers used in master_mps_to_derivatives.C; - // these should be considered private for CGAL end-users: - const A_Matrix& A_matrix() { return A_; } - const Vector& b_vector() { return b_; } - const R_vector& r_vector() { return row_types_; } - void add_entry_in_A(unsigned int j, unsigned int i, const IT& val) { - add_entry_in_A (j, i, val, Sparse_A()); - } -private: // helpers to deal with sparse/dense representation: - - void add_column (const Tag_true /*sparse_A*/) - { - // append a new column to A_ (it's empty by default) - A_.push_back(A_col()); - } - - void add_column (const Tag_false /*sparse_A*/) - { - // append a new empty column to A_ - A_.push_back(A_col(row_names.size(), IT(0))); - } - - void initialize_D(unsigned int dimension, const Tag_true /*sparse_D*/ ) - { - // generate dimension many rows (empty by default) - for (unsigned int i=0; isecond; - else - return it0; - } - - const IT& get_entry_in_A(unsigned int j,unsigned int i, - const Tag_false /*sparse_A*/) - { - return A_[j][i]; - } - - void set_entry_in_D(unsigned int i, unsigned int j, const IT& val, - const Tag_true /*sparse_D*/) - { - if (val != it0) D_[i][j] = val; - } - - void set_entry_in_D(unsigned int i, unsigned int j, const IT& val, - const Tag_false /*sparse_D*/) - { - D_[i][j] = val; - } - - const IT& get_entry_in_D(unsigned int i,unsigned int j, - const Tag_true /*sparse_D*/) - { - typename Map::const_iterator it = D_[i].find(j); - if (it != D_[i].end()) - return it->second; - else - return it0; - } - - const IT& get_entry_in_D(unsigned int i,unsigned int j, - const Tag_false /*sparse_D*/) - { - return D_[i][j]; - } - -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; - } - - bool err3(const char* msg, - const std::string& parameter1, - const std::string& parameter2, - const std::string& parameter3) { - error_msg = - replace1(replace1(replace1(msg,parameter1),parameter2),parameter3); - 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: - + // parsing routines // (Note: returns true iff a line-break was eaten.) bool whitespace() { @@ -1570,330 +1097,619 @@ private: // parsing routines: return from.good(); } - bool name_section(); - bool rows_section(); - bool columns_section(); - bool rhs_section(); - bool ranges_section(); - bool bounds_section(); - bool qmatrix_section(); - -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 + bool name_section() { - return verbosity_; + const std::string t = token(); + if (t != "NAME") + return this->err("expected 'NAME'"); + // NAME: everything found until line break; whitespaces are allowed + char c; + std::string token; + std::string whitespaces; + if (whitespace()) + // line break eaten, name is empty + return true; + do { + from.get(c); + if (c == '\r' || c == '\n') break; + if (isspace(c)) + whitespaces.push_back(c); // save whitespace + else { + // new actual character found: previous whitespaces belong to name + name += whitespaces; + whitespaces.clear(); + name.push_back(c); + } + } while (true); + return true; } - // If is_valid() returns false, this routine returns an error - // string describing the problem that was encountered. - // - // Precondition: !is_valid() - const std::string& error() const; - - // Returns the first comment that was read from the MPS stream. - const std::string& comment() const; - - // Returns the number of variables in the QP. - // - // Precondition: is_valid() - int n() const + bool rows_section() { - CGAL_qpe_assertion(is_valid()); - return var_names.size(); - } + std::string t = token(); + if (t != "ROWS") + return this->err1("expected 'ROWS' but found '%'",t); - // Returns the number of constraints in the QP. - // - // Precondition: is_valid() - 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. - const std::string& name_of_variable(int i) - { - CGAL_qpe_assertion(0<=i && i=, <=, or = constraint: + this->set_r (i, + type == 'G'? CGAL::LARGER : + (type == 'E'? CGAL::EQUAL : CGAL::SMALLER)); + if (row_names.find(t) != row_names.end()) + return this->err1("duplicate row name '%' in section ROWS",t); + row_names.insert(String_int_pair(t,i)); + row_by_index.push_back(t); + ++i; } - is_nonnegative_ = true; + break; + default: + return + this->err1 + ("expected 'N', 'L', 'E', or 'G' in ROWS section but found '%'", + symbol); + } + t = token(); } - return is_nonnegative_; + put_token_back(t); + + return true; } + + bool columns_section() + { + std::string t = token(); + if (t != "COLUMNS") + return this->err1("expected 'COLUMNS' but found '%'",t); + + t = token(); + while (t != "RHS") { + // find variable name: + unsigned int var_index; + std::string col_name; + const Index_map::const_iterator var_name = var_names.find(t); + if (var_name == var_names.end()) { // new variable? + var_index = var_names.size(); + col_name = t; + var_names.insert(String_int_pair(t,var_index)); + var_by_index.push_back(t); + } else { // variable that is already known? + var_index = var_name->second; + col_name = var_name->first; + } + + bool doItAgain = true; + for (int i=0; doItAgain; ++i) { + // read row identifier: + t = token(); + + // read number: + NT val; + if (!number(val)) + return this->err2 + ("number expected after row identifier '%' in '%' COLUMNS record", + t,col_name); + + // store number: + if (t == obj) { // objective row? + this->set_c(var_index, val); + } else { // not objective row? + const Index_map::const_iterator row_name = row_names.find(t); + if (row_name == row_names.end()) + return this->err1 + ("unknown row identifier '%' in section COLUMNS",t); + this->set_a (var_index, row_name->second, val); + } + + // determine if we need to read another number: + doItAgain = i==0 && !whitespace(); + } + + // read next token: + t = token(); + } + put_token_back(t); + + return true; + } + + bool rhs_section() + { + this->set_c0 (nt0); // no constant term yet + std::string t = token(); + if (t != "RHS") + return this->err1("expected 'RHS' but found '%'",t); + + t = token(); + std::string rhs_id; + while (t != "RANGES" && t != "BOUNDS" && + t != "DMATRIX" && t != "QMATRIX" && t != "QUADOBJ" && + t != "ENDATA") { + // read rhs identifier and if it is different from the one + // from the previous iteration, ignore the whole row: + bool ignore = false; + std::string ignored; + if (rhs_id.size() == 0) { // first time we enter the loop? + rhs_id = t; + } else { // rhs_id already set + if (t != rhs_id) { + ignore = true; // ignore other rhs identifiers + ignored = t; + } + } + + bool doItAgain = true; + for (int i=0; doItAgain; ++i) { + // read row identifier: + t = token(); + + // read number: + NT val; + if (!number(val)) + return this->err1("number expected after '%' in this RHS record",t); + + // store number: + const Index_map::const_iterator row_name = row_names.find(t); + if (row_name == row_names.end()) { + // no corresponding constraint; is it the constant term? + if (t == obj) + this->set_c0(-val); + else + return this->err1("unknown row identifier '%' in section RHS",t); + } else { + // we have an actual constraint + if (!ignore) { + this->set_b(row_name->second, val); + } else { + this->warn1("rhs with identifier '%' ignored", ignored); + } + } + + // determine if we need to read another number: + doItAgain = i==0 && !whitespace(); + } + + // read next token: + t = token(); + } + put_token_back(t); + + return true; + } + + bool ranges_section() + { + std::string t = token(); + if (t != "RANGES") { // (Note: RANGES section is optional.) + put_token_back(t); + return true; + } + + t = token(); + std::string range_id; + while ((t != "BOUNDS" && t != "QMATRIX" && + t != "DMATRIX" && t != "QUADOBJ" && t != "ENDATA")) { + // read rhs identifier and if it is different from the one + // from the previous iteration, ignore the whole row: + bool ignore = false; + std::string ignored; + if (range_id.size() == 0) { // first time we enter the loop? + range_id = t; + } else { // range_id already set + if (t != range_id) { + ignore = true; // ignore other range identifiers + ignored = t; + } + } + bool doItAgain = true; + for (int i=0; doItAgain; ++i) { + // read row identifier: + t = token(); + + // read number: + NT val; + if (!number(val)) + return this->err1 + ("number expected after '%' in this RANGES record",t); + + // duplicate the constraint, depending on sign of val and type + // of constraint + const Index_map::const_iterator row_name = row_names.find(t); + if (row_name == row_names.end()) { + return this->err1("unknown row identifier '%' in section RANGES",t); + } else { + if (!ignore) { + int index = row_name->second; + CGAL::Comparison_result type = *(this->get_r()+index); + // duplicate the row, unless it has already been duplicated + const Index_map::const_iterator duplicated_row_name = + duplicated_row_names.find(t); + if (duplicated_row_name != duplicated_row_names.end()) + return this->err1 + ("duplicate row identifier '%' in section RANGES",t); + duplicated_row_names.insert(*row_name); + int new_index = this->get_m(); + for (unsigned int j=0; jget_a()+j))[index]; + this->set_a (j, new_index, val); + } + // determine rhs for this new row. Here are the rules: + // if r is the ranges value and b is the old right-hand + // side, then we have h <= constraint <= u according to + // this table: + // + // row type sign of r h u + // ---------------------------------------------- + // G + or - b b + |r| + // L + or - b - |r| b + // E + b b + |r| + // E - b - |r| b + + switch (type) { + case CGAL::LARGER: // introduce "<= b+|r|" + this->set_r(new_index, CGAL::SMALLER); + this->set_b(new_index, *(this->get_b()+index) + CGAL::abs(val)); + break; + case CGAL::SMALLER: // introduce ">= b-|r|" + this->set_r(new_index, CGAL::LARGER); + this->set_b(new_index, *(this->get_b()+index) - CGAL::abs(val)); + break; + case CGAL::EQUAL: + if (CGAL_NTS is_positive (val)) { + // introduce "<= b+|r|" + this->set_r(new_index, CGAL::SMALLER); + } else { + // introduce ">= b-|r|" + this->set_r(new_index, CGAL::LARGER); + } + this->set_b(new_index, *(this->get_b()+index) + val); + break; + default: + CGAL_qpe_assertion(false); + } + } else { + this->warn1("range with identifier '%' ignored", ignored); + } + } + + // determine if we need to read another number: + doItAgain = i==0 && !whitespace(); + } + + // read next token: + t = token(); + } + put_token_back(t); + + return true; + } + + bool bounds_section() + { + std::string t = token(); + if (t != "BOUNDS") { // (Note: BOUNDS section is optional.) + put_token_back(t); + return true; + } + + t = token(); + std::string bound_id; + while (t != "QMATRIX" && t != "DMATRIX" && t != "QUADOBJ" && t != "ENDATA") { + // process type of bound: + enum Bound_type { LO, UP, FX, FR, MI, PL}; + Bound_type type; + if (t=="LO") + type = LO; + else if (t=="UP") + type = UP; + else if (t=="FX") + type = FX; + else if (t=="FR") + type = FR; + else if (t=="MI") + type = MI; + else if (t=="PL") + type = PL; + else + return + this->err1 + ("expected 'LO', 'UP', 'FX', 'FR', 'MI', or 'PL' here but found '%'", + t); + + // remember bound: + const std::string bound = t; + + // find bound label; there may be several, but we only process + // the bounds having the first bound label that occurs. This + // label may be empty, though + t = token(); // bound label or variable name (case of empty bound label) + if (bound_id.size() == 0) { // first time we see a bound label / variable? + const Index_map::const_iterator var_name = var_names.find(t); + if (var_name != var_names.end()) { // is the token a variable? + bound_id = " "; // there is no bound label + put_token_back(t); // the variable name is processed below + } else + bound_id = t; // we found a bound label + } else { + // now we already know the bound label + if (bound_id == " ") // empty bound label? + put_token_back(t); // the variable name is processed below + else + if (t != bound_id) { + this->warn1("ignoring all bounds for bound label '%'",t); + this->warn1("(only bounds for bound label '%' are accepted)", + bound_id); + } + } + + // find variable name; + t = token(); + const Index_map::const_iterator var_name = var_names.find(t); + if (var_name == var_names.end()) // unknown variable? + return this->err1("unknown variable '%' in BOUNDS section",t); + const unsigned int var_index = var_name->second;; + + // read value of bound, if appropriate: + NT val; + if (type==LO || type==UP || type==FX) + if (!number(val)) + return this->err2("expected number after '%' in % bound",t,bound); + + // store bound: + switch (type) { + case FX: + this->set_u (var_index, true, val); + // no break here!! + case LO: + this->set_l (var_index, true, val); + break; + case UP: + this->set_u (var_index, true, val); + if (val <= 0 && *(this->get_fl()+var_index) + && *(this->get_l()+var_index) == 0) + if (val < 0) + this->set_l(var_index, false); + break; + case FR: + this->set_u(var_index, false); + this->set_l(var_index, false); + break; + case MI: + this->set_l(var_index, false); + break; + case PL: + this->set_u(var_index, false); + break; + default: + CGAL_qpe_assertion(false); + } + + // read next token: + t = token(); + } + put_token_back(t); + + return true; + } + + bool qmatrix_section() + { + std::string t = token(); + if (t!="QMATRIX" && t!="DMATRIX" && t!="QUADOBJ") { // optional + put_token_back(t); + return true; + } + + // remember section name: + D_section = t; + const bool multiply_by_two = t=="DMATRIX"; + + t = token(); + std::string bound_id; + while (t != "ENDATA") { + // find first variable name; + const Index_map::const_iterator var1_name = var_names.find(t); + if (var1_name == var_names.end()) // unknown variable? + return this->err2("unknown first variable '%' in '%' section", + t, D_section); + const unsigned int var1_index = var1_name->second; + + // find second variable name; + t = token(); + const Index_map::const_iterator var2_name = var_names.find(t); + if (var2_name == var_names.end()) // unknown variable? + return this->err2("unknown second variable '%' in '%' section", + t, D_section); + const unsigned int var2_index = var2_name->second;; + + // read value: + NT val; + if (!number(val)) + return this->err2("expected number after '%' in section '%'", + t, D_section); + + // multiply by two if approriate: + if (multiply_by_two) + val *= NT(2); + + // set entry in D: + int i, j; + if (var2_index <= var1_index) { + i = var1_index; j = var2_index; + } else { + i = var2_index; j = var1_index; + } + // rule out that we previously put a different (nonzero) value at (i,j) + NT old_val = this->get_d()[i][j]; + if (!CGAL::is_zero(old_val) && old_val != val) + return this->err3("nonsymmetric '%' section at variables '%' and '%'", + D_section, var1_name->first, var2_name->first); + this->set_d(i, j, val); + + // read next token: + t = token(); + } + put_token_back(t); + + return true; + } + }; -template -std::ostream& operator<<(std::ostream& o, - QP_from_mps& qp); - -// Quadratic_program_from_mps, inherits from QP_from_mps -// ----------------------------------------------------- -template -class Quadratic_program_from_mps : - public QP_from_mps +// Quadratic_program +// ----------------- +template +class Quadratic_program: + public Quadratic_program_base { +public: + typedef NT_ NT; private: - typedef QP_from_mps - Base; + typedef Quadratic_program_base Base; public: QP_MODEL_ITERATOR_TYPES; - Quadratic_program_from_mps(std::istream& in, bool use_CPLEX_convention=true, - int verbosity=0) - : Base (in, use_CPLEX_convention, verbosity) + Quadratic_program (CGAL::Comparison_result default_r = CGAL::EQUAL) + : Base (false, false, default_r) {} }; -// Sparse_quadratic_program_from_mps, inherits from QP_from_mps -// ------------------------------------------------------------ -template -class Sparse_quadratic_program_from_mps : - public QP_from_mps +// Nonnegative_quadratic_program +// ----------------------------- +template +class Nonnegative_quadratic_program: + public Quadratic_program_base { +public: + typedef NT_ NT; private: - typedef QP_from_mps - Base; + typedef Quadratic_program_base Base; public: QP_MODEL_ITERATOR_TYPES; - Sparse_quadratic_program_from_mps - (std::istream& in, bool use_CPLEX_convention=true, - int verbosity=0) - : Base (in, use_CPLEX_convention, verbosity) + Nonnegative_quadratic_program + (CGAL::Comparison_result default_r = CGAL::EQUAL) + : Base (false, true, default_r) {} }; -// Linear_program_from_mps, inherits from QP_from_mps -// -------------------------------------------------- -template -class Linear_program_from_mps : - public QP_from_mps +// Nonnegative_linear_program +// -------------------------- +template +class Nonnegative_linear_program: + public Quadratic_program_base { +public: + typedef NT_ NT; private: - typedef QP_from_mps - Base; + typedef Quadratic_program_base Base; public: QP_MODEL_ITERATOR_TYPES; - Linear_program_from_mps(std::istream& in,bool use_CPLEX_convention=true, - int verbosity=0) - : Base (in, use_CPLEX_convention, verbosity) + Nonnegative_linear_program + (CGAL::Comparison_result default_r = CGAL::EQUAL) + : Base (true, true, default_r) {} }; -// Sparse_linear_program_from_mps, inherits from QP_from_mps -// --------------------------------------------------------- -template -class Sparse_linear_program_from_mps : - public QP_from_mps +// Linear_program +// -------------- +template +class Linear_program: + public Quadratic_program_base { +public: + typedef NT_ NT; private: - typedef QP_from_mps - Base; + typedef Quadratic_program_base Base; public: QP_MODEL_ITERATOR_TYPES; - Sparse_linear_program_from_mps - (std::istream& in,bool use_CPLEX_convention=true, - int verbosity=0) - : Base (in, use_CPLEX_convention, verbosity) + Linear_program + (CGAL::Comparison_result default_r = CGAL::EQUAL) + : Base (true, false, default_r) + {} +}; + +// Quadratic_program_from_mps +// -------------------------- +template +class Quadratic_program_from_mps: + public Quadratic_program_from_mps_base +{ +public: + typedef NT_ NT; +private: + typedef Quadratic_program_from_mps_base Base; +public: + QP_MODEL_ITERATOR_TYPES; + Quadratic_program_from_mps (std::istream& in) + : Base (in, false, false) + {} +}; + +// Nonnegative_quadratic_program_from_mps +// -------------------------------------- +template +class Nonnegative_quadratic_program_from_mps: + public Quadratic_program_from_mps_base +{ +public: + typedef NT_ NT; +private: + typedef Quadratic_program_from_mps_base Base; +public: + QP_MODEL_ITERATOR_TYPES; + Nonnegative_quadratic_program_from_mps (std::istream& in) + : Base (in, false, true) + {} +}; + +// Nonnegative_linear_program_from_mps +// ----------------------------------- +template +class Nonnegative_linear_program_from_mps: + public Quadratic_program_from_mps_base +{ +public: + typedef NT_ NT; +private: + typedef Quadratic_program_from_mps_base Base; +public: + QP_MODEL_ITERATOR_TYPES; + Nonnegative_linear_program_from_mps (std::istream& in) + : Base (in, true, true) + {} +}; + +// Linear_program_from_mps +// ----------------------- +template +class Linear_program_from_mps: + public Quadratic_program_from_mps_base +{ +public: + typedef NT_ NT; +private: + typedef Quadratic_program_from_mps_base Base; +public: + QP_MODEL_ITERATOR_TYPES; + Linear_program_from_mps (std::istream& in) + : Base (in, true, false) {} }; CGAL_END_NAMESPACE -#include - #endif // CGAL_QP_MODELS_H diff --git a/QP_solver/include/CGAL/QP_solution.h b/QP_solver/include/CGAL/QP_solution.h index e50b7a80e23..b93825d1080 100644 --- a/QP_solver/include/CGAL/QP_solution.h +++ b/QP_solver/include/CGAL/QP_solution.h @@ -231,85 +231,85 @@ public: Quotient solution() const { - CGAL_qpe_precondition_msg(*(this->ptr()) != 0, "Solution not initialized"); + CGAL_qpe_assertion_msg(*(this->ptr()) != 0, "Solution not initialized"); return (*(this->Ptr()))->solution(); } QP_status status() const { - CGAL_qpe_precondition_msg(*(this->ptr()) != 0, "Solution not initialized"); + CGAL_qpe_assertion_msg(*(this->ptr()) != 0, "Solution not initialized"); return (*(this->Ptr()))->status(); } Variable_value_iterator variable_values_begin() const { - CGAL_qpe_precondition_msg(*(this->ptr()) != 0, "Solution not initialized"); + CGAL_qpe_assertion_msg(*(this->ptr()) != 0, "Solution not initialized"); return (*(this->Ptr()))->original_variable_values_begin(); } Variable_value_iterator variable_values_end() const { - CGAL_qpe_precondition_msg(*(this->ptr()) != 0, "Solution not initialized"); + CGAL_qpe_assertion_msg(*(this->ptr()) != 0, "Solution not initialized"); return (*(this->Ptr()))->original_variable_values_end(); } Variable_numerator_iterator variable_numerators_begin() const { - CGAL_qpe_precondition_msg(*(this->ptr()) != 0, "Solution not initialized"); + CGAL_qpe_assertion_msg(*(this->ptr()) != 0, "Solution not initialized"); return (*(this->Ptr()))->original_variables_numerator_begin(); } Variable_numerator_iterator variable_numerators_end() const { - CGAL_qpe_precondition_msg(*(this->ptr()) != 0, "Solution not initialized"); + CGAL_qpe_assertion_msg(*(this->ptr()) != 0, "Solution not initialized"); return (*(this->Ptr()))->original_variables_numerator_end(); } // ET variable_numerator_value (int i) const // { -// CGAL_qpe_precondition_msg(*(this->ptr()) != 0, "Solution not initialized"); +// CGAL_qpe_assertion_msg(*(this->ptr()) != 0, "Solution not initialized"); // return (*(this->Ptr()))->variable_numerator_value(i); // } const ET& variables_common_denominator() const { - CGAL_qpe_precondition_msg(*(this->ptr()) != 0, "Solution not initialized"); + CGAL_qpe_assertion_msg(*(this->ptr()) != 0, "Solution not initialized"); return (*(this->Ptr()))->variables_common_denominator(); } Index_iterator basic_variable_indices_begin() const { - CGAL_qpe_precondition_msg(*(this->ptr()) != 0, "Solution not initialized"); + CGAL_qpe_assertion_msg(*(this->ptr()) != 0, "Solution not initialized"); return (*(this->Ptr()))->basic_original_variable_indices_begin(); } Index_iterator basic_variable_indices_end() const { - CGAL_qpe_precondition_msg(*(this->ptr()) != 0, "Solution not initialized"); + CGAL_qpe_assertion_msg(*(this->ptr()) != 0, "Solution not initialized"); return (*(this->Ptr()))->basic_original_variable_indices_end(); } int number_of_basic_variables() const { - CGAL_qpe_precondition_msg(*(this->ptr()) != 0, "Solution not initialized"); + CGAL_qpe_assertion_msg(*(this->ptr()) != 0, "Solution not initialized"); return (*(this->Ptr()))->number_of_basic_original_variables(); } Index_iterator basic_constraint_indices_begin() const { - CGAL_qpe_precondition_msg(*(this->ptr()) != 0, "Solution not initialized"); + CGAL_qpe_assertion_msg(*(this->ptr()) != 0, "Solution not initialized"); return (*(this->Ptr()))->basic_constraint_indices_begin(); } Index_iterator basic_constraint_indices_end() const { - CGAL_qpe_precondition_msg(*(this->ptr()) != 0, "Solution not initialized"); + CGAL_qpe_assertion_msg(*(this->ptr()) != 0, "Solution not initialized"); return (*(this->Ptr()))->basic_constraint_indices_end(); } int number_of_basic_constraints() const { - CGAL_qpe_precondition_msg(*(this->ptr()) != 0, "Solution not initialized"); + CGAL_qpe_assertion_msg(*(this->ptr()) != 0, "Solution not initialized"); return (*(this->Ptr()))->number_of_basic_constraints(); } @@ -319,46 +319,46 @@ public: // ---------- // ET optimality_certificate_numerator (int i) // { -// CGAL_qpe_precondition_msg(*(this->ptr()) != 0, "Solution not initialized"); +// CGAL_qpe_assertion_msg(*(this->ptr()) != 0, "Solution not initialized"); // return (*(this->Ptr()))-> // } Optimality_certificate_numerator_iterator optimality_certifcate_numerator_begin() const { - CGAL_qpe_precondition_msg(*(this->ptr()) != 0, "Solution not initialized"); - CGAL_qpe_precondition(status() == QP_OPTIMAL); + CGAL_qpe_assertion_msg(*(this->ptr()) != 0, "Solution not initialized"); + CGAL_qpe_assertion(status() == QP_OPTIMAL); return (*(this->Ptr()))->optimality_certifcate_numerator_begin(); } Optimality_certificate_numerator_iterator optimality_certifcate_numerator_end() const { - CGAL_qpe_precondition_msg(*(this->ptr()) != 0, "Solution not initialized"); - CGAL_qpe_precondition(status() == QP_OPTIMAL); + CGAL_qpe_assertion_msg(*(this->ptr()) != 0, "Solution not initialized"); + CGAL_qpe_assertion(status() == QP_OPTIMAL); return (*(this->Ptr()))->optimality_certifcate_numerator_end(); } Optimality_certificate_iterator optimality_certificate_begin() const { - CGAL_qpe_precondition_msg(*(this->ptr()) != 0, "Solution not initialized"); - CGAL_qpe_precondition(status() == QP_OPTIMAL); + CGAL_qpe_assertion_msg(*(this->ptr()) != 0, "Solution not initialized"); + CGAL_qpe_assertion(status() == QP_OPTIMAL); return (*(this->Ptr()))->optimality_certificate_begin(); } Optimality_certificate_iterator optimality_certificate_end() const { - CGAL_qpe_precondition_msg(*(this->ptr()) != 0, "Solution not initialized"); - CGAL_qpe_precondition(status() == QP_OPTIMAL); + CGAL_qpe_assertion_msg(*(this->ptr()) != 0, "Solution not initialized"); + CGAL_qpe_assertion(status() == QP_OPTIMAL); return (*(this->Ptr()))->optimality_certificate_end(); } ET optimality_certificate_denominator() const { - CGAL_qpe_precondition_msg(*(this->ptr()) != 0, "Solution not initialized"); - CGAL_qpe_precondition(status() == QP_OPTIMAL); + CGAL_qpe_assertion_msg(*(this->ptr()) != 0, "Solution not initialized"); + CGAL_qpe_assertion(status() == QP_OPTIMAL); return (*(this->Ptr()))->optimality_certificate_denominator(); } @@ -367,16 +367,16 @@ public: Infeasibility_certificate_iterator infeasibility_certificate_begin() const { - CGAL_qpe_precondition_msg(*(this->ptr()) != 0, "Solution not initialized"); - CGAL_qpe_precondition(status() == QP_INFEASIBLE); + CGAL_qpe_assertion_msg(*(this->ptr()) != 0, "Solution not initialized"); + CGAL_qpe_assertion(status() == QP_INFEASIBLE); return (*(this->Ptr()))->optimality_certificate_numerator_begin(); } Infeasibility_certificate_iterator infeasibility_certificate_end() const { - CGAL_qpe_precondition_msg(*(this->ptr()) != 0, "Solution not initialized"); - CGAL_qpe_precondition(status() == QP_INFEASIBLE); + CGAL_qpe_assertion_msg(*(this->ptr()) != 0, "Solution not initialized"); + CGAL_qpe_assertion(status() == QP_INFEASIBLE); return (*(this->Ptr()))->optimality_certificate_numerator_end(); } @@ -384,15 +384,15 @@ public: // ------------- Unboundedness_certificate_iterator unboundedness_certificate_begin() const { - CGAL_qpe_precondition_msg(*(this->ptr()) != 0, "Solution not initialized"); - CGAL_qpe_precondition(status() == QP_UNBOUNDED); + CGAL_qpe_assertion_msg(*(this->ptr()) != 0, "Solution not initialized"); + CGAL_qpe_assertion(status() == QP_UNBOUNDED); return (*(this->Ptr()))->unbounded_direction_begin(); } Unboundedness_certificate_iterator unboundedness_certificate_end() const { - CGAL_qpe_precondition_msg(*(this->ptr()) != 0, "Solution not initialized"); - CGAL_qpe_precondition(status() == QP_UNBOUNDED); + CGAL_qpe_assertion_msg(*(this->ptr()) != 0, "Solution not initialized"); + CGAL_qpe_assertion(status() == QP_UNBOUNDED); return (*(this->Ptr()))->unbounded_direction_end(); } diff --git a/QP_solver/include/CGAL/QP_solver.h b/QP_solver/include/CGAL/QP_solver.h index 735997589e9..32785ce1072 100644 --- a/QP_solver/include/CGAL/QP_solver.h +++ b/QP_solver/include/CGAL/QP_solver.h @@ -534,14 +534,14 @@ private: // ---------- // pivot step QP_status pivot( ) - { CGAL_qpe_precondition( phase() > 0); - CGAL_qpe_precondition( phase() < 3); + { CGAL_qpe_assertion( phase() > 0); + CGAL_qpe_assertion( phase() < 3); pivot_step(); return status(); } // solve QP QP_status solve( ) - { CGAL_qpe_precondition( phase() > 0); + { CGAL_qpe_assertion( phase() > 0); while ( phase() < 3) { pivot_step(); } return status(); } @@ -686,15 +686,15 @@ public: // only the pricing strategies (including user-defined ones bool is_basic( int j) const { - CGAL_qpe_precondition(j >= 0); - CGAL_qpe_precondition(j < number_of_working_variables()); + CGAL_qpe_assertion(j >= 0); + CGAL_qpe_assertion(j < number_of_working_variables()); return (in_B[ j] >= 0); } bool is_original(int j) const { - CGAL_qpe_precondition(j >= 0); - CGAL_qpe_precondition(j < number_of_working_variables()); + CGAL_qpe_assertion(j >= 0); + CGAL_qpe_assertion(j < number_of_working_variables()); return (j < qp_n); } @@ -726,7 +726,7 @@ public: // only the pricing strategies (including user-defined ones // Returns w[j] for an original variable x_j. ET w_j_numerator(int j) const { - CGAL_qpe_precondition((0 <= j) && (j < qp_n) && is_phaseII); + CGAL_qpe_assertion((0 <= j) && (j < qp_n) && is_phaseII); return w[j]; } @@ -1970,7 +1970,7 @@ template < typename Q, typename ET, typename Tags > inline bool QP_solver:: basis_matrix_stays_regular() { - CGAL_qpe_precondition( is_phaseII); + CGAL_qpe_assertion( is_phaseII); int new_row, k; if ( has_ineq && (i >= qp_n)) { // slack variable diff --git a/QP_solver/include/CGAL/QP_solver/Initialization.h b/QP_solver/include/CGAL/QP_solver/Initialization.h index fb5ac2cac14..2b11e2075bc 100644 --- a/QP_solver/include/CGAL/QP_solver/Initialization.h +++ b/QP_solver/include/CGAL/QP_solver/Initialization.h @@ -76,7 +76,7 @@ template < typename Q, typename ET, typename Tags > void QP_solver:: set_D(const Q& qp, Tag_false /*is_linear*/) { - qp_D = qp.d(); + qp_D = qp.get_d(); } template < typename Q, typename ET, typename Tags > @@ -84,15 +84,15 @@ void QP_solver:: set(const Q& qp) { // assertions: - CGAL_qpe_precondition(qp.n() > 0); - CGAL_qpe_precondition(qp.m() >= 0); + CGAL_qpe_assertion(qp.get_n() >= 0); + CGAL_qpe_assertion(qp.get_m() >= 0); // store QP - qp_n = qp.n(); qp_m = qp.m(); - qp_A = qp.a(); qp_b = qp.b(); qp_c = qp.c(); qp_c0 = qp.c0(); + qp_n = qp.get_n(); qp_m = qp.get_m(); + qp_A = qp.get_a(); qp_b = qp.get_b(); qp_c = qp.get_c(); qp_c0 = qp.get_c0(); set_D(qp, Is_linear()); - qp_r = qp.r(); + qp_r = qp.get_r(); // set up slack variables and auxiliary problem // -------------------------------------------- @@ -171,10 +171,10 @@ set_explicit_bounds(const Q& /*qp*/, Tag_true) { template < typename Q, typename ET, typename Tags > void QP_solver:: set_explicit_bounds(const Q& qp, Tag_false) { - qp_fl = qp.fl(); - qp_l = qp.l(); - qp_fu = qp.fu(); - qp_u = qp.u(); + qp_fl = qp.get_fl(); + qp_l = qp.get_l(); + qp_fu = qp.get_fu(); + qp_u = qp.get_u(); } @@ -339,7 +339,7 @@ init() init_solution(); // initialize pricing strategy - CGAL_qpe_precondition(strategyP != static_cast< Pricing_strategy*>(0)); + CGAL_qpe_assertion(strategyP != static_cast< Pricing_strategy*>(0)); strategyP->init(0); // basic feasible solution already available? @@ -389,8 +389,8 @@ init_basis() // we only have equality constraints // art_A.push_back(std::make_pair(s_i, !slack_A[s_i].second)); - CGAL_qpe_precondition(s_i_absolute >= 0); - CGAL_qpe_precondition(s_i_absolute == slack_A[s_i].first); + CGAL_qpe_assertion(s_i_absolute >= 0); + CGAL_qpe_assertion(s_i_absolute == slack_A[s_i].first); art_A.push_back(std::make_pair(s_i_absolute, !slack_A[s_i].second)); } @@ -572,7 +572,7 @@ init_solution() // latter restricted to basic variables B_O: if (!minus_c_B.empty()) minus_c_B.clear(); minus_c_B.insert(minus_c_B.end(), l, -et1); // todo: what is minus_c_B? - CGAL_qpe_precondition(l >= (int)art_A.size()); + CGAL_qpe_assertion(l >= (int)art_A.size()); if (art_s_i > 0) minus_c_B[art_A.size()-1] *= ET(qp_n+qp_m); // Note: the idea here is to // give more weight to the diff --git a/QP_solver/include/CGAL/QP_solver/QP_basis_inverse.h b/QP_solver/include/CGAL/QP_solver/QP_basis_inverse.h index 59b233496d6..a02cce8458f 100644 --- a/QP_solver/include/CGAL/QP_solver/QP_basis_inverse.h +++ b/QP_solver/include/CGAL/QP_solver/QP_basis_inverse.h @@ -103,12 +103,12 @@ class QP_basis_inverse { // special matrix-vector multiplication functions for LPs template < class ForwardIterator, class OutputIterator > inline void multiply_l( ForwardIterator v_x_it, OutputIterator y_l_it) const - { CGAL_qpe_precondition( is_LP || is_phaseI); + { CGAL_qpe_assertion( is_LP || is_phaseI); multiply__l( v_x_it, y_l_it); } template < class ForwardIterator, class OutputIterator > inline void multiply_x( ForwardIterator v_l_it, OutputIterator y_x_it) const - { CGAL_qpe_precondition( is_LP || is_phaseI); + { CGAL_qpe_assertion( is_LP || is_phaseI); multiply__x( v_l_it, y_x_it); } // vector-matrix multiplication ( x^T = u^T M ) @@ -221,10 +221,10 @@ class QP_basis_inverse { // swap functions void swap_variable( unsigned int j) // ``to the end'' of R - { CGAL_qpe_precondition( j < b); + { CGAL_qpe_assertion( j < b); swap_variable( j, Is_LP()); } void swap_constraint( unsigned int i) // ``to the end'' of P - { CGAL_qpe_precondition( i < s); + { CGAL_qpe_assertion( i < s); swap_constraint( i, Is_LP()); } private: @@ -323,13 +323,13 @@ class QP_basis_inverse { void init( unsigned int art_size, InputIterator art_first) { - CGAL_qpe_precondition_msg( art_size <= l, \ + CGAL_qpe_assertion_msg( art_size <= l, \ "There are more equality constraints than original variables!"); init( art_size, art_first, Is_LP()); d = et1; - CGAL_qpe_postcondition( s == art_size); - CGAL_qpe_postcondition( b == art_size); + CGAL_qpe_assertion( s == art_size); + CGAL_qpe_assertion( b == art_size); is_phaseI = true; is_phaseII = false; @@ -438,7 +438,7 @@ class QP_basis_inverse { // update matrix in-place // ---------------------- // handle sign of new denominator - CGAL_qpe_precondition( z != et0); + CGAL_qpe_assertion( z != et0); bool z_neg = ( z < et0); // update matrix @@ -478,7 +478,7 @@ class QP_basis_inverse { // store new denominator // --------------------- d = ( z_neg ? -z : z); - CGAL_qpe_postcondition( d > et0); + CGAL_qpe_assertion( d > et0); CGAL_qpe_debug { if ( vout.verbose()) print(); @@ -502,7 +502,7 @@ class QP_basis_inverse { Tag_false()); // ignore 1st argument ET z = -inner_product_x( x_x.begin(), u_x_it); bool z_neg = ( z < et0); - CGAL_qpe_precondition( z != et0); + CGAL_qpe_assertion( z != et0); // update matrix update_inplace_QP( x_l.begin(), x_x.begin(), z, ( z_neg ? -d : d)); @@ -535,7 +535,7 @@ class QP_basis_inverse { // store new denominator // --------------------- d = ( z_neg ? -z : z); - CGAL_qpe_postcondition( d > et0); + CGAL_qpe_assertion( d > et0); CGAL_qpe_debug { if ( vout.verbose()) print(); @@ -548,8 +548,8 @@ class QP_basis_inverse { enter_original_leave_original( RandomAccessIterator y_x_it, unsigned int k) { // assert LP case or phase I - CGAL_qpe_precondition( is_LP || is_phaseI); - CGAL_qpe_precondition( k < b); + CGAL_qpe_assertion( is_LP || is_phaseI); + CGAL_qpe_assertion( k < b); // update matrix in place // ---------------------- @@ -599,7 +599,7 @@ class QP_basis_inverse { // store new denominator // --------------------- d = ( z_neg ? -z : z); - CGAL_qpe_postcondition( d > et0); + CGAL_qpe_assertion( d > et0); // diagnostic output CGAL_qpe_debug { @@ -613,8 +613,8 @@ class QP_basis_inverse { enter_slack_leave_slack( ForwardIterator u_x_it, unsigned int k) { // assert LP case or phase I - CGAL_qpe_precondition( is_LP || is_phaseI); - CGAL_qpe_precondition( k < s); + CGAL_qpe_assertion( is_LP || is_phaseI); + CGAL_qpe_assertion( k < s); // compute new row of basis inverse multiply__l( u_x_it, x_x.begin()); @@ -663,7 +663,7 @@ class QP_basis_inverse { // store new denominator // --------------------- d = ( z_neg ? -z : z); - CGAL_qpe_postcondition( d > et0); + CGAL_qpe_assertion( d > et0); // diagnostic output CGAL_qpe_debug { @@ -677,7 +677,7 @@ class QP_basis_inverse { ForwardIterator2 u_x_it) { // assert LP case or phase I - CGAL_qpe_precondition( is_LP || is_phaseI); + CGAL_qpe_assertion( is_LP || is_phaseI); // update matrix in-place // ---------------------- @@ -685,7 +685,7 @@ class QP_basis_inverse { multiply__l( u_x_it, x_x.begin()); ET z = d*u_x_it[ b] - inner_product_x( y_x_it, u_x_it); bool z_neg = ( z < et0); - CGAL_qpe_precondition( z != et0); + CGAL_qpe_assertion( z != et0); // update matrix update_inplace_LP( x_x.begin(), y_x_it, z, ( z_neg ? -d : d)); @@ -722,7 +722,7 @@ class QP_basis_inverse { // store new denominator // --------------------- d = ( z_neg ? -z : z); - CGAL_qpe_postcondition( d > et0); + CGAL_qpe_assertion( d > et0); CGAL_qpe_debug { if ( vout.verbose()) print(); @@ -762,21 +762,21 @@ class QP_basis_inverse { // append row in Q if no allocated row available void ensure_physical_row (unsigned int row) { unsigned int rows = M.size(); - CGAL_qpe_precondition(rows >= row); + CGAL_qpe_assertion(rows >= row); if (rows == row) { M.push_back(Row(row+1, et0)); // do we have to grow x_x? - CGAL_qpe_precondition(x_x.size() >= row-l); + CGAL_qpe_assertion(x_x.size() >= row-l); if (x_x.size() == row-l) x_x.push_back(et0); // do we have to grow tmp_x? - CGAL_qpe_precondition(tmp_x.size() >= row-l); + CGAL_qpe_assertion(tmp_x.size() >= row-l); if (tmp_x.size() == row-l) tmp_x.push_back(et0); - CGAL_qpe_postcondition(M[row].size()==row+1); + CGAL_qpe_assertion(M[row].size()==row+1); CGAL_qpe_debug { if ( vout.verbose()) { vout << "physical row " << (row) << " appended in Q\n"; @@ -1101,8 +1101,8 @@ template < class ET_, class Is_LP_ > inline const ET_& QP_basis_inverse:: entry( unsigned int r, unsigned int c, Tag_false) const { - CGAL_qpe_precondition( ( r < s) || ( ( r >= l) && ( r < l+b))); - CGAL_qpe_precondition( ( c < s) || ( ( c >= l) && ( c < l+b))); + CGAL_qpe_assertion( ( r < s) || ( ( r >= l) && ( r < l+b))); + CGAL_qpe_assertion( ( c < s) || ( ( c >= l) && ( c < l+b))); return ( c < r ? M[ r][ c] : M[ c][ r]); } @@ -1111,8 +1111,8 @@ template < class ET_, class Is_LP_ > inline const ET_& QP_basis_inverse:: entry( unsigned int r, unsigned int c, Tag_true) const { - CGAL_qpe_precondition( r < s); - CGAL_qpe_precondition( c < b); + CGAL_qpe_assertion( r < s); + CGAL_qpe_assertion( c < b); return M[ r][ c]; } diff --git a/QP_solver/include/CGAL/QP_solver/QP_basis_inverse_impl.h b/QP_solver/include/CGAL/QP_solver/QP_basis_inverse_impl.h index ce4584d33b7..19aac51f21c 100644 --- a/QP_solver/include/CGAL/QP_solver/QP_basis_inverse_impl.h +++ b/QP_solver/include/CGAL/QP_solver/QP_basis_inverse_impl.h @@ -33,8 +33,8 @@ template < class ET_, class Is_LP_ > void QP_basis_inverse:: set( int n, int m, int nr_equalities) { - CGAL_qpe_precondition( n > 0); - //CGAL_qpe_precondition( m > 0); + CGAL_qpe_assertion( n >= 0); + CGAL_qpe_assertion( m >= 0); b = s = 0; // l is the maximum size of the basis in phase I l = (std::min)( n+nr_equalities+1, m); @@ -69,7 +69,7 @@ leave_original( ) --b; ET z = M[ l+b][ l+b]; bool z_neg = ( z < et0); - CGAL_qpe_precondition( z != et0); + CGAL_qpe_assertion( z != et0); // update matrix in place update_inplace_QP( M[ l+b].begin(), M[ l+b].begin()+l, @@ -77,7 +77,7 @@ leave_original( ) // store new denominator d = ( z_neg ? -z : z); - CGAL_qpe_postcondition( d > et0); + CGAL_qpe_assertion( d > et0); CGAL_qpe_debug { if ( vout.verbose()) print(); @@ -96,7 +96,7 @@ enter_slack( ) --s; ET z = M[ s][ s]; bool z_neg = ( z < et0); - CGAL_qpe_precondition( z != et0); + CGAL_qpe_assertion( z != et0); // update matrix in place typename Matrix::iterator col_it; @@ -111,7 +111,7 @@ enter_slack( ) // store new denominator d = ( z_neg ? -z : z); - CGAL_qpe_postcondition( d > et0); + CGAL_qpe_assertion( d > et0); CGAL_qpe_debug { if ( vout.verbose()) print(); @@ -124,7 +124,7 @@ void QP_basis_inverse:: enter_slack_leave_original( ) { // assert LP case or phase I - CGAL_qpe_precondition( is_LP || is_phaseI); + CGAL_qpe_assertion( is_LP || is_phaseI); // update matrix in-place // ---------------------- @@ -145,7 +145,7 @@ enter_slack_leave_original( ) } ET z = (*matrix_it)[ b]; bool z_neg = ( z < et0); - CGAL_qpe_precondition( z != et0); + CGAL_qpe_assertion( z != et0); // update matrix update_inplace_LP( matrix_it->begin(), x_x.begin(), -z, ( z_neg ? d : -d)); @@ -153,7 +153,7 @@ enter_slack_leave_original( ) // store new denominator // --------------------- d = ( z_neg ? -z : z); - CGAL_qpe_postcondition( d > et0); + CGAL_qpe_assertion( d > et0); CGAL_qpe_debug { if ( vout.verbose()) print(); @@ -172,7 +172,7 @@ z_replace_original_by_original(ForwardIterator y_l_it, { // assert QP case and phaseII - CGAL_qpe_precondition(is_QP && is_phaseII); + CGAL_qpe_assertion(is_QP && is_phaseII); // prepare \hat{k}_{1} -scalar @@ -197,7 +197,7 @@ z_replace_original_by_original(ForwardIterator y_l_it, // prepare \hat{k}_{2} -scalar ET hat_k_2 = s_nu - (et2 * s_delta * hat_k_1); - CGAL_qpe_precondition( d != et0); + CGAL_qpe_assertion( d != et0); // update matrix in place z_update_inplace(x_l.begin(), x_x.begin(), tmp_l.begin(), tmp_x.begin(), @@ -206,7 +206,7 @@ z_replace_original_by_original(ForwardIterator y_l_it, // store new denominator d = CGAL::integral_division(hat_k_1 * hat_k_1, d); - CGAL_qpe_postcondition( d > et0); + CGAL_qpe_assertion( d > et0); CGAL_qpe_debug { if ( vout.verbose()) print(); @@ -223,7 +223,7 @@ z_replace_original_by_slack( ) { // assert QP case and phaseII - CGAL_qpe_precondition(is_QP && is_phaseII); + CGAL_qpe_assertion(is_QP && is_phaseII); // adapt s and b --s; --b; @@ -240,7 +240,7 @@ z_replace_original_by_slack( ) // prepare \hat{\xi} -scalar ET hat_xi = M[s][s]; - CGAL_qpe_precondition( d != et0); + CGAL_qpe_assertion( d != et0); // update matrix in place z_update_inplace(x_l.begin(), x_x.begin(), tmp_l.begin(), tmp_x.begin(), @@ -249,7 +249,7 @@ z_replace_original_by_slack( ) // store new denominator d = CGAL::integral_division(hat_kappa * hat_kappa, d); - CGAL_qpe_postcondition( d > et0); + CGAL_qpe_assertion( d > et0); CGAL_qpe_debug { if ( vout.verbose()) print(); @@ -269,13 +269,13 @@ z_replace_slack_by_original(ForwardIterator y_l_it, const ET& hat_nu) { // assert QP case and phaseII - CGAL_qpe_precondition(is_QP && is_phaseII); + CGAL_qpe_assertion(is_QP && is_phaseII); // get copies of y_l_it and y_x_it for later use ForwardIterator y_l_it_copy = y_l_it; ForwardIterator y_x_it_copy = y_x_it; - CGAL_qpe_precondition( d != et0); + CGAL_qpe_assertion( d != et0); // prepare \hat{\phi} @@ -349,7 +349,7 @@ z_replace_slack_by_original(ForwardIterator y_l_it, // store new denominator d = CGAL::integral_division(hat_kappa * hat_kappa, d); - CGAL_qpe_postcondition( d > et0); + CGAL_qpe_assertion( d > et0); CGAL_qpe_debug { if ( vout.verbose()) print(); @@ -367,7 +367,7 @@ z_replace_slack_by_slack(ForwardIterator u_x_it, unsigned int k_j) { // assert QP case and phaseII - CGAL_qpe_precondition(is_QP && is_phaseII); + CGAL_qpe_assertion(is_QP && is_phaseII); // prepare \hat{v} -vector in x_l, x_x multiply(u_x_it, u_x_it, x_l.begin(), x_x.begin(),Tag_false(), @@ -383,7 +383,7 @@ z_replace_slack_by_slack(ForwardIterator u_x_it, unsigned int k_j) // prepare \hat{k}_{3} -scalar ET hat_k_3 = -M[k_j][k_j]; - CGAL_qpe_precondition( d != et0); + CGAL_qpe_assertion( d != et0); // update matrix in place z_update_inplace(x_l.begin(), x_x.begin(), tmp_l.begin(), tmp_x.begin(), @@ -392,7 +392,7 @@ z_replace_slack_by_slack(ForwardIterator u_x_it, unsigned int k_j) // store new denominator d = CGAL::integral_division(hat_k_1 * hat_k_1, d); - CGAL_qpe_postcondition( d > et0); + CGAL_qpe_assertion( d > et0); CGAL_qpe_debug { if ( vout.verbose()) print(); diff --git a/QP_solver/include/CGAL/QP_solver/QP_functions_impl.h b/QP_solver/include/CGAL/QP_solver/QP_functions_impl.h index 5e6cda82126..4f1ce7fd395 100644 --- a/QP_solver/include/CGAL/QP_solver/QP_functions_impl.h +++ b/QP_solver/include/CGAL/QP_solver/QP_functions_impl.h @@ -32,8 +32,8 @@ namespace QP_functions_detail { template bool is_in_equational_form (const R& r) { - typename R::R_iterator it = r.r(); - typename R::R_iterator end = it + r.m(); + typename R::R_iterator it = r.get_r(); + typename R::R_iterator end = it + r.get_m(); for (; it < end; ++it) if (*it != CGAL::EQUAL) return false; return true; @@ -67,7 +67,7 @@ namespace QP_functions_detail { typename Ar::R_iterator, C_iterator> LP; // auxiliary LP - LP lp (ar.n(), ar.m(), ar.a(), B_iterator(0), ar.r(), C_iterator(0)); + LP lp (ar.get_n(), ar.get_m(), ar.get_a(), B_iterator(0), ar.get_r(), C_iterator(0)); // solver Tags typedef QP_solver_impl::QP_tags< @@ -98,11 +98,11 @@ namespace QP_functions_detail { (std::ostream& out, const P& p, CGAL::Tag_false /*is_nonnegative*/) { - typename P::FL_iterator fl = p.fl(); - typename P::FU_iterator fu = p.fu(); - typename P::L_iterator l = p.l(); - typename P::U_iterator u = p.u(); - int n = p.n(); + typename P::FL_iterator fl = p.get_fl(); + typename P::FU_iterator fu = p.get_fu(); + typename P::L_iterator l = p.get_l(); + typename P::U_iterator u = p.get_u(); + int n = p.get_n(); out << "BOUNDS\n"; for (int j=0; j::value_type IT; out << "COLUMNS\n"; @@ -322,10 +322,10 @@ namespace QP_functions_detail { } // RHS section: - typename P::B_iterator b = p.b(); + typename P::B_iterator b = p.get_b(); out << "RHS\n"; - if (!CGAL_NTS is_zero (p.c0())) - out << " rhs obj " << -p.c0() << "\n"; + if (!CGAL_NTS is_zero (p.get_c0())) + out << " rhs obj " << -p.get_c0() << "\n"; for (int i=0; i -// Bernd Gaertner -// Franz Wessendorp -// Kaspar Fischer - -#include -#include -#include -#include - -CGAL_BEGIN_NAMESPACE - -template -QP_from_mps:: -QP_from_mps(std::istream& in,bool use_CPLEX_convention, - int verbosity) - : has_linear_tag (check_tag(Is_linear_())), - verbosity_(verbosity), from(in), - is_format_okay_(false), - is_linear_(true), - use_CPLEX_convention(use_CPLEX_convention), - it0(0), - is_nonnegative_cached(false), - use_put_back_token(false) -{ - // read NAME section: - if (!name_section()) - return; - - // read ROWS section: - if (!rows_section()) - return; - - // read COLUMNS section: - if (!columns_section()) - return; - - // read RHS section: - if (!rhs_section()) - return; - - // check for (optional) RANGES section: - if (!ranges_section()) - return; - - // read optional BOUNDS section: - if (!bounds_section()) - return; - - // initialize matrix D (in the linear case, this is not needed, - // since we return a Const_oneset_iterator that never accesses D - if (!has_linear_tag) - initialize_D(var_names.size(), Sparse_D()); - - // read optional QMATRIX section: - if (!qmatrix_section()) - return; - - // check for ENDATA: - const std::string end = token(); - if (end != "ENDATA") { - err1("ENDDATA expected but found '%'",end); - return; - } - - //std::cout << "MPS stream successfully read." << std::endl; - is_format_okay_ = true; -} - -template -bool QP_from_mps::is_valid() const -{ - return is_format_okay_; -} - -template -const std::string& QP_from_mps::error() const -{ - CGAL_qpe_assertion(!is_valid()); - return error_msg; -} - -template -const std::string& QP_from_mps::comment() const -{ - return comment_; -} - -template -bool QP_from_mps -::is_symmetric(Tag_false /*sparse_D*/, unsigned int&i, unsigned int&j) const -{ - // only called if we have a qp, i.e. if D is initialized - const unsigned int var_nr = var_names.size(); - for (i=0; i -bool QP_from_mps -::is_symmetric(Tag_true /*sparse_D*/, unsigned int&i, unsigned int&j) const -{ - // only called if we have a qp, i.e. if D is initialized - const unsigned int var_nr = var_names.size(); - for (i=0; ifirst; - // check entry (j, i) - IT expected_val = b->second; - IT found_val = it0; - typename Map::const_iterator it = D_[j].find(i); - if (it != D_[j].end()) found_val = it->second; - if (expected_val != found_val) return false; - } - } - return true; -} - - -template -bool QP_from_mps::name_section() -{ - const std::string t = token(); - if (t != "NAME") - return err("expected 'NAME'"); - // NAME: everything found until line break; whitespaces are allowed - char c; - std::string token; - std::string whitespaces; - if (whitespace()) - // line break eaten, name is empty - return true; - do { - from.get(c); - if (c == '\r' || c == '\n') break; - if (isspace(c)) - whitespaces.push_back(c); // save whitespace - else { - // new actual character found: previous whitespaces belong to name - name += whitespaces; - whitespaces.clear(); - name.push_back(c); - } - } while (true); - return true; -} - -template -bool QP_from_mps::rows_section() -{ - std::string t = token(); - if (t != "ROWS") - return err1("expected 'ROWS' but found '%'",t); - - // read 'N', 'G', 'L', or 'E', and the name of the constraint: - t = token(); - while (t != "COLUMNS") { - const char type = t[0]; - const std::string symbol(t); // for error message below - t = token(); - switch (type) { - case 'N': - // register name of objective row: - if (obj.size() == 0) // remember first (and ignore others) - obj = t; - break; - case 'G': - case 'L': - case 'E': - { - // register name of >=, <=, or = constraint: - const unsigned int index = row_types_.size(); - row_types_.push_back(type == 'G'? CGAL::LARGER : - (type == 'E'? CGAL::EQUAL : CGAL::SMALLER)); - if (row_names.find(t) != row_names.end()) - return err1("duplicate row name '%' in section ROWS",t); - row_names.insert(String_int_pair(t,index)); - row_by_index.push_back(t); - b_.push_back(IT(0)); - } - break; - default: - return err1( - "expected 'N', 'L', 'E', or 'G' in ROWS section but found '%'", - symbol); - } - t = token(); - } - put_token_back(t); - - return true; -} - -template -bool QP_from_mps::columns_section() -{ - std::string t = token(); - if (t != "COLUMNS") - return err1("expected 'COLUMNS' but found '%'",t); - - t = token(); - while (t != "RHS") { - // find variable name: - unsigned int var_index; - std::string col_name; - const Index_map::const_iterator var_name = var_names.find(t); - if (var_name == var_names.end()) { // new variable? - var_index = var_names.size(); - col_name = t; - var_names.insert(String_int_pair(t,var_index)); - var_by_index.push_back(t); - add_column (Sparse_A_()); - c_.push_back(IT(0)); - fl_.push_back(true); // default lower bound is finite... - l_.push_back(IT(0)); // ...namely zero - fu_.push_back(false); // default upper bound is infinite - u_.push_back(IT()); // (dummy value) - } else { // variable that is already known? - var_index = var_name->second; - col_name = var_name->first; - } - - bool doItAgain = true; - for (int i=0; doItAgain; ++i) { - // read row identifier: - t = token(); - - // read number: - IT val; - if (!number(val)) - return err2("number expected after row identifier '%' in '%' COLUMNS record",t,col_name); - - // store number: - if (t == obj) { // objective row? - c_[var_index] = val; - } else { // not objective row? - const Index_map::const_iterator row_name = row_names.find(t); - if (row_name == row_names.end()) - return err1("unknown row identifier '%' in section COLUMNS",t); - set_entry_in_A (var_index, row_name->second, val, Sparse_A_()); - } - - // determine if we need to read another number: - doItAgain = i==0 && !whitespace(); - } - - // read next token: - t = token(); - } - put_token_back(t); - - return true; -} - -template -bool QP_from_mps::rhs_section() -{ - c_0 = IT(0); // no constant term yet - std::string t = token(); - if (t != "RHS") - return err1("expected 'RHS' but found '%'",t); - - t = token(); - std::string rhs_id; - while (t != "RANGES" && t != "BOUNDS" && - t != "DMATRIX" && t != "QMATRIX" && t != "QUADOBJ" && - t != "ENDATA") { - // read rhs identifier and if it is different from the one - // from the previous iteration, ignore the whole row: - bool ignore = false; - std::string ignored; - if (rhs_id.size() == 0) { // first time we enter the loop? - rhs_id = t; - } else { // rhs_id already set - if (t != rhs_id) { - ignore = true; // ignore other rhs identifiers - ignored = t; - } - } - - bool doItAgain = true; - for (int i=0; doItAgain; ++i) { - // read row identifier: - t = token(); - - // read number: - IT val; - if (!number(val)) - return err1("number expected after '%' in this RHS record",t); - - // store number: - const Index_map::const_iterator row_name = row_names.find(t); - if (row_name == row_names.end()) { - // no corresponding constraint; is it the constant term? - if (t == obj) - c_0 = -val; - else - return err1("unknown row identifier '%' in section RHS",t); - } else { - // we have an actual constraint - if (!ignore) { - b_[row_name->second] = val; - } else { - warn1("rhs with identifier '%' ignored", ignored); - } - } - - // determine if we need to read another number: - doItAgain = i==0 && !whitespace(); - } - - // read next token: - t = token(); - } - put_token_back(t); - - return true; -} - -template -bool QP_from_mps::ranges_section() -{ - std::string t = token(); - if (t != "RANGES") { // (Note: RANGES section is optional.) - put_token_back(t); - return true; - } - - t = token(); - std::string range_id; - while ((t != "BOUNDS" && t != "QMATRIX" && - t != "DMATRIX" && t != "QUADOBJ" && t != "ENDATA")) { - // read rhs identifier and if it is different from the one - // from the previous iteration, ignore the whole row: - bool ignore = false; - std::string ignored; - if (range_id.size() == 0) { // first time we enter the loop? - range_id = t; - } else { // range_id already set - if (t != range_id) { - ignore = true; // ignore other range identifiers - ignored = t; - } - } - bool doItAgain = true; - for (int i=0; doItAgain; ++i) { - // read row identifier: - t = token(); - - // read number: - IT val; - if (!number(val)) - return err1("number expected after '%' in this RANGES record",t); - - // duplicate the constraint, depending on sign of val and type - // of constraint - const Index_map::const_iterator row_name = row_names.find(t); - if (row_name == row_names.end()) { - return err1("unknown row identifier '%' in section RANGES",t); - } else { - if (!ignore) { - int index = row_name->second; - CGAL::Comparison_result type = row_types_[index]; - // duplicate the row, unless it has already been duplicated - const Index_map::const_iterator duplicated_row_name = - duplicated_row_names.find(t); - if (duplicated_row_name != duplicated_row_names.end()) - return err1("duplicate row identifier '%' in section RANGES",t); - duplicated_row_names.insert(*row_name); - int new_index = b_.size(); - for (unsigned int j=0; j= b-|r|" - row_types_.push_back(CGAL::LARGER); - b_.push_back(b_[index] - CGAL::abs(val)); - break; - case CGAL::EQUAL: - if (CGAL_NTS is_positive (val)) { - // introduce "<= b+|r|" - row_types_.push_back(CGAL::SMALLER); - } else { - // introduce ">= b-|r|" - row_types_.push_back(CGAL::LARGER); - } - b_.push_back(b_[index] + val); - break; - default: - CGAL_qpe_assertion(false); - } - } else { - warn1("range with identifier '%' ignored", ignored); - } - } - - // determine if we need to read another number: - doItAgain = i==0 && !whitespace(); - } - - // read next token: - t = token(); - } - put_token_back(t); - - return true; - -} - - - -template -bool QP_from_mps::bounds_section() -{ - std::string t = token(); - if (t != "BOUNDS") { // (Note: BOUNDS section is optional.) - put_token_back(t); - return true; - } - - t = token(); - std::string bound_id; - while (t != "QMATRIX" && t != "DMATRIX" && t != "QUADOBJ" && t != "ENDATA") { - // process type of bound: - enum Bound_type { LO, UP, FX, FR, MI, PL}; - Bound_type type; - if (t=="LO") - type = LO; - else if (t=="UP") - type = UP; - else if (t=="FX") - type = FX; - else if (t=="FR") - type = FR; - else if (t=="MI") - type = MI; - else if (t=="PL") - type = PL; - else - return - err1("expected 'LO', 'UP', 'FX', 'FR', 'MI', or 'PL' here but found '%'",t); - - // remember bound: - const std::string bound = t; - - // find bound label; there may be several, but we only process - // the bounds having the first bound label that occurs. This - // label may be empty, though - t = token(); // bound label or variable name (case of empty bound label) - if (bound_id.size() == 0) { // first time we see a bound label / variable? - const Index_map::const_iterator var_name = var_names.find(t); - if (var_name != var_names.end()) { // is the token a variable? - bound_id = " "; // there is no bound label - put_token_back(t); // the variable name is processed below - } else - bound_id = t; // we found a bound label - } else { - // now we already know the bound label - if (bound_id == " ") // empty bound label? - put_token_back(t); // the variable name is processed below - else - if (t != bound_id) { - warn1("ignoring all bounds for bound label '%'",t); - warn1("(only bounds for bound label '%' are accepted)",bound_id); - } - } - - // find variable name; - t = token(); - const Index_map::const_iterator var_name = var_names.find(t); - if (var_name == var_names.end()) // unknown variable? - return err1("unknown variable '%' in BOUNDS section",t); - const unsigned int var_index = var_name->second;; - - // read value of bound, if appropriate: - IT val; - if (type==LO || type==UP || type==FX) - if (!number(val)) - return err2("expected number after '%' in % bound",t,bound); - - // store bound: - switch (type) { - case FX: - fu_[var_index] = true; - u_ [var_index] = val; - case LO: - fl_[var_index] = true; - l_ [var_index] = val; - break; - case UP: - fu_[var_index] = true; - u_ [var_index] = val; - if (val <= 0 && fl_[var_index] == true && l_[var_index] == 0) - if (val < 0 || !use_CPLEX_convention) - fl_[var_index] = false; - break; - case FR: - fu_[var_index] = false; - fl_[var_index] = false; - break; - case MI: - fl_[var_index] = false; - break; - case PL: - fu_[var_index] = false; - break; - default: - CGAL_qpe_assertion(false); - } - - // read next token: - t = token(); - } - put_token_back(t); - - return true; -} - -template -bool QP_from_mps::qmatrix_section() -{ - std::string t = token(); - if (t!="QMATRIX" && t!="DMATRIX" && t!="QUADOBJ") { // optional - put_token_back(t); - return true; - } - - // remember section name: - D_section = t; - const bool multiply_by_two = t=="DMATRIX"; - const bool only_get_lower_part = t =="QUADOBJ"; - - t = token(); - std::string bound_id; - while (t != "ENDATA") { - // find first variable name; - const Index_map::const_iterator var1_name = var_names.find(t); - if (var1_name == var_names.end()) // unknown variable? - return err2("unknown first variable '%' in '%' section", t, D_section); - const unsigned int var1_index = var1_name->second;; - //std::cout << "qvar1 " << t << std::endl; - - // find second variable name; - t = token(); - const Index_map::const_iterator var2_name = var_names.find(t); - if (var2_name == var_names.end()) // unknown variable? - return err2("unknown second variable '%' in '%' section",t, D_section); - const unsigned int var2_index = var2_name->second;; - //std::cout << "qvar2 " << t << std::endl; - - // read value: - IT val; - if (!number(val)) - return err1("expected number after '%' in section QMATRIX",t); - - // multiply by two if approriate: - if (multiply_by_two) - val *= IT(2); - - // mark problem as nonlinear if value is nonzero, and - // bail out if we are supposed to read a linear program - if (is_linear_ && !CGAL::is_zero(val)) { - is_linear_ = false; - if (has_linear_tag) - return err1 - ("nonzero value in '%' section while reading linear program", - D_section); - } - - // set entry in D: - set_entry_in_D(var1_index, var2_index, val, Sparse_D()); - if (only_get_lower_part) - // duplicate entry if not on diagonal - if (var1_index != var2_index) - set_entry_in_D(var2_index, var1_index, val, Sparse_D()); - - // read next token: - t = token(); - } - put_token_back(t); - - // now check symmetry - unsigned int bad_i, bad_j; - if (!is_symmetric(Sparse_D(), bad_i, bad_j)) { - std::string bad_i_name = var_by_index[bad_i]; - std::string bad_j_name = var_by_index[bad_j]; - return - err3("nonsymmetric '%' section for variables '%' and '%'", - D_section, bad_i_name, bad_j_name); - } - - return true; -} - -CGAL_END_NAMESPACE diff --git a/QP_solver/include/CGAL/QP_solver/QP_partial_exact_pricing.h b/QP_solver/include/CGAL/QP_solver/QP_partial_exact_pricing.h index 622d33e7cfe..c4242184255 100644 --- a/QP_solver/include/CGAL/QP_solver/QP_partial_exact_pricing.h +++ b/QP_solver/include/CGAL/QP_solver/QP_partial_exact_pricing.h @@ -203,7 +203,7 @@ pricing_helper(int& direction, Tag_false /*is_in_standard_form*/) it != this->inactive_set_end(); ++it) { // don't price basics/artificials - CGAL_qpe_precondition (!this->solver().is_basic(*it)); + CGAL_qpe_assertion (!this->solver().is_basic(*it)); if (this->solver().is_artificial( *it)) continue; // compute mu_j diff --git a/QP_solver/include/CGAL/QP_solver/QP_pricing_strategy.h b/QP_solver/include/CGAL/QP_solver/QP_pricing_strategy.h index f2b498bf129..48eb594f686 100644 --- a/QP_solver/include/CGAL/QP_solver/QP_pricing_strategy.h +++ b/QP_solver/include/CGAL/QP_solver/QP_pricing_strategy.h @@ -173,8 +173,8 @@ template bool QP_pricing_strategy:: is_improving (int j, const NT& mu, const NT& nt0 ) const { - CGAL_qpe_precondition(!this->solver().is_basic(j)); - CGAL_qpe_precondition(!this->solver().is_artificial(j)); + CGAL_qpe_assertion(!this->solver().is_basic(j)); + CGAL_qpe_assertion(!this->solver().is_artificial(j)); if (this->solver().is_original(j)) { const Bound_index bnd_ind = this->solver().nonbasic_original_variable_bound_index(j); @@ -207,8 +207,8 @@ template bool QP_pricing_strategy:: price_dantzig (int j, const NT& mu, const NT& nt0, int& min_j, NT& min_mu, int& direction) { - CGAL_qpe_precondition(!this->solver().is_basic(j)); - CGAL_qpe_precondition(!this->solver().is_artificial(j)); + CGAL_qpe_assertion(!this->solver().is_basic(j)); + CGAL_qpe_assertion(!this->solver().is_artificial(j)); if (this->solver().is_original(j)) { // original variable const Bound_index bnd_ind = diff --git a/QP_solver/include/CGAL/QP_solver/QP_solver_impl.h b/QP_solver/include/CGAL/QP_solver/QP_solver_impl.h index b48262eb603..e4982b497e1 100644 --- a/QP_solver/include/CGAL/QP_solver/QP_solver_impl.h +++ b/QP_solver/include/CGAL/QP_solver/QP_solver_impl.h @@ -1690,7 +1690,7 @@ void QP_solver:: enter_variable( ) { - CGAL_qpe_precondition (is_phaseII); + CGAL_qpe_assertion (is_phaseII); CGAL_qpe_debug { vout2 << "--> nonbasic (" << variable_type( j) << ") variable " << j << " enters basis" << std::endl << std::endl; @@ -1711,7 +1711,7 @@ enter_variable( ) // correct size). We check here // whether we need to enlarge // them. - CGAL_qpe_precondition(minus_c_B.size() == B_O.size()); + CGAL_qpe_assertion(minus_c_B.size() == B_O.size()); minus_c_B.push_back(et0); q_x_O.push_back(et0); tmp_x .push_back(et0); @@ -2184,7 +2184,7 @@ z_replace_variable_slack_by_original( ) // correct size). We check here // whether we need to enlarge // them. - CGAL_qpe_precondition(minus_c_B.size() == B_O.size()); + CGAL_qpe_assertion(minus_c_B.size() == B_O.size()); minus_c_B.push_back(et0); q_x_O.push_back(et0); tmp_x .push_back(et0); @@ -2950,8 +2950,8 @@ template < typename Q, typename ET, typename Tags > void QP_solver:: set_pricing_strategy( Pricing_strategy *strategy) { - CGAL_qpe_precondition( phase() != 1); - CGAL_qpe_precondition( phase() != 2); + CGAL_qpe_assertion( phase() != 1); + CGAL_qpe_assertion( phase() != 2); if (defaultStrategy != static_cast< Pricing_strategy*>( 0)) delete defaultStrategy; diff --git a/QP_solver/include/CGAL/QP_solver/QP_solver_nonstandardform_impl.h b/QP_solver/include/CGAL/QP_solver/QP_solver_nonstandardform_impl.h index de9100c3104..1028f64895e 100644 --- a/QP_solver/include/CGAL/QP_solver/QP_solver_nonstandardform_impl.h +++ b/QP_solver/include/CGAL/QP_solver/QP_solver_nonstandardform_impl.h @@ -126,7 +126,7 @@ template < typename Q, typename ET, typename Tags > void QP_solver:: multiply__A_CxN_O(Value_iterator out) const { - CGAL_qpe_precondition(!check_tag(Is_nonnegative())); + CGAL_qpe_assertion(!check_tag(Is_nonnegative())); // initialize with zero vector: std::fill_n(out, C.size(), et0); @@ -157,7 +157,7 @@ template < typename Q, typename ET, typename Tags > void QP_solver:: multiply__2D_OxN_O(Value_iterator out) const { - CGAL_qpe_precondition(!check_tag(Is_nonnegative())); + CGAL_qpe_assertion(!check_tag(Is_nonnegative())); // initialize with zero vector: std::fill_n(out, B_O.size(), et0); @@ -203,7 +203,7 @@ template < typename Q, typename ET, typename Tags > void QP_solver:: init_r_B_O() { - CGAL_qpe_precondition(!check_tag(Is_nonnegative()) && + CGAL_qpe_assertion(!check_tag(Is_nonnegative()) && !check_tag(Is_linear())); r_B_O.resize(B_O.size()); multiply__2D_B_OxN_O(r_B_O.begin()); @@ -217,7 +217,7 @@ template < typename Q, typename ET, typename Tags > void QP_solver:: init_w() { - CGAL_qpe_precondition(!check_tag(Is_nonnegative()) && + CGAL_qpe_assertion(!check_tag(Is_nonnegative()) && !check_tag(Is_linear())); w.resize(qp_n); multiply__2D_OxN_O(w.begin()); diff --git a/QP_solver/include/CGAL/QP_solver/QP_solver_validity_impl.h b/QP_solver/include/CGAL/QP_solver/QP_solver_validity_impl.h index 23bbe0ba0d3..5d12e67ad8c 100644 --- a/QP_solver/include/CGAL/QP_solver/QP_solver_validity_impl.h +++ b/QP_solver/include/CGAL/QP_solver/QP_solver_validity_impl.h @@ -25,8 +25,8 @@ template < typename Q, typename ET, typename Tags > ET QP_solver::optimality_certificate_numerator(int i) const { // we use the vector lambda which conforms to C (basic constraints) - CGAL_qpe_precondition (i >= 0); - CGAL_qpe_precondition (i <= qp_m); + CGAL_qpe_assertion (i >= 0); + CGAL_qpe_assertion (i <= qp_m); if (no_ineq) return lambda[i]; else { @@ -710,7 +710,7 @@ bool QP_solver::is_solution_unbounded() const // w^TDw = 0, (C11) // (c^T+2x^TD)w < 0. (C12) - CGAL_expensive_precondition(is_solution_feasible()); + CGAL_expensive_assertion(is_solution_feasible()); // get solution vector of original problem (multiplied by d): Values x(qp_n, et0); diff --git a/QP_solver/include/CGAL/QP_solver/iterator.h b/QP_solver/include/CGAL/QP_solver/iterator.h index 2c09c0b3f33..29981c83c4e 100644 --- a/QP_solver/include/CGAL/QP_solver/iterator.h +++ b/QP_solver/include/CGAL/QP_solver/iterator.h @@ -41,8 +41,8 @@ public: typedef std::random_access_iterator_tag iterator_category; typedef typename Map::difference_type difference_type; typedef typename Map::mapped_type value_type; - typedef value_type* pointer; - typedef value_type& reference; + typedef const value_type* pointer; + typedef const value_type& reference; typedef Fake_random_access_const_iterator Self; typedef difference_type Diff; @@ -118,8 +118,8 @@ public: typedef std::random_access_iterator_tag iterator_category; typedef Diff difference_type; typedef typename Op::result_type value_type; - typedef value_type* pointer; - typedef value_type& reference; + typedef const value_type* pointer; + typedef const value_type& reference; typedef Transform_diff_const_iterator Self; typedef value_type Val; diff --git a/QP_solver/test/QP_solver/master_mps_to_derivatives.cpp b/QP_solver/test/QP_solver/master_mps_to_derivatives.cpp index 7ff6314fb9f..10aa11ab93f 100644 --- a/QP_solver/test/QP_solver/master_mps_to_derivatives.cpp +++ b/QP_solver/test/QP_solver/master_mps_to_derivatives.cpp @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -37,13 +38,6 @@ #include #include -using CGAL::Tag_true; -using CGAL::Tag_false; - -typedef Tag_false Sparse_D; -typedef Tag_false Sparse_A; -typedef Tag_false Is_linear; - // Routines to output to MPS format: namespace QP_from_mps_detail { @@ -151,8 +145,7 @@ template // exact number type compatible with IT (ET is used, // for instance, by QP in the query methods // has_equalities_only_and_full_rank()) -void create_shifted_instance(CGAL::QP_from_mps - & qp, +void create_shifted_instance(const CGAL::Quadratic_program_from_mps & qp, const char *file, // Note: "Bernd3" and // not "Bernd3.mps". const char *dir) @@ -172,8 +165,8 @@ void create_shifted_instance(CGAL::QP_from_mps // where v = [1,...,n]^T. // extract data from qp: - const int n = qp.n(); - const int m = qp.m(); + const int n = qp.get_n(); + const int m = qp.get_m(); // offset vector: std::vector v(n); @@ -184,13 +177,13 @@ void create_shifted_instance(CGAL::QP_from_mps std::vector Av(m, IT(0)); for (int i=0; i mvTD(n, IT(0)); // -2D^Tv for (int i=0; i()), - qp.r(), - qp.fl(), + qp.get_r(), + qp.get_fl(), make_transform_iterator( - make_zip_iterator(make_tuple(qp.l(),v.begin())), + make_zip_iterator(make_tuple(qp.get_l(),v.begin())), tuple_add()), - qp.fu(), + qp.get_fu(), make_transform_iterator( - make_zip_iterator(make_tuple(qp.u(),v.begin())), + make_zip_iterator(make_tuple(qp.get_u(),v.begin())), tuple_add()), - qp.d(), + qp.get_d(), make_transform_iterator( - make_zip_iterator(make_tuple(qp.c(),mvTD.begin())), + make_zip_iterator(make_tuple(qp.get_c(),mvTD.begin())), tuple_add()), - qp.c0() + qp.get_c0() ) ); -// n, m, -// qp.a(), -// make_transform_iterator( -// make_zip_iterator(make_tuple(qp.b(),Av.begin())), -// tuple_add()), -// make_transform_iterator( -// make_zip_iterator(make_tuple(qp.c(),mvTD.begin())), -// tuple_add()), qp.c0(), -// qp.d(), qp.fu(), qp.fl(), -// make_transform_iterator( -// make_zip_iterator(make_tuple(qp.u(),v.begin())), -// tuple_add()), -// make_transform_iterator( -// make_zip_iterator(make_tuple(qp.l(),v.begin())), -// tuple_add()), -// qp.r()); out->close(); } @@ -251,8 +228,7 @@ template // exact number type compatible with IT (ET is used, // for instance, by QP in the query methods // has_equalities_only_and_full_rank()) -void create_free_instance(CGAL::QP_from_mps& qp_, +void create_free_instance(CGAL::Quadratic_program_from_mps& qp, const char *file, // Note: "Bernd3" and // not "Bernd3.mps". const char *dir) @@ -266,78 +242,46 @@ void create_free_instance(CGAL::QP_from_mps QP_MPS; - typedef typename QP_MPS::Vector Vector; - typedef typename QP_MPS::B_iterator Vector_iterator; - typedef typename QP_MPS::A_Matrix Matrix; - typedef typename QP_MPS::A_Beginner A_Beginner; - typedef typename QP_MPS::A_iterator A_iterator; - typedef CGAL::Comparison_result Row_type; - typedef typename QP_MPS::R_vector R_vector; - - // copy the qp - QP_MPS qp (qp_); - - // copy some of its vectors (they get manipulated) - Vector b = qp.b_vector(); - R_vector row_types = qp.r_vector(); + const unsigned int n = qp.get_n(); + unsigned int m = qp.get_m(); // add rows to A and corresponding entries to b: - int nr_of_rows_added = 0; for (unsigned int i=0; i= l + if (*(qp.get_fl()+i)) { // x >= l // add a row to A: for (unsigned int j=0; j out = create_output_file(file, dir, "free"); write_MPS(*out, "", // deduce number-type "Freed instance of original file", "master_mps_to_derivatives-create_free_instance", - qp.problem_name(), - CGAL::make_quadratic_program_from_iterators ( - n, m+nr_of_rows_added, - A_iterator(qp.A_matrix().begin(),A_Beginner()), - b.begin(), - row_types.begin(), - CGAL::Const_oneset_iterator(false), // fl - qp.l(), // dummy - CGAL::Const_oneset_iterator(false), // fu - qp.u(), // dummy - qp.d(), - qp.c(), qp.c0())); + qp.get_problem_name(), + qp); out->close(); } @@ -364,20 +308,19 @@ bool create_derivatives(const char *path, } // load QP instance: - const int verbosity = 5; typedef typename QP_from_mps_detail::IT_to_ET::ET ET; - typedef CGAL::QP_from_mps QP; - QP qp(f,true,verbosity); + typedef CGAL::Quadratic_program_from_mps QP; + QP qp(f); // check for format errors in MPS file: if (!qp.is_valid()) { - msg = "Input is not a valid MPS file: " + qp.error(); + msg = "Input is not a valid MPS file: " + qp.get_error(); return false; } cerr << " MPS-file successfully input.\n"; // no derivatives if comment says so - if (qp.comment().find(std::string("Derivatives: none"))!=std::string::npos) + if (qp.get_comment().find(std::string("Derivatives: none"))!=std::string::npos) cerr << " No derivatives made.\n"; else { // derivates: diff --git a/QP_solver/test/QP_solver/test_MPS.cpp b/QP_solver/test/QP_solver/test_MPS.cpp index de620d98f01..1b5c53bbe98 100644 --- a/QP_solver/test/QP_solver/test_MPS.cpp +++ b/QP_solver/test/QP_solver/test_MPS.cpp @@ -55,13 +55,13 @@ int main(const int argNr,const char **args) { #else typedef CGAL::Gmpz ET; #endif - typedef CGAL::QP_from_mps QP; - QP qp(std::cin,true,verbosity); + typedef CGAL::Quadratic_program_from_mps QP; + QP qp(std::cin); // check for format errors in MPS f\ile: if (!qp.is_valid()) { cout << "Input is not a valid MPS file." << endl - << "Error: " << qp.error() << endl; + << "Error: " << qp.get_error() << endl; std::exit(2); } @@ -84,8 +84,8 @@ int main(const int argNr,const char **args) { cout << "Variable values:" << endl; Solver::Variable_value_iterator it = s.original_variable_values_begin() ; - for (int i=0; i < qp.n(); ++it, ++i) - cout << " " << qp.name_of_variable(i) << " = " + for (int i=0; i < qp.get_n(); ++it, ++i) + cout << " " << qp.get_name_of_variable(i) << " = " << CGAL::to_double(*it) << endl; return 0; } diff --git a/QP_solver/test/QP_solver/test_empty_qp.cpp b/QP_solver/test/QP_solver/test_empty_qp.cpp new file mode 100644 index 00000000000..61866ac90f1 --- /dev/null +++ b/QP_solver/test/QP_solver/test_empty_qp.cpp @@ -0,0 +1,29 @@ +#include +#include +#include +#include +#include +#include + +// choose exact integral type +#ifndef CGAL_USE_GMP +#include +typedef CGAL::MP_Float ET; +#else +#include +typedef CGAL::Gmpz ET; +#endif + +int main() +{ + CGAL::Quadratic_program qp; // no variables, no constraints + assert (qp.is_valid()); + + CGAL::Quadratic_program_solution s = + CGAL::solve_quadratic_program (qp, ET()); + + std::cout << "Solution = " << s.solution() << std::endl; + std::cout << "Status = " << s.status() << std::endl; + + return 0; +} diff --git a/QP_solver/test/QP_solver/test_solver.cpp b/QP_solver/test/QP_solver/test_solver.cpp index a55966d3f99..41fa14e6c83 100644 --- a/QP_solver/test/QP_solver/test_solver.cpp +++ b/QP_solver/test/QP_solver/test_solver.cpp @@ -337,23 +337,15 @@ bool process(const std::string& filename, // extract verbosity: const int verbosity = options.find("Verbosity")->second; - // read QP instance, first using dense representation: + // read QP instance std::ifstream in(filename.c_str()); if (!in) bailout1("could not open file '%'",filename); typedef CGAL::Quadratic_program_from_mps QP_instance; - QP_instance qp(in,true,verbosity); + QP_instance qp(in); in.close(); - // then read it again, using sparse representation - std::ifstream in2(filename.c_str()); - if (!in2) - bailout1("could not open file '%'",filename); - typedef CGAL::Sparse_quadratic_program_from_mps Sparse_QP_instance; - Sparse_QP_instance qp2(in2,true,verbosity); - in2.close(); - - std::string comment = qp.comment(); + std::string comment = qp.get_comment(); // check for the number-type: Input_type type; @@ -402,26 +394,13 @@ bool process(const std::string& filename, (is_rational(ET())? "Gmpq" : "Double")) << endl; - // check for format errors in MPS file (dense): + // check for format errors in MPS file: if (!qp.is_valid()) { cout << "Input is not a valid MPS file." << endl - << "Error: " << qp.error() << endl; + << "Error: " << qp.get_error() << endl; return false; } - // check for format errors in MPS file (sparse): - if (!qp2.is_valid()) { - cout << "Input is not a valid MPS file." << endl - << "Error: " << qp2.error() << endl; - return false; - } - - // compare qp1, qp2 - if (!CGAL::QP_functions_detail::are_equal_qp (qp, qp2)) { - cout << "Dense/Sparse readers disagree.\n" << endl; - return false; - } - // print program (using QMATRIX format), read it back in and check // whether it still agrees with the original program std::stringstream inout; @@ -430,100 +409,58 @@ bool process(const std::string& filename, CGAL::QP_functions_detail::print_program (inout, qp, std::string("test_io_mps"), Is_linear(),Is_nonnegative()); - QP_instance qp3(inout, true, verbosity); - CGAL_qpe_assertion (qp3.is_valid()); - if (!CGAL::QP_functions_detail::are_equal_qp (qp, qp3)) { - cout << "Warning: MPS reader and MPS writer disagree.\n" << endl; - } - - // copy program and check whether it is still the same - if (!qp.is_linear() && !qp.is_nonnegative()) { - CGAL::Quadratic_program qp4 (qp.n(), qp.m(), qp.a(), qp.b(), qp.r(), - qp.fl(), qp.l(), qp.fu(), qp.u(), - qp.d(), qp.c(), qp.c0()); - if (!CGAL::QP_functions_detail::are_equal_qp (qp, qp4)) { - cout << "Program not correctly copied.\n" << endl; - return false; - } - // test default/copy constructor, assignment - CGAL::Quadratic_program qp5; - qp5 = qp4; - if (!CGAL::QP_functions_detail::are_equal_qp (qp5, qp4)) { - cout << "Program not correctly assigned.\n" << endl; - return false; - } - CGAL::Quadratic_program qp6 (qp4); - if (!CGAL::QP_functions_detail::are_equal_qp (qp6, qp4)) { - cout << "Program not correctly copy-constructed.\n" << endl; - return false; - } - } - - if (qp.is_linear() && !qp.is_nonnegative()) { - CGAL::Linear_program qp4 (qp.n(), qp.m(), qp.a(), qp.b(), qp.r(), - qp.fl(), qp.l(), qp.fu(), qp.u(), - qp.c(), qp.c0()); - if (!CGAL::QP_functions_detail::are_equal_qp (qp, qp4)) { - cout << "Program not correctly copied.\n" << endl; - return false; - } - // test default/copy constructor, assignment - CGAL::Linear_program qp5; - qp5 = qp4; - if (!CGAL::QP_functions_detail::are_equal_qp (qp5, qp4)) { - cout << "Program not correctly assigned.\n" << endl; - return false; - } - CGAL::Linear_program qp6 (qp4); - if (!CGAL::QP_functions_detail::are_equal_qp (qp6, qp4)) { - cout << "Program not correctly copy-constructed.\n" << endl; - return false; - } - } - - if (!qp.is_linear() && qp.is_nonnegative()) { - CGAL::Nonnegative_quadratic_program - qp4 (qp.n(), qp.m(), qp.a(), qp.b(), qp.r(), - qp.d(), qp.c(), qp.c0()); - if (!CGAL::QP_functions_detail::are_equal_qp (qp, qp4)) { - cout << "Program not correctly copied.\n" << endl; - return false; - } - // test default/copy constructor, assignment - CGAL::Nonnegative_quadratic_program qp5; - qp5 = qp4; - if (!CGAL::QP_functions_detail::are_equal_qp (qp5, qp4)) { - cout << "Program not correctly assigned.\n" << endl; - return false; - } - CGAL::Nonnegative_quadratic_program qp6 (qp4); - if (!CGAL::QP_functions_detail::are_equal_qp (qp6, qp4)) { - cout << "Program not correctly copy-constructed.\n" << endl; - return false; - } - } + // test all four readers if (qp.is_linear() && qp.is_nonnegative()) { - CGAL::Nonnegative_linear_program - qp4 (qp.n(), qp.m(), qp.a(), qp.b(), qp.r(), - qp.c(), qp.c0()); - if (!CGAL::QP_functions_detail::are_equal_qp (qp, qp4)) { - cout << "Program not correctly copied.\n" << endl; - return false; + CGAL::Nonnegative_linear_program_from_mps qp2(inout); + CGAL_qpe_assertion (qp2.is_valid()); + if (!CGAL::QP_functions_detail::are_equal_qp (qp, qp2)) { + cout << "Warning: MPS reader (NLP) and MPS writer disagree.\n" << endl; } - // test default/copy constructor, assignment - CGAL::Nonnegative_linear_program qp5; - qp5 = qp4; - if (!CGAL::QP_functions_detail::are_equal_qp (qp5, qp4)) { - cout << "Program not correctly assigned.\n" << endl; - return false; + } + if (qp.is_linear() && !qp.is_nonnegative()) { + CGAL::Linear_program_from_mps qp2(inout); + CGAL_qpe_assertion (qp2.is_valid()); + if (!CGAL::QP_functions_detail::are_equal_qp (qp, qp2)) { + cout << "Warning: MPS reader (LP) and MPS writer disagree.\n" << endl; } - CGAL::Nonnegative_linear_program qp6 (qp4); - if (!CGAL::QP_functions_detail::are_equal_qp (qp6, qp4)) { - cout << "Program not correctly copy-constructed.\n" << endl; - return false; + } + if (!qp.is_linear() && !qp.is_nonnegative()) { + CGAL::Quadratic_program_from_mps qp2(inout); + CGAL_qpe_assertion (qp2.is_valid()); + if (!CGAL::QP_functions_detail::are_equal_qp (qp, qp2)) { + cout << "Warning: MPS reader (QP) and MPS writer disagree.\n" << endl; } } + if (!qp.is_linear() && qp.is_nonnegative()) { + CGAL::Nonnegative_quadratic_program_from_mps qp2(inout); + CGAL_qpe_assertion (qp2.is_valid()); + if (!CGAL::QP_functions_detail::are_equal_qp (qp, qp2)) { + cout << "Warning: MPS reader (NQP) and MPS writer disagree.\n" << endl; + } + } + // now copy from the iterators, check for equality + CGAL::Quadratic_program_base + qp4 (qp.get_n(), qp.get_m(), qp.get_a(), qp.get_b(), qp.get_r(), + qp.get_fl(), qp.get_l(), qp.get_fu(), qp.get_u(), + qp.get_d(), qp.get_c(), qp.get_c0()); + if (!CGAL::QP_functions_detail::are_equal_qp (qp, qp4)) { + cout << "Program not correctly copied.\n" << endl; + return false; + } + // test consistency of types + if (qp.is_linear() != qp4.is_linear()) { + cout << "Program types inconsistent (linearity): " + << qp.is_linear() << " vs. " << qp4.is_linear() + << "\n"<< endl; + return false; + } + if (qp.is_nonnegative() != qp4.is_nonnegative()) { + cout << "Program types inconsistent (nonnegativity): " + << qp.is_nonnegative() << " vs. " << qp4.is_nonnegative() + << "\n"<< endl; + return false; + } typedef CGAL::QP_solver_impl::QP_tags Tags; @@ -548,14 +485,15 @@ bool process(const std::string& filename, // general form typedef CGAL::QP_solver_impl::QP_tags LocalTags; - typedef CGAL::Quadratic_program + typedef CGAL::Quadratic_program_base LocalQP; CGAL::QP_pricing_strategy *slocal = new CGAL::QP_full_exact_pricing (); - LocalQP qplocal (qp.n(), qp.m(), qp.a(), qp.b(), qp.r(), - qp.fl(), qp.l(), qp.fu(), qp.u(), - qp.d(), qp.c(), qp.c0()); + LocalQP qplocal (qp.get_n(), qp.get_m(), qp.get_a(), qp.get_b(), + qp.get_r(), + qp.get_fl(), qp.get_l(), qp.get_fu(), qp.get_u(), + qp.get_d(), qp.get_c(), qp.get_c0()); CGAL::QP_solver solverlocal (qplocal, slocal, 0); std::cout << "(c) "; delete slocal;