Skip to content

Commit

Permalink
feat: only compute std dev on components that output values
Browse files Browse the repository at this point in the history
Fixes #94
  • Loading branch information
metacosm committed Jul 9, 2024
1 parent ef55607 commit cc59f1a
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 8 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package net.laprun.sustainability.power.measure;

import java.time.Duration;
import java.util.stream.IntStream;
import java.util.HashSet;
import java.util.Set;

import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;

Expand All @@ -13,6 +14,7 @@ public class OngoingPowerMeasure implements PowerMeasure {
private final DescriptiveStatistics total;
private final long startedAt;
private final double[] averages;
private final Set<Integer> nonZeroComponents;
private double minTotal = Double.MAX_VALUE;
private double maxTotal;
private int samples;
Expand All @@ -25,10 +27,12 @@ public OngoingPowerMeasure(SensorMetadata sensorMetadata, Duration duration, Dur

final var initialWindow = (int) (duration.toMillis() / frequency.toMillis());
total = new DescriptiveStatistics(initialWindow);
this.measures = new DescriptiveStatistics[sensorMetadata.componentCardinality()];
this.measures = new DescriptiveStatistics[numComponents];
for (int i = 0; i < measures.length; i++) {
measures[i] = new DescriptiveStatistics(initialWindow);
}

nonZeroComponents = new HashSet<>(numComponents);
}

@Override
Expand All @@ -46,6 +50,10 @@ public void recordMeasure(double[] components) {
samples++;
for (int component = 0; component < components.length; component++) {
final var componentValue = components[component];
// record that the value is not zero
if (componentValue != 0) {
nonZeroComponents.add(component);
}
measures[component].addValue(componentValue);
averages[component] = averages[component] == 0 ? componentValue
: (previousSize * averages[component] + componentValue) / samples;
Expand Down Expand Up @@ -89,7 +97,7 @@ public double[] averagesPerComponent() {
public StdDev standardDeviations() {
final var cardinality = sensorMetadata.componentCardinality();
final var stdDevs = new double[cardinality];
IntStream.range(0, cardinality)
nonZeroComponents.stream()
.parallel()
.forEach(component -> stdDevs[component] = measures[component].getStandardDeviation());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,34 +15,40 @@ public class OngoingPowerMeasureTest {
void testStatistics() {
final var m1c1 = 10.0;
final var m1c2 = 12.0;
final var m1c3 = 0.0;
final var m2c1 = 8.0;
final var m2c2 = 17.0;
final var m2c3 = 0.0;
final var metadata = new SensorMetadata(Map.of(), null, new int[0]) {

@Override
public int componentCardinality() {
return 2;
return 3;
}
};
final var measure = new OngoingPowerMeasure(metadata, Duration.ofSeconds(1), Duration.ofMillis(500));

final var components = new double[metadata.componentCardinality()];
components[0] = m1c1;
components[1] = m1c2;
components[2] = m1c3;
measure.recordMeasure(components);

components[0] = m2c1;
components[1] = m2c2;
components[2] = m2c3;
measure.recordMeasure(components);

assertEquals(m1c1 + m1c2 + m2c1 + m2c2, measure.total());
assertEquals((m1c1 + m1c2 + m2c1 + m2c2) / 2, measure.average());
assertEquals(Math.min(m1c1 + m1c2, m2c1 + m2c2), measure.minMeasuredTotal());
assertEquals(Math.max(m1c1 + m1c2, m2c1 + m2c2), measure.maxMeasuredTotal());
assertEquals(m1c1 + m1c2 + m2c1 + m2c2 + m1c3 + m2c3, measure.total());
assertEquals((m1c1 + m1c2 + m2c1 + m2c2 + m1c3 + m2c3) / 2, measure.average());
assertEquals(Math.min(m1c1 + m1c2 + m1c3, m2c1 + m2c2 + m2c3), measure.minMeasuredTotal());
assertEquals(Math.max(m1c1 + m1c2 + m1c3, m2c1 + m2c2 + m2c3), measure.maxMeasuredTotal());
final var c1Avg = measure.averagesPerComponent()[0];
final var c2Avg = measure.averagesPerComponent()[1];
final var c3Avg = measure.averagesPerComponent()[2];
assertEquals((m1c1 + m2c1) / 2, c1Avg);
assertEquals((m1c2 + m2c2) / 2, c2Avg);
assertEquals(0, c3Avg);

final var stdVarForC1 = Math.sqrt((Math.pow(m1c1 - c1Avg, 2) + Math.pow(m2c1 - c1Avg, 2)) / (2 - 1));
final var stdVarForC2 = Math.sqrt((Math.pow(m1c2 - c2Avg, 2) + Math.pow(m2c2 - c2Avg, 2)) / (2 - 1));
Expand All @@ -51,5 +57,7 @@ public int componentCardinality() {
"Standard Deviation did not match the expected value");
assertEquals(stdVarForC2, measure.standardDeviations().perComponent()[1], 0.0001,
"Standard Deviation did not match the expected value");
assertEquals(0, measure.standardDeviations().perComponent()[2], 0.0001,
"Standard Deviation did not match the expected value");
}
}

0 comments on commit cc59f1a

Please sign in to comment.