5233
|
1 ## Copyright (C) 2005 Nicolo' Giorgetti |
|
2 ## |
|
3 ## This file is part of Octave. |
|
4 ## |
|
5 ## Octave is free software; you can redistribute it and/or modify it |
|
6 ## under the terms of the GNU General Public License as published by |
|
7 ## the Free Software Foundation; either version 2, or (at your option) |
|
8 ## any later version. |
|
9 ## |
|
10 ## Octave is distributed in the hope that it will be useful, but |
|
11 ## WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
13 ## General Public License for more details. |
|
14 ## |
|
15 ## You should have received a copy of the GNU General Public License |
|
16 ## along with Octave; see the file COPYING. If not, write to the Free |
5307
|
17 ## Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
|
18 ## 02110-1301, USA. |
5233
|
19 |
5244
|
20 ## -*- texinfo -*- |
|
21 ## @deftypefn {Function File} {[@var{xopt}, @var{fmin}, @var{status}, @var{extra}] =} glpk (@var{c}, @var{a}, @var{b}, @var{lb}, @var{ub}, @var{ctype}, @var{vartype}, @var{sense}, @var{param}) |
|
22 ## Solve a linear program using the GNU GLPK library. Given three |
|
23 ## arguments, @code{glpk} solves the following standard LP: |
|
24 ## |
6741
|
25 ## @iftex |
|
26 ## @tex |
|
27 ## $$ |
|
28 ## \min_x C^T x |
|
29 ## $$ |
|
30 ## @end tex |
|
31 ## @end iftex |
|
32 ## @ifnottex |
5244
|
33 ## @example |
|
34 ## min C'*x |
|
35 ## @end example |
6741
|
36 ## @end ifnottex |
5244
|
37 ## |
5237
|
38 ## subject to |
5244
|
39 ## |
6741
|
40 ## @iftex |
|
41 ## @tex |
|
42 ## $$ |
|
43 ## Ax = b \qquad x \geq 0 |
|
44 ## $$ |
|
45 ## @end tex |
|
46 ## @end iftex |
|
47 ## @ifnottex |
5244
|
48 ## @example |
|
49 ## @group |
|
50 ## A*x = b |
|
51 ## x >= 0 |
|
52 ## @end group |
|
53 ## @end example |
6741
|
54 ## @end ifnottex |
5244
|
55 ## |
5237
|
56 ## but may also solve problems of the form |
5244
|
57 ## |
6741
|
58 ## @iftex |
|
59 ## @tex |
|
60 ## $$ |
|
61 ## [ \min_x | \max_x ] C^T x |
|
62 ## $$ |
|
63 ## @end tex |
|
64 ## @end iftex |
|
65 ## @ifnottex |
5244
|
66 ## @example |
|
67 ## [ min | max ] C'*x |
|
68 ## @end example |
6741
|
69 ## @end ifnottex |
5244
|
70 ## |
5237
|
71 ## subject to |
5244
|
72 ## |
6741
|
73 ## @iftex |
|
74 ## @tex |
|
75 ## $$ |
|
76 ## Ax [ = | \leq | \geq ] b \qquad LB \leq x \leq UB |
|
77 ## $$ |
|
78 ## @end tex |
|
79 ## @end iftex |
|
80 ## @ifnottex |
5244
|
81 ## @example |
|
82 ## @group |
|
83 ## A*x [ "=" | "<=" | ">=" ] b |
|
84 ## x >= LB |
|
85 ## x <= UB |
|
86 ## @end group |
|
87 ## @end example |
6741
|
88 ## @end ifnottex |
5244
|
89 ## |
|
90 ## Input arguments: |
|
91 ## |
|
92 ## @table @var |
|
93 ## @item c |
|
94 ## A column array containing the objective function coefficients. |
|
95 ## |
|
96 ## @item a |
|
97 ## A matrix containing the constraints coefficients. |
|
98 ## |
|
99 ## @item b |
|
100 ## A column array containing the right-hand side value for each constraint |
|
101 ## in the constraint matrix. |
|
102 ## |
|
103 ## @item lb |
|
104 ## An array containing the lower bound on each of the variables. If |
|
105 ## @var{lb} is not supplied, the default lower bound for the variables is |
|
106 ## zero. |
|
107 ## |
|
108 ## @item ub |
|
109 ## An array containing the upper bound on each of the variables. If |
|
110 ## @var{ub} is not supplied, the default upper bound is assumed to be |
|
111 ## infinite. |
|
112 ## |
|
113 ## @item ctype |
|
114 ## An array of characters containing the sense of each constraint in the |
|
115 ## constraint matrix. Each element of the array may be one of the |
|
116 ## following values |
|
117 ## @table @code |
|
118 ## @item "F" |
|
119 ## Free (unbounded) variable (the constraint is ignored). |
|
120 ## @item "U" |
|
121 ## Variable with upper bound (@code{A(i,:)*x <= b(i)}). |
|
122 ## @item "S" |
|
123 ## Fixed Variable (@code{A(i,:)*x = b(i)}). |
|
124 ## @item "L" |
|
125 ## Variable with lower bound (@code{A(i,:)*x >= b(i)}). |
|
126 ## @item "D" |
|
127 ## Double-bounded variable (@code{A(i,:)*x >= -b(i)} @emph{and} |
|
128 ## (@code{A(i,:)*x <= b(i)}). |
|
129 ## @end table |
|
130 ## |
|
131 ## @item vartype |
|
132 ## A column array containing the types of the variables. |
|
133 ## @table @code |
|
134 ## @item "F" |
|
135 ## "C" |
|
136 ## Continuous variable. |
|
137 ## "I" |
|
138 ## Integer variable |
|
139 ## @end table |
|
140 ## |
|
141 ## @item sense |
|
142 ## If @var{sense} is 1, the problem is a minimization. If @var{sense} is |
|
143 ## -1, the problem is a maximization. The default value is 1. |
|
144 ## |
|
145 ## @item param |
|
146 ## A structure containing the following parameters used to define the |
|
147 ## behavior of solver. Missing elements in the structure take on default |
|
148 ## values, so you only need to set the elements that you wish to change |
|
149 ## from the default. |
|
150 ## |
|
151 ## Integer parameters: |
|
152 ## |
|
153 ## @table @code |
|
154 ## @item msglev (@code{LPX_K_MSGLEV}, default: 1) |
|
155 ## Level of messages output by solver routines: |
|
156 ## @table @asis |
|
157 ## @item 0 |
|
158 ## No output. |
|
159 ## @item 1 |
|
160 ## Error messages only. |
|
161 ## @item 2 |
|
162 ## Normal output . |
|
163 ## @item 3 |
|
164 ## Full output (includes informational messages). |
|
165 ## @end table |
|
166 ## |
|
167 ## @item scale (@code{LPX_K_SCALE}, default: 1) |
|
168 ## Scaling option: |
|
169 ## @table @asis |
|
170 ## @item 0 |
|
171 ## No scaling . |
|
172 ## @item 1 |
|
173 ## Equilibration scaling . |
|
174 ## @item 2 |
|
175 ## Geometric mean scaling, then equilibration scaling. |
|
176 ## @end table |
|
177 ## |
|
178 ## @item dual (@code{LPX_K_DUAL}, default: 0) |
|
179 ## Dual simplex option: |
|
180 ## @table @asis |
|
181 ## @item 0 |
|
182 ## Do not use the dual simplex. |
|
183 ## @item 1 |
|
184 ## If initial basic solution is dual feasible, use the dual simplex. |
|
185 ## @end table |
|
186 ## |
|
187 ## @item price (@code{LPX_K_PRICE}, default: 1) |
|
188 ## Pricing option (for both primal and dual simplex): |
|
189 ## @table @asis |
|
190 ## @item 0 |
|
191 ## Textbook pricing. |
|
192 ## @item 1 |
|
193 ## Steepest edge pricing. |
|
194 ## @end table |
|
195 ## |
|
196 ## @item round (@code{LPX_K_ROUND}, default: 0) |
|
197 ## Solution rounding option: |
|
198 ## @table @asis |
|
199 ## @item 0 |
|
200 ## Report all primal and dual values "as is". |
|
201 ## @item 1 |
|
202 ## Replace tiny primal and dual values by exact zero. |
|
203 ## @end table |
|
204 ## |
|
205 ## @item itlim (@code{LPX_K_ITLIM}, default: -1) |
|
206 ## Simplex iterations limit. If this value is positive, it is decreased by |
|
207 ## one each time when one simplex iteration has been performed, and |
|
208 ## reaching zero value signals the solver to stop the search. Negative |
|
209 ## value means no iterations limit. |
|
210 ## |
|
211 ## @item itcnt (@code{LPX_K_OUTFRQ}, default: 200) |
|
212 ## Output frequency, in iterations. This parameter specifies how |
|
213 ## frequently the solver sends information about the solution to the |
|
214 ## standard output. |
|
215 ## |
|
216 ## @item branch (@code{LPX_K_BRANCH}, default: 2) |
|
217 ## Branching heuristic option (for MIP only): |
|
218 ## @table @asis |
|
219 ## @item 0 |
|
220 ## Branch on the first variable. |
|
221 ## @item 1 |
|
222 ## Branch on the last variable. |
|
223 ## @item 2 |
|
224 ## Branch using a heuristic by Driebeck and Tomlin. |
|
225 ## @end table |
|
226 ## |
|
227 ## @item btrack (@code{LPX_K_BTRACK}, default: 2) |
|
228 ## Backtracking heuristic option (for MIP only): |
|
229 ## @table @asis |
|
230 ## @item 0 |
|
231 ## Depth first search. |
|
232 ## @item 1 |
|
233 ## Breadth first search. |
|
234 ## @item 2 |
|
235 ## Backtrack using the best projection heuristic. |
|
236 ## @end table |
|
237 ## |
|
238 ## @item presol (@code{LPX_K_PRESOL}, default: 1) |
|
239 ## If this flag is set, the routine lpx_simplex solves the problem using |
|
240 ## the built-in LP presolver. Otherwise the LP presolver is not used. |
|
241 ## |
|
242 ## @item lpsolver (default: 1) |
|
243 ## Select which solver to use. If the problem is a MIP problem this flag |
|
244 ## will be ignored. |
|
245 ## @table @asis |
|
246 ## @item 1 |
|
247 ## Revised simplex method. |
|
248 ## @item 2 |
|
249 ## Interior point method. |
|
250 ## @end table |
|
251 ## @item save (default: 0) |
|
252 ## If this parameter is nonzero, save a copy of the problem problem in |
|
253 ## CPLEX LP format to the file @file{"outpb.lp"}. There is currently no |
|
254 ## way to change the name of the output file. |
|
255 ## @end table |
|
256 ## |
|
257 ## Real parameters: |
|
258 ## |
|
259 ## @table @code |
|
260 ## @item relax (@code{LPX_K_RELAX}, default: 0.07) |
|
261 ## Relaxation parameter used in the ratio test. If it is zero, the textbook |
|
262 ## ratio test is used. If it is non-zero (should be positive), Harris' |
|
263 ## two-pass ratio test is used. In the latter case on the first pass of the |
|
264 ## ratio test basic variables (in the case of primal simplex) or reduced |
|
265 ## costs of non-basic variables (in the case of dual simplex) are allowed |
|
266 ## to slightly violate their bounds, but not more than |
|
267 ## @code{relax*tolbnd} or @code{relax*toldj (thus, @code{relax} is a |
6248
|
268 ## percentage of @code{tolbnd} or @code{toldj}}. |
5244
|
269 ## |
|
270 ## @item tolbnd (@code{LPX_K_TOLBND}, default: 10e-7) |
5289
|
271 ## Relative tolerance used to check if the current basic solution is primal |
5244
|
272 ## feasible. It is not recommended that you change this parameter unless you |
|
273 ## have a detailed understanding of its purpose. |
|
274 ## |
|
275 ## @item toldj (@code{LPX_K_TOLDJ}, default: 10e-7) |
|
276 ## Absolute tolerance used to check if the current basic solution is dual |
|
277 ## feasible. It is not recommended that you change this parameter unless you |
|
278 ## have a detailed understanding of its purpose. |
|
279 ## |
|
280 ## @item tolpiv (@code{LPX_K_TOLPIV}, default: 10e-9) |
|
281 ## Relative tolerance used to choose eligible pivotal elements of the |
|
282 ## simplex table. It is not recommended that you change this parameter unless you |
|
283 ## have a detailed understanding of its purpose. |
|
284 ## |
5289
|
285 ## @item objll (@code{LPX_K_OBJLL}, default: -DBL_MAX) |
5244
|
286 ## Lower limit of the objective function. If on the phase II the objective |
|
287 ## function reaches this limit and continues decreasing, the solver stops |
|
288 ## the search. This parameter is used in the dual simplex method only. |
|
289 ## |
|
290 ## @item objul (@code{LPX_K_OBJUL}, default: +DBL_MAX) |
|
291 ## Upper limit of the objective function. If on the phase II the objective |
|
292 ## function reaches this limit and continues increasing, the solver stops |
|
293 ## the search. This parameter is used in the dual simplex only. |
|
294 ## |
|
295 ## @item tmlim (@code{LPX_K_TMLIM}, default: -1.0) |
|
296 ## Searching time limit, in seconds. If this value is positive, it is |
|
297 ## decreased each time when one simplex iteration has been performed by the |
|
298 ## amount of time spent for the iteration, and reaching zero value signals |
|
299 ## the solver to stop the search. Negative value means no time limit. |
|
300 ## |
|
301 ## @item outdly (@code{LPX_K_OUTDLY}, default: 0.0) |
|
302 ## Output delay, in seconds. This parameter specifies how long the solver |
|
303 ## should delay sending information about the solution to the standard |
|
304 ## output. Non-positive value means no delay. |
|
305 ## |
|
306 ## @item tolint (@code{LPX_K_TOLINT}, default: 10e-5) |
5289
|
307 ## Relative tolerance used to check if the current basic solution is integer |
5244
|
308 ## feasible. It is not recommended that you change this parameter unless |
|
309 ## you have a detailed understanding of its purpose. |
|
310 ## |
|
311 ## @item tolobj (@code{LPX_K_TOLOBJ}, default: 10e-7) |
|
312 ## Relative tolerance used to check if the value of the objective function |
|
313 ## is not better than in the best known integer feasible solution. It is |
|
314 ## not recommended that you change this parameter unless you have a |
|
315 ## detailed understanding of its purpose. |
|
316 ## @end table |
|
317 ## @end table |
|
318 ## |
|
319 ## Output values: |
|
320 ## |
|
321 ## @table @var |
|
322 ## @item xopt |
|
323 ## The optimizer (the value of the decision variables at the optimum). |
|
324 ## @item fopt |
|
325 ## The optimum value of the objective function. |
|
326 ## @item status |
|
327 ## Status of the optimization. |
|
328 ## |
|
329 ## Simplex Method: |
|
330 ## @table @asis |
|
331 ## @item 180 (@code{LPX_OPT}) |
|
332 ## Solution is optimal. |
|
333 ## @item 181 (@code{LPX_FEAS}) |
|
334 ## Solution is feasible. |
|
335 ## @item 182 (@code{LPX_INFEAS}) |
|
336 ## Solution is infeasible. |
|
337 ## @item 183 (@code{LPX_NOFEAS}) |
|
338 ## Problem has no feasible solution. |
|
339 ## @item 184 (@code{LPX_UNBND}) |
|
340 ## Problem has no unbounded solution. |
|
341 ## @item 185 (@code{LPX_UNDEF}) |
|
342 ## Solution status is undefined. |
|
343 ## @end table |
|
344 ## Interior Point Method: |
|
345 ## @table @asis |
|
346 ## @item 150 (@code{LPX_T_UNDEF}) |
|
347 ## The interior point method is undefined. |
|
348 ## @item 151 (@code{LPX_T_OPT}) |
|
349 ## The interior point method is optimal. |
|
350 ## @end table |
|
351 ## Mixed Integer Method: |
|
352 ## @table @asis |
|
353 ## @item 170 (@code{LPX_I_UNDEF}) |
|
354 ## The status is undefined. |
|
355 ## @item 171 (@code{LPX_I_OPT}) |
|
356 ## The solution is integer optimal. |
|
357 ## @item 172 (@code{LPX_I_FEAS}) |
|
358 ## Solution integer feasible but its optimality has not been proven |
|
359 ## @item 173 (@code{LPX_I_NOFEAS}) |
|
360 ## No integer feasible solution. |
|
361 ## @end table |
|
362 ## @noindent |
|
363 ## If an error occurs, @var{status} will contain one of the following |
|
364 ## codes: |
5232
|
365 ## |
5244
|
366 ## @table @asis |
|
367 ## @item 204 (@code{LPX_E_FAULT}) |
|
368 ## Unable to start the search. |
|
369 ## @item 205 (@code{LPX_E_OBJLL}) |
|
370 ## Objective function lower limit reached. |
|
371 ## @item 206 (@code{LPX_E_OBJUL}) |
|
372 ## Objective function upper limit reached. |
|
373 ## @item 207 (@code{LPX_E_ITLIM}) |
|
374 ## Iterations limit exhausted. |
|
375 ## @item 208 (@code{LPX_E_TMLIM}) |
|
376 ## Time limit exhausted. |
|
377 ## @item 209 (@code{LPX_E_NOFEAS}) |
|
378 ## No feasible solution. |
|
379 ## @item 210 (@code{LPX_E_INSTAB}) |
|
380 ## Numerical instability. |
|
381 ## @item 211 (@code{LPX_E_SING}) |
|
382 ## Problems with basis matrix. |
|
383 ## @item 212 (@code{LPX_E_NOCONV}) |
|
384 ## No convergence (interior). |
|
385 ## @item 213 (@code{LPX_E_NOPFS}) |
|
386 ## No primal feasible solution (LP presolver). |
|
387 ## @item 214 (@code{LPX_E_NODFS}) |
|
388 ## No dual feasible solution (LP presolver). |
|
389 ## @end table |
|
390 ## @item extra |
|
391 ## A data structure containing the following fields: |
|
392 ## @table @code |
|
393 ## @item lambda |
|
394 ## Dual variables. |
|
395 ## @item redcosts |
|
396 ## Reduced Costs. |
|
397 ## @item time |
|
398 ## Time (in seconds) used for solving LP/MIP problem. |
|
399 ## @item mem |
6333
|
400 ## Memory (in bytes) used for solving LP/MIP problem (this is not |
|
401 ## available if the version of GLPK is 4.15 or later). |
5244
|
402 ## @end table |
|
403 ## @end table |
|
404 ## |
|
405 ## Example: |
|
406 ## |
|
407 ## @example |
|
408 ## @group |
|
409 ## c = [10, 6, 4]'; |
|
410 ## a = [ 1, 1, 1; |
|
411 ## 10, 4, 5; |
|
412 ## 2, 2, 6]; |
|
413 ## b = [100, 600, 300]'; |
|
414 ## lb = [0, 0, 0]'; |
|
415 ## ub = []; |
|
416 ## ctype = "UUU"; |
|
417 ## vartype = "CCC"; |
|
418 ## s = -1; |
|
419 ## |
|
420 ## param.msglev = 1; |
|
421 ## param.itlim = 100; |
|
422 ## |
|
423 ## [xmin, fmin, status, extra] = ... |
|
424 ## glpk (c, a, b, lb, ub, ctype, vartype, s, param); |
|
425 ## @end group |
|
426 ## @end example |
|
427 ## @end deftypefn |
5232
|
428 |
5233
|
429 ## Author: Nicolo' Giorgetti <giorgetti@dii.unisi.it> |
|
430 ## Adapted-by: jwe |
5232
|
431 |
5237
|
432 function [xopt, fmin, status, extra] = glpk (c, a, b, lb, ub, ctype, vartype, sense, param) |
5232
|
433 |
5233
|
434 ## If there is no input output the version and syntax |
5237
|
435 if (nargin < 3 || nargin > 9) |
6046
|
436 print_usage (); |
5233
|
437 return; |
|
438 endif |
5232
|
439 |
5233
|
440 if (all (size (c) > 1) || iscomplex (c) || ischar (c)) |
|
441 error ("C must be a real vector"); |
|
442 return; |
|
443 endif |
|
444 nx = length (c); |
|
445 ## Force column vector. |
|
446 c = c(:); |
5232
|
447 |
5237
|
448 ## 2) Matrix constraint |
5232
|
449 |
5233
|
450 if (isempty (a)) |
|
451 error ("A cannot be an empty matrix"); |
|
452 return; |
|
453 endif |
|
454 [nc, nxa] = size(a); |
|
455 if (! isreal (a) || nxa != nx) |
|
456 error ("A must be a real valued %d by %d matrix", nc, nx); |
|
457 return; |
|
458 endif |
|
459 |
5237
|
460 ## 3) RHS |
5232
|
461 |
5233
|
462 if (isempty (b)) |
|
463 error ("B cannot be an empty vector"); |
|
464 return; |
|
465 endif |
|
466 if (! isreal (b) || length (b) != nc) |
|
467 error ("B must be a real valued %d by 1 vector", nc); |
|
468 return; |
|
469 endif |
|
470 |
5237
|
471 ## 4) Vector with the lower bound of each variable |
5232
|
472 |
5237
|
473 if (nargin > 3) |
5233
|
474 if (isempty (lb)) |
5237
|
475 lb = zeros (0, nx, 1); |
5233
|
476 elseif (! isreal (lb) || all (size (lb) > 1) || length (lb) != nx) |
|
477 error ("LB must be a real valued %d by 1 column vector", nx); |
|
478 return; |
|
479 endif |
|
480 else |
5237
|
481 lb = zeros (nx, 1); |
5233
|
482 end |
|
483 |
5237
|
484 ## 5) Vector with the upper bound of each variable |
5232
|
485 |
5237
|
486 if (nargin > 4) |
5233
|
487 if (isempty (ub)) |
|
488 ub = repmat (Inf, nx, 1); |
|
489 elseif (! isreal (ub) || all (size (ub) > 1) || length (ub) != nx) |
|
490 error ("UB must be a real valued %d by 1 column vector", nx); |
|
491 return; |
|
492 endif |
|
493 else |
|
494 ub = repmat (Inf, nx, 1); |
|
495 end |
5232
|
496 |
5237
|
497 ## 6) Sense of each constraint |
5232
|
498 |
5237
|
499 if (nargin > 5) |
|
500 if (isempty (ctype)) |
|
501 ctype = repmat ("S", nc, 1); |
|
502 elseif (! ischar (ctype) || all (size (ctype) > 1) || length (ctype) != nc) |
5244
|
503 error ("CTYPE must be a char valued vector of length %d", nc); |
5237
|
504 return; |
|
505 elseif (! all (ctype == "F" | ctype == "U" | ctype == "S" |
|
506 | ctype == "L" | ctype == "D")) |
|
507 error ("CTYPE must contain only F, U, S, L, or D"); |
|
508 return; |
|
509 endif |
|
510 else |
|
511 ctype = repmat ("S", nc, 1); |
|
512 end |
|
513 |
|
514 ## 7) Vector with the type of variables |
|
515 |
|
516 if (nargin > 6) |
5289
|
517 if (isempty (vartype)) |
5233
|
518 vartype = repmat ("C", nx, 1); |
|
519 elseif (! ischar (vartype) || all (size (vartype) > 1) |
|
520 || length (vartype) != nx) |
5244
|
521 error ("VARTYPE must be a char valued vector of length %d", nx); |
5233
|
522 return; |
|
523 elseif (! all (vartype == "C" | vartype == "I")) |
|
524 error ("VARTYPE must contain only C or I"); |
|
525 return; |
|
526 endif |
|
527 else |
|
528 ## As default we consider continuous vars |
|
529 vartype = repmat ("C", nx, 1); |
|
530 endif |
5232
|
531 |
5289
|
532 ## 8) Sense of optimization |
|
533 |
|
534 if (nargin > 7) |
|
535 if (isempty (sense)) |
|
536 sense = 1; |
|
537 elseif (ischar (sense) || all (size (sense) > 1) || ! isreal (sense)) |
|
538 error ("SENSE must be an integer value"); |
|
539 elseif (sense >= 0) |
|
540 sense = 1; |
|
541 else |
|
542 sense = -1; |
|
543 endif |
|
544 else |
|
545 sense = 1; |
|
546 endif |
|
547 |
|
548 ## 9) Parameters vector |
5233
|
549 |
|
550 if (nargin > 8) |
|
551 if (! isstruct (param)) |
|
552 error ("PARAM must be a structure"); |
|
553 return; |
|
554 endif |
|
555 else |
|
556 param = struct (); |
|
557 endif |
5232
|
558 |
5233
|
559 [xopt, fmin, status, extra] = ... |
5237
|
560 __glpk__ (c, a, b, lb, ub, ctype, vartype, sense, param); |
5232
|
561 |
|
562 endfunction |