Esempio n. 1
0
 public static final ObjFunHandle getHandle(long alphaBin, OpenLongObjectHashMap map) {
   Object h = map.get(alphaBin);
   if (h == null) {
     h = new ObjFunHandle(alphaBin);
     map.put(alphaBin, h);
   }
   return (ObjFunHandle) h;
 }
Esempio n. 2
0
  @Override
  protected double sampleAlpha(
      Matrix direction, Matrix Aobj, Matrix objConst, double alphaLow, double alphaHigh) {
    // Construct distribution over the randomly sampled line given by the direction and the bounds
    // [alphaLow, alphaHigh]
    Matrix AobjD = Aobj.mtimes(direction);
    Matrix AobjP = Aobj.mtimes(currentPt);

    OpenLongObjectHashMap alphaMap = new OpenLongObjectHashMap();
    long alphaLowBin = Math.round(alphaLow * alphaRoundingScheme);
    ObjFunHandle alphaLowHandle = ObjFunHandle.getHandle(alphaLowBin, alphaMap);

    for (int i = 0; i < Aobj.getRowCount(); i++) {
      double rate = AobjD.getAsDouble(i, 0);
      double constant = AobjP.getAsDouble(i, 0) + objConst.getAsDouble(i, 0);
      double alpha = (-constant) / rate;
      long alphaBin = Math.round(alpha * alphaRoundingScheme);
      log.trace("Alpha {}", alpha);
      log.trace("Rate {} Constant {}", rate, constant);
      if (rate > epsilon && alpha < alphaHigh) {
        ObjFunHandle h;
        if (alpha <= alphaLow) {
          // This evidence is active over the entire interval
          h = alphaLowHandle;
        } else {
          // This evidence will get active once we reach alpha in the interval
          h = ObjFunHandle.getHandle(alphaBin, alphaMap);
        }
        h.increaseBy(rate, constant);
      } else if (rate < -epsilon && alpha > alphaLow) {
        alphaLowHandle.increaseBy(rate, constant);
        if (alpha >= alphaHigh) {
          // This evidence is active over the entire interval
        } else {
          // This evidence will get inactive once we reach alpha in the interval
          ObjFunHandle h = ObjFunHandle.getHandle(alphaBin, alphaMap);
          h.increaseBy(-rate, -constant);
        }
      } else { // Considered 0
        alphaLowHandle.increaseBy(0.0, constant);
      }
    }
    ObjFunHandle.getHandle(Math.round(alphaHigh * alphaRoundingScheme), alphaMap);
    AobjD = null;
    AobjP = null;

    int length = alphaMap.size();
    LongArrayList alphaBinsL = new LongArrayList(length);
    ObjectArrayList handlesL = new ObjectArrayList(length);
    alphaMap.pairsSortedByKey(alphaBinsL, handlesL);
    assert alphaBinsL.size() == length && handlesL.size() == length;

    double[] logcumulative = new double[length];
    double[] cumRate = new double[length - 1];
    double[] cumConst = new double[length - 1];
    long[] alphaBins = alphaBinsL.elements();
    Object[] handles = handlesL.elements();

    log.trace("alphaBins: {}", Arrays.toString(alphaBins));
    log.trace("handles: {}", Arrays.toString(handles));

    // Now compute the cumulative probability distribution
    ObjFunHandle base = (ObjFunHandle) handles[0];
    double baserate = base.getRate();
    double baseconstant = base.getConstant();
    double basealpha = alphaBins[0] / (double) alphaRoundingScheme;
    double baselogdivisor = baserate * basealpha + baseconstant;

    logcumulative[0] = 0.0;
    double rate = 0.0;
    double constant = 0.0;
    for (int i = 1; i < length; i++) {
      ObjFunHandle h = (ObjFunHandle) handles[i - 1];
      rate += h.getRate();
      cumRate[i - 1] = rate;
      constant += h.getConstant();
      cumConst[i - 1] = constant;
      double aL = alphaBins[i - 1] / (double) alphaRoundingScheme,
          aU = alphaBins[i] / (double) alphaRoundingScheme;
      double increment;
      if (rate < -epsilon || rate > epsilon)
        increment =
            1.0
                / rate
                * (Math.exp(baselogdivisor - rate * aL - constant)
                    - Math.exp(baselogdivisor - rate * aU - constant));
      else increment = (aU - aL) * Math.exp(baselogdivisor - constant);
      assert increment > -epsilon : increment;
      logcumulative[i] = logcumulative[i - 1] + increment;
    }
    double total = logcumulative[length - 1];
    double randomPt = Math.random() * total;
    log.trace("Random Pt {}", randomPt);

    log.trace("logcumulative: {}", Arrays.toString(logcumulative));

    int findIndex = Arrays.binarySearch(logcumulative, randomPt);
    log.trace("Find Index {}", findIndex);
    double alphaPt;
    if (findIndex >= 0) alphaPt = alphaBins[findIndex] / (double) alphaRoundingScheme;
    else {
      findIndex = -findIndex - 1;
      assert findIndex > 0 : findIndex;
      double aL = alphaBins[findIndex - 1] / (double) alphaRoundingScheme;
      final double crate = cumRate[findIndex - 1];
      final double cconstant = cumConst[findIndex - 1];
      log.trace("R {}, c {} aL " + aL, crate, cconstant);
      if (crate < -epsilon || crate > epsilon) {
        double targetValue =
            -randomPt
                + logcumulative[findIndex - 1]
                + 1.0 / crate * Math.exp(-cconstant - crate * aL + baselogdivisor);
        log.trace("Target value {}", targetValue);
        log.trace("Log: {}, inside log {}", Math.log(crate * targetValue), crate * targetValue);
        alphaPt = -1.0 / crate * (Math.log(crate * targetValue) + cconstant - baselogdivisor);
      } else {
        double kcons = Math.exp(baselogdivisor - cconstant);
        alphaPt = randomPt / kcons - logcumulative[findIndex - 1] / kcons + aL;
      }
      assert !Double.isNaN(alphaPt)
          : "C: "
              + cconstant
              + " | R: "
              + crate
              + " Pt: "
              + randomPt
              + " aL: "
              + aL
              + "  C0:"
              + logcumulative[findIndex - 1];
    }
    assert alphaPt >= alphaLow - epsilon && alphaPt <= alphaHigh + epsilon : alphaPt;
    alphaPt = Math.max(alphaPt, alphaLow);
    alphaPt = Math.min(alphaPt, alphaHigh);
    log.trace("Sampled alpha {}", alphaPt);

    return alphaPt;
  }