public static DoublePopulationStatisticsAggregator combine(Collection<DoublePopulationStatisticsAggregator> aggregators) { Random random = new Random(); DoublePopulationStatisticsAggregator result = new DoublePopulationStatisticsAggregator(); for (DoublePopulationStatisticsAggregator aggregator : aggregators) { if (aggregator.maximum > result.maximum) { result.maximum = aggregator.maximum; } if (aggregator.minimum < result.minimum) { result.minimum = aggregator.minimum; } result.numValues += aggregator.numValues; result.total += aggregator.total; } // Now we can create a stream of values based on a // random sample of the aggregators reservoirs but // with the number of values in their streams a weight // and reservoir sample that. This assumes that all given reservoirs // have the same size. for (DoublePopulationStatisticsAggregator aggregator : aggregators) { double ratio = (double) aggregator.numValues / (double) result.numValues; for (double value : aggregator.reservoirSample.getReservoir()) { if ((Math.abs(random.nextDouble()) / Double.MAX_VALUE) < ratio) { result.reservoirSample.sample(value, random); } } } return result; }
public void sample(ReservoirSample other, Random random) { for (int i = 0; i < other.getSize(); ++i) { sample(other.getReservoir()[i], random); } }
public void aggregate(double minimum, double maximum, long numValues, double total, double[] values) { if (maximum > this.maximum) { this.maximum = maximum; } if (minimum < this.minimum) { this.minimum = minimum; } this.numValues += numValues; this.total += total; this.reservoirSample.sample(values, random); }
public DoublePopulationStatisticsAggregator(double minimum, double maximum, long numValues, double total, double[] randomSample) { this.minimum = minimum; this.maximum = maximum; this.numValues = numValues; this.total = total; this.reservoirSample.sample(randomSample, random); }
public void sample(double[] values, Random random) { for (double value : values) { sample(value, random); } }