/* glpapi3.c (glp_call_ipm1) */

/*----------------------------------------------------------------------
-- Copyright (C) 2000, 2001, 2002 Andrew Makhorin <mao@mai2.rcnet.ru>,
--               Department for Applied Informatics, Moscow Aviation
--               Institute, Moscow, Russia. All rights reserved.
--
-- This file is a part of GLPK (GNU Linear Programming Kit).
--
-- GLPK 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.
--
-- GLPK 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 GLPK; see the file COPYING. If not, write to the Free
-- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-- 02111-1307, USA.
----------------------------------------------------------------------*/

#include <stddef.h>
#include "glpk.h"
#include "glpipm.h"

/*----------------------------------------------------------------------
-- glp_call_ipm1 - solve LP problem using interior point method.
--
-- *Synopsis*
--
-- #include "glpk.h"
-- int glp_call_ipm1(LPI *lpi);
--
-- *Description*
--
-- The routine glp_call_ipm1 is an interface to a LP problem solver
-- based on the primal-dual interior point method.
--
-- This routine obtains problem data from the problem object, which the
-- parameter lpi points to, solves the problem, and stores the computed
-- solution back to the problem object.
--
-- On each iteration the interior point solver reports some information
-- about the current point. This information is sent to stdout and has
-- the following format:
--
--    nnn: F = fff; rpi = ppp; rdi = ddd; gap = ggg
--
-- where nnn is number of iteration (0 means the starting point), fff
-- is current value of the objective function (in case of maximization
-- this value has opposite sign), ppp is relative primal infeasibility,
-- ddd is relative dual infeasibility, ggg is relative primal-dual gap
-- (the difference between values of primal and dual objectives).
--
-- Note that this solver is *tentative* and hasn't got many important
-- features (no dense column handling, no iterative refinement of the
-- solution, no optimal basis identification, etc.).
--
-- The routine glp_call_ipm1 returns one of the following codes:
--
-- 0 - optimal solution found;
-- 1 - problem has no feasible (primal or dual) solution;
-- 2 - no convergence;
-- 3 - iteration limit exceeded;
-- 4 - numerical unstability on solving Newtonian system.
--
-- In case of non-zero return code the routine returns the best point
-- which has been reached during optimization. */

int glp_call_ipm1(LPI *lpi)
{     LP *lp;
      LPSOL *sol;
      int ret, status, i, j;
      /* check control parameter for correctness */
      /* extract LP problem data from the problem object */
      lp = extract_prob(lpi);
      /* warn about dense columns */
      if (lp->m > 200)
      {  for (j = 1; j <= lp->n; j++)
         {  if (count_nz(lp->A, -j) > lp->m / 10)
            {  print("*WARNING* THE PROBLEM HAS DENSE COLUMN(S)");
               break;
            }
         }
      }
      /* create LP solution block */
      sol = create_lpsol(lp->m, lp->n);
      /* call the primal-dual interior point method */
      ret = ipm1_driver(lp, sol);
      if (ret == 0)
         status = GLP_OPT;
      else
         status = GLP_UNDEF;
      /* store obtained LP solution back to the problem object */
      glp_put_soln_info(lpi, '?', status, sol->objval);
      for (i = 1; i <= sol->m; i++)
         glp_put_row_soln(lpi, i, 'B', sol->valx[i], 0.0);
      for (j = 1; j <= sol->n; j++)
         glp_put_col_soln(lpi, j, 'B', sol->valx[sol->m+j], 0.0);
      /* free working data structures */
      delete_lp(lp);
      delete_lpsol(sol);
      /* return to the application program */
      return ret;
}

/* eof */
