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 */
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; }
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); } }