home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / octave-1.1.1p1-base.tgz / octave-1.1.1p1-base.tar / fsf / octave / src / f-qpsol.cc < prev    next >
C/C++ Source or Header  |  1995-01-30  |  9KB  |  418 lines

  1. // f-qpsol.cc                                           -*- C++ -*-
  2. /*
  3.  
  4. Copyright (C) 1993, 1994, 1995 John W. Eaton
  5.  
  6. This file is part of Octave.
  7.  
  8. Octave is free software; you can redistribute it and/or modify it
  9. under the terms of the GNU General Public License as published by the
  10. Free Software Foundation; either version 2, or (at your option) any
  11. later version.
  12.  
  13. Octave is distributed in the hope that it will be useful, but WITHOUT
  14. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  15. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  16. for more details.
  17.  
  18. You should have received a copy of the GNU General Public License
  19. along with Octave; see the file COPYING.  If not, write to the Free
  20. Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  
  22. */
  23.  
  24. #ifdef HAVE_CONFIG_H
  25. #include "config.h"
  26. #endif
  27.  
  28. #include <strstream.h>
  29.  
  30. #include "QPSOL.h"
  31.  
  32. #include "tree-const.h"
  33. #include "variables.h"
  34. #include "gripes.h"
  35. #include "error.h"
  36. #include "utils.h"
  37. #include "pager.h"
  38. #include "help.h"
  39. #include "defun-dld.h"
  40.  
  41. #ifndef QPSOL_MISSING
  42.  
  43. // This should probably be defined in some shared file and declared in
  44. // a header file...
  45. extern int linear_constraints_ok (const ColumnVector& x,
  46.                   const ColumnVector& llb, const Matrix& c,
  47.                   const ColumnVector& lub, char *warn_for,
  48.                   int warn);
  49.  
  50. static QPSOL_options qpsol_opts;
  51.  
  52. #endif
  53.  
  54. #if defined (QPSOL_MISSING)
  55. DEFUN_DLD_BUILTIN ("qpsol", Fqpsol, Sqpsol, 9, 3,
  56.   "This function requires QPSOL, which is not freely\n\
  57. redistributable.  For more information, read the file\n\
  58. libcruft/qpsol/README.MISSING in the source distribution.")
  59. #else
  60. DEFUN_DLD_BUILTIN ("qpsol", Fqpsol, Sqpsol, 9, 3,
  61.   "[X, OBJ, INFO, LAMBDA] = qpsol (X, H, C [, LB, UB] [, LB, A, UB])\n\
  62. \n\
  63. Groups of arguments surrounded in `[]' are optional, but\n\
  64. must appear in the same relative order shown above.")
  65. #endif
  66. {
  67. /*
  68.  
  69. Handle all of the following:
  70.  
  71.   1. qpsol (x, H, c)
  72.   2. qpsol (x, H, c, lb, ub)
  73.   3. qpsol (x, H, c, lb, ub, llb, A, lub)
  74.   4. qpsol (x, H, c,         llb, A, lub)
  75.  
  76. */
  77.  
  78.   Octave_object retval;
  79.  
  80. #if defined (QPSOL_MISSING)
  81.  
  82. // Force a bad value of inform, and empty matrices for x, phi, and lambda.
  83.  
  84.   retval.resize (4, Matrix ());
  85.  
  86.   retval(2) = -1.0;
  87.  
  88.   print_usage ("qpsol");
  89.  
  90. #else
  91.  
  92.   int nargin = args.length ();
  93.  
  94.   if (nargin < 3 || nargin == 4 || nargin == 7 || nargin > 8
  95.       || nargout > 4)
  96.     {
  97.       print_usage ("qpsol");
  98.       return retval;
  99.     }
  100.  
  101.   ColumnVector x = args(0).vector_value ();
  102.  
  103.   if (error_state || x.capacity () == 0)
  104.     {
  105.       error ("qpsol: expecting vector as first argument");
  106.       return retval;
  107.     }
  108.  
  109.   Matrix H = args(1).matrix_value ();
  110.  
  111.   if (error_state || H.rows () != H.columns () || H.rows () != x.capacity ())
  112.     {
  113.       error ("qpsol: H must be a square matrix consistent with the size of x");
  114.       return retval;
  115.     }
  116.  
  117.   ColumnVector c = args(2).vector_value ();
  118.  
  119.   if (error_state || c.capacity () != x.capacity ())
  120.     {
  121.       error ("qpsol: c must be a vector the same size as x");
  122.       return retval;
  123.     }
  124.  
  125.   Bounds bounds;
  126.   if (nargin == 5 || nargin == 8)
  127.     {
  128.       ColumnVector lb = args(3).vector_value ();
  129.       ColumnVector ub = args(4).vector_value ();
  130.  
  131.       int lb_len = lb.capacity ();
  132.       int ub_len = ub.capacity ();
  133.  
  134.       if (error_state || lb_len != ub_len || lb_len != x.capacity ())
  135.     {
  136.       error ("qpsol: lower and upper bounds and decision variable vector");
  137.       error ("must all have the same number of elements");
  138.       return retval;
  139.     }
  140.  
  141.       bounds.resize (lb_len);
  142.       bounds.set_lower_bounds (lb);
  143.       bounds.set_upper_bounds (ub);
  144.     }
  145.  
  146.   ColumnVector soln;
  147.   double objf;
  148.   ColumnVector lambda;
  149.   int inform;
  150.  
  151.   if (nargin == 3)
  152.     {
  153.       // 1. qpsol (x, H, c)
  154.  
  155.       QPSOL qp (x, H, c);
  156.       qp.copy (qpsol_opts);
  157.       soln = qp.minimize (objf, inform, lambda);
  158.  
  159.       goto solved;
  160.     }
  161.  
  162.   if (nargin == 5)
  163.     {
  164.       //  2. qpsol (x, H, c, lb, ub)
  165.  
  166.       QPSOL qp (x, H, c, bounds);
  167.       qp.copy (qpsol_opts);
  168.       soln = qp.minimize (objf, inform, lambda);
  169.  
  170.       goto solved;
  171.     }
  172.  
  173.   if (nargin == 6 || nargin == 8)
  174.     {
  175.       ColumnVector lub = args(nargin-1).vector_value ();
  176.       ColumnVector llb = args(nargin-3).vector_value ();
  177.  
  178.       if (error_state || llb.capacity () == 0 || lub.capacity () == 0)
  179.     {
  180.       error ("qpsol: bounds for linear constraints must be vectors");
  181.       return retval;
  182.     }
  183.  
  184.       Matrix A = args(nargin-2).matrix_value ();
  185.  
  186.       if (error_state)
  187.     {
  188.       error ("qpsol: invalid linear constraint matrix");
  189.       return retval;
  190.     }
  191.  
  192.       if (! linear_constraints_ok (x, llb, A, lub, "qpsol", 1))
  193.     return retval;
  194.  
  195.       LinConst linear_constraints (llb, A, lub);
  196.  
  197.       if (nargin == 8)
  198.     {
  199.       // 3. qpsol (x, H, c, lb, ub, llb, A, lub)
  200.  
  201.       QPSOL qp (x, H, c, bounds, linear_constraints);
  202.       qp.copy (qpsol_opts);
  203.       soln = qp.minimize (objf, inform, lambda);
  204.     }
  205.       else
  206.     {
  207.       // 4. qpsol (x, H, c,         llb, A, lub)
  208.  
  209.      QPSOL qp (x, H, c, linear_constraints);
  210.      qp.copy (qpsol_opts);
  211.      soln = qp.minimize (objf, inform, lambda);
  212.        }
  213.       goto solved;
  214.     }
  215.  
  216.   return retval;
  217.  
  218.  solved:
  219.  
  220.   retval.resize (nargout ? nargout : 1);
  221.   retval(0) = soln, 1;
  222.   if (nargout > 1)
  223.     retval(1) = objf;
  224.   if (nargout > 2)
  225.     retval(2) = (double) inform;
  226.   if (nargout > 3)
  227.     retval(3) = lambda;
  228.  
  229. #endif
  230.  
  231.   return retval;
  232. }
  233.  
  234. #ifndef QPSOL_MISSING
  235.  
  236. typedef void (QPSOL_options::*d_set_opt_mf) (double);
  237. typedef void (QPSOL_options::*i_set_opt_mf) (int);
  238. typedef double (QPSOL_options::*d_get_opt_mf) (void);
  239. typedef int (QPSOL_options::*i_get_opt_mf) (void);
  240.  
  241. #define MAX_TOKENS 2
  242.  
  243. struct QPSOL_OPTIONS
  244. {
  245.   const char *keyword;
  246.   const char *kw_tok[MAX_TOKENS + 1];
  247.   int min_len[MAX_TOKENS + 1];
  248.   int min_toks_to_match;
  249.   d_set_opt_mf d_set_fcn;
  250.   i_set_opt_mf i_set_fcn;
  251.   d_get_opt_mf d_get_fcn;
  252.   i_get_opt_mf i_get_fcn;
  253. };
  254.  
  255. static QPSOL_OPTIONS qpsol_option_table [] =
  256. {
  257.   { "feasibility tolerance",
  258.     { "feasibility", "tolerance", 0, },
  259.     { 1, 0, 0, }, 1,
  260.     QPSOL_options::set_feasibility_tolerance, 0,
  261.     QPSOL_options::feasibility_tolerance, 0, },
  262.  
  263.   { "infinite bound",
  264.     { "infinite", "bound", 0, },
  265.     { 2, 0, 0, }, 1,
  266.     QPSOL_options::set_infinite_bound, 0,
  267.     QPSOL_options::infinite_bound, 0, },
  268.  
  269.   { "iteration limit",
  270.     { "iteration", "limit", 0, },
  271.     { 2, 0, 0, }, 1,
  272.     0, QPSOL_options::set_iteration_limit,
  273.     0, QPSOL_options::iteration_limit, },
  274.  
  275.   { "print level",
  276.     { "print", "level", 0, },
  277.     { 1, 0, 0, }, 1,
  278.     0, QPSOL_options::set_print_level,
  279.     0, QPSOL_options::print_level, },
  280.  
  281.   { 0,
  282.     { 0, 0, 0, },
  283.     { 0, 0, 0, }, 0,
  284.     0, 0, 0, 0, },
  285. };
  286.  
  287. static void
  288. print_qpsol_option_list (void)
  289. {
  290.   ostrstream output_buf;
  291.  
  292.   print_usage ("qpsol_options", 1);
  293.  
  294.   output_buf << "\n"
  295.          << "Options for qpsol include:\n\n"
  296.          << "  keyword                                  value\n"
  297.          << "  -------                                  -----\n\n";
  298.  
  299.   QPSOL_OPTIONS *list = qpsol_option_table;
  300.  
  301.   const char *keyword;
  302.   while ((keyword = list->keyword) != 0)
  303.     {
  304.       output_buf.form ("  %-40s ", keyword);
  305.       if (list->d_get_fcn)
  306.     {
  307.       double val = (qpsol_opts.*list->d_get_fcn) ();
  308.       if (val < 0.0)
  309.         output_buf << "computed automatically";
  310.       else
  311.         output_buf << val;
  312.     }
  313.       else
  314.     {
  315.       int val = (qpsol_opts.*list->i_get_fcn) ();
  316.       if (val < 0)
  317.         output_buf << "depends on problem size";
  318.       else
  319.         output_buf << val;
  320.     }
  321.       output_buf << "\n";
  322.       list++;
  323.     }
  324.  
  325.   output_buf << "\n" << ends;
  326.   maybe_page_output (output_buf);
  327. }
  328.  
  329. static void
  330. do_qpsol_option (char *keyword, double val)
  331. {
  332.   QPSOL_OPTIONS *list = qpsol_option_table;
  333.  
  334.   while (list->keyword != 0)
  335.     {
  336.       if (keyword_almost_match (list->kw_tok, list->min_len, keyword,
  337.                 list->min_toks_to_match, MAX_TOKENS))
  338.     {
  339.       if (list->d_set_fcn)
  340.         (qpsol_opts.*list->d_set_fcn) (val);
  341.       else
  342.         {
  343.           if (xisnan (val))
  344.         {
  345.           error ("qpsol_options: %s: expecting integer, found NaN",
  346.              keyword);
  347.         }
  348.           else
  349.         (qpsol_opts.*list->i_set_fcn) (NINT (val));
  350.         }
  351.       return;
  352.     }
  353.       list++;
  354.     }
  355.  
  356.   warning ("qpsol_options: no match for `%s'", keyword);
  357. }
  358.  
  359. #endif
  360.  
  361. #if defined (QPSOL_MISSING)
  362. DEFUN_DLD_BUILTIN ("qpsol_options", Fqpsol_options, Sqpsol_options, -1, 1,
  363.   "This function requires QPSOL, which is not freely\n\
  364. redistributable.  For more information, read the file\n\
  365. libcruft/qpsol/README.MISSING in the source distribution.")
  366. #else
  367. DEFUN_DLD_BUILTIN ("qpsol_options", Fqpsol_options, Sqpsol_options, -1, 1,
  368.   "qpsol_options (KEYWORD, VALUE)\n
  369. \n\
  370. Set or show options for qpsol.  Keywords may be abbreviated\n\
  371. to the shortest match.")
  372. #endif
  373. {
  374.   Octave_object retval;
  375.  
  376. #if defined (QPSOL_MISSING)
  377.  
  378.   print_usage ("qpsol");
  379.  
  380. #else
  381.  
  382.   int nargin = args.length ();
  383.  
  384.   if (nargin == 0)
  385.     {
  386.       print_qpsol_option_list ();
  387.       return retval;
  388.     }
  389.   else if (nargin == 2)
  390.     {
  391.       char *keyword = args(0).string_value ();
  392.  
  393.       if (! error_state)
  394.     {
  395.       double val = args(1).double_value ();
  396.  
  397.       if (! error_state)
  398.         {
  399.           do_qpsol_option (keyword, val);
  400.           return retval;
  401.         }
  402.     }
  403.     }
  404.  
  405.   print_usage ("qpsol_options");
  406.  
  407. #endif
  408.  
  409.   return retval;
  410. }
  411.  
  412. /*
  413. ;;; Local Variables: ***
  414. ;;; mode: C++ ***
  415. ;;; page-delimiter: "^/\\*" ***
  416. ;;; End: ***
  417. */
  418.