STATIC void restartPricer(lprec *lp, MYBOOL isdual) { REAL *sEdge, seNorm, hold; int i, j, m; MYBOOL isDEVEX; if(!applyPricer(lp)) return; /* Store the active/current pricing type */ if(isdual == AUTOMATIC) isdual = (MYBOOL) lp->edgeVector[0]; else lp->edgeVector[0] = isdual; m = lp->rows; /* Determine strategy and check if we have strategy fallback for the primal */ isDEVEX = is_piv_rule(lp, PRICER_DEVEX); if(!isDEVEX && !isdual) isDEVEX = is_piv_mode(lp, PRICE_PRIMALFALLBACK); /* Check if we only need to do the simple DEVEX initialization */ if(isDEVEX && !DEVEX_ENHANCED) { if(isdual) { for(i = 1; i <= m; i++) lp->edgeVector[lp->var_basic[i]] = 1.0; } else { for(i = 1; i <= lp->sum; i++) if(!lp->is_basic[i]) lp->edgeVector[i] = 1.0; } return; } /* Otherwise do the full Steepest Edge norm initialization */ sEdge = (REAL *) malloc((m + 1) * sizeof(*sEdge)); if(isdual) { /* Extract the rows of the basis inverse and compute their squared norms */ for(i = 1; i <= m; i++) { bsolve(lp, i, sEdge, NULL, 0, 0.0); /* Compute the edge norm */ seNorm = 0; for(j = 1; j <= m; j++) { hold = sEdge[j]; seNorm += hold*hold; } j = lp->var_basic[i]; lp->edgeVector[j] = seNorm; } } else { /* Solve a=Bb for b over all non-basic variables and compute their squared norms */ for(i = 1; i <= lp->sum; i++) { if(lp->is_basic[i]) continue; fsolve(lp, i, sEdge, NULL, 0, 0.0, FALSE); /* Compute the edge norm */ seNorm = 1; for(j = 1; j <= m; j++) { hold = sEdge[j]; seNorm += hold*hold; } lp->edgeVector[i] = seNorm; } } free(sEdge); }
STATIC void updatePricer(lprec *lp, int rownr, int colnr, REAL *pcol, REAL *prow, int *nzprow) { REAL *vEdge = NULL, cEdge, hold, *newEdge, *w = NULL; int i, m, n, exitcol, errlevel = DETAILED; MYBOOL forceRefresh = FALSE, isDual, isDEVEX; if(!applyPricer(lp)) return; /* Make sure we have something to update */ hold = lp->edgeVector[0]; if(hold < 0) return; isDual = (MYBOOL) (hold > 0); /* Do common initializations and computations */ m = lp->rows; n = lp->sum; isDEVEX = is_piv_rule(lp, PRICER_DEVEX); exitcol = lp->var_basic[rownr]; /* Solve/copy Bw = a */ /* formWeights(lp, colnr, NULL, &w); Experimental */ formWeights(lp, colnr, pcol, &w); /* Price norms for the dual simplex - the basic columns */ if(isDual) { REAL rw; int targetcol; /* Don't need to compute cross-products with DEVEX */ if(!isDEVEX) { allocREAL(lp, &vEdge, m+1, FALSE); /* Extract the row of the inverse containing the leaving variable and then form the dot products against the other variables, i.e. "Tau" */ #if 0 /* Extract row explicitly */ bsolve(lp, rownr, vEdge, 0, 0.0); #else /* Reuse previously extracted row data */ MEMCOPY(vEdge, prow, m+1); vEdge[0] = 0; #endif lp->bfp_ftran_normal(lp, vEdge, NULL); } /* Deal with the variable entering the basis to become a new leaving candidate */ cEdge = lp->edgeVector[exitcol]; rw = w[rownr]; hold = 1 / rw; lp->edgeVector[colnr] = (hold*hold) * cEdge; /* Possibly adjust initial value in case of Devex */ if(isDEVEX && !DEVEX_ENHANCED && (lp->edgeVector[colnr] < DEVEX_MINVALUE)) lp->edgeVector[colnr] = DEVEX_MINVALUE; #ifdef Paranoia if(lp->edgeVector[colnr] <= lp->epsmachine) report(lp, errlevel, "updatePricer: Invalid dual norm %g at entering index %d - iteration %d\n", lp->edgeVector[colnr], rownr, lp->total_iter+lp->current_iter); #endif /* Then loop over all basic variables, but skip the leaving row */ for(i = 1; i <= m; i++) { if(i == rownr) continue; targetcol = lp->var_basic[i]; hold = w[i]; if(hold == 0) continue; hold /= rw; if(fabs(hold) < lp->epsmachine) continue; newEdge = &(lp->edgeVector[targetcol]); *newEdge += (hold*hold) * cEdge; if(isDEVEX) { if((*newEdge) > DEVEX_RESTARTLIMIT) { forceRefresh = TRUE; break; } } else { *newEdge -= 2*hold*vEdge[i]; #ifdef xxApplySteepestEdgeMinimum *newEdge = my_max(*newEdge, hold*hold+1); /* Kludge; use the primal lower bound */ #else if(*newEdge <= 0) { report(lp, errlevel, "updatePricer: Invalid dual norm %g at index %d - iteration %d\n", *newEdge, i, lp->total_iter+lp->current_iter); forceRefresh = TRUE; break; } #endif } } } /* Price norms for the primal simplex - the non-basic columns */ else { REAL *vTemp, *vAlpha, cAlpha; int *coltarget; allocREAL(lp, &vTemp, m+1, TRUE); allocREAL(lp, &vAlpha, n+1, TRUE); /* Check if we have strategy fallback for the primal */ if(!isDEVEX) isDEVEX = is_piv_mode(lp, PRICE_PRIMALFALLBACK); /* Initialize column target array */ coltarget = (int *) mempool_obtainVector(lp->workarrays, lp->sum+1, sizeof(*coltarget)); if(!get_colIndexA(lp, SCAN_ALLVARS+USE_NONBASICVARS, coltarget, FALSE)) { mempool_releaseVector(lp->workarrays, (char *) coltarget, FALSE); return; } /* Don't need to compute cross-products with DEVEX */ if(!isDEVEX) { vEdge = (REAL *) calloc((n + 1), sizeof(*vEdge)); /* Compute v and then N'v */ MEMCOPY(vTemp, w, m+1); bsolve(lp, -1, vTemp, NULL, lp->epsmachine*DOUBLEROUND, 0.0); vTemp[0] = 0; prod_xA(lp, coltarget, vTemp, NULL, XRESULT_FREE, lp->epsmachine, 0.0, vEdge, NULL); } /* Compute Sigma and then Alpha */ bsolve(lp, rownr, vTemp, NULL, 0*DOUBLEROUND, 0.0); vTemp[0] = 0; prod_xA(lp, coltarget, vTemp, NULL, XRESULT_FREE, lp->epsmachine, 0.0, vAlpha, NULL); mempool_releaseVector(lp->workarrays, (char *) coltarget, FALSE); /* Update the squared steepest edge norms; first store some constants */ cEdge = lp->edgeVector[colnr]; cAlpha = vAlpha[colnr]; /* Deal with the variable leaving the basis to become a new entry candidate */ hold = 1 / cAlpha; lp->edgeVector[exitcol] = (hold*hold) * cEdge; /* Possibly adjust initial value in case of Devex */ if(isDEVEX && !DEVEX_ENHANCED && (lp->edgeVector[exitcol] < DEVEX_MINVALUE)) lp->edgeVector[exitcol] = DEVEX_MINVALUE; #ifdef Paranoia if(lp->edgeVector[exitcol] <= lp->epsmachine) report(lp, errlevel, "updatePricer: Invalid primal norm %g at leaving index %d - iteration %d\n", lp->edgeVector[exitcol], exitcol, lp->total_iter+lp->current_iter); #endif /* Then loop over all non-basic variables, but skip the entering column */ for(i = 1; i <= lp->sum; i++) { if(lp->is_basic[i] || (i == colnr)) continue; hold = vAlpha[i]; if(hold == 0) continue; hold /= cAlpha; if(fabs(hold) < lp->epsmachine) continue; newEdge = &(lp->edgeVector[i]); *newEdge += (hold*hold) * cEdge; if(isDEVEX) { if((*newEdge) > DEVEX_RESTARTLIMIT) { forceRefresh = TRUE; break; } } else { *newEdge -= 2*hold*vEdge[i]; #ifdef ApplySteepestEdgeMinimum *newEdge = my_max(*newEdge, hold*hold+1); #else if(*newEdge < 0) { report(lp, errlevel, "updatePricer: Invalid primal norm %g at index %d - iteration %d\n", *newEdge, i, lp->total_iter+lp->current_iter); if(lp->spx_trace) report(lp, errlevel, "Error detail: (RelAlpha=%g, vEdge=%g, cEdge=%g)\n", hold, vEdge[i], cEdge); forceRefresh = TRUE; break; } #endif } } FREE(vAlpha); FREE(vTemp); } if(vEdge != NULL) FREE(vEdge); freeWeights(w); if(forceRefresh) restartPricer(lp, AUTOMATIC); }
STATIC MYBOOL restartPricer(lprec *lp, MYBOOL isdual) { REAL *sEdge = NULL, seNorm, hold; int i, j, m; MYBOOL isDEVEX, ok = applyPricer(lp); /* Correction from V6, apparently, via Kjell Eikland and the ** lpSolve mailing list 2014-06-18 2:57 p.m. */ if (ok && (lp->edgeVector[0] < 0) && (isdual == AUTOMATIC)) ok = FALSE; if(!ok) return( ok ); /* Store the active/current pricing type */ if(isdual == AUTOMATIC) isdual = (MYBOOL) lp->edgeVector[0]; else lp->edgeVector[0] = isdual; m = lp->rows; /* Determine strategy and check if we have strategy fallback for the primal */ isDEVEX = is_piv_rule(lp, PRICER_DEVEX); if(!isDEVEX && !isdual) isDEVEX = is_piv_mode(lp, PRICE_PRIMALFALLBACK); /* Check if we only need to do the simple DEVEX initialization */ if(!is_piv_mode(lp, PRICE_TRUENORMINIT)) { if(isdual) { for(i = 1; i <= m; i++) lp->edgeVector[lp->var_basic[i]] = 1.0; } else { for(i = 1; i <= lp->sum; i++) if(!lp->is_basic[i]) lp->edgeVector[i] = 1.0; } return( ok ); } /* Otherwise do the full Steepest Edge norm initialization */ ok = allocREAL(lp, &sEdge, m+1, FALSE); if(!ok) return( ok ); if(isdual) { /* Extract the rows of the basis inverse and compute their squared norms */ for(i = 1; i <= m; i++) { bsolve(lp, i, sEdge, NULL, 0, 0.0); /* Compute the edge norm */ seNorm = 0; for(j = 1; j <= m; j++) { hold = sEdge[j]; seNorm += hold*hold; } j = lp->var_basic[i]; lp->edgeVector[j] = seNorm; } } else { /* Solve a=Bb for b over all non-basic variables and compute their squared norms */ for(i = 1; i <= lp->sum; i++) { if(lp->is_basic[i]) continue; fsolve(lp, i, sEdge, NULL, 0, 0.0, FALSE); /* Compute the edge norm */ seNorm = 1; for(j = 1; j <= m; j++) { hold = sEdge[j]; seNorm += hold*hold; } lp->edgeVector[i] = seNorm; } } FREE(sEdge); return( ok ); }