Example #1
0
File: lu.c Project: cran/fastclime
void refactor(
    int m,
    int *kA,
    int *iA,
    double *A,
    int *basics,
    int col_out,
    int v
)
{
	double starttime, endtime;
	double rffactor = 1.0;
	int    from_scratch;
	int    k;

        /*------------------------------------------------------+
        | Check if it is time to refactor from scratch         */
	if (e_iter > 0) {
	    from_scratch = TRUE;
	    for (k=kE[e_iter]; k<kE[e_iter+1]; k++) {
	        if (iE[k] == col_out) {
		    from_scratch = FALSE;
		    break;
	        }
	    }
	} else {
	    from_scratch = FALSE;
	}

	if ( (e_iter > 2 && cumtime/(e_iter+1) >= ocumtime/e_iter)
           || e_iter >= E_N || from_scratch == TRUE) {
		ocumtime = 0.0;
		cumtime  = 0.0;
		lufac( m, kA, iA, A, basics, v );
		cumtime  *= rffactor;
		enz = 0;
		e_iter = 0;
		from_scratch = TRUE;
		return;
	}
       
	ocumtime  = cumtime;
	starttime = (double) clock();
	E_d[e_iter] = col_out;	
        e_iter++;
	endtime = (double) clock();
	cumtime += endtime - starttime;

	from_scratch = FALSE;

}
int solver2(
    int m,		/* number of constraints */
    int N,		/* number of variables */
    int nz,		/* number of nonzeros in sparse constraint matrix */
    int *ia, 		/* array row indices */
    int *ka, 		/* array of indices into ia and a */
    double *a,		/* array of nonzeros in the constraint matrix */
    double *b, 		/* right-hand side */
    double *c,          /* objective coefficients */
    double *c2,         /* objective coefficients */
    double  f, 		/* objective function shift */
    int *basics,
    int *nonbasics,
    int *basicflag,
    int *freevars,
    int d1,
    int d2,
    double **BETAhat
    )
{

    double  *x_B;	/* primal basics */
    double  *y_N;	/* dual nonbasics */

    double  *xbar_B;	/* primal basic perturbation */
    double  *ybar_N;	/* dual nonbasic perturbation */

    double  *dy_N;	/*  dual  basics step direction - values (sparse) */
    int    *idy_N;	/*  dual  basics step direction - row indices */
    int     ndy_N;	/* number of nonz in dy_N */

    double  *dx_B;	/* primal basics step direction - values (sparse) */
    int    *idx_B;	/* primal basics step direction - row indices */
    int     ndx_B;	/* number of nonz in dx_B */

    double  *at;	/* sparse data structure for A^T */
    int    *iat;
    int    *kat;

    int     col_in;	/* entering column; index in 'nonbasics' */
    int     col_out;	/* leaving column; index in 'basics' */

    int     iter = 0;	/* number of iterations */
    int     i,j,k,n,v=0, j1,j2,ii;

    double  s, t, sbar, tbar, mu=HUGE_VAL, old_mu, primal_obj;

    double  *vec;
    int    *ivec;
    int     nvec;

    int	    status=0;

    int     from_scratch;

    /*******************************************************************
    * For convenience, we put...
    *******************************************************************/

    int n0 = d1*d2;
    n = N-m;

    /*******************************************************************
    * Read in the Data and initialize the common memory sites.
    *******************************************************************/

    CALLOC(    x_B, m,   double );      
    CALLOC( xbar_B, m,   double );      
    CALLOC(   dx_B, m,   double );      
    CALLOC(    y_N, n,   double );      
    CALLOC( ybar_N, n,   double );      
    CALLOC(   dy_N, n,   double );      
    CALLOC(    vec, N,   double );
    CALLOC(  idx_B, m,    int );      
    CALLOC(  idy_N, n,    int );      
    CALLOC(   ivec, N,    int );
    CALLOC(     at, nz,  double );
    CALLOC(    iat, nz,   int );
    CALLOC(    kat, m+1,  int );

    /**************************************************************** 
    *  Initialization.              				    *
    ****************************************************************/

    atnum(m,N,ka,ia,a,kat,iat,at);

    lufac( m, ka, ia, a, basics, 0);

    for (j=0; j<n; j++) {
	  y_N[j] = 0;
    }
    nvec = 0;
    for (i=0; i<m; i++) {
       	if (c[basics[i]] != 0.0) {
 	    vec[nvec] = c[basics[i]];
 	    ivec[nvec] = i;
	    nvec++;
	}
    }

    

    btsolve( m, vec, ivec, &nvec );  		
    Nt_times_y( N, at, iat, kat, basicflag, vec, ivec, nvec, 
		     dy_N, idy_N, &ndy_N );
    for (k=0; k<ndy_N; k++) {
	y_N[idy_N[k]] = dy_N[k];
    }
    for (j=0; j<n; j++) {
	y_N[j] -= c[nonbasics[j]];
    }

    for (j=0; j<n; j++) {
	   ybar_N[j] = 0;
    }
    nvec = 0;
    for (i=0; i<m; i++) {
	if (c2[basics[i]] != 0.0) {
	    vec[nvec] = c2[basics[i]];
	    ivec[nvec] = i;
	    nvec++;
	}
    }
    btsolve( m, vec, ivec, &nvec );  		
    Nt_times_y( N, at, iat, kat, basicflag, vec, ivec, nvec, 
		     dy_N, idy_N, &ndy_N );
    for (k=0; k<ndy_N; k++) {
	ybar_N[idy_N[k]] = dy_N[k];
    }
    for (j=0; j<n; j++) {
	ybar_N[j] -= c2[nonbasics[j]];
	if (ybar_N[j] < 0) printf("error: ybar_N[%d] = %e \n", j, ybar_N[j]);
    }

    for (i=0; i<m; i++) {
	       x_B[i] = 0;
	    xbar_B[i] = 0;
    }
    nvec = 0;
    for (i=0; i<m; i++) {
      if ( b[i] != 0.0 ) {
	 vec[nvec] = b[i];
	ivec[nvec] = i;
	nvec++;
      }
    }

    bsolve( m, vec, ivec, &nvec );
    for (i=0; i<nvec; i++) {
	x_B[ivec[i]] = vec[i];
           if (vec[i] < 0) printf("error: x_B[%d] = %e \n", i, vec[i]);
    }
/*
    printf ("m = %d,n = %d,nz = %d\n",m,N,nz);
    printf(
"---------------------------------------------------------------------------\n"
"          |   Primal      |        |                           arithmetic  \n"
"  Iter    |  Obj Value    |   mu   |   nonz(L)     nonz(U)     operations  \n"
"- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n"
);*/

    /****************************************************************
    * 	Main loop                                                   *
    ****************************************************************/

    for (iter=0; iter<MAX_ITER; iter++) {


      /*************************************************************
      * STEP 1: Find mu                                            *
      *************************************************************/

      old_mu = mu;
      mu = -HUGE_VAL;
      col_in  = -1;
      for (j=0; j<n; j++) {
		if (ybar_N[j] > EPS2) { 
			if ( mu < -y_N[j]/ybar_N[j] ) {
			     mu = -y_N[j]/ybar_N[j];
			     col_in  = j;
			}
		}
      }
      col_out = -1;
      for (i=0; i<m; i++) {
         if (freevars[basics[i]] == 0) {
		if (xbar_B[i] > EPS2) { 
			if ( mu < -x_B[i]/xbar_B[i] ) {
			     mu = -x_B[i]/xbar_B[i];
			     col_out = i;
			     col_in  = -1;
			}
		}
         }
      }

      /*************************************************************
      * STEP 0: Record current portfolio                           *
      *************************************************************/

      primal_obj = sdotprod(c,x_B,basics,m) + f;
      if ( mu <= EPS3 || primal_obj > -EPS0) {	/* OPTIMAL */
          for (j1=0; j1<d1; j1++) {
	      for (j2=0; j2<d2; j2++) {
		  BETAhat[j1][j2] = 0;
	      }
	  }
	  for (i=0; i<m; i++) {
	    if (basics[i] < n0 && x_B[i] > EPS0) {
	      ii = basics[i];
	      j1 = ii%d1;
	      j2 = ii/d1;
	      BETAhat[j1][j2] = x_B[i];
	    }
	    else if (basics[i] < 2*n0 && x_B[i] > EPS0) {
	      ii = basics[i]-n0;
	      j1 = ii%d1;
	      j2 = ii/d1;
	      BETAhat[j1][j2] = -x_B[i];
	    }
	  }
          for (j1=0; j1<d1; j1++) {
            for (j2=0; j2<d2; j2++) {
	      if (ABS(BETAhat[j1][j2]) > 1e-5) {
	      }
            }
          }
	  status = 0;
	  break;
      }

      if ( col_out >= 0 ) {

        /*************************************************************
	*                          -1  T                             *
	* STEP 2: Compute dy  = -(B  N) e                            * 
	*                   N            i			     *
	*         where i = col_out                                  *
        *************************************************************/

	vec[0] = -1.0;
	ivec[0] = col_out;
	nvec = 1;

	btsolve( m, vec, ivec, &nvec );  		

	Nt_times_y( N, at, iat, kat, basicflag, vec, ivec, nvec, 
		     dy_N, idy_N, &ndy_N );

        /*************************************************************
	* STEP 3: Ratio test to find entering column                 * 
        *************************************************************/

	col_in = ratio_test2( dy_N, idy_N, ndy_N, y_N, ybar_N, mu );

	if (col_in == -1) { 	/* INFEASIBLE*/
	    status = 2;
	    printf("infeasible \n");
	    break;
	}

        /*************************************************************
	*                        -1                                  *
	* STEP 4: Compute dx  = B  N e                               * 
	*                   B         j                              *
	*                                                            *
        *************************************************************/

	j = nonbasics[col_in];
	for (i=0, k=ka[j]; k<ka[j+1]; i++, k++) {
	     dx_B[i] =  a[k];
	    idx_B[i] = ia[k];
	}
	ndx_B = i;

	bsolve( m, dx_B, idx_B, &ndx_B );

      } else {

        /*************************************************************
	*                        -1                                  *
	* STEP 2: Compute dx  = B  N e                               * 
	*                   B         j                              *
        *************************************************************/

	j = nonbasics[col_in];
	for (i=0, k=ka[j]; k<ka[j+1]; i++, k++) {
	     dx_B[i] =  a[k];
	    idx_B[i] = ia[k];
	}
	ndx_B = i;

	bsolve( m, dx_B, idx_B, &ndx_B );

        /*************************************************************
	* STEP 3: Ratio test to find leaving column                  * 
        *************************************************************/

	col_out = ratio_test( dx_B, idx_B, ndx_B, x_B, xbar_B, basics, freevars, mu );

	if (col_out == -1) {	/* UNBOUNDED */
	    status = 1;
	    printf("unbounded \n");
	    break;
	}

        /*************************************************************
	*                          -1  T                             *
	* STEP 4: Compute dy  = -(B  N) e                            * 
	*                   N            i			     *
	*                                                            *
        *************************************************************/

	 vec[0] = -1.0;
	ivec[0] = col_out;
	nvec = 1;

	btsolve( m, vec, ivec, &nvec );  		

	Nt_times_y( N, at, iat, kat, basicflag, vec, ivec, nvec, 
		     dy_N, idy_N, &ndy_N );

      }

      /*************************************************************
      *                                                            *
      * STEP 5: Put       t = x /dx                                *
      *                        i   i                               *
      *                   _   _                                    *
      *                   t = x /dx                                *
      *                        i   i                               *
      *                   s = y /dy                                *
      *                        j   j                               *
      *                   _   _                                    *
      *                   s = y /dy                                *
      *                        j   j                               *
      *************************************************************/

      for (k=0; k<ndx_B; k++) if (idx_B[k] == col_out) break;

      t    =    x_B[col_out]/dx_B[k];
      tbar = xbar_B[col_out]/dx_B[k];

      for (k=0; k<ndy_N; k++) if (idy_N[k] == col_in) break;

      s    =    y_N[col_in]/dy_N[k];
      sbar = ybar_N[col_in]/dy_N[k];

      /*************************************************************
      *                                _    _    _                 *
      * STEP 7: Set y  = y  - s dy     y  = y  - s dy              *
      *              N    N       N     N    N       N             *
      *                                _    _                      *
      *             y  = s             y  = s                      *
      *              i                  i                          *
      *             _    _    _                                    *
      *             x  = x  - t dx     x  = x  - t dx              *
      *              B    B       B     B    B       B             *
      *             _    _                                         *
      *             x  = t             x  = t                      *
      *              j                  j                          *
      *************************************************************/

      for (k=0; k<ndy_N; k++) {
		j = idy_N[k];
		y_N[j]    -= s   *dy_N[k];
		ybar_N[j] -= sbar*dy_N[k];
      }

      y_N[col_in]    = s;
      ybar_N[col_in] = sbar;

      for (k=0; k<ndx_B; k++) {
		i = idx_B[k];
		x_B[i]    -= t   *dx_B[k];
		xbar_B[i] -= tbar*dx_B[k];

      }

      x_B[col_out]     = t;
      xbar_B[col_out]  = tbar;

      /*************************************************************
      * STEP 8: Update basis                                       * 
      *************************************************************/

      i =    basics[col_out];
      j = nonbasics[col_in];
      basics[col_out]   = j;
      nonbasics[col_in] = i;
      basicflag[i] = -col_in-1;
      basicflag[j] = col_out;

      /*************************************************************
      * STEP 9: Refactor basis and print statistics                *
      *************************************************************/

      from_scratch = refactor( m, ka, ia, a, basics, col_out, v);

      if (from_scratch) {
          primal_obj = sdotprod(c,x_B,basics,m) + f;
/*          printf("%8d %14.7e %9.2e \n", iter, high(primal_obj), high(mu));
            fflush(stdout);*/
      }
    } 

    primal_obj = sdotprod(c,x_B,basics,m) + f;

    /****************************************************************
    * 	Transcribe solution to x vector and dual solution to y      *
    ****************************************************************/

    /****************************************************************
    * 	Split out slack variables and shift dual variables.
    ****************************************************************/

    /****************************************************************
    * 	Free work space                                             *
    ****************************************************************/
 
    Nt_times_y(-1, at, iat, kat, basicflag, vec, ivec, nvec, dy_N, idy_N, &ndy_N);

    FREE(at);
    FREE(iat);

    FREE(xbar_B);
    FREE(kat);
    FREE(ybar_N);

    lu_clo();
    btsolve(0, vec, ivec, &nvec);
    bsolve(0, vec, ivec, &nvec);

    FREE(  vec );
    FREE( ivec );
    FREE(  x_B );
    FREE(  y_N );
    FREE( dx_B );
    FREE(idx_B );
    FREE( dy_N );
    FREE(idy_N );
    FREE( nonbasics );
    FREE( basics );

    
    return status;
}   /* End of solver */
Example #3
0
int refactor(
    int m,
    int *kA,
    int *iA,
    double *A,
    int *basics,
    int col_out,
    int v
)
{
	int i, j, k, kk, kkk, kkkk, imax;

	int changes, row, col, row2, col2, cnt;
	int bumpstart, bumpend;
	int Utnz=0;

	double val;

	static int	*iwork=NULL;
	static double	*dwork=NULL;
	static void	**pwork=NULL;

	static double *y=NULL;
	static int  *tag=NULL;
	static int  currtag=1;

	static int call=0;
	double starttime, endtime;
	double rffactor = 1.0;

	int    from_scratch;

        /*------------------------------------------------------+
        | Check if it is time to refactor from scratch         */

	call++;
	if ( col_out < 0 || call <= 1) {
		ocumtime = 0.0;
		cumtime  = 0.0;
		lufac( m, kA, iA, A, basics, v );
		cumtime  *= rffactor;
		from_scratch = TRUE;
		return from_scratch;
	}
	if ( call > 3 && cumtime/call >= ocumtime/(call-1) ) {
		ocumtime = 0.0;
		cumtime  = 0.0;
		call = 1;
		lufac( m, kA, iA, A, basics, v );
		cumtime  *= rffactor;
		from_scratch = TRUE;
		return from_scratch;
	}

	ocumtime  = cumtime;
	starttime = (double) clock();

        /*------------------------------------------------------+
        | Allocate storage for work arrays                     */

	if (iwork == NULL) MALLOC( iwork, m, int);
        if (dwork == NULL) MALLOC( dwork, m, double);
        if (pwork == NULL) MALLOC( pwork, m, void *);

        /*------------------------------------------------------+
        | Put col_out into `new' indices                       */

	col_out = icolperm[col_out];

        /*------------------------------------------------------+
        | Compute largest row index for new column             */

	if (inewcol == NULL) { 
	    printf("ERROR: refactoring before bsolving \n");
	    exit(0);
	}

	imax=0;
	for (k=0; k<nnewcol; k++) {
	    imax = MAX(imax, inewcol[k]);
	}

	if (imax < col_out) { 
	    printf("singular matrix \n");
	    from_scratch = FALSE;
	    return from_scratch;
	}

        /*------------------------------------------------------+
        | Insert newcol into col_out column of U (and Ut)       |
	|                                                       |
	|             0 1 2 3 4 5                               |
	|                                                       |
	|          0  x * x x x x                               |
	|          1    * x x x x                               |
	|    U  =  2    * x x x x (here col_out=1 and imax=4)   |
	|          3    *   x x x                               |
	|          4    *     x x                               |
	|          5            x                              */

	/* first remove oldcol from Ut */
	for (k=0; k<degU[col_out]; k++) {
	    row = U[col_out][k].i;
	    for (kk=0; kk<degUt[row]; kk++) {
		if (Ut[row][kk].i == col_out) break; /* INEFFICIENT */
	    }
	    if (kk < degUt[row]) {
		degUt[row]--;
		Bswap( Ut[row], degUt[row], kk );
	    }
	}

	degU[col_out] = nnewcol;
	REALLOC( U[col_out], nnewcol, VALIND );
	kkkk = 0;
	diag[col_out] = 0.0;
	for (k=0; k<nnewcol; k++) {
	    row = inewcol[k];
	    val =  newcol[k];
	    if (row != col_out) {
	        U[col_out][kkkk].i = row;
	        U[col_out][kkkk].d = val;
		kkkk++;

		kkk = degUt[row];
		degUt[row]++;
		REALLOC( Ut[row], degUt[row], VALIND );
		Ut[row][kkk].i = col_out;
		Ut[row][kkk].d = val;
	    } else {
		diag[row] = val;
	    }
	}
	degU[col_out] = kkkk;

        /*------------------------------------------------------+
        | Allocate storage for permutation arrays and shift     |
	| so that indexing begins at col_out                   */

	REALLOC( perm, nr+1, int *);
	REALLOC(iperm, nr+1, int *);
	MALLOC(  perm[nr], imax-col_out+1, int );  perm[nr] -= col_out;
	MALLOC( iperm[nr], imax-col_out+1, int ); iperm[nr] -= col_out;
	REALLOC(     rows, nr+1, int );
	REALLOC( col_outs, nr+1, int );
	REALLOC(    imaxs, nr+1, int );

        /*------------------------------------------------------+
        | Initialize permutation arrays so that col_out is      |
	| cyclically permuted to imax.  After permutation:      |
	|                                                       |
	|             0 2 3 4 1 5                               |
	|                                                       |
	|          0  x x x x * x                               |
	|    U  =  2    x x x * x (here col_out=1 and imax=4)   |
	|          3      x x * x                               |
	|          4        x * x                               |
	|          1    x x x * x                               |
	|          5            x                               |
	|                                                      */

	for (j=col_out; j<imax; j++) {
	     perm[nr][j]   = j+1;
	    iperm[nr][j+1] = j;
	}
	 perm[nr][imax]    = col_out;
	iperm[nr][col_out] = imax;

        /*------------------------------------------------------+
        | Look for singleton columns/rows and permute columns   |
	| to upper-left and rows to lower-right position in     |
	| bump.  Don't forget that the diagonal is stored       |
	| separately in diag[] and that this contributes one    |
	| nonzero to each column/row investigated.             */

	bumpstart = col_out;
	bumpend   = imax;
	do {
	    changes = 0;

            /*------------------------------------------------------+
            | First look for columns.                               |
	    |                                                       |
	    |       0 1 2 3 4 5          0 3 1 2 4 5                |
	    |                                                       |
	    |    0  x x x x * x       0  x x x x * x                |
	    |    1    x x   * x       3    x     * x                |
	    |    2      x   * x  -->  1      x x * x                |
	    |    3        x * x       2        x * x                |
	    |    4    x x   * x       4      x x * x                |
	    |    5            x       5            x                |
	    |                                                      */

	    for (j=bumpstart; j<bumpend; j++) {
		col = perm[nr][j];
		cnt = 0;
		for (k=0; k<degU[col]; k++) {
		    int Ui = U[col][k].i;
		    if (Ui >= col_out && Ui <= imax) {
		        row = iperm[nr][ Ui ];
		        if (bumpstart <= row && row <= bumpend) cnt++;
		    }
		}

		if (cnt == 0) {
		    cycperm(j, bumpstart, perm[nr], iperm[nr]);
		    bumpstart++;
		    changes++;
		} 
	    }

            /*------------------------------------------------------+
            | Now look for rows.                                    |
	    |                                                       |
	    |       0 1 2 3 4 5          0 2 3 4 1 5                |
	    |                                                       |
	    |    0  x x x x * x       0  x x x * x x                |
	    |    1    x       x       2    x x *   x                |
	    |    2      x x * x  -->  3      x *   x                |
	    |    3        x * x       4    x x * x x                |
	    |    4    x x x * x       1          x x                |
	    |    5            x       5            x                |
	    |                                                      */

	    for (i=bumpend-1; i>=bumpstart; i--) {
		row = perm[nr][i];
		cnt = 0;
		for (k=0; k<degUt[row]; k++) {
		    int Uti = Ut[row][k].i;
		    if (Uti >= col_out && Uti <= imax) {
			col = iperm[nr][ Uti ];
			if (bumpstart <= col && col <= bumpend) cnt++;
		    }
		}

		if (cnt == 0) {
		    cycperm(i, bumpend, perm[nr], iperm[nr]);
		    bumpend--;
		    changes++;
		} 
	    }
	} while (changes > 0);

        /*------------------------------------------------------+
        | Permute rows/columns of U and Ut.                    */

        /*------------------------------------------------------+
        | Permute columns of U and diag.                       */

	for (j=col_out; j<=imax; j++) { 
	    dwork[j] = diag[j]; 
	    iwork[j] = degU[j]; 
	    pwork[j] = (void *)U[j]; 
	}
	for (j=col_out; j<=imax; j++) { 
	    diag[j]  = dwork[perm[nr][j]]; 
	    degU[j]  = iwork[perm[nr][j]]; 
	    U[j]     = (VALIND *)pwork[perm[nr][j]]; 
	}

        /*------------------------------------------------------+
        | Permute rows of U.                                   */

	for (j=col_out; j<m; j++) {
	    for (k=0; k<degU[j]; k++) {
		row = U[j][k].i;
		if (col_out <= row && row <= imax) U[j][k].i = iperm[nr][row];
	    }
	}

        /*------------------------------------------------------+
        | Permute rows of Ut.                                  */

	for (i=col_out; i<=imax; i++) { 
	    iwork[i] = degUt[i]; 
	    pwork[i] = (void *)Ut[i]; 
	}
	for (i=col_out; i<=imax; i++) { 
	    degUt[i]  = iwork[perm[nr][i]]; 
	    Ut[i]     = (VALIND *)pwork[perm[nr][i]]; 
	}

        /*------------------------------------------------------+
        | Permute columns of Ut.                               */

	for (i=0; i<=imax; i++) {
	    for (k=0; k<degUt[i]; k++) {
		col = Ut[i][k].i;
		if (col_out <= col && col <= imax) Ut[i][k].i = iperm[nr][col];
	    }
	}

        /*------------------------------------------------------+
        | Record bump row for later use.                       */

	row          = bumpend;
	rows[nr]     = row;
	col_outs[nr] = col_out;
	imaxs[nr]    = imax;

	if (   y == NULL ) CALLOC(   y, m, double );
	if ( tag == NULL ) CALLOC( tag, m, int );

        /*------------------------------------------------------+
        | Scatter bump row into a dense vector.                */

	for (k=0; k<degUt[row]; k++) {
	    col = Ut[row][k].i;
	    y[col] = Ut[row][k].d;
	    tag[col] = currtag;
	    addtree(col);
	}
	y[row] = diag[row];
	tag[row] = currtag;
	addtree(row);

        /*------------------------------------------------------+
        | Remove bump row from U.                              */

	for (k=0; k<degUt[row]; k++) {
	    col = Ut[row][k].i;
	    for (kk=0; kk<degU[col]; kk++) {
		if (U[col][kk].i == row) break;   /* INEFFICIENT */
	    }
	    if (kk < degU[col]) {
		degU[col]--;
		Bswap(U[col], degU[col], kk);
	    }
	}

        /*------------------------------------------------------+
        | Do Gaussian elimination on scatter vector.           */

	REALLOC( row_list, nr+1, int * );
	MALLOC(  row_list[nr], m, int );
	REALLOC(ngauss, nr+1, int );
	REALLOC( gauss, nr+1, double * );
	MALLOC(  gauss[nr], m, double );

	k=0;
	for (col=getfirst(); col<bumpend; col=getnext()) {
	    row2 = col;
	    row_list[nr][k] = row2;
	    gauss[nr][k] = y[col] / diag[row2];
	    for (kk=0; kk<degUt[row2]; kk++) {
		col2 = Ut[row2][kk].i;
		if (tag[col2] != currtag) {
		    y[col2] = 0.0;
		    tag[col2] = currtag;
		    addtree(col2);
		} 
		y[col2] -= gauss[nr][k] * Ut[row2][kk].d;
	    }
	    k++;
	}
	if (col != bumpend) printf("ERROR: col != bumpend \n");
	ngauss[nr] = k;
	REALLOC(  gauss[nr], k, double );
	REALLOC(  row_list[nr], k, int );

        /*------------------------------------------------------+
        | Add eliminated row to U.  kk counts nonzeros in       |
	| eliminated row.                                      */

	diag[col] = y[col];
	kk = 0;
	for (col=getnext(); col != -1; col=getnext()) {
	    if ( ABS(y[col])>EPS ) {
		k = degU[col];
		degU[col]++;
		REALLOC( U[col], degU[col], VALIND );
		U[col][k].i = row;
		U[col][k].d = y[col];
		kk++;
	    }
	}

	REALLOC( Ut[row], kk, VALIND );

        /*------------------------------------------------------+
        | Remove bump row from Ut and replace with eliminated   |
	| row.                                                 */

	k = 0;
	for (col=getfirst(); col != -1; col=getnext()) {
	    if ( col>bumpend && ABS(y[col]) > EPS ) {
		Ut[row][k].d = y[col];
		Ut[row][k].i = col;
		k++;
	    }
	}
	degUt[row] = k;

	if (k != kk) printf("ERROR: alloc'ed wrong size for Ut\n");

	currtag++;
	killtree();

        /*------------------------------------------------------+
	| Apply permutation to colperm and icolperm            */

	for (j=col_out; j<=imax; j++) { iwork[j] = colperm[j]; }
	for (j=col_out; j<=imax; j++) {icolperm[ colperm[ perm[nr][j]]] = j;}
	for (j=col_out; j<=imax; j++) { colperm[iperm[nr][j]] = iwork[j];}

        /*------------------------------------------------------+
	| Increment number of refactorizations.                */

	nr++;

        for (i=0; i<m; i++) {
                k = degUt[i]; Utnz += k;
        }

        if (v) {
                printf("            %9d ", Utnz);
                fflush(stdout);
        }

	endtime = (double) clock();
	cumtime += endtime - starttime;

	from_scratch = FALSE;
	return from_scratch;
}
Example #4
0
void solver20(
    int m,		/* number of constraints */
    int n,		/* number of variables */
    int nz,		/* number of nonzeros in sparse constraint matrix */
    int *ia, 		/* array row indices */
    int *ka, 		/* array of indices into ia and a */
    double *a,		/* array of nonzeros in the constraint matrix */
    double *b, 		/* right-hand side */
    double *c          /* objective coefficients */
    )
{

	/*structure of the solver*/

    int *basics;
    int *nonbasics;
    int *basicflag;
    double  *x_B;	/* primal basics */
    double  *y_N;	/* dual nonbasics */
    double  *xbar_B;	/* primal basic perturbation */
    double  *ybar_N;    /* dual nonbasic perturbation*/
    double  *dy_N;	/*  dual  basics step direction - values (sparse) */
    int    *idy_N;	/*  dual  basics step direction - row indices */
    int     ndy_N=0;	/* number of nonz in dy_N */
    double  *dx_B;	/* primal basics step direction - values (sparse) */
    int    *idx_B;	/* primal basics step direction - row indices */
    int     ndx_B;	/* number of nonz in dx_B */
    double  *at;	/* sparse data structure for a^t */
    int    *iat;
    int    *kat;
    int     col_in;	/* entering column; index in 'nonbasics' */
    int     col_out;	/* leaving column; index in 'basics' */
    int     iter = 0;	/* number of iterations */
    int     i,j,k,v=0;
    double  s, t, sbar, tbar, mu=HUGE_VAL;
    double  *vec;
    int    *ivec;
    int     nvec;
    int     N;

    N=m+n;

	 /*******************************************************************
    * read in the data and initialize the common memory sites.
    *******************************************************************/

	//add the slack variables

    i = 0;
    k = ka[n];
    for (j=n; j<N; j++) {	
	a[k] = 1.0;
	ia[k] = i;
	i++;
	k++;
	ka[j+1] = k;
    }
    nz = k;

    MALLOC(    x_B, m,   double );      
    MALLOC( xbar_B, m,   double );      
    MALLOC(   dx_B, m,   double );  
    MALLOC(    y_N, n,   double );
    MALLOC( ybar_N, n,   double );           
    MALLOC(   dy_N, n,   double );  
    MALLOC(    vec, N,   double );
    MALLOC(   ivec, N,    int );
    MALLOC(  idx_B, m,    int );      
    MALLOC(  idy_N, n,    int );      
    MALLOC(     at, nz,  double );
    MALLOC(    iat, nz,   int );
    MALLOC(    kat, m+1,  int );
    MALLOC(   basics,    m,   int );      
    MALLOC(   nonbasics, n,   int );      
    MALLOC(   basicflag, N,   int );
    CALLOC(   x, N, double );

    /**************************************************************** 
    *  initialization.              				    *
    ****************************************************************/

    atnum(m,N,ka,ia,a,kat,iat,at);

    for (j=0; j<n; j++) {
	nonbasics[j] = j;
	basicflag[j] = -j-1;
	      y_N[j] = -c[j];
           ybar_N[j] = 1;
    }

    for (i=0; i<m; i++) {
	    basics[i] = n+i;
       basicflag[n+i] = i;
	       x_B[i] = b[i];
	    xbar_B[i] = 1;
    }

    lufac( m, ka, ia, a, basics, 0 );

 for (iter=0; iter<MAX_ITER; iter++) {

      /*************************************************************
      * step 1: find mu                                            *
      *************************************************************/
      mu = -HUGE_VAL;
      col_in  = -1;
      for (j=0; j<n; j++) {
		if (ybar_N[j] > EPS2) { 
			if ( mu < -y_N[j]/ybar_N[j] ) {
			     mu = -y_N[j]/ybar_N[j];
			     col_in  = j;
			}
		}
      }
      col_out = -1;

     for (i=0; i<m; i++) {
		if (xbar_B[i] > EPS2) { 
			if ( mu < -x_B[i]/xbar_B[i] ) {
			     mu = -x_B[i]/xbar_B[i];
			     col_out = i;
			     col_in  = -1;
			}
		}
      }
     
       if ( mu <= lambda0 ) {	/* optimal */
          status0=0;       
	  break;

      }

        /*************************************************************
	*                          -1  t                             *
	* step 2: compute dy  = -(b  n) e                            * 
	*                   n            i			     *
	*         where i = col_out                                  *
        *************************************************************/
     if ( col_out >= 0 ) {
	vec[0] = -1.0;
	ivec[0] = col_out;
	nvec = 1;

	btsolve( m, vec, ivec, &nvec );  
	Nt_times_y( N, at, iat, kat, basicflag, vec, ivec, nvec, 
		     dy_N, idy_N, &ndy_N );

	col_in = ratio_test0( dy_N, idy_N, ndy_N, y_N, ybar_N,mu );

        /*************************************************************
	* STEP 3: Ratio test to find entering column                 * 
        *************************************************************/

	if (col_in == -1) { 	/* infeasible */
	    status0 = 1;
	    break;
	}

        /*************************************************************
	*                        -1                                  *
	* step 4: compute dx  = b  n e                               * 
	*                   b         j                              *
	*                                                            *
        *************************************************************/

	j = nonbasics[col_in];
	for (i=0, k=ka[j]; k<ka[j+1]; i++, k++) {
	     dx_B[i] =  a[k];
	    idx_B[i] = ia[k];
	}
	ndx_B = i;
	bsolve( m, dx_B, idx_B, &ndx_B );

        }

        else {

        /*************************************************************
	*                        -1                                  *
	* STEP 2: Compute dx  = B  N e                               * 
	*                   B         j                              *
        *************************************************************/

	j = nonbasics[col_in];
	for (i=0, k=ka[j]; k<ka[j+1]; i++, k++) {
	     dx_B[i] =  a[k];
	    idx_B[i] = ia[k];
	}
	ndx_B = i;
	bsolve( m, dx_B, idx_B, &ndx_B );

        /*************************************************************
	* STEP 3: Ratio test to find leaving column                  * 
        *************************************************************/

	col_out = ratio_test0( dx_B, idx_B, ndx_B, x_B, xbar_B, mu );

	if (col_out == -1) {	/* UNBOUNDED */
	    status0 = 2;
	    break;
	}

        /*************************************************************
	*                          -1  T                             *
	* STEP 4: Compute dy  = -(B  N) e                            * 
	*                   N            i			     *
	*                                                            *
        *************************************************************/

	 vec[0] = -1.0;
	ivec[0] = col_out;
	nvec = 1;

	btsolve( m, vec, ivec, &nvec );  		
	Nt_times_y( N, at, iat, kat, basicflag, vec, ivec, nvec, 
		     dy_N, idy_N, &ndy_N );

      }

      /*************************************************************
      *                                                            *
      * step 5: put       t = x /dx                                *
      *                        i   i                               *
      *                   _   _                                    *
      *                   t = x /dx                                *
      *                        i   i                               *
      *                   s = y /dy                                *
      *                        j   j                               *
      *                   _   _                                    *
      *                   s = y /dy                                *
      *                        j   j                               *
      *************************************************************/

      for (k=0; k<ndx_B; k++) if (idx_B[k] == col_out) break;

      t    =    x_B[col_out]/dx_B[k];
      tbar = xbar_B[col_out]/dx_B[k];

      for (k=0; k<ndy_N; k++) if (idy_N[k] == col_in) break;

      s    =    y_N[col_in]/dy_N[k];
      sbar = ybar_N[col_in]/dy_N[k];


      /*************************************************************
      *                                _    _    _                 *
      * step 7: set y  = y  - s dy     y  = y  - s dy              *
      *              n    n       n     n    n       n             *
      *                                _    _                      *
      *             y  = s             y  = s                      *
      *              i                  i                          *
      *             _    _    _                                    *
      *             x  = x  - t dx     x  = x  - t dx              *
      *              b    b       b     b    b       b             *
      *             _    _                                         *
      *             x  = t             x  = t                      *
      *              j                  j                          *
      *************************************************************/


      for (k=0; k<ndy_N; k++) {
		j = idy_N[k];
		y_N[j]    -= s   *dy_N[k];
                ybar_N[j] -= sbar*dy_N[k];
      }
      
      y_N[col_in]    = s;
      ybar_N[col_in] = sbar;

      for (k=0; k<ndx_B; k++) {
		i = idx_B[k];
		x_B[i]    -= t   *dx_B[k];
		xbar_B[i] -= tbar*dx_B[k];

      }

      x_B[col_out]     = t;
      xbar_B[col_out]  = tbar;

      /*************************************************************
      * step 8: update basis                                       * 
      *************************************************************/

      i =    basics[col_out];
      j = nonbasics[col_in];
      basics[col_out]   = j;
      nonbasics[col_in] = i;
      basicflag[i] = -col_in-1;
      basicflag[j] = col_out;


      /*************************************************************
      * step 9: refactor basis and print statistics                *
      *************************************************************/

      refactor( m, ka, ia, a, basics, col_out, v );

  } 

   

      for (i=0; i<m; i++) {
	  x[basics[i]] = x_B[i];
      }


      if(iter>=1){
          Nt_times_y( -1, at, iat, kat, basicflag, vec, ivec, nvec, 
		     dy_N, idy_N, &ndy_N );
      }


    /****************************************************************
    * 	free work space                                             *
    ****************************************************************/

    FREE(  vec );
    FREE( ivec );
    FREE(  x_B );
    FREE(  y_N );
    FREE( dx_B );
    FREE(idx_B );
    FREE( dy_N );
    FREE(idy_N );
    FREE(xbar_B);
    FREE(ybar_N);
    FREE( nonbasics );
    FREE( basics );
    FREE(at);
    FREE(iat);
    FREE(basicflag);
    FREE(kat);

    if(iter>=1){
       lu_clo();
       btsolve(0, vec, ivec, &nvec);
       bsolve(0, vec, ivec, &nvec);
    }


}