chrono::nanoseconds doUpdateDualsHypersparse(InstanceData const& instance, IterationData const& d) { SparseMatrixCSC const &A = instance.A; int nrow = A.nrow, ncol = A.ncol; vector<double> redcost = d.reducedCosts; IndexedVector tabrow(d.normalizedTableauRow); double stepsize = 1; auto t = chrono::high_resolution_clock::now(); for (int j = 0; j < tabrow.nnz; j++) { int i = tabrow.nzidx.at(j); double dnew = redcost.at(i) - stepsize*tabrow.elts.at(i); if (d.variableState.at(i) == AtLower) { if (dnew >= dualTol) { redcost.at(i) = dnew; } else { redcost.at(i) = -dualTol; } } else if (d.variableState[i] == AtUpper) { if (dnew <= dualTol) { redcost.at(i) = dnew; } else { redcost.at(i) = dualTol; } } } auto t2 = chrono::high_resolution_clock::now(); return chrono::duration_cast<chrono::nanoseconds>(t2-t); }
chrono::nanoseconds doTwoPassRatioTestHypersparse(InstanceData const& instance, IterationData const& d) { SparseMatrixCSC const &A = instance.A; int nrow = A.nrow, ncol = A.ncol; vector<int> candidates(ncol); int ncandidates = 0; double thetaMax = 1e25; const double pivotTol = 1e-7, dualTol = 1e-7; IndexedVector tabrow(d.normalizedTableauRow); auto t = chrono::high_resolution_clock::now(); for (int k = 0; k < tabrow.nnz; k++) { int i = tabrow.nzidx.at(k); VariableState thisState = d.variableState.at(i); double pivotElt = tabrow.elts.at(i); if ( (thisState == AtLower && pivotElt > pivotTol) || (thisState == AtUpper && pivotElt < -pivotTol)) { candidates.at(ncandidates++) = i; double ratio; if (pivotElt < 0.) { ratio = (d.reducedCosts.at(i) - dualTol)/pivotElt; } else { ratio = (d.reducedCosts.at(i) + dualTol)/pivotElt; } if (ratio < thetaMax) { thetaMax = ratio; } } } int enter = -1; double maxAlpha = 0.; for (int k = 0; k < ncandidates; k++) { int i = candidates.at(k); double ratio = d.reducedCosts.at(i)/tabrow.elts.at(i); if (ratio <= thetaMax) { double absalpha = abs(tabrow.elts.at(i)); if (absalpha > maxAlpha) { maxAlpha = absalpha; enter = i; } } } auto t2 = chrono::high_resolution_clock::now(); return chrono::duration_cast<chrono::nanoseconds>(t2-t); }
int tabs2x( struct tabprm* tab, int ncoord, int nelem, const double world[], double x[], int stat[]) { static const char *function = "tabs2x"; int tabedge(struct tabprm *); int tabrow(struct tabprm *, const double *); int tabvox(struct tabprm *, const double *, int, double **, unsigned int *); int edge, i, ic, iv, k, *Km, M, m, n, nv, offset, status; double *dcrd, delta, *Psi, psi_m, **tabcoord, upsilon; register int *statp; register const double *wp; register double *xp; struct wcserr **err; if (tab == 0x0) return TABERR_NULL_POINTER; err = &(tab->err); /* Initialize if required. */ if (tab->flag != TABSET) { if ((status = tabset(tab))) return status; } /* This is used a lot. */ M = tab->M; tabcoord = 0x0; nv = 0; if (M > 1) { nv = 1 << M; tabcoord = calloc(nv, sizeof(double *)); } status = 0; wp = world; xp = x; statp = stat; for (n = 0; n < ncoord; n++) { /* Locate this coordinate in the coordinate array. */ edge = 0; for (m = 0; m < M; m++) { tab->p0[m] = 0; } for (ic = 0; ic < tab->nc; ic++) { if (tab->p0[0] == 0) { /* New row, could it contain a solution? */ if (edge || tabrow(tab, wp)) { /* No, skip it. */ ic += tab->K[0]; tab->p0[1]++; edge = tabedge(tab); /* Because ic will be incremented when the loop is reentered. */ ic--; continue; } } if (M == 1) { /* Deal with the one-dimensional case separately for efficiency. */ if (*wp == tab->coord[0]) { tab->p0[0] = 0; tab->delta[0] = 0.0; break; } else if (ic < tab->nc - 1) { if (((tab->coord[ic] <= *wp && *wp <= tab->coord[ic+1]) || (tab->coord[ic] >= *wp && *wp >= tab->coord[ic+1])) && (tab->index[0] == 0x0 || tab->index[0][ic] != tab->index[0][ic+1])) { tab->p0[0] = ic; tab->delta[0] = (*wp - tab->coord[ic]) / (tab->coord[ic+1] - tab->coord[ic]); break; } } } else { /* Multi-dimensional tables are harder. */ if (!edge) { /* Addresses of the coordinates for each corner of the "voxel". */ for (iv = 0; iv < nv; iv++) { offset = 0; for (m = M-1; m >= 0; m--) { offset *= tab->K[m]; offset += tab->p0[m]; if ((iv & (1 << m)) && (tab->K[m] > 1)) offset++; } tabcoord[iv] = tab->coord + offset*M; } if (tabvox(tab, wp, 0, tabcoord, 0x0) == 0) { /* Found a solution. */ break; } } /* Next voxel. */ tab->p0[0]++; edge = tabedge(tab); } } if (ic == tab->nc) { /* Coordinate not found; allow minor extrapolation. */ if (M == 1) { /* Should there be a solution? */ if (tab->extrema[0] <= *wp && *wp <= tab->extrema[1]) { dcrd = tab->coord; for (i = 0; i < 2; i++) { if (i) dcrd += tab->K[0] - 2; delta = (*wp - *dcrd) / (*(dcrd+1) - *dcrd); if (i == 0) { if (-0.5 <= delta && delta <= 0.0) { tab->p0[0] = 0; tab->delta[0] = delta; ic = 0; break; } } else { if (1.0 <= delta && delta <= 1.5) { tab->p0[0] = tab->K[0] - 1; tab->delta[0] = delta - 1.0; ic = 0; } } } } } else { /* Multi-dimensional tables. */ /* >>> TBD <<< */ } } if (ic == tab->nc) { /* Coordinate not found. */ *statp = 1; status = wcserr_set(TAB_ERRMSG(TABERR_BAD_WORLD)); } else { /* Determine the intermediate world coordinates. */ Km = tab->K; for (m = 0; m < M; m++, Km++) { /* N.B. Upsilon_m and psi_m are 1-relative FITS indexes. */ upsilon = (tab->p0[m] + 1) + tab->delta[m]; if (upsilon < 0.5 || upsilon > *Km + 0.5) { /* Index out of range. */ *statp = 1; status = wcserr_set(TAB_ERRMSG(TABERR_BAD_WORLD)); } else { /* Do inverse lookup of the index vector. */ Psi = tab->index[m]; if (Psi == 0x0) { /* Default indexing. */ psi_m = upsilon; } else { /* Decrement Psi and use 1-relative C array indexing to match the 1-relative FITS indexing. */ Psi--; if (*Km == 1) { /* Degenerate index vector. */ psi_m = Psi[1]; } else { k = (int)(upsilon); psi_m = Psi[k]; if (k < *Km) { psi_m += (upsilon - k) * (Psi[k+1] - Psi[k]); } } } i = tab->map[m]; xp[i] = psi_m - tab->crval[m]; } } *statp = 0; } wp += nelem; xp += nelem; statp++; } if (tabcoord) free(tabcoord); return status; }