- added sparse MPS readers

- documented MPS format
This commit is contained in:
Bernd Gärtner 2007-04-03 10:04:21 +00:00
parent 49f3e78255
commit 9d3b0d0327
8 changed files with 385 additions and 10 deletions

3
.gitattributes vendored
View File

@ -1827,6 +1827,7 @@ 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
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_pointers.tex -text
@ -1836,6 +1837,8 @@ QP_solver/doc_tex/QP_solver_ref/Nonnegative_quadratic_program_from_pointers.tex
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/examples/QP_solver/double_qp_solver.cin -text
QP_solver/examples/QP_solver/double_qp_solver.data -text
QP_solver/examples/QP_solver/integer_qp_solver.cin -text

View File

@ -6,7 +6,7 @@
An object of class \ccRefName\ describes a linear program of the form
%%
\begin{eqnarray*}
\mbox{(QP)}& \mbox{minimize} & x^{T}Dx+c^{T}x+c_0 \\
\mbox{(QP)}& \mbox{minimize} & c^{T}x+c_0 \\
&\mbox{subject to} & Ax\qprel b, \\
& & l \leq x \leq u
\end{eqnarray*}
@ -27,7 +27,21 @@ $x$,
\item $c_0$ is a constant.
\end{itemize}
This class reads the program data from a file in MPS format.
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.
\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<NT>} 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.
\ccIsModel
\ccc{LinearProgramInterface}
@ -36,9 +50,22 @@ This class reads the program data from a file in MPS format.
\ccIndexClassCreation
\ccCreationVariable{lp}
\ccConstructor{Linear_program_from_mps(std::istream& in)} {reads \ccVar\ fromthe stream \ccc{in}.}
\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{Sparse_linear_program_from_mps<NT>}\\
\ccc{Linear_program<NT>}\\
\ccc{Linear_program_from_iterators<A_it, B_it, R_it, FL_it, L_it, FU_it, U_it, D_it, C_it>}\\
\ccc{Linear_program_from_pointers<NT>}

View File

@ -0,0 +1,148 @@
\begin{ccRefConcept}{MPSFormat}
MPS is a commonly used file format for storing linear and quadratic
programs according to the concepts \ccc{LinearProgramInterface} and
\ccc{QuadraticProgramInterface}. \cgal\ supports a large subset of
this format, but there are MPS files around that we cannot read (for
example, files that encode integrality constraints on the variables).
Also, there might be some other MPS-based solvers that will not be able
to read the MPS files written by \cgal, since we do not strictly
adhere to the very rigid layout requirements of the original MPS
format.
Let's look at an example first. The quadratic program
\[
\begin{array}{lrcl}
\mbox{minimize} & x^2 + 4(y-4)^2 &(=& x^2 + 4y^2 - 32y + 64) \\
\mbox{subject to} & x + y &\leq& 7 \\
& -x + 2y &\leq& 4 \\
& x &\geq& 0 \\
& y &\geq& 0 \\
& y &\leq& 4
\end{array}
\]
has the following description in MPS format.
\begin{verbatim}
NAME MY_MPS
ROWS
N obj
L c0
L c1
COLUMNS
x0 c0 1
x0 c1 -1
x1 obj -32
x1 c0 1
x1 c1 2
RHS
rhs obj -64
rhs c0 7
rhs c1 4
BOUNDS
UP BND x1 4
QMATRIX
x0 x0 2
x1 x1 8
ENDATA
\end{verbatim}
Here comes a semiformal description of the format in general.
\section*{NAME section}
This (mandatory) section consists of a single line
starting with \texttt{NAME}. Everything starting from the
first non-whitespace after that until the end of the line
constitutes the name of the problem.
\section*{ROWS section}
In the (mandatory) \texttt{ROW} section, you find one line for every
constraint, where the letter \texttt{L} indicates relation $\leq$,
letter \texttt{G} stands for $\geq$, and \texttt{E} for $=$. In
addition, there is a row for the linear objective function (indicated
by letter \texttt{N}). In that section, names are asigned to the
constraints (here: \texttt{c0, c1}) and the objective function (here:
\texttt{obj}). An MPS file may encode several linear objective
functions by using several rows starting with \texttt{N}, but we ignore
all but the first.
\section*{COLUMNS section}
The (mandatory) \texttt{COLUMNS} section encodes the constraint matrix
$A$ and the linear objective function vector $c$. Every line consists
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$.
\section*{RHS section}
This (mandatory) section encodes the right-hand side vector $b$ and
the constant term $c_0$ in the objective function. The first token in
every line is an identifier (here: \texttt{rhs}). An MPS file may
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
$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$.
\section*{BOUNDS section}
This (optional) section encodes the lower and upper bound vectors $l$
and $u$ for the variables. The default bounds for any variable $x_j$ are
$0\leq x_j\leq \infty$; the
\texttt{BOUNDS} section is used to override these defaults. In particular,
if there is no \texttt{BOUNDS} section, the program is nonnegative and
actually a model of the concept \ccc{NonnegativeQuadraticProgramInterface}
or \ccc{NonnegativeLinearProgramInterface}.
The first token in every line is succeeded by an (optional) identifier
(here: \texttt{BND}). An MPS file may encode several bound vectors $l$
and $u$ by using several such identifiers, but we ignore all lines
having an identifier different from that of the first line. The first
token $t$ itself determines the type of the bound, and the token $j$
after the bound identifier names the variable to which the bound applies
In case of bound types \texttt{FX}, \texttt{LO}, and
\texttt{UP}, there is another token $val$ that specifices the bound
value. Here is how bound type and value determine a bound for variable
$x_j$. There may be several bound specifications for a single variable, and
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) \\
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$)\\
FR & $-\infty \leq x_j\leq\infty$ (previous bounds are discarded)\\
MI & $x_j\geq -\infty$ (upper bound remains unchanged)\\
PL & $x_j\leq \infty$ (lower bound remains unchanged)
\end{tabular}
\section*{QMATRIX / QUADOBJ / DMATRIX section}
This (optional) section encodes the quadratic objective
function matrix $D$. Every line is a sequence $i j val$ of
three tokens, where both $i$ and $j$ name variables, and
$val$ is the value $2D_{i,j}$ (in case of \texttt{QMATRIX}
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.
If this seftion 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.
\end{ccRefConcept}

View File

@ -29,7 +29,23 @@ $x$,
\item $c_0$ is a constant.
\end{itemize}
This class reads the program data from a file in extended MPS format.
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.
\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<NT>}
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.
\ccIsModel
\ccc{QuadraticProgramInterface}
@ -38,9 +54,25 @@ This class reads the program data from a file in extended MPS format.
\ccIndexClassCreation
\ccCreationVariable{qp}
\ccConstructor{Quadratic_program_from_mps(std::istream& in)} {reads \ccVar\ fromthe stream \ccc{in}.}
\ccConstructor{Quadratic_program_from_mps(std::istream& in)} {reads \ccVar\ fromthe 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{Sparse_quadratic_program_from_mps<NT>}\\
\ccc{Quadratic_program<NT>}\\
\ccc{Quadratic_program_from_iterators<A_it, B_it, R_it, FL_it, L_it, FU_it, U_it, D_it, C_it>}\\
\ccc{Quadratic_program_from_pointers<NT>}

View File

@ -0,0 +1,72 @@
\begin{ccRefClass}{Sparse_linear_program_from_mps<NT>}
\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.
\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<NT>}
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<NT>}\\
\ccc{Linear_program<NT>}\\
\ccc{Linear_program_from_iterators<A_it, B_it, R_it, FL_it, L_it, FU_it, U_it, D_it, C_it>}\\
\ccc{Linear_program_from_pointers<NT>}
\end{ccRefClass}

View File

@ -0,0 +1,78 @@
\begin{ccRefClass}{Sparse_quadratic_program_from_mps<NT>}
\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.
\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<NT>}
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<NT>}\\
\ccc{Quadratic_program<NT>}\\
\ccc{Quadratic_program_from_iterators<A_it, B_it, R_it, FL_it, L_it, FU_it, U_it, D_it, C_it>}\\
\ccc{Quadratic_program_from_pointers<NT>}
\end{ccRefClass}

View File

@ -7,14 +7,18 @@
\ccHeading{Concepts}
\ccRefConceptPage{QuadraticProgramInterface}\\
$\quad$ (for quadratic programs with variable bounds $\mathbf{l} \leq x \leq \mathbf{u}$) \\
$\quad$ (for quadratic programs with variable bounds $l\leq x \leq u$) \\
\ccRefConceptPage{LinearProgramInterface} \\
$\quad$(for linear programs with variable bounds $\mathbf{l} \leq x \leq \mathbf{u}$)\\
$\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}$) \\
\ccRefConceptPage{NonnegativeLinearProgramInterface}\\
$\quad$ (for linear programs with variable bounds $x\geq\mathbf{0}$)
\ccRefConceptPage{MPSFormat}\\
$\quad$ (the format used for reading and writing linear and quadratic
programs)
\ccHeading{Classes}
There is one major class that represents the solution of a program
@ -42,7 +46,12 @@ $\quad$ (for quadratic programs with no variable bounds, wrapping given iterator
\ccc{Free_quadratic_program_from_pointers<NT>}\\
$\quad$ (for quadratic programs with no variable bounds, wrapping given pointers)\\
\ccc{Quadratic_program_from_mps<NT>}\\
$\quad$ (for quadratic programs copied from an input stream)
$\quad$ (for quadratic programs copied from an input stream in
\ccc{MPSFormat})\\
\ccc{Sparse_quadratic_program_from_mps<NT>}\\
$\quad$ (for sparse quadratic programs copied from an input stream in
\ccc{MPSFormat})
These are the models for \ccc{LinearProgramInterface}.
@ -63,8 +72,11 @@ iterators)\\
$\quad$ (for linear programs with no variable bounds, wrapping given
pointers)\\
\ccc{Linear_program_from_mps<NT>}\\
$\quad$ (for linear programs copied from an input stream)
$\quad$ (for linear programs copied from an input stream in
\ccc{MPSFormat})\\
\ccc{Sparse_linear_program_from_mps<NT>}\\
$\quad$ (for sparse linear programs copied from an input stream in
\ccc{MPSFormat})
For \ccc{NonnegativeQuadraticProgramInterface}, we offer these
three models.

View File

@ -10,6 +10,7 @@
\input{QP_solver_ref/NonnegativeQuadraticProgramInterface}
\input{QP_solver_ref/LinearProgramInterface}
\input{QP_solver_ref/NonnegativeLinearProgramInterface}
\input{QP_solver_ref/MPSFormat}
\input{QP_solver_ref/Quadratic_program}
\input{QP_solver_ref/Quadratic_program_from_iterators}
@ -18,6 +19,7 @@
\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}
@ -26,6 +28,7 @@
\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}