# HG changeset patch # User jwe # Date 1111613326 0 # Node ID 652e8aa49fa7e99db3cdeb4a982a5e9a804bdead # Parent 6879f10db3a43f26f247012613219c49a266c143 [project @ 2005-03-23 21:28:45 by jwe] diff -r 6879f10db3a4 -r 652e8aa49fa7 scripts/ChangeLog --- a/scripts/ChangeLog Wed Mar 23 17:11:08 2005 +0000 +++ b/scripts/ChangeLog Wed Mar 23 21:28:46 2005 +0000 @@ -1,5 +1,14 @@ +2005-03-23 John W. Eaton + + * optimization/glpk.m: Simplify interface. By default, solve + standard LP min C'*x s.t. A*x = b, x >= 0. + * optimization/glpkmex.m: New file. + 2005-03-22 John W. Eaton + * configure.in (AC_CONFIG_FILES): Add optimization/Makefile to the + list. + * optimization/glpk.m: Adapt to Octave coding style. No need for varargout or varargin. Print usage message if nargin > 11. diff -r 6879f10db3a4 -r 652e8aa49fa7 scripts/configure.in --- a/scripts/configure.in Wed Mar 23 17:11:08 2005 +0000 +++ b/scripts/configure.in Wed Mar 23 21:28:46 2005 +0000 @@ -32,7 +32,8 @@ control/obsolete/Makefile control/system/Makefile \ control/util/Makefile deprecated/Makefile elfun/Makefile \ finance/Makefile general/Makefile image/Makefile io/Makefile \ - linear-algebra/Makefile miscellaneous/Makefile plot/Makefile \ + linear-algebra/Makefile miscellaneous/Makefile \ + optimization/Makefile plot/Makefile \ polynomial/Makefile quaternion/Makefile set/Makefile \ signal/Makefile sparse/Makefile specfun/Makefile \ special-matrix/Makefile startup/Makefile statistics/Makefile \ diff -r 6879f10db3a4 -r 652e8aa49fa7 scripts/optimization/glpk.m --- a/scripts/optimization/glpk.m Wed Mar 23 17:11:08 2005 +0000 +++ b/scripts/optimization/glpk.m Wed Mar 23 21:28:46 2005 +0000 @@ -19,19 +19,28 @@ ## GLPK - An Octave Interface for the GNU GLPK library ## -## This routine calls the glpk library to solve an LP/MIP problem. A typical -## LP problem has following structure: +## This routine calls the glpk library to solve an LP/MIP problem. By +## default, glpk solves the following standard LP: +## +## min C'*x +## +## subject to +## +## A*x = b +## x >= 0 ## -## [min|max] C'x -## s.t. -## Ax ["="|"<="|">="] b -## {x <= UB} -## {x >= LB} +## but may also solve problems of the form +## +## [min|max] C'x +## +## subject to +## +## Ax ["="|"<="|">="] b +## {x <= UB} +## {x >= LB} ## ## The calling syntax is: -## [XOPT,FOPT,STATUS,EXTRA]=glpk(SENSE,C,... -## A,B,CTYPE,LB,UB,... -## VARTYPE,PARAM,LPSOLVER,SAVE) +## [XOPT,FOPT,STATUS,EXTRA]=glpk(C,A,B,LB,UB,CTYPE,VARTYPE,SENSE,PARAM) ## ## For a quick reference to the syntax just type glpk at command prompt. ## @@ -40,11 +49,6 @@ ## ## --- INPUTS --- ## -## SENSE: indicates whether the problem is a minimization -## or maximization problem. -## SENSE = 1 minimize -## SENSE = -1 maximize. -## ## C: A column array containing the objective function ## coefficients. ## @@ -53,6 +57,12 @@ ## B: A column array containing the right-hand side value for ## each constraint in the constraint matrix. ## +## LB: An array of at least length numcols containing the lower +## bound on each of the variables. +## +## UB: An array of at least length numcols containing the upper +## bound on each of the variables. +## ## CTYPE: A column array containing the sense of each constraint ## in the constraint matrix. ## CTYPE(i) = 'F' Free (unbounded) variable @@ -62,30 +72,20 @@ ## CTYPE(i) = 'D' Double-bounded variable ## (This is case sensitive). ## -## LB: An array of at least length numcols containing the lower -## bound on each of the variables. -## -## UB: An array of at least length numcols containing the upper -## bound on each of the variables. -## ## VARTYPE: A column array containing the types of the variables. ## VARTYPE(i) = 'C' continuous variable ## VARTYPE(i) = 'I' Integer variable ## (This is case sensitive). ## +## SENSE: indicates whether the problem is a minimization +## or maximization problem. +## SENSE = 1 minimize +## SENSE = -1 maximize. +## ## PARAM: A structure containing some parameters used to define ## the behavior of solver. For more details type ## HELP GLPKPARAMS. ## -## LPSOLVER: Selects which solver using to solve LP problems. -## LPSOLVER=1 Revised Simplex Method -## LPSOLVER=2 Interior Point Method -## If the problem is a MIP problem this flag will be ignored. -## -## SAVE: Saves a copy of the problem if SAVE<>0. -## The file name can not be specified and defaults to "outpb.lp". -## The output file is CPLEX LP format. -## ## --- OUTPUTS --- ## ## XOPT: The optimizer. @@ -145,11 +145,11 @@ ## Author: Nicolo' Giorgetti ## Adapted-by: jwe -function [xopt, fmin, status, extra] = glpk (sense, c, a, b, ctype, lb, ub, vartype, param, lpsolver, savepb) +function [xopt, fmin, status, extra] = glpk (c, a, b, lb, ub, ctype, vartype, sense, param) ## If there is no input output the version and syntax - if (nargin < 4 || nargin > 11) - usage ("[xopt, fopt, status, extra] = glpk (sense, c, a, b, ctype, lb, ub, vartype, param, lpsolver, savepb"); + if (nargin < 3 || nargin > 9) + usage ("[xopt, fopt, status, extra] = glpk (c, a, b, lb, ub, ctype, vartype, sense, param)"); return; endif @@ -161,7 +161,7 @@ ## Force column vector. c = c(:); - ## 3) Matrix constraint + ## 2) Matrix constraint if (isempty (a)) error ("A cannot be an empty matrix"); @@ -173,7 +173,7 @@ return; endif - ## 4) RHS + ## 3) RHS if (isempty (b)) error ("B cannot be an empty vector"); @@ -184,39 +184,22 @@ return; endif - ## 5) Sense of each constraint + ## 4) Vector with the lower bound of each variable - if (nargin > 4) - if (isempty (ctype)) - ctype = repmat ("U", nc, 1); - elseif (! ischar (ctype) || all (size (ctype) > 1) || length (ctype) != nc) - error ("CTYPE must be a char valued %d by 1 column vector", nc); - return; - elseif (! all (ctype == "F" | ctype == "U" | ctype == "S" - | ctype == "L" | ctype == "D")) - error ("CTYPE must contain only F, U, S, L, or D"); - return; - endif - else - ctype = repmat ("U", nc, 1); - end - - ## 6) Vector with the lower bound of each variable - - if (nargin > 5) + if (nargin > 3) if (isempty (lb)) - lb = repmat (-Inf, nx, 1); + lb = zeros (0, nx, 1); elseif (! isreal (lb) || all (size (lb) > 1) || length (lb) != nx) error ("LB must be a real valued %d by 1 column vector", nx); return; endif else - lb = repmat (-Inf, nx, 1); + lb = zeros (nx, 1); end - ## 7) Vector with the upper bound of each variable + ## 5) Vector with the upper bound of each variable - if (nargin > 6) + if (nargin > 4) if (isempty (ub)) ub = repmat (Inf, nx, 1); elseif (! isreal (ub) || all (size (ub) > 1) || length (ub) != nx) @@ -227,9 +210,26 @@ ub = repmat (Inf, nx, 1); end - ## 8) Vector with the type of variables + ## 6) Sense of each constraint - if (nargin > 7) + if (nargin > 5) + if (isempty (ctype)) + ctype = repmat ("S", nc, 1); + elseif (! ischar (ctype) || all (size (ctype) > 1) || length (ctype) != nc) + error ("CTYPE must be a char valued %d by 1 column vector", nc); + return; + elseif (! all (ctype == "F" | ctype == "U" | ctype == "S" + | ctype == "L" | ctype == "D")) + error ("CTYPE must contain only F, U, S, L, or D"); + return; + endif + else + ctype = repmat ("S", nc, 1); + end + + ## 7) Vector with the type of variables + + if (nargin > 6) if isempty (vartype) vartype = repmat ("C", nx, 1); elseif (! ischar (vartype) || all (size (vartype) > 1) @@ -245,7 +245,7 @@ vartype = repmat ("C", nx, 1); endif - ## 9) Parameters vector + ## 8) Parameters vector if (nargin > 8) if (! isstruct (param)) @@ -256,29 +256,7 @@ param = struct (); endif - ## 10) Select solver method: simplex or interior point - - if (nargin > 9) - if (! (isreal (lpsolver) && isscalar (lpsolver))) - error ("LPSOLVER must be a real scalar value"); - return; - endif - else - lpsolver = 1; - endif - - ## 11) Save the problem - - if (nargin > 10) - if (! (isreal (savepb) && isscalar (lpsolver))) - error ("LPSOLVER must be a real scalar value"); - return; - endif - else - savepb = 0; - end - [xopt, fmin, status, extra] = ... - __glpk__ (sense, c, a, b, ctype, lb, ub, vartype, param, lpsolver, savepb); + __glpk__ (c, a, b, lb, ub, ctype, vartype, sense, param); endfunction diff -r 6879f10db3a4 -r 652e8aa49fa7 scripts/optimization/glpkmex.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/optimization/glpkmex.m Wed Mar 23 21:28:46 2005 +0000 @@ -0,0 +1,108 @@ +## Copyright (C) 2005 Nicolo' Giorgetti +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2, or (at your option) +## any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, write to the Free +## Software Foundation, 59 Temple Place - Suite 330, Boston, MA +## 02111-1307, USA. + +## GLPKMEX - An Octave Interface for the GNU GLPK library +## +## This function is provided for compatibility with the old Matlab +## interface to GLPK. + +function [xopt, fopt, status, extra] = glpkmex (varargin) + + ## If there is no input output the version and syntax + if (nargin < 4 || nargin > 11) + usage ("[xopt, fopt, status, extra] = glpkmex (sense, c, a, b, ctype, lb, ub, vartype, param, lpsolver, savepb"); + return; + endif + + ## reorder args: + ## + ## glpkmex glpk + ## + ## 1 sense c + ## 2 c a + ## 3 a b + ## 4 b lb + ## 5 ctype ub + ## 6 lb ctype + ## 7 ub vartype + ## 8 vartype sense + ## 9 param param + ## 10 lpsolver + ## 11 savepb + + sense = varargin{1}; + c = varargin{2}; + a = varargin{3}; + b = varargin{4}; + + nx = length (c); + + if (nargin > 4) + ctype = varargin{5}; + else + ctype = repmat ("U", nx, 1); + endif + + if (nargin > 5) + lb = varargin{6}; + else + lb = repmat (-Inf, nx, 1); + endif + + if (nargin > 6) + ub = varargin{7}; + else + ub = repmat (Inf, nx, 1); + endif + + if (nargin > 7) + vartype = varargin{8}; + else + vartype = repmat ("C", nx, 1); + endif + + if (nargin > 8) + param = varargin{9}; + else + param = struct (); + endif + + if (nargin > 9 && ! isfield (param, "lpsolver")) + param.lpsolver = varargin{10}; + endif + + if (nargin > 10 && ! isfield (param, "save")) + param.lpsolver = varargin{11}; + endif + + if (nargout == 0) + glpk (c, a, b, lb, ub, ctype, vartype, sense, param); + elseif (nargout == 1) + xopt = glpk (c, a, b, lb, ub, ctype, vartype, sense, param); + elseif (nargout == 2) + [xopt, fopt] = glpk (c, a, b, lb, ub, ctype, vartype, sense, param); + elseif (nargout == 3) + [xopt, fopt, status] = ... + glpk (c, a, b, lb, ub, ctype, vartype, sense, param); + else + [xopt, fopt, status, extra] = ... + glpk (c, a, b, lb, ub, ctype, vartype, sense, param); + endif + +endfunction diff -r 6879f10db3a4 -r 652e8aa49fa7 scripts/optimization/glpkparams.m --- a/scripts/optimization/glpkparams.m Wed Mar 23 17:11:08 2005 +0000 +++ b/scripts/optimization/glpkparams.m Wed Mar 23 21:28:46 2005 +0000 @@ -70,6 +70,16 @@ % problem using the built-in LP presolver. Otherwise the LP % presolver is not used. % +% lpsolver type: int, default: 1 +% Select which solver to use: +% 1 revised simplex method +% 2 interior point method +% If the problem is a MIP problem this flag will be ignored. +% +% save type: int, default 0 +% If this parameter is nonzero, save a copy of the problem +% problem in CPLEX LP format to the file "outpb.lp". There +% is currently no way to change the name of the output file. % % ----------------------- % 2 Real parameters diff -r 6879f10db3a4 -r 652e8aa49fa7 scripts/optimization/glpktest1 --- a/scripts/optimization/glpktest1 Wed Mar 23 17:11:08 2005 +0000 +++ b/scripts/optimization/glpktest1 Wed Mar 23 21:28:46 2005 +0000 @@ -1,17 +1,20 @@ -clear; - -disp('1st problem'); -s=-1; -c=[10,6,4]'; -a=[1,1,1;... - 10,4,5;... - 2,2,6]; -b=[100,600,300]'; -ctype=['U','U','U']'; -lb=[0,0,0]'; -ub=[]'; -vartype=['C','C','C']'; -param.msglev=3; -lpsolver=1; -save_pb=1; -[xmin,fmin,status,extra]=glpk(s,c,a,b,ctype,lb,ub,vartype,param,lpsolver,save_pb) +clear; + +disp('1st problem'); +s=-1; +c=[10,6,4]'; +a=[1,1,1;... + 10,4,5;... + 2,2,6]; +b=[100,600,300]'; +ctype=['U','U','U']'; +lb=[0,0,0]'; +ub=[]'; +vartype=['C','C','C']'; +param.msglev=3; +param.lpsolver=1; +param.save=1; +[xmin,fmin,status,extra]=glpk(c,a,b,lb,ub,ctype,vartype,s,param) +lpsolver = param.lpsolver; +save_pb = param.save; +[xmin,fmin,status,extra]=glpkmex(s,c,a,b,ctype,lb,ub,vartype,param,lpsolver,save_pb) diff -r 6879f10db3a4 -r 652e8aa49fa7 scripts/optimization/glpktest2 --- a/scripts/optimization/glpktest2 Wed Mar 23 17:11:08 2005 +0000 +++ b/scripts/optimization/glpktest2 Wed Mar 23 21:28:46 2005 +0000 @@ -9,7 +9,8 @@ lb=[0;0]; ub=[]; vartype=['I';'I']; param.msglev=1; -[xmin,fmin,status,extra]=glpk(s,c,a,b,ctype,lb,ub,vartype,param) +[xmin,fmin,status,extra]=glpk(c,a,b,lb,ub,ctype,vartype,s,param) +[xmin,fmin,status,extra]=glpkmex(s,c,a,b,ctype,lb,ub,vartype,param) pause; disp('3rd problem'); @@ -22,4 +23,5 @@ ctype=['S','S','S']'; lb=[0,0,0,0,0]'; ub=[]; vartype=['C','C','C','C','C']'; -[xmin,fmin,status,extra]=glpk(s,c,a,b,ctype,lb,ub,vartype) +[xmin,fmin,status,extra]=glpk(c,a,b,lb,ub,ctype,vartype,s) +[xmin,fmin,status,extra]=glpkmex(s,c,a,b,ctype,lb,ub,vartype) diff -r 6879f10db3a4 -r 652e8aa49fa7 src/ChangeLog --- a/src/ChangeLog Wed Mar 23 17:11:08 2005 +0000 +++ b/src/ChangeLog Wed Mar 23 21:28:46 2005 +0000 @@ -1,3 +1,12 @@ +2005-03-23 John W. Eaton + + * DLD-FUNCTIONS/__glpk__.cc (F__glpk__): Accept lpsolver and + save_pb in param arg instead of as separate args. + Arg list now matches new interface for glpk.m. + + * toplev.cc (do_octave_atexit): Call reset_error_handler before + each call to feval. + 2005-03-22 John W. Eaton * Makefile.in: Add special rule for __glpk__.oct. diff -r 6879f10db3a4 -r 652e8aa49fa7 src/DLD-FUNCTIONS/__glpk__.cc --- a/src/DLD-FUNCTIONS/__glpk__.cc Wed Mar 23 17:11:08 2005 +0000 +++ b/src/DLD-FUNCTIONS/__glpk__.cc Wed Mar 23 21:28:46 2005 +0000 @@ -378,26 +378,18 @@ return retval; } - //-- 1st Input. Sense of optimization. - volatile int sense; - double SENSE = args(0).scalar_value (); - if (SENSE >= 0) - sense = 1; - else - sense = -1; + //-- 1nd Input. A column array containing the objective function + //-- coefficients. + int mrowsc = args(0).rows(); - //-- 2nd Input. A column array containing the objective function - //-- coefficients. - int mrowsc = args(1).rows(); - - Matrix C (args(1).matrix_value ()); + Matrix C (args(0).matrix_value ()); double *c = C.fortran_vec (); - //-- 3rd Input. A matrix containing the constraints coefficients. + //-- 2nd Input. A matrix containing the constraints coefficients. // If matrix A is NOT a sparse matrix // if(!mxIsSparse(A_IN)){ - int mrowsA = args(2).rows(); - Matrix A (args(2).matrix_value ()); // get the matrix + int mrowsA = args(1).rows(); + Matrix A (args(1).matrix_value ()); // get the matrix Array rn (mrowsA*mrowsc+1); Array cn (mrowsA*mrowsc+1); ColumnVector a (mrowsA*mrowsc+1, 0.0); @@ -449,19 +441,14 @@ // } // } - //-- 4th Input. A column array containing the right-hand side value + //-- 3rd Input. A column array containing the right-hand side value // for each constraint in the constraint matrix. - Matrix B (args(3).matrix_value ()); + Matrix B (args(2).matrix_value ()); double *b = B.fortran_vec (); - //-- 5th Input. A column array containing the sense of each constraint - //-- in the constraint matrix. - charMatrix CTYPE (args(4).char_matrix_value ()); - char *ctype = CTYPE.fortran_vec (); - - //-- 6th Input. An array of length mrowsc containing the lower + //-- 4th Input. An array of length mrowsc containing the lower //-- bound on each of the variables. - Matrix LB (args(5).matrix_value ()); + Matrix LB (args(3).matrix_value ()); double *lb = LB.fortran_vec (); //-- LB argument, default: Free @@ -477,9 +464,9 @@ freeLB(i) = 0; } - //-- 7th Input. An array of at least length numcols containing the upper + //-- 5th Input. An array of at least length numcols containing the upper //-- bound on each of the variables. - Matrix UB (args(6).matrix_value ()); + Matrix UB (args(4).matrix_value ()); double *ub = UB.fortran_vec (); @@ -495,8 +482,13 @@ freeUB(i) = 0; } - //-- 8th Input. A column array containing the types of the variables. - charMatrix VTYPE (args(7).char_matrix_value ()); + //-- 6th Input. A column array containing the sense of each constraint + //-- in the constraint matrix. + charMatrix CTYPE (args(5).char_matrix_value ()); + char *ctype = CTYPE.fortran_vec (); + + //-- 7th Input. A column array containing the types of the variables. + charMatrix VTYPE (args(6).char_matrix_value ()); Array vartype (mrowsc); volatile int isMIP = 0; @@ -511,6 +503,14 @@ vartype(i) = LPX_CV; } + //-- 8th Input. Sense of optimization. + volatile int sense; + double SENSE = args(7).scalar_value (); + if (SENSE >= 0) + sense = 1; + else + sense = -1; + //-- 9th Input. A structure containing the control parameters. Octave_map PARAM = args(8).map_value (); @@ -645,6 +645,28 @@ lpxIntParam[16] = static_cast (numtmp); } + //-- LPsolver option + volatile int lpsolver = 1; + if (PARAM.contains ("lpsolver")) + { + octave_value tmp = PARAM.contents (PARAM.seek ("lpsolver"))(0); + double numtmp = tmp.scalar_value (); + if (numtmp != 1 && numtmp != 2) + { + OCTOUT << "'lpsolver' parameter must be only:\n\t1 - simplex method,\n\t2 - interior point method\n"; + return retval; + } + lpsolver = static_cast (numtmp); + } + + //-- Save option + volatile int save_pb = 0; + if (PARAM.contains ("save")) + { + octave_value tmp = PARAM.contents (PARAM.seek ("save"))(0); + save_pb = (tmp.scalar_value () != 0); + } + //-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //-- Real parameters //-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -716,16 +738,6 @@ lpxRealParam[9] = tmp.scalar_value (); } - //-- 10th Input. If the problem is a LP problem you may select which solver - //-- use: RSM (Revised Simplex Method) or IPM (Interior Point Method). - //-- If the problem is a MIP problem this field will be ignored. - octave_value tmp = args(9).scalar_value (); - int lpsolver = static_cast (tmp.scalar_value ()); - - //-- 11th Input. Saves a copy of the problem if SAVE<>0. - tmp = args(10).scalar_value(); - int save_pb = (tmp.scalar_value() != 0); - //-- Assign pointers to the output parameters ColumnVector xmin (mrowsc); ColumnVector fmin (1); diff -r 6879f10db3a4 -r 652e8aa49fa7 src/toplev.cc --- a/src/toplev.cc Wed Mar 23 17:11:08 2005 +0000 +++ b/src/toplev.cc Wed Mar 23 21:28:46 2005 +0000 @@ -541,6 +541,8 @@ octave_atexit_functions.pop (); + reset_error_handler (); + feval (fcn, octave_value_list (), 0); flush_octave_stdout ();