/* glprsm.h */

/*----------------------------------------------------------------------
-- 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.
----------------------------------------------------------------------*/

#ifndef _GLPRSM_H
#define _GLPRSM_H

#include "glpinv.h"
#include "glpk.h"
#include "glplp.h"

#define btran                 _glp_btran
#define build_basis           _glp_build_basis
#define change_b              _glp_change_b
#define check_bbar            _glp_check_bbar
#define check_cbar            _glp_check_cbar
#define check_dvec            _glp_check_dvec
#define check_gvec            _glp_check_gvec
#define check_rr              _glp_check_rr
#define check_rsm             _glp_check_rsm
#define create_rsm            _glp_create_rsm
#define delete_rsm            _glp_delete_rsm
#define dual_col              _glp_dual_col
#define dual_row              _glp_dual_row
#define eval_bbar             _glp_eval_bbar
#define eval_cbar             _glp_eval_cbar
#define eval_col              _glp_eval_col
#define eval_pi               _glp_eval_pi
#define eval_row              _glp_eval_row
#define eval_xn               _glp_eval_xn
#define eval_zeta             _glp_eval_zeta
#define exact_dvec            _glp_exact_dvec
#define exact_gvec            _glp_exact_gvec
#define ftran                 _glp_ftran
#define harris_col            _glp_harris_col
#define harris_row            _glp_harris_row
#define init_dvec             _glp_init_dvec
#define init_gvec             _glp_init_gvec
#define invert_b              _glp_invert_b
#define pivot_col             _glp_pivot_col
#define pivot_row             _glp_pivot_row
#define rsm_dual              _glp_rsm_dual
#define rsm_feas              _glp_rsm_feas
#define rsm_primal            _glp_rsm_primal
#define rsm1_driver           _glp_rsm1_driver
#define scale_rsm             _glp_scale_rsm
#define update_b              _glp_update_b
#define update_dvec           _glp_update_dvec
#define update_gvec           _glp_update_gvec

typedef struct RSM RSM;

struct RSM
{     /* revised simplex method common block */
      int m;
      /* number of rows (auxiliary variables) */
      int n;
      /* number of columns (structural variables) */
      int *type; /* int type[1+m+n]; */
      /* type[0] is not used; type[k] specifies the type of variable
         x[k] (1 <= k <= m+n):
         'F' - free variable:    -inf <  x[k] < +inf
         'L' - lower bound:      l[k] <= x[k] < +inf
         'U' - upper bound:      -inf <  x[k] <= u[k]
         'D' - double bound:     l[k] <= x[k] <= u[k]
         'S' - fixed variable:   l[k]  = x[k]  = u[k] */
      double *lb; /* double lb[1+m+n]; */
      /* lb[0] is not used; lb[k] is the lower bound of variable x[k]
         (1 <= k <= m+n); if x[k] has no lower bound, lb[k] is zero */
      double *ub; /* double ub[1+m+n]; */
      /* ub[0] is not used; ub[k] is the upper bound of variable x[k]
         (1 <= k <= m+n); if x[k] has no upper bound, ub[k] is zero;
         if x[k] is fixed variable, lb[k] is equal to ub[k] */
      MAT *A; /* MAT A[1:m,1:m+n]; */
      /* expanded matrix of constraint coefficients A~ = (I | -A),
         where I is the unity matrix, A is the original matrix of the LP
         problem; using the matrix A~ the system of equality constraints
         may be written in homogeneous form A~*x = 0, where x = (xR, xS)
         is the united vector of all variables, xR = (x[1],...,x[m]) is
         the subvector of auxiliary variables, xS = (x[m+1],...,x[m+n])
         is the subvector of structural variables */
      int *posx; /* int posx[1+m+n]; */
      /* posx[0] is not used; posx[k] is the position of the variable
         x[k] (1 <= k <= m+n) in the vector xB of basis variables or in
         the vector xN of non-basis variables:
         posx[k] = +i means that x[k] = xB[i] (1 <= i <= m)
         posx[k] = -j means that x[k] = xN[j] (1 <= j <= n) */
      int *indb; /* int indb[1+m]; */
      /* indb[0] is not used; indb[i] = k means that xB[i] = x[k] */
      int *indn; /* int indn[1+n]; */
      /* indn[0] is not used; indn[j] = k means that xN[j] = x[k] */
      int *tagn; /* int tagn[1+n]; */
      /* tagn[0] is not used; tagn[j] is the status of the non-basis
         variable xN[j] (1 <= j <= n):
         'L' - non-basis variable on its lower bound
         'U' - non-basis variable on its upper bound
         'F' - non-basis free variable
         'S' - non-basis fixed variable */
      INV *inv;
      /* an invertable (factorized) form of the basis matrix */
      int iter;
      /* iteration count (increased each time when the current basis is
         replaced by the adjacent one) */
};

/*** operations on basis matrix ***/

extern int invert_b(RSM *rsm);
/* rebuild representation of the basis matrix */

extern void ftran(RSM *rsm, double u[], int save);
/* perform forward transformation */

extern void btran(RSM *rsm, double u[]);
/* perform backward transformation */

extern int update_b(RSM *rsm, int p);
/* update representation of the basis matrix */

/*** operations on simplex table ***/

extern void check_rsm(RSM *rsm);
/* check common block for correctness */

extern double eval_xn(RSM *rsm, int j);
/* determine value of non-basic variable */

extern void eval_bbar(RSM *rsm, double bbar[]);
/* compute values of basic variables */

extern void eval_pi(RSM *rsm, double c[], double pi[]);
/* compute simplex multipliers */

extern void eval_cbar(RSM *rsm, double c[], double pi[], double cbar[]);
/* compute reduced costs of non-basic variables */

extern int check_rr(double x, double x0, double tol);
/* check relative residual */

extern int check_bbar(RSM *rsm, double bbar[], double tol);
/* check basis solution for primal feasibility */

extern int check_cbar(RSM *rsm, double c[], double cbar[], double tol);
/* check basis solution for dual feasibility */

extern void eval_col(RSM *rsm, int j, double aj[], int save);
/* compute column of the simplex table */

extern void eval_zeta(RSM *rsm, int i, double zeta[]);
/* compute row of the inverse */

extern void eval_row(RSM *rsm, double zeta[], double ai[]);
/* compute row of the simplex table */

extern int change_b(RSM *rsm, int p, int tagp, int q);
/* change basis */

/*** primal steepest edge routines ***/

extern void init_gvec(RSM *rsm, double gvec[]);
/* initialize the vector gamma */

extern void update_gvec(RSM *rsm, double gvec[], int p, int q,
      double ap[], double aq[], double w[]);
/* update the vector gamma */

extern double exact_gvec(RSM *rsm, int j);
/* compute exact value of gamma[j] */

extern double check_gvec(RSM *rsm, double gvec[]);
/* check accuracy of the vector gamma */

/*** dual steepest edge routines ***/

extern void init_dvec(RSM *rsm, double dvec[]);
/* initialize the vector delta */

extern void update_dvec(RSM *rsm, double dvec[], int p, int q,
      double ap[], double aq[], double w[]);
/* update the vector delta */

extern double exact_dvec(RSM *rsm, int i);
/* compute exact value of delta[i] */

extern double check_dvec(RSM *rsm, double dvec[]);
/* check accuracy of the vector delta */

/*** primal simplex method routines ***/

extern int pivot_col(RSM *rsm, double c[], double cbar[], double gvec[],
      double tol);
/* choose non-basic variable (primal) */

extern int pivot_row(RSM *rsm, int q, int dir, double aq[],
      double bbar[], int *tagp, double tol);
/* choose basic variable (primal, standard technique) */

extern int harris_row(RSM *rsm, int q, int dir, double aq[],
      double bbar[], int *tagp, double tol, double tol1);
/* choose basic variable (primal, Harris technique) */

/*** dual simplex method routines ***/

extern int dual_row(RSM *rsm, double bbar[], double dvec[], int *tagp,
      double tol);
/* choose basic variable (dual) */

extern int dual_col(RSM *rsm, int tagp, double ap[], double cbar[],
      double tol);
/* choose non-basic variable (dual, standard technique) */

extern int harris_col(RSM *rsm, int tagp, double ap[], double c[],
      double cbar[], double tol, double tol1);
/* choose non-basic variable (dual, Harris technique) */

/*** driver simplex method routines ***/

extern int rsm_primal(RSM *rsm, int (*monit)(void), double c[],
      double tol_bnd, double tol_dj, double tol_piv, double gvec[],
      int relax);
/* find optimal solution using primal simplex method */

extern int rsm_dual(RSM *rsm, int (*monit)(void), double c[],
      double tol_bnd, double tol_dj, double tol_piv, double dvec[],
      int relax);
/* find optimal solution using dual simplex method */

extern int rsm_feas(RSM *rsm, int (*monit)(void),
      double tol_bnd, double tol_dj, double tol_piv, double gvec[],
      int relax);
/* find feasible solution using primal simplex method */

struct rsm1_cp
{     /* control parameters passed to the rsm1_driver routine */
      int what;
      /* this parameter specifies what basis solution should be found
         by the solver:
         0 - initial solution
         1 - primal feasible solution
         2 - optimal solution */
      int scale;
      /* if this flag is set, the solver performs automatic scaling the
         problem; otherwise the scaling is not used */
      int dual;
      /* if this flag is set, the solver uses the dual simplex method
         in order to find the primal feasible basis solution; otherwise
         the solver uses the primal simplex method */
      int steep;
      /* if this flag is set, the solver uses the steepest edge pricing
         (for both primal and dual simplex) proposed by Goldfarb & Reid;
         otherwise the solver uses the standard "textbook" pricing */
      int relax;
      /* if this flag is set, the solver uses two-pass ratio test (for
         both primal and dual simplex) proposed by P.Harris; otherwise
         the solver uses the standard "textbook" ratio test */
      double tol_bnd;
      /* relative tolerance which is used to see if the solution is
         primal feasible */
      double tol_dj;
      /* relative tolerance which is used to see if the solution is
         dual feasible */
      double tol_piv;
      /* relative tolerance which is used to choose the pivot element
         of the simplex table */
      int iter_max;
      /* maximal allowed number of iterations (0 means no limit) */
      int round;
      /* if this flag is set, the solver replaces computed values of
         basic variables and reduced costs of non-basic variables which
         are close to zero by exact zeros; otherwise the solver remains
         all computed values and reduced costs "as is" */
};

extern int rsm1_driver(LP *lp, LPSOL *sol, struct rsm1_cp *cp);
/* driver for the revised simplex method */

/*** auxiliary routines ***/

extern RSM *create_rsm(LPI *lp);
/* create revised simplex method common block */

extern void delete_rsm(RSM *rsm);
/* delete revised simplex method common block */

extern void scale_rsm(RSM *rsm, double R[], double S[]);
/* scale problem components in RSM block */

extern int build_basis(RSM *rsm, LPI *lp);
/* build advanced basis */

#endif

/* eof */
