下面列出了java.util.function.ToDoubleFunction#applyAsDouble ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* Returns a {@code Collector} that produces the sum of a double-valued
* function applied to the input elements. If no elements are present,
* the result is 0.
*
* <p>The sum returned can vary depending upon the order in which
* values are recorded, due to accumulated rounding error in
* addition of values of differing magnitudes. Values sorted by increasing
* absolute magnitude tend to yield more accurate results. If any recorded
* value is a {@code NaN} or the sum is at any point a {@code NaN} then the
* sum will be {@code NaN}.
*
* @param <T> the type of the input elements
* @param mapper a function extracting the property to be summed
* @return a {@code Collector} that produces the sum of a derived property
*/
public static <T> Collector<T, ?, Double>
summingDouble(ToDoubleFunction<? super T> mapper) {
/*
* In the arrays allocated for the collect operation, index 0
* holds the high-order bits of the running sum, index 1 holds
* the low-order bits of the sum computed via compensated
* summation, and index 2 holds the simple sum used to compute
* the proper result if the stream contains infinite values of
* the same sign.
*/
return new CollectorImpl<>(
() -> new double[3],
(a, t) -> { double val = mapper.applyAsDouble(t);
sumWithCompensation(a, val);
a[2] += val;},
(a, b) -> { sumWithCompensation(a, b[0]);
a[2] += b[2];
return sumWithCompensation(a, b[1]); },
a -> computeFinalSum(a),
CH_NOID);
}
/**
* Returns a {@code Collector} that produces the sum of a double-valued
* function applied to the input elements. If no elements are present,
* the result is 0.
*
* <p>The sum returned can vary depending upon the order in which
* values are recorded, due to accumulated rounding error in
* addition of values of differing magnitudes. Values sorted by increasing
* absolute magnitude tend to yield more accurate results. If any recorded
* value is a {@code NaN} or the sum is at any point a {@code NaN} then the
* sum will be {@code NaN}.
*
* @param <T> the type of the input elements
* @param mapper a function extracting the property to be summed
* @return a {@code Collector} that produces the sum of a derived property
*/
public static <T> Collector<T, ?, Double>
summingDouble(ToDoubleFunction<? super T> mapper) {
/*
* In the arrays allocated for the collect operation, index 0
* holds the high-order bits of the running sum, index 1 holds
* the low-order bits of the sum computed via compensated
* summation, and index 2 holds the simple sum used to compute
* the proper result if the stream contains infinite values of
* the same sign.
*/
return new CollectorImpl<>(
() -> new double[3],
(a, t) -> { sumWithCompensation(a, mapper.applyAsDouble(t));
a[2] += mapper.applyAsDouble(t);},
(a, b) -> { sumWithCompensation(a, b[0]);
a[2] += b[2];
return sumWithCompensation(a, b[1]); },
a -> computeFinalSum(a),
CH_NOID);
}
/**
* Returns a {@code Collector} that produces the sum of a double-valued
* function applied to the input elements. If no elements are present,
* the result is 0.
*
* <p>The sum returned can vary depending upon the order in which
* values are recorded, due to accumulated rounding error in
* addition of values of differing magnitudes. Values sorted by increasing
* absolute magnitude tend to yield more accurate results. If any recorded
* value is a {@code NaN} or the sum is at any point a {@code NaN} then the
* sum will be {@code NaN}.
*
* @param <T> the type of the input elements
* @param mapper a function extracting the property to be summed
* @return a {@code Collector} that produces the sum of a derived property
*/
public static <T> Collector<T, ?, Double>
summingDouble(ToDoubleFunction<? super T> mapper) {
/*
* In the arrays allocated for the collect operation, index 0
* holds the high-order bits of the running sum, index 1 holds
* the low-order bits of the sum computed via compensated
* summation, and index 2 holds the simple sum used to compute
* the proper result if the stream contains infinite values of
* the same sign.
*/
return new CollectorImpl<>(
() -> new double[3],
(a, t) -> { sumWithCompensation(a, mapper.applyAsDouble(t));
a[2] += mapper.applyAsDouble(t);},
(a, b) -> { sumWithCompensation(a, b[0]);
a[2] += b[2];
return sumWithCompensation(a, b[1]); },
a -> computeFinalSum(a),
CH_NOID);
}
/**
* Returns a {@code Collector} that produces the sum of a double-valued
* function applied to the input elements. If no elements are present,
* the result is 0.
*
* <p>The sum returned can vary depending upon the order in which
* values are recorded, due to accumulated rounding error in
* addition of values of differing magnitudes. Values sorted by increasing
* absolute magnitude tend to yield more accurate results. If any recorded
* value is a {@code NaN} or the sum is at any point a {@code NaN} then the
* sum will be {@code NaN}.
*
* @param <T> the type of the input elements
* @param mapper a function extracting the property to be summed
* @return a {@code Collector} that produces the sum of a derived property
*/
public static <T> Collector<T, ?, Double>
summingDouble(ToDoubleFunction<? super T> mapper) {
/*
* In the arrays allocated for the collect operation, index 0
* holds the high-order bits of the running sum, index 1 holds
* the low-order bits of the sum computed via compensated
* summation, and index 2 holds the simple sum used to compute
* the proper result if the stream contains infinite values of
* the same sign.
*/
return new CollectorImpl<>(
() -> new double[3],
(a, t) -> { sumWithCompensation(a, mapper.applyAsDouble(t));
a[2] += mapper.applyAsDouble(t);},
(a, b) -> { sumWithCompensation(a, b[0]);
a[2] += b[2];
return sumWithCompensation(a, b[1]); },
a -> computeFinalSum(a),
CH_NOID);
}
/**
* Returns a {@code Collector} that produces the sum of a double-valued
* function applied to the input elements. If no elements are present,
* the result is 0.
*
* <p>The sum returned can vary depending upon the order in which
* values are recorded, due to accumulated rounding error in
* addition of values of differing magnitudes. Values sorted by increasing
* absolute magnitude tend to yield more accurate results. If any recorded
* value is a {@code NaN} or the sum is at any point a {@code NaN} then the
* sum will be {@code NaN}.
*
* @param <T> the type of the input elements
* @param mapper a function extracting the property to be summed
* @return a {@code Collector} that produces the sum of a derived property
*/
public static <T> Collector<T, ?, Double>
summingDouble(ToDoubleFunction<? super T> mapper) {
/*
* In the arrays allocated for the collect operation, index 0
* holds the high-order bits of the running sum, index 1 holds
* the low-order bits of the sum computed via compensated
* summation, and index 2 holds the simple sum used to compute
* the proper result if the stream contains infinite values of
* the same sign.
*/
return new CollectorImpl<>(
() -> new double[3],
(a, t) -> { sumWithCompensation(a, mapper.applyAsDouble(t));
a[2] += mapper.applyAsDouble(t);},
(a, b) -> { sumWithCompensation(a, b[0]);
a[2] += b[2];
return sumWithCompensation(a, b[1]); },
a -> computeFinalSum(a),
CH_NOID);
}
@Override
protected <T> io.micrometer.core.instrument.Gauge newGauge(Meter.Id id, @Nullable T obj, ToDoubleFunction<T> valueFunction) {
final WeakReference<T> ref = new WeakReference<>(obj);
Gauge<Double> gauge = () -> {
T obj2 = ref.get();
if (obj2 != null) {
try {
return valueFunction.applyAsDouble(obj2);
} catch (Throwable ex) {
logger.log("Failed to apply the value function for the gauge '" + id.getName() + "'.", ex);
}
}
return nullGaugeValue();
};
registry.register(hierarchicalName(id), gauge);
return new DropwizardGauge(id, gauge);
}
/**
* Returns a {@code Collector} that produces the sum of a double-valued
* function applied to the input elements. If no elements are present,
* the result is 0.
*
* <p>The sum returned can vary depending upon the order in which
* values are recorded, due to accumulated rounding error in
* addition of values of differing magnitudes. Values sorted by increasing
* absolute magnitude tend to yield more accurate results. If any recorded
* value is a {@code NaN} or the sum is at any point a {@code NaN} then the
* sum will be {@code NaN}.
*
* @param <T> the type of the input elements
* @param mapper a function extracting the property to be summed
* @return a {@code Collector} that produces the sum of a derived property
*/
public static <T> Collector<T, ?, Double>
summingDouble(ToDoubleFunction<? super T> mapper) {
/*
* In the arrays allocated for the collect operation, index 0
* holds the high-order bits of the running sum, index 1 holds
* the low-order bits of the sum computed via compensated
* summation, and index 2 holds the simple sum used to compute
* the proper result if the stream contains infinite values of
* the same sign.
*/
return new CollectorImpl<>(
() -> new double[3],
(a, t) -> { sumWithCompensation(a, mapper.applyAsDouble(t));
a[2] += mapper.applyAsDouble(t);},
(a, b) -> { sumWithCompensation(a, b[0]);
a[2] += b[2];
return sumWithCompensation(a, b[1]); },
a -> computeFinalSum(a),
CH_NOID);
}
private double evaluateInstances(final Instances instances) throws DatasetEvaluationFailedException {
ToDoubleFunction<Instances> benchmarkFunction = EvaluationUtils.getBenchmarkFunctionByName(this.evaluationFunctionName);
try {
return benchmarkFunction.applyAsDouble(instances);
} catch (Exception e) {
throw new DatasetEvaluationFailedException("Cannot evaluate instances", e);
}
}
/**
* Update the {@link LoadProfile} and {@link TimeEstimate} of this instance.
*
* @param configuration provides the necessary functions
*/
private void updateCostEstimate(Configuration configuration) {
if (!this.operator.isExecutionOperator()) return;
// Estimate the LoadProfile.
final LoadProfileEstimator loadProfileEstimator = this.getLoadProfileEstimator();
try {
this.loadProfile = LoadProfileEstimators.estimateLoadProfile(this, loadProfileEstimator);
} catch (Exception e) {
throw new RheemException(String.format("Load profile estimation for %s failed.", this.operator), e);
}
// Calculate the TimeEstimate.
final ExecutionOperator executionOperator = (ExecutionOperator) this.operator;
final Platform platform = executionOperator.getPlatform();
final LoadProfileToTimeConverter timeConverter = configuration.getLoadProfileToTimeConverterProvider().provideFor(platform);
this.timeEstimate = TimeEstimate.MINIMUM.plus(timeConverter.convert(this.loadProfile));
if (OptimizationContext.this.logger.isDebugEnabled()) {
OptimizationContext.this.logger.debug(
"Setting time estimate of {} to {}.", this.operator, this.timeEstimate
);
}
// Calculate the cost estimate.
final TimeToCostConverter timeToCostConverter = configuration.getTimeToCostConverterProvider().provideFor(platform);
this.costEstimate = timeToCostConverter.convertWithoutFixCosts(this.timeEstimate);
// Squash the cost estimate.
final ToDoubleFunction<ProbabilisticDoubleInterval> costSquasher = configuration.getCostSquasherProvider().provide();
this.squashedCostEstimate = costSquasher.applyAsDouble(this.costEstimate);
}
/**
* Basic constructor that will always be called and initializes all fields.
*/
private PlanEnumerator(Collection<Operator> startOperators,
OptimizationContext optimizationContext,
OperatorAlternative.Alternative enumeratedAlternative,
Map<OperatorAlternative, OperatorAlternative.Alternative> presettledAlternatives,
Map<ExecutionOperator, ExecutionTask> executedTasks,
Map<OutputSlot<?>, Collection<Channel>> openChannels) {
this.optimizationContext = optimizationContext;
this.enumeratedAlternative = enumeratedAlternative;
this.presettledAlternatives = presettledAlternatives;
this.executedTasks = executedTasks;
this.openChannels = openChannels;
// Set up start Operators.
for (Operator startOperator : startOperators) {
this.scheduleForEnumeration(startOperator, optimizationContext);
}
// Configure the enumeration.
final Configuration configuration = this.optimizationContext.getConfiguration();
this.isEnumeratingBranchesFirst = configuration.getBooleanProperty(
"rheem.core.optimizer.enumeration.branchesfirst", true
);
// Configure the concatenations.
final String priorityFunctionName = configuration.getStringProperty(
"rheem.core.optimizer.enumeration.concatenationprio"
);
ToDoubleFunction<ConcatenationActivator> concatenationPriorityFunction;
switch (priorityFunctionName) {
case "slots":
concatenationPriorityFunction = ConcatenationActivator::countNumOfOpenSlots;
break;
case "plans":
concatenationPriorityFunction = ConcatenationActivator::estimateNumConcatenatedPlanImplementations;
break;
case "plans2":
concatenationPriorityFunction = ConcatenationActivator::estimateNumConcatenatedPlanImplementations2;
break;
case "random":
// Randomly generate a priority. However, avoid re-generate priorities, because that would increase
// of a concatenation activator being processed, the longer it is in the queue (I guess).
concatenationPriorityFunction = activator -> {
if (!Double.isNaN(activator.priority)) return activator.priority;
return Math.random();
};
break;
case "none":
concatenationPriorityFunction = activator -> 0d;
break;
default:
throw new RheemException("Unknown concatenation priority function: " + priorityFunctionName);
}
boolean isInvertConcatenationPriorities = configuration.getBooleanProperty(
"rheem.core.optimizer.enumeration.invertconcatenations", false
);
this.concatenationPriorityFunction = isInvertConcatenationPriorities ?
activator -> -concatenationPriorityFunction.applyAsDouble(activator) :
concatenationPriorityFunction;
}
/**
* Returns a {@code Collector} that produces the arithmetic mean of a double-valued
* function applied to the input elements. If no elements are present,
* the result is 0.
*
* <p>The average returned can vary depending upon the order in which
* values are recorded, due to accumulated rounding error in
* addition of values of differing magnitudes. Values sorted by increasing
* absolute magnitude tend to yield more accurate results. If any recorded
* value is a {@code NaN} or the sum is at any point a {@code NaN} then the
* average will be {@code NaN}.
*
* @implNote The {@code double} format can represent all
* consecutive integers in the range -2<sup>53</sup> to
* 2<sup>53</sup>. If the pipeline has more than 2<sup>53</sup>
* values, the divisor in the average computation will saturate at
* 2<sup>53</sup>, leading to additional numerical errors.
*
* @param <T> the type of the input elements
* @param mapper a function extracting the property to be summed
* @return a {@code Collector} that produces the sum of a derived property
*/
public static <T> Collector<T, ?, Double>
averagingDouble(ToDoubleFunction<? super T> mapper) {
/*
* In the arrays allocated for the collect operation, index 0
* holds the high-order bits of the running sum, index 1 holds
* the low-order bits of the sum computed via compensated
* summation, and index 2 holds the number of values seen.
*/
return new CollectorImpl<>(
() -> new double[4],
(a, t) -> { sumWithCompensation(a, mapper.applyAsDouble(t)); a[2]++; a[3]+= mapper.applyAsDouble(t);},
(a, b) -> { sumWithCompensation(a, b[0]); sumWithCompensation(a, b[1]); a[2] += b[2]; a[3] += b[3]; return a; },
a -> (a[2] == 0) ? 0.0d : (computeFinalSum(a) / a[2]),
CH_NOID);
}
/**
* Returns a {@code Collector} that produces the arithmetic mean of a double-valued
* function applied to the input elements. If no elements are present,
* the result is 0.
*
* <p>The average returned can vary depending upon the order in which
* values are recorded, due to accumulated rounding error in
* addition of values of differing magnitudes. Values sorted by increasing
* absolute magnitude tend to yield more accurate results. If any recorded
* value is a {@code NaN} or the sum is at any point a {@code NaN} then the
* average will be {@code NaN}.
*
* @implNote The {@code double} format can represent all
* consecutive integers in the range -2<sup>53</sup> to
* 2<sup>53</sup>. If the pipeline has more than 2<sup>53</sup>
* values, the divisor in the average computation will saturate at
* 2<sup>53</sup>, leading to additional numerical errors.
*
* @param <T> the type of the input elements
* @param mapper a function extracting the property to be summed
* @return a {@code Collector} that produces the sum of a derived property
*/
public static <T> Collector<T, ?, Double>
averagingDouble(ToDoubleFunction<? super T> mapper) {
/*
* In the arrays allocated for the collect operation, index 0
* holds the high-order bits of the running sum, index 1 holds
* the low-order bits of the sum computed via compensated
* summation, and index 2 holds the number of values seen.
*/
return new CollectorImpl<>(
() -> new double[4],
(a, t) -> { sumWithCompensation(a, mapper.applyAsDouble(t)); a[2]++; a[3]+= mapper.applyAsDouble(t);},
(a, b) -> { sumWithCompensation(a, b[0]); sumWithCompensation(a, b[1]); a[2] += b[2]; a[3] += b[3]; return a; },
a -> (a[2] == 0) ? 0.0d : (computeFinalSum(a) / a[2]),
CH_NOID);
}
/**
* Returns a {@code Collector} that produces the arithmetic mean of a double-valued
* function applied to the input elements. If no elements are present,
* the result is 0.
*
* <p>The average returned can vary depending upon the order in which
* values are recorded, due to accumulated rounding error in
* addition of values of differing magnitudes. Values sorted by increasing
* absolute magnitude tend to yield more accurate results. If any recorded
* value is a {@code NaN} or the sum is at any point a {@code NaN} then the
* average will be {@code NaN}.
*
* @implNote The {@code double} format can represent all
* consecutive integers in the range -2<sup>53</sup> to
* 2<sup>53</sup>. If the pipeline has more than 2<sup>53</sup>
* values, the divisor in the average computation will saturate at
* 2<sup>53</sup>, leading to additional numerical errors.
*
* @param <T> the type of the input elements
* @param mapper a function extracting the property to be summed
* @return a {@code Collector} that produces the sum of a derived property
*/
public static <T> Collector<T, ?, Double>
averagingDouble(ToDoubleFunction<? super T> mapper) {
/*
* In the arrays allocated for the collect operation, index 0
* holds the high-order bits of the running sum, index 1 holds
* the low-order bits of the sum computed via compensated
* summation, and index 2 holds the number of values seen.
*/
return new CollectorImpl<>(
() -> new double[4],
(a, t) -> { sumWithCompensation(a, mapper.applyAsDouble(t)); a[2]++; a[3]+= mapper.applyAsDouble(t);},
(a, b) -> { sumWithCompensation(a, b[0]); sumWithCompensation(a, b[1]); a[2] += b[2]; a[3] += b[3]; return a; },
a -> (a[2] == 0) ? 0.0d : (computeFinalSum(a) / a[2]),
CH_NOID);
}
private void checkIntersects(Bounds3D b, ToDoubleFunction<Vector3D> getter,
BiFunction<Vector3D, Double, Vector3D> setter) {
Vector3D min = b.getMin();
Vector3D max = b.getMax();
double minValue = getter.applyAsDouble(min);
double maxValue = getter.applyAsDouble(max);
double midValue = (0.5 * (maxValue - minValue)) + minValue;
// check all possible interval relationships
// start below minValue
Assert.assertFalse(b.intersects(Bounds3D.from(
setter.apply(min, minValue - 2), setter.apply(max, minValue - 1))));
Assert.assertTrue(b.intersects(Bounds3D.from(
setter.apply(min, minValue - 2), setter.apply(max, minValue))));
Assert.assertTrue(b.intersects(Bounds3D.from(
setter.apply(min, minValue - 2), setter.apply(max, midValue))));
Assert.assertTrue(b.intersects(Bounds3D.from(
setter.apply(min, minValue - 2), setter.apply(max, maxValue))));
Assert.assertTrue(b.intersects(Bounds3D.from(
setter.apply(min, minValue - 2), setter.apply(max, maxValue + 1))));
// start on minValue
Assert.assertTrue(b.intersects(Bounds3D.from(
setter.apply(min, minValue), setter.apply(max, minValue))));
Assert.assertTrue(b.intersects(Bounds3D.from(
setter.apply(min, minValue), setter.apply(max, midValue))));
Assert.assertTrue(b.intersects(Bounds3D.from(
setter.apply(min, minValue), setter.apply(max, maxValue))));
Assert.assertTrue(b.intersects(Bounds3D.from(
setter.apply(min, minValue), setter.apply(max, maxValue + 1))));
// start on midValue
Assert.assertTrue(b.intersects(Bounds3D.from(
setter.apply(min, midValue), setter.apply(max, midValue))));
Assert.assertTrue(b.intersects(Bounds3D.from(
setter.apply(min, midValue), setter.apply(max, maxValue))));
Assert.assertTrue(b.intersects(Bounds3D.from(
setter.apply(min, midValue), setter.apply(max, maxValue + 1))));
// start on maxValue
Assert.assertTrue(b.intersects(Bounds3D.from(
setter.apply(min, maxValue), setter.apply(max, maxValue))));
Assert.assertTrue(b.intersects(Bounds3D.from(
setter.apply(min, maxValue), setter.apply(max, maxValue + 1))));
// start above maxValue
Assert.assertFalse(b.intersects(Bounds3D.from(
setter.apply(min, maxValue + 1), setter.apply(max, maxValue + 2))));
}
private void checkIntersects(Bounds2D b, ToDoubleFunction<Vector2D> getter,
BiFunction<Vector2D, Double, Vector2D> setter) {
Vector2D min = b.getMin();
Vector2D max = b.getMax();
double minValue = getter.applyAsDouble(min);
double maxValue = getter.applyAsDouble(max);
double midValue = (0.5 * (maxValue - minValue)) + minValue;
// check all possible interval relationships
// start below minValue
Assert.assertFalse(b.intersects(Bounds2D.from(
setter.apply(min, minValue - 2), setter.apply(max, minValue - 1))));
Assert.assertTrue(b.intersects(Bounds2D.from(
setter.apply(min, minValue - 2), setter.apply(max, minValue))));
Assert.assertTrue(b.intersects(Bounds2D.from(
setter.apply(min, minValue - 2), setter.apply(max, midValue))));
Assert.assertTrue(b.intersects(Bounds2D.from(
setter.apply(min, minValue - 2), setter.apply(max, maxValue))));
Assert.assertTrue(b.intersects(Bounds2D.from(
setter.apply(min, minValue - 2), setter.apply(max, maxValue + 1))));
// start on minValue
Assert.assertTrue(b.intersects(Bounds2D.from(
setter.apply(min, minValue), setter.apply(max, minValue))));
Assert.assertTrue(b.intersects(Bounds2D.from(
setter.apply(min, minValue), setter.apply(max, midValue))));
Assert.assertTrue(b.intersects(Bounds2D.from(
setter.apply(min, minValue), setter.apply(max, maxValue))));
Assert.assertTrue(b.intersects(Bounds2D.from(
setter.apply(min, minValue), setter.apply(max, maxValue + 1))));
// start on midValue
Assert.assertTrue(b.intersects(Bounds2D.from(
setter.apply(min, midValue), setter.apply(max, midValue))));
Assert.assertTrue(b.intersects(Bounds2D.from(
setter.apply(min, midValue), setter.apply(max, maxValue))));
Assert.assertTrue(b.intersects(Bounds2D.from(
setter.apply(min, midValue), setter.apply(max, maxValue + 1))));
// start on maxValue
Assert.assertTrue(b.intersects(Bounds2D.from(
setter.apply(min, maxValue), setter.apply(max, maxValue))));
Assert.assertTrue(b.intersects(Bounds2D.from(
setter.apply(min, maxValue), setter.apply(max, maxValue + 1))));
// start above maxValue
Assert.assertFalse(b.intersects(Bounds2D.from(
setter.apply(min, maxValue + 1), setter.apply(max, maxValue + 2))));
}
/**
* Returns a {@code Collector} that produces the arithmetic mean of a double-valued
* function applied to the input elements. If no elements are present,
* the result is 0.
*
* <p>The average returned can vary depending upon the order in which
* values are recorded, due to accumulated rounding error in
* addition of values of differing magnitudes. Values sorted by increasing
* absolute magnitude tend to yield more accurate results. If any recorded
* value is a {@code NaN} or the sum is at any point a {@code NaN} then the
* average will be {@code NaN}.
*
* @implNote The {@code double} format can represent all
* consecutive integers in the range -2<sup>53</sup> to
* 2<sup>53</sup>. If the pipeline has more than 2<sup>53</sup>
* values, the divisor in the average computation will saturate at
* 2<sup>53</sup>, leading to additional numerical errors.
*
* @param <T> the type of the input elements
* @param mapper a function extracting the property to be summed
* @return a {@code Collector} that produces the sum of a derived property
*/
public static <T> Collector<T, ?, Double>
averagingDouble(ToDoubleFunction<? super T> mapper) {
/*
* In the arrays allocated for the collect operation, index 0
* holds the high-order bits of the running sum, index 1 holds
* the low-order bits of the sum computed via compensated
* summation, and index 2 holds the number of values seen.
*/
return new CollectorImpl<>(
() -> new double[4],
(a, t) -> { sumWithCompensation(a, mapper.applyAsDouble(t)); a[2]++; a[3]+= mapper.applyAsDouble(t);},
(a, b) -> { sumWithCompensation(a, b[0]); sumWithCompensation(a, b[1]); a[2] += b[2]; a[3] += b[3]; return a; },
a -> (a[2] == 0) ? 0.0d : (computeFinalSum(a) / a[2]),
CH_NOID);
}
@Override
public void evaluate(final ExperimentDBEntry experimentEntry, final IExperimentIntermediateResultProcessor processor) throws ExperimentEvaluationFailedException {
String dataSetFolder = this.config.getDatasetFolder();
if (dataSetFolder == null || !(new File(dataSetFolder).exists())) {
throw new IllegalArgumentException("Data set folder must exist!");
}
Map<String, String> description = experimentEntry.getExperiment().getValuesOfKeyFields();
// Get benchmark function
String benchmark = description.get("benchmark");
ToDoubleFunction<Instances> benchmarkFunction = EvaluationUtils.getBenchmarkFunctionByName(benchmark);
Map<String, Object> results = new HashMap<>();
int seed = Integer.parseInt(description.get("seed"));
String dataSet = description.get("dataset");
// Read prior ranking
try {
List<IKVStore> mlPlanScores = this.adapter.getResultsOfQuery("SELECT score FROM mlplanRanking WHERE seed = " + seed + " and dataset = \"" + dataSet + "\" ORDER BY variation ASC");
// Retrieve prior ranking from data base
double[] priorRanking = new double[MAX_COUNT_VARIATIONS];
for (int i = 0; i < priorRanking.length; i++) {
double varScore = mlPlanScores.get(i).getAsDouble("score");
priorRanking[i] = varScore;
}
if (logger.isDebugEnabled()) {
logger.debug("Prior ranking: {}", Arrays.toString(priorRanking));
}
// Compute score
double[] scores = new double[MAX_COUNT_VARIATIONS];
for (int i = 0; i < priorRanking.length; i++) {
String filePath = dataSetFolder + File.separator + dataSet + "_" + seed + "_" + i + ".arff";
Instances variation = FileUtils.readSingleInstances(filePath);
scores[i] = benchmarkFunction.applyAsDouble(variation);
}
// Calculate Kendall's Tau result
double kendallsTau = EvaluationUtils.rankKendallsTau(priorRanking, scores);
results.put("kendallsTau", kendallsTau);
results.put("benchmarkRanking", Arrays.toString(scores));
results.put("mlplanRanking", Arrays.toString(priorRanking));
processor.processResults(results);
} catch (Exception e) {
throw new ExperimentEvaluationFailedException(e);
}
}
/**
* Returns a {@code Collector} that produces the arithmetic mean of a double-valued
* function applied to the input elements. If no elements are present,
* the result is 0.
*
* <p>The average returned can vary depending upon the order in which
* values are recorded, due to accumulated rounding error in
* addition of values of differing magnitudes. Values sorted by increasing
* absolute magnitude tend to yield more accurate results. If any recorded
* value is a {@code NaN} or the sum is at any point a {@code NaN} then the
* average will be {@code NaN}.
*
* @implNote The {@code double} format can represent all
* consecutive integers in the range -2<sup>53</sup> to
* 2<sup>53</sup>. If the pipeline has more than 2<sup>53</sup>
* values, the divisor in the average computation will saturate at
* 2<sup>53</sup>, leading to additional numerical errors.
*
* @param <T> the type of the input elements
* @param mapper a function extracting the property to be summed
* @return a {@code Collector} that produces the sum of a derived property
*/
public static <T> Collector<T, ?, Double>
averagingDouble(ToDoubleFunction<? super T> mapper) {
/*
* In the arrays allocated for the collect operation, index 0
* holds the high-order bits of the running sum, index 1 holds
* the low-order bits of the sum computed via compensated
* summation, and index 2 holds the number of values seen.
*/
return new CollectorImpl<>(
() -> new double[4],
(a, t) -> { sumWithCompensation(a, mapper.applyAsDouble(t)); a[2]++; a[3]+= mapper.applyAsDouble(t);},
(a, b) -> { sumWithCompensation(a, b[0]); sumWithCompensation(a, b[1]); a[2] += b[2]; a[3] += b[3]; return a; },
a -> (a[2] == 0) ? 0.0d : (computeFinalSum(a) / a[2]),
CH_NOID);
}
private double getTwtValue(boolean bool, TwtData twtData, ToDoubleFunction<TwtData> f) {
return bool ? f.applyAsDouble(twtData) : Double.NaN;
}
/**
* Update the fitness of this instance.
*
* @param fitnessFunction calculates the fitness for this instance
* @return the new fitness
*/
public double updateFitness(ToDoubleFunction<Individual> fitnessFunction) {
return this.fitness = fitnessFunction.applyAsDouble(this);
}