/* glpspx2.c */

/*----------------------------------------------------------------------
-- 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 "glplib.h"
#include "glpspx.h"

/*----------------------------------------------------------------------
-- spx_create_b - create representation of the basis matrix.
--
-- *Synopsis*
--
-- #include "glpspx.h"
-- SPXBAS *spx_create_b(int m);
--
-- *Description*
--
-- The routine spx_create_b creates some representation of the basis
-- matrix of the order m. Being created the representation initially
-- corresponds to the unity matrix.
--
-- *Returns*
--
-- The routine returns a pointer to the created representation. */

SPXBAS *spx_create_b(int m)
{     SPXBAS *B;
      B = umalloc(sizeof(SPXBAS));
      B->inv = inv_create(m, 100);
      return B;
}

/*----------------------------------------------------------------------
-- spx_invert_b - compute representation of the basis matrix.
--
-- *Synopsis*
--
-- #include "glpspx.h"
-- int spx_invert_b(SPXBAS *B, SPXMAT *A, int indb[]);
--
-- *Description*
--
-- The routine spx_invert_b computes the representation B for the given
-- basis matrix.
--
-- The basis matrix is specified by the parameters A and indb as it is
-- described in comments to the routine spx_get_bi.
--
-- *Returns*
--
-- If the representation has been successfully computed, the routine
-- returns zero. Otherwise, if the given basis matrix is singular or
-- ill-conditioned, the routine returns non-zero.
--
-- In case of non-zero return code the representation becomes invalid
-- and therefore it should not be used in other operations until the
-- cause of failure has been eliminated and the representation has been
-- recomputed again using the routine spx_invert_b. */

struct spx_invert_b_dsa
{     SPXMAT *A;
      int *indb;
};

static int spx_invert_b_col(void *info, int j, int rn[], double bj[])
{     struct spx_invert_b_dsa *dsa = info;
      return spx_get_bi(dsa->A, dsa->indb, j, rn, bj);
}

int spx_invert_b(SPXBAS *B, SPXMAT *A, int indb[])
{     static double tol[1+3] = { 0.00, 0.10, 0.30, 0.70 };
      struct spx_invert_b_dsa _dsa, *dsa = &_dsa;
      int try, ret;
      dsa->A = A;
      dsa->indb = indb;
      for (try = 1; try <= 3; try++)
      {  B->inv->luf->piv_tol = tol[try];
         ret = inv_decomp(B->inv, dsa, spx_invert_b_col);
         if (ret == 0) break;
      }
      return ret;
}

/*----------------------------------------------------------------------
-- spx_repair_b - repair the basis matrix.
--
-- *Synopsis*
--
-- #include "glpspx.h"
-- void spx_repair_b(SPXBAS *B, int indb[]);
--
-- *Description*
--
-- The routine spx_repair_b is intended to "repair" the basis matrix if
-- the routine spx_invert_b reports non-zero code, which means that the
-- basis matrix is singular or ill-conditioned.
--
-- The routine corrects the basis matrix specified by the array indb
-- replacing linearly dependent basic columns by appropriate columns of
-- the unity matrix (which correspond to auxiliary variables). Changes
-- made by the routine are stored in the array indb. */

void spx_repair_b(SPXBAS *B, int indb[])
{     LUF *luf = B->inv->luf;
      int j;
      for (j = luf->rank+1; j <= luf->n; j++)
         indb[luf->qq_col[j]] = luf->pp_row[j];
      return;
}

/*----------------------------------------------------------------------
-- spx_ftran - perform forward transformation.
--
-- *Synopsis*
--
-- #include "glpspx.h"
-- void spx_ftran(SPXBAS *B, double z[], int save);
--
-- *Description*
--
-- The routine spx_ftran performs forward transformation (FTRAN) of the
-- given vector using the representation of the basis matrix.
--
-- In order to perform FTRAN the routine solves the system B*z' = z,
-- where B is the basis matrix, z' is vector of unknowns (transformed
-- vector that should be computed), z is vector of right-hand sides
-- (input vector that should be transformed).
--
-- On entry the array z should contain components of the vector z in
-- locations z[1], z[2], ..., z[m], where m is the order of the basis
-- matrix. On exit this array will contain components of the vector z'
-- in the same locations.
--
-- The parameter save is a flag. If this flag is set, it means that the
-- input vector z is a column of the non-basic variable, which has been
-- chosen to enter the basis. In this case the routine spx_ftran saves
-- this column in order that the routine spx_update_b could update the
-- representation for an adjacent basis using this partially transformed
-- column. The simplex method routine should call the routine spx_ftran
-- with the save flag set at least once before a subsequent call to the
-- routine spx_update_b. */

void spx_ftran(SPXBAS *B, double z[], int save)
{     inv_ftran(B->inv, z, save);
      return;
}

/*----------------------------------------------------------------------
-- spx_btran - perform backward transformation.
--
-- *Synopsis*
--
-- #include "glpspx.h"
-- void spx_btran(SPXBAS *B, double z[]);
--
-- *Description*
--
-- The routine spx_btran performs backward transformation (BTRAN) of the
-- given vector using the representation of the basis matrix.
--
-- In order to perform BTRAN the routine solves the system BT*z' = z,
-- where BT is a matrix transposed to the basis matrix B, z' is vector
-- of unknowns (transformed vector that should be computed), z is vector
-- of right-hand sides (input vector that should be transformed).
--
-- On entry the array z should contain components of the vector z in
-- locations z[1], z[2], ..., z[m], where m is the order of the basis
-- matrix. On exit this array will contain components of the vector z'
-- in the same locations. */

void spx_btran(SPXBAS *B, double z[])
{     inv_btran(B->inv, z);
      return;
}

/*----------------------------------------------------------------------
-- spx_update_b - update representation of the basis matrix.
--
-- *Synopsis*
--
-- #include "glpspx.h"
-- int spx_update_b(SPXBAS *B, int i);
--
-- *Description*
--
-- The routine spx_update_b recomputes (updates) the representation,
-- which on entry corresponds to the current basis matrix B, in order
-- that the new representation would correspond to the adjacent basis
-- matrix B', which differs from B in the i-th column.
--
-- The new i-th column of the basis matrix is passed implictly to the
-- routine spx_update_b. It is assumed that this column was saved before
-- by the routine spx_ftran (see above).
--
-- *Returns*
--
-- If the representation has been successfully updated, the routine
-- returns zero. Otherwise, if the representation became inaccurate or
-- too long, the routine returns non-zero.
--
-- In case of non-zero return code the representation becomes invalid
-- and therefore should not be used until it has been recomputed using
-- the routine spx_invert_b. */

int spx_update_b(SPXBAS *B, int i)
{     int ret;
      ret = inv_update(B->inv, i);
      return ret;
}

/*----------------------------------------------------------------------
-- spx_delete_b - delete representation of the basis matrix.
--
-- *Synopsis*
--
-- #include "glpspx.h"
-- void spx_delete_b(SPXBAS *B);
--
-- *Description*
--
-- The routine spx_delete_b deletes the representation specified by the
-- parameter B, freeing all the memory allocated to this object. */

void spx_delete_b(SPXBAS *B)
{     inv_delete(B->inv);
      ufree(B);
      return;
}

/* eof */
