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);
}
Esempio n. 3
0
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;
}