/************************************************************************
* retroLP solves linear programs using the simplex method.             *
* Copyright (C) 2001, 2003, 2005 Gavriel Yarmish & Richard Van Slyke.  *
* For further information, and gpl licensing, see the end of this file.*
************************************************************************/

// We return from choose_row with three basic types of results
// specified by nonbasicflag:
// 1. Non-feasible variable becomes feasible
//       This should only happen in Phase 1. We modify the
//       Phase 1 objective and call row_choice again
// 2. The non-basic variable chosen by column_choice
//    moves to one of its bounds, staying non-basic
// 3. The non-basic variable becomes basic. We pivot.

// If return value is 0, we continue; if -1 we have unbounded
// solution;

#include "simplex.h"
#include "params.h"
#include "long_clock.h"
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<time.h>

long pivot_plus(LP_state *, long , long, double *, short *,
  double );
void tswitch(var_type *, var_type *);
void lswitch(long *, long *);
void dswitch(double *, double *);
extern long miter;

// Support for measuring pivot and running times
// Using clock ticks for short runs, "LongClocks" for longer ones


	extern clock_t   pclock,     // Total ticks used in pivots.
                    pstart,     // Start of pivot interval
                    pstop;      // End of pivot interval
   extern LongClock tlong,
                    ptlong;
long change_state
(
  short phase,              // Phase 1 or 2
  LP_state *lp,             // LP data structure
  long ip,                  // Pivot row (-1 if unbounded; 0 if no pivot)
  long jp,                  // Pivot column
  double dx,                // Change in basic variable
  iter_result nonbasicflag, // Type of state change
  double *valj,             // Value for proposed col.
  short *up_flag,           // Up or down for proposed col.
  double delta              // To pass for CCR2 to pivot+
)
{

    long i, j, jn = 0;

    switch(nonbasicflag)
    {
    case UNBOUNDED:  // No row binding; unbounded
                     // solution possible.
       return -1;
    case NOPIVOTLBOUND:  // No pivot, non-basic goes to
                         // lower bound.
       for(i=0;i<=lp->m+1;i++)lp->b[i]+=dx*lp->a[jp][i];
       lp->nrange[jp]= ATLOWER;
       lp->x[jp] += dx;
       assert(fabs(lp->x[jp] - lp->nl[jp]) < delf);
       break;
    case NOPIVOTUBOUND:  // No pivot, non-basic goes to
                         // upper bound.

       for(i=0;i<=lp->m+1;i++)lp->b[i]+=dx*lp->a[jp][i];
       lp->nrange[jp]= ATUPPER;
       lp->x[jp] += dx;
       assert(fabs(lp->x[jp] - lp->nu[jp]) < delf);
       break;
    case BASICTOFEASIBLEL:  // Infeasible basic becomes
                            // feasible at lower bound,
                            // Phase 1 objective must be
                            // modified.
    // Adjust Phase I objective to reflect variable becoming
    // feasible
       lp->b[lp->m + 1] -= lp->b[ip];
       for(j=0;j<=lp->n;j++)lp->a[j][lp->m + 1] -= lp->a[j][ip];
       // Fall Through
    case PIVOTLBOUND:  // Pivot, basic goes
                       // non-basic at lower bound.

       lp->x[jp] += dx;
       for(i=0;i<=lp->m+1;i++)lp->b[i]+=dx*lp->a[jp][i];
       miter++;
       assert( (jp > 0) && (ip > 0) );
       dswitch( &(lp->b[ip]), &(lp->x[jp]) );
       if(lp->btype[ip]==FIXED)lp->nrange[jp]= ATBOTH;
       else lp->nrange[jp]= ATLOWER;
       tswitch(&(lp->btype[ip]), &(lp->ntype[jp]));
       lp->brange[ip] = BETWEEN;
       lswitch(&(lp->ibasic[ip]), &(lp->jnonbasic[jp]));
       dswitch(&(lp->bu[ip]),&(lp->nu[jp]));
       dswitch(&(lp->bl[ip]),&(lp->nl[jp]));
       pstart = clock();
       jn = pivot_plus(lp,ip,jp, valj, up_flag, delta );
       pstop = clock();
       pclock+=pstop-pstart;
       pclock = ptlong.reinitLongClock(pclock);
       assert((lp->b[ip] >= lp->bl[ip] - delf)&&(lp->b[ip] <= lp->bu[ip] + delf));
       break;
    case BASICTOFEASIBLEU: // Infeasible basic becomes
                           // feasible at upper bound,
                           // Phase 1 objective must be
                           // modified.
    // Adjust Phase I objective to reflect variable becoming
    // feasible
       lp->b[lp->m + 1] += lp->b[ip];
       for(j=0;j<=lp->n;j++)lp->a[j][lp->m + 1] += lp->a[j][ip];
       // Fall Through
    case PIVOTUBOUND: // Pivot, basic goes
                      // non-basic at upper bound.

       lp->x[jp] += dx;
       for(i=0;i<=lp->m+1;i++)lp->b[i]+=dx*lp->a[jp][i];
       miter++;
       assert( (jp > 0) && (ip > 0) );
       dswitch( &(lp->b[ip]), &(lp->x[jp]) );
       if(lp->btype[ip]==FIXED)lp->nrange[jp]= ATBOTH;
       else lp->nrange[jp]= ATUPPER;
       tswitch(&(lp->btype[ip]), &(lp->ntype[jp]));
       lp->brange[ip] = BETWEEN;
       lswitch(&(lp->ibasic[ip]), &(lp->jnonbasic[jp]));
       dswitch(&(lp->bu[ip]),&(lp->nu[jp]));
       dswitch(&(lp->bl[ip]),&(lp->nl[jp]));
       pstart = clock();
       jn = pivot_plus(lp,ip,jp, valj, up_flag, delta );
       pstop = clock();
       pclock+=pstop-pstart;
       pclock = ptlong.reinitLongClock(pclock);
       assert((lp->b[ip] >= lp->bl[ip] - delf)&&(lp->b[ip] <= lp->bu[ip] + delf));
       break;
    case NONBASICTOFEASIBLEL:  // Infeasible non-basic becomes
                               // feasible at lower bound,
                               // Phase 1 objective must be
                               // modified.
    // Adjust Phase I objective to reflect variable becoming
    // feasible
       lp->a[jp][lp->m + 1]+=1.0;
       for(i=0;i<=lp->m + 1;i++) lp->b[i] += dx*lp->a[jp][i];
       break;
    case NONBASICTOFEASIBLEU: // Infeasible non-basic becomes
                              // feasible at upper bound,
                              // Phase 1 objective must be
                              // modified.
    // Adjust Phase I objective to reflect variable becoming
    // feasible
       lp->a[jp][lp->m + 1]-=1.0;
       for(i=0;i<=lp->m + 1;i++) lp->b[i] += dx*lp->a[jp][i];
       break;
    default:
       printf("\nInvalid result code");
       exit(301);
    }
    return jn;
}

/************************************************************************
* retroLP solves linear programs using the simplex method.             *
* Copyright (C) 2001, 2003, 2005 Gavriel Yarmish & Richard Van Slyke.  *
*                                                                      *
* This program 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 of the License, or    *
* (at your option) any later version.                                  *
*                                                                      *
* This program 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 this program; if not, write to the Free Software          *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,           *
*                                                                      *
************************************************************************/