srecord noeq ProbabilisticBinaryMaximumSearch( IF1 scoreFunction, IVF1> action, DoubleRange startRange) extends Probabilistic { double featureSize = 1.0; // stop when range is shorter than twice this double defaultRecursionProbability = 1.0; //0.99; bool probabilitiesCanGoUp = true; bool verbose; // sigmoid function (R to (0; 1)) swappable double scoreToProbability(double score) { ret arctanSigmoid_zeroToOne(score); } double probabilityScore(double x) { ret scoreToProbability(scoreFunction.get(x)); } WithProbability probabilityScored(double x) { ret WithProbability(probabilityScore(x), x); } swappable double recursionProbability(DoubleRange r) { ret halfLength(r) >= featureSize ? defaultRecursionProbability : 0.0; } run { lookAtRange(startRange); } selfType verbose(bool verbose) { this.verbose = verbose; this; } void lookAtRange(DoubleRange r) { double previousP = probabilitiesCanGoUp ? 1.0 : ps.currentProbability(); double x = chooseMiddlePoint(r); double score = scoreFunction.get(x); double scoreP = scoreToProbability(score); double actionP = previousP * scoreP; if (verbose) printVars lookAtRange(+r, +x, +score, +scoreP, +previousP, +actionP); at(actionP, () -> action.get(withProbability(scoreP, x))); double recP_raw = recursionProbability(r); double recP = actionP * recP_raw; if (verbose) printVars ("lookAtRange ", +recP_raw, +recP); at(recP, () -> lookAtRange(lowerHalf(r))); at(recP, () -> lookAtRange(upperHalf(r))); } // You can adjust this, for example to look at integer coordinates only swappable double chooseMiddlePoint(DoubleRange r) { ret center(r); } }