/* The main function: pivot */ ptrdiff_t Basis_Pivot(PT_Basis pB, PT_Matrix pA, ptrdiff_t enter, ptrdiff_t leave) { ptrdiff_t m, nW, Wl, c, r; PT_Index pW, pZ, pWc; PT_Matrix pG, pX, pF; ptrdiff_t left; /* abbreviations */ pW = pB->pW; pWc = pB->pWc; pZ = pB->pZ; pG = pB->pG; pX = pB->pX; pF = pB->pF; /* get dimensions */ m = Matrix_Rows(pA); nW = Index_Length(pW); /* determine the leaving variable */ if(leave < Index_Length(pW)) { left = Index_Get(pW,leave); } else { left = Index_Get(pZ,leave-Index_Length(pW))+m; } /* printf("\n ---------------------------------------\n"); */ /* printf("enter = %ld, leave = %ld\n", enter, leave); */ /* Four cases */ if(enter < m) { /* r = find(B.Wc == enter) */ r = Index_FindElement(pWc, enter); if(leave < nW) { /* printf("case 1:\n"); */ Wl = Index_Get(pW,leave); /* G_l,* = M_e,Z */ /* Basis_Print(pB); */ /* Update matrix G with the row corresponding to the entering variable */ Matrix_GetRow(pA, pB->y, enter, pZ); Matrix_ReplaceRow(pG, leave, pB->y); /* X_r,* = M_Wl,Z */ /* Update matrix X with the row corresponing to the leaving variable from index set pW. Similarly, we must update matrix F as its gets overwritten by dgesv routine. */ Matrix_GetRow(pA, pB->y, Wl, pZ); Matrix_ReplaceRow(pF, r, pB->y); Matrix_ReplaceRow(pX, r, pB->y); /* smart update with LUmod */ LU_Replace_Row(pB->pLX, pB->pUX, r, pB->y, pB->z, pB->w); /* Wc_r = Wl, W_l = e */ /* update index sets */ Index_Replace(pWc, r, Wl); Index_Replace(pW, leave, enter); } else /* leave >= nW */ { /* printf("case 2:\n"); */ Index_Add(pW,enter); c = leave-nW; /* Replace row r and column c with the last row and column of X and remove last row/column. */ Matrix_RemoveRow(pX,r); Matrix_RemoveCol(pX,c); /* We must update matrix F as well */ Matrix_RemoveRow(pF,r); Matrix_RemoveCol(pF,c); /* smart update with LUmod */ LU_Shrink(pB->pLX, pB->pUX, r, c, pB->y, pB->z, pB->w); /* Update indices */ Index_Remove(pWc, r); Index_Remove(pZ, c); /* Update G matrix */ Matrix_RemoveCol(pG, c); Matrix_GetRow(pA, pB->y, enter, pZ); Matrix_AddRow(pG, pB->y); } } else /* enter >= m */ { if(leave < nW) { /* printf("case 3:\n"); */ Wl = Index_Get(pW,leave); /* Add row Wl and column e-m to X */ if(Index_Length(pZ) > 0) { Matrix_GetRow(pA, pB->y, Wl, pZ); Matrix_GetCol(pA, pB->z, pWc, enter-m); } pB->y[Index_Length(pZ)] = C_SEL(pA,Wl,enter-m); /* updating F */ Matrix_AddCol(pF, pB->z); Matrix_AddRow(pF, pB->y); /* updating X */ Matrix_AddCol(pX, pB->z); Matrix_AddRow(pX, pB->y); /* update with LUmod */ LU_Expand(pB->pLX, pB->pUX, pB->y, pB->z, pB->w); /* printf("pX col=\n"); */ /* Matrix_Print_col(pX); */ /* Remove row Wl from G */ /* and add column e-m */ Matrix_RemoveRow(pG, leave); Index_Remove(pW, leave); Matrix_GetCol(pA, pB->z, pW, enter-m); Matrix_AddCol(pG, pB->z); /* Extend Wc and Z */ Index_Add(pWc, Wl); Index_Add(pZ, enter-m); } else /* leave >= nW */ { /* printf("case 4:\n"); */ /* Replace column */ c = leave - nW; /* G_*,c = M_w,(e-m) */ Matrix_GetCol(pA, pB->y, pW, enter-m); Matrix_ReplaceCol(pG, c, pB->y); /* X_*,c = M_Wc,(e-m) */ Matrix_GetCol(pA, pB->z, pWc, enter-m); /* Vector_Print_raw(pB->z,m); */ /* Basis_Print(pB); */ /* update matrices X, F by replacing column */ Matrix_ReplaceCol(pX, c, pB->z); Matrix_ReplaceCol(pF, c, pB->z); /* update for LUmod */ LU_Replace_Col(pB->pLX, pB->pUX, c, pB->y, pB->z, pB->w); /* Update Z */ Index_Replace(pZ, c, enter-m); } } /* create column-wise upper triangular matrix Ut from U*/ Matrix_Triu(pB->pUt, pB->pUX, pB->r); return left; }
/* If something goes wrong, returned value contains LCP_flag (negative values). */ ptrdiff_t LexMinRatio(PT_Basis pB, PT_Matrix pA, double *v, T_Options options) { ptrdiff_t m, i, j, k, incx, info; PT_Index pP; double *rat, *q; double minrat=0.0, alpha; m = Matrix_Rows(pA); pP = pB->pP; rat = pB->y; q = pB->w; /* used to obtain an identity matrix in lex-pivot operation */ alpha = 0.0; /* increment of each vectors is 1 */ incx = 1; /* Compute the index set of positive v s */ Index_Length(pP) = 0; for (j=0, i=0;i<m;i++) { if ( v[i] > options.zerotol ) { Index_Add(pP, i); /* The positive elements of 1/v are now the first |pP| elements */ v[j++] = v[i]; } } if(Index_Length(pP) == 0) /* Problem infeasible */ return LCP_INFEASIBLE; /* q = A(:,m+1) */ memcpy(q,&(C_SEL(pA, 0, m+1)),m*sizeof(double)); for (i=0; i<m+1; i++) { /* Basis_Print(pB); */ /* Index_Print(pP); */ /* rat = iB*q */ info = Basis_Solve(pB, q, rat, options); if (info!=0) { #ifdef MATLAB_MEX_FILE if (options.verbose) { printf("Numerical problems with Basis_Solve in LexRatio.\n"); } #endif return LCP_CODEERROR; } /* printf("q after Basis_Solve in LexRatio=\n"); */ /* Vector_Print_raw(q,m); */ /* rat = rat(pP) / v(pP) */ /* find minimum ratio */ minrat = rat[Index_Get(pP,0)]/v[0]; for (j=0; j<Index_Length(pP); j++) { rat[j] = rat[Index_Get(pP,j)]/v[j]; if (rat[j] < minrat) { minrat = rat[j]; } } /* printf("minrat=%lf\n",minrat); */ /* printf("Ratio vector after=\n"); */ /* Vector_Print_raw(rat,m); */ /* printf("positive index set:\n"); */ /* Index_Print(pP); */ /* remove all indices that are greater than the minumum ratio with some tolerance */ /* Move all elements equal to minrat to the start of the list */ for (k=0, j=0;j<Index_Length(pP);j++) { /* printf("j=%ld, fabs(minrat - rat[lndex_Get(pP,j)]) = %f\n", j, fabs(minrat - rat[Index_Get(pP,j)])); */ if (fabs(minrat - rat[j]) < options.lextol) { Index_Set(pP,k,Index_Get(pP,j)); /*pP is now a set of indices with equal ratio */ v[k++] = v[j]; } } pP->len = k; /* printf("new index set:\n"); */ /* Index_Print(pP); */ if(Index_Length(pP) <= 0) { /* Vector_Print_raw(v,m); */ /* Vector_Print_raw(rat,m); */ /* mexPrintf("minrat = %lf, length(pP) = %ld\n",minrat,Index_Length(pP)); */ /* Index_Print(pP); */ #ifdef MATLAB_MEX_FILE if (options.verbose) { printf("Numerical problems with finding lexicographic minimum. You can refine this using the 'lextol' feature in options.\n"); } #endif return LCP_CODEERROR; } if(Index_Length(pP) > 1) { /* printf("Taking lex-pivot\n"); */ /* Need to make a lex-comparison */ /* q = 0*q */ dscal(&m, &alpha, q, &incx); q[i] = 1.0; } else { return Index_Get(pP,0); } } /* if the lex-pivot failed, pick the largest element from v_i vector i=0, ..., k */ return Index_Get(pP, idamax(&k, v, &incx)-1); /* mexErrMsgTxt("Did not find a lex-min. This should be impossible."); */ /* return LCP_INFEASIBLE; */ }