• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 The Guava Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.common.math;
18 
19 import static com.google.common.math.StatsTesting.ALLOWED_ERROR;
20 import static com.google.common.math.StatsTesting.ALL_MANY_VALUES;
21 import static com.google.common.math.StatsTesting.ALL_PAIRED_STATS;
22 import static com.google.common.math.StatsTesting.CONSTANT_VALUES_PAIRED_STATS;
23 import static com.google.common.math.StatsTesting.DUPLICATE_MANY_VALUES_PAIRED_STATS;
24 import static com.google.common.math.StatsTesting.EMPTY_PAIRED_STATS;
25 import static com.google.common.math.StatsTesting.EMPTY_STATS_ITERABLE;
26 import static com.google.common.math.StatsTesting.HORIZONTAL_VALUES_PAIRED_STATS;
27 import static com.google.common.math.StatsTesting.MANY_VALUES;
28 import static com.google.common.math.StatsTesting.MANY_VALUES_COUNT;
29 import static com.google.common.math.StatsTesting.MANY_VALUES_PAIRED_STATS;
30 import static com.google.common.math.StatsTesting.MANY_VALUES_STATS_ITERABLE;
31 import static com.google.common.math.StatsTesting.MANY_VALUES_STATS_VARARGS;
32 import static com.google.common.math.StatsTesting.MANY_VALUES_SUM_OF_PRODUCTS_OF_DELTAS;
33 import static com.google.common.math.StatsTesting.ONE_VALUE_PAIRED_STATS;
34 import static com.google.common.math.StatsTesting.ONE_VALUE_STATS;
35 import static com.google.common.math.StatsTesting.OTHER_MANY_VALUES;
36 import static com.google.common.math.StatsTesting.OTHER_MANY_VALUES_STATS;
37 import static com.google.common.math.StatsTesting.OTHER_ONE_VALUE_STATS;
38 import static com.google.common.math.StatsTesting.OTHER_TWO_VALUES_STATS;
39 import static com.google.common.math.StatsTesting.TWO_VALUES_PAIRED_STATS;
40 import static com.google.common.math.StatsTesting.TWO_VALUES_STATS;
41 import static com.google.common.math.StatsTesting.TWO_VALUES_SUM_OF_PRODUCTS_OF_DELTAS;
42 import static com.google.common.math.StatsTesting.VERTICAL_VALUES_PAIRED_STATS;
43 import static com.google.common.math.StatsTesting.assertDiagonalLinearTransformation;
44 import static com.google.common.math.StatsTesting.assertHorizontalLinearTransformation;
45 import static com.google.common.math.StatsTesting.assertLinearTransformationNaN;
46 import static com.google.common.math.StatsTesting.assertStatsApproxEqual;
47 import static com.google.common.math.StatsTesting.assertVerticalLinearTransformation;
48 import static com.google.common.math.StatsTesting.createPairedStatsOf;
49 import static com.google.common.truth.Truth.assertThat;
50 import static com.google.common.truth.Truth.assertWithMessage;
51 
52 import com.google.common.collect.ImmutableList;
53 import com.google.common.math.StatsTesting.ManyValues;
54 import com.google.common.testing.EqualsTester;
55 import com.google.common.testing.SerializableTester;
56 import java.nio.ByteBuffer;
57 import java.nio.ByteOrder;
58 import junit.framework.TestCase;
59 
60 /**
61  * Tests for {@link PairedStats}. This tests instances created by {@link
62  * PairedStatsAccumulator#snapshot}.
63  *
64  * @author Pete Gillin
65  */
66 public class PairedStatsTest extends TestCase {
67 
testCount()68   public void testCount() {
69     assertThat(EMPTY_PAIRED_STATS.count()).isEqualTo(0);
70     assertThat(ONE_VALUE_PAIRED_STATS.count()).isEqualTo(1);
71     assertThat(TWO_VALUES_PAIRED_STATS.count()).isEqualTo(2);
72     assertThat(MANY_VALUES_PAIRED_STATS.count()).isEqualTo(MANY_VALUES_COUNT);
73   }
74 
testXStats()75   public void testXStats() {
76     assertStatsApproxEqual(EMPTY_STATS_ITERABLE, EMPTY_PAIRED_STATS.xStats());
77     assertStatsApproxEqual(ONE_VALUE_STATS, ONE_VALUE_PAIRED_STATS.xStats());
78     assertStatsApproxEqual(TWO_VALUES_STATS, TWO_VALUES_PAIRED_STATS.xStats());
79     assertStatsApproxEqual(MANY_VALUES_STATS_ITERABLE, MANY_VALUES_PAIRED_STATS.xStats());
80   }
81 
testYStats()82   public void testYStats() {
83     assertStatsApproxEqual(EMPTY_STATS_ITERABLE, EMPTY_PAIRED_STATS.yStats());
84     assertStatsApproxEqual(OTHER_ONE_VALUE_STATS, ONE_VALUE_PAIRED_STATS.yStats());
85     assertStatsApproxEqual(OTHER_TWO_VALUES_STATS, TWO_VALUES_PAIRED_STATS.yStats());
86     assertStatsApproxEqual(OTHER_MANY_VALUES_STATS, MANY_VALUES_PAIRED_STATS.yStats());
87   }
88 
testPopulationCovariance()89   public void testPopulationCovariance() {
90     try {
91       EMPTY_PAIRED_STATS.populationCovariance();
92       fail("Expected IllegalStateException");
93     } catch (IllegalStateException expected) {
94     }
95     assertThat(ONE_VALUE_PAIRED_STATS.populationCovariance()).isWithin(0.0).of(0.0);
96     assertThat(createSingleStats(Double.POSITIVE_INFINITY, 1.23).populationCovariance()).isNaN();
97     assertThat(createSingleStats(Double.NEGATIVE_INFINITY, 1.23).populationCovariance()).isNaN();
98     assertThat(createSingleStats(Double.NaN, 1.23).populationCovariance()).isNaN();
99     assertThat(TWO_VALUES_PAIRED_STATS.populationCovariance())
100         .isWithin(ALLOWED_ERROR)
101         .of(TWO_VALUES_SUM_OF_PRODUCTS_OF_DELTAS / 2);
102     // For datasets of many double values, we test many combinations of finite and non-finite
103     // x-values:
104     for (ManyValues values : ALL_MANY_VALUES) {
105       PairedStats stats = createPairedStatsOf(values.asIterable(), OTHER_MANY_VALUES);
106       double populationCovariance = stats.populationCovariance();
107       if (values.hasAnyNonFinite()) {
108         assertWithMessage("population covariance of " + values).that(populationCovariance).isNaN();
109       } else {
110         assertWithMessage("population covariance of " + values)
111             .that(populationCovariance)
112             .isWithin(ALLOWED_ERROR)
113             .of(MANY_VALUES_SUM_OF_PRODUCTS_OF_DELTAS / MANY_VALUES_COUNT);
114       }
115     }
116     assertThat(HORIZONTAL_VALUES_PAIRED_STATS.populationCovariance())
117         .isWithin(ALLOWED_ERROR)
118         .of(0.0);
119     assertThat(VERTICAL_VALUES_PAIRED_STATS.populationCovariance()).isWithin(ALLOWED_ERROR).of(0.0);
120     assertThat(CONSTANT_VALUES_PAIRED_STATS.populationCovariance()).isWithin(ALLOWED_ERROR).of(0.0);
121   }
122 
testSampleCovariance()123   public void testSampleCovariance() {
124     try {
125       EMPTY_PAIRED_STATS.sampleCovariance();
126       fail("Expected IllegalStateException");
127     } catch (IllegalStateException expected) {
128     }
129     try {
130       ONE_VALUE_PAIRED_STATS.sampleCovariance();
131       fail("Expected IllegalStateException");
132     } catch (IllegalStateException expected) {
133     }
134     assertThat(TWO_VALUES_PAIRED_STATS.sampleCovariance())
135         .isWithin(ALLOWED_ERROR)
136         .of(TWO_VALUES_SUM_OF_PRODUCTS_OF_DELTAS);
137     assertThat(MANY_VALUES_PAIRED_STATS.sampleCovariance())
138         .isWithin(ALLOWED_ERROR)
139         .of(MANY_VALUES_SUM_OF_PRODUCTS_OF_DELTAS / (MANY_VALUES_COUNT - 1));
140     assertThat(HORIZONTAL_VALUES_PAIRED_STATS.sampleCovariance()).isWithin(ALLOWED_ERROR).of(0.0);
141     assertThat(VERTICAL_VALUES_PAIRED_STATS.sampleCovariance()).isWithin(ALLOWED_ERROR).of(0.0);
142     assertThat(CONSTANT_VALUES_PAIRED_STATS.sampleCovariance()).isWithin(ALLOWED_ERROR).of(0.0);
143   }
144 
testPearsonsCorrelationCoefficient()145   public void testPearsonsCorrelationCoefficient() {
146     try {
147       EMPTY_PAIRED_STATS.pearsonsCorrelationCoefficient();
148       fail("Expected IllegalStateException");
149     } catch (IllegalStateException expected) {
150     }
151     try {
152       ONE_VALUE_PAIRED_STATS.pearsonsCorrelationCoefficient();
153       fail("Expected IllegalStateException");
154     } catch (IllegalStateException expected) {
155     }
156     try {
157       createSingleStats(Double.POSITIVE_INFINITY, 1.23).pearsonsCorrelationCoefficient();
158       fail("Expected IllegalStateException");
159     } catch (IllegalStateException expected) {
160     }
161     assertThat(TWO_VALUES_PAIRED_STATS.pearsonsCorrelationCoefficient())
162         .isWithin(ALLOWED_ERROR)
163         .of(
164             TWO_VALUES_PAIRED_STATS.populationCovariance()
165                 / (TWO_VALUES_PAIRED_STATS.xStats().populationStandardDeviation()
166                     * TWO_VALUES_PAIRED_STATS.yStats().populationStandardDeviation()));
167     // For datasets of many double values, we test many combinations of finite and non-finite
168     // y-values:
169     for (ManyValues values : ALL_MANY_VALUES) {
170       PairedStats stats = createPairedStatsOf(MANY_VALUES, values.asIterable());
171       double pearsonsCorrelationCoefficient = stats.pearsonsCorrelationCoefficient();
172       if (values.hasAnyNonFinite()) {
173         assertWithMessage("Pearson's correlation coefficient of " + values)
174             .that(pearsonsCorrelationCoefficient)
175             .isNaN();
176       } else {
177         assertWithMessage("Pearson's correlation coefficient of " + values)
178             .that(pearsonsCorrelationCoefficient)
179             .isWithin(ALLOWED_ERROR)
180             .of(
181                 stats.populationCovariance()
182                     / (stats.xStats().populationStandardDeviation()
183                         * stats.yStats().populationStandardDeviation()));
184       }
185     }
186     try {
187       HORIZONTAL_VALUES_PAIRED_STATS.pearsonsCorrelationCoefficient();
188       fail("Expected IllegalStateException");
189     } catch (IllegalStateException expected) {
190     }
191     try {
192       VERTICAL_VALUES_PAIRED_STATS.pearsonsCorrelationCoefficient();
193       fail("Expected IllegalStateException");
194     } catch (IllegalStateException expected) {
195     }
196     try {
197       CONSTANT_VALUES_PAIRED_STATS.pearsonsCorrelationCoefficient();
198       fail("Expected IllegalStateException");
199     } catch (IllegalStateException expected) {
200     }
201   }
202 
testLeastSquaresFit()203   public void testLeastSquaresFit() {
204     try {
205       EMPTY_PAIRED_STATS.leastSquaresFit();
206       fail("Expected IllegalStateException");
207     } catch (IllegalStateException expected) {
208     }
209     try {
210       ONE_VALUE_PAIRED_STATS.leastSquaresFit();
211       fail("Expected IllegalStateException");
212     } catch (IllegalStateException expected) {
213     }
214     try {
215       createSingleStats(Double.POSITIVE_INFINITY, 1.23).leastSquaresFit();
216       fail("Expected IllegalStateException");
217     } catch (IllegalStateException expected) {
218     }
219     assertDiagonalLinearTransformation(
220         TWO_VALUES_PAIRED_STATS.leastSquaresFit(),
221         TWO_VALUES_PAIRED_STATS.xStats().mean(),
222         TWO_VALUES_PAIRED_STATS.yStats().mean(),
223         TWO_VALUES_PAIRED_STATS.xStats().populationVariance(),
224         TWO_VALUES_PAIRED_STATS.populationCovariance());
225     // For datasets of many double values, we test many combinations of finite and non-finite
226     // x-values:
227     for (ManyValues values : ALL_MANY_VALUES) {
228       PairedStats stats = createPairedStatsOf(values.asIterable(), OTHER_MANY_VALUES);
229       LinearTransformation fit = stats.leastSquaresFit();
230       if (values.hasAnyNonFinite()) {
231         assertLinearTransformationNaN(fit);
232       } else {
233         assertDiagonalLinearTransformation(
234             fit,
235             stats.xStats().mean(),
236             stats.yStats().mean(),
237             stats.xStats().populationVariance(),
238             stats.populationCovariance());
239       }
240     }
241     assertHorizontalLinearTransformation(
242         HORIZONTAL_VALUES_PAIRED_STATS.leastSquaresFit(),
243         HORIZONTAL_VALUES_PAIRED_STATS.yStats().mean());
244     assertVerticalLinearTransformation(
245         VERTICAL_VALUES_PAIRED_STATS.leastSquaresFit(),
246         VERTICAL_VALUES_PAIRED_STATS.xStats().mean());
247     try {
248       CONSTANT_VALUES_PAIRED_STATS.leastSquaresFit();
249       fail("Expected IllegalStateException");
250     } catch (IllegalStateException expected) {
251     }
252   }
253 
testEqualsAndHashCode()254   public void testEqualsAndHashCode() {
255     new EqualsTester()
256         .addEqualityGroup(
257             MANY_VALUES_PAIRED_STATS,
258             DUPLICATE_MANY_VALUES_PAIRED_STATS,
259             SerializableTester.reserialize(MANY_VALUES_PAIRED_STATS))
260         .addEqualityGroup(
261             new PairedStats(MANY_VALUES_STATS_ITERABLE, OTHER_MANY_VALUES_STATS, 1.23),
262             new PairedStats(MANY_VALUES_STATS_VARARGS, OTHER_MANY_VALUES_STATS, 1.23))
263         .addEqualityGroup(
264             new PairedStats(OTHER_MANY_VALUES_STATS, MANY_VALUES_STATS_ITERABLE, 1.23))
265         .addEqualityGroup(
266             new PairedStats(MANY_VALUES_STATS_ITERABLE, MANY_VALUES_STATS_ITERABLE, 1.23))
267         .addEqualityGroup(new PairedStats(TWO_VALUES_STATS, MANY_VALUES_STATS_ITERABLE, 1.23))
268         .addEqualityGroup(new PairedStats(MANY_VALUES_STATS_ITERABLE, ONE_VALUE_STATS, 1.23))
269         .addEqualityGroup(
270             new PairedStats(MANY_VALUES_STATS_ITERABLE, MANY_VALUES_STATS_ITERABLE, 1.234))
271         .testEquals();
272   }
273 
testSerializable()274   public void testSerializable() {
275     SerializableTester.reserializeAndAssert(MANY_VALUES_PAIRED_STATS);
276   }
277 
testToString()278   public void testToString() {
279     assertThat(EMPTY_PAIRED_STATS.toString())
280         .isEqualTo("PairedStats{xStats=Stats{count=0}, yStats=Stats{count=0}}");
281     assertThat(MANY_VALUES_PAIRED_STATS.toString())
282         .isEqualTo(
283             "PairedStats{xStats="
284                 + MANY_VALUES_PAIRED_STATS.xStats()
285                 + ", yStats="
286                 + MANY_VALUES_PAIRED_STATS.yStats()
287                 + ", populationCovariance="
288                 + MANY_VALUES_PAIRED_STATS.populationCovariance()
289                 + "}");
290   }
291 
createSingleStats(double x, double y)292   private PairedStats createSingleStats(double x, double y) {
293     return createPairedStatsOf(ImmutableList.of(x), ImmutableList.of(y));
294   }
295 
testToByteArrayAndFromByteArrayRoundTrip()296   public void testToByteArrayAndFromByteArrayRoundTrip() {
297     for (PairedStats pairedStats : ALL_PAIRED_STATS) {
298       byte[] pairedStatsByteArray = pairedStats.toByteArray();
299 
300       // Round trip to byte array and back
301       assertThat(PairedStats.fromByteArray(pairedStatsByteArray)).isEqualTo(pairedStats);
302     }
303   }
304 
testFromByteArray_withNullInputThrowsNullPointerException()305   public void testFromByteArray_withNullInputThrowsNullPointerException() {
306     try {
307       PairedStats.fromByteArray(null);
308       fail("Expected NullPointerException");
309     } catch (NullPointerException expected) {
310     }
311   }
312 
testFromByteArray_withEmptyArrayInputThrowsIllegalArgumentException()313   public void testFromByteArray_withEmptyArrayInputThrowsIllegalArgumentException() {
314     try {
315       PairedStats.fromByteArray(new byte[0]);
316       fail("Expected IllegalArgumentException");
317     } catch (IllegalArgumentException expected) {
318     }
319   }
320 
testFromByteArray_withTooLongArrayInputThrowsIllegalArgumentException()321   public void testFromByteArray_withTooLongArrayInputThrowsIllegalArgumentException() {
322     byte[] buffer = MANY_VALUES_PAIRED_STATS.toByteArray();
323     byte[] tooLongByteArray =
324         ByteBuffer.allocate(buffer.length + 2)
325             .order(ByteOrder.LITTLE_ENDIAN)
326             .put(buffer)
327             .putChar('.')
328             .array();
329     try {
330       PairedStats.fromByteArray(tooLongByteArray);
331       fail("Expected IllegalArgumentException");
332     } catch (IllegalArgumentException expected) {
333     }
334   }
335 
testFromByteArrayWithTooShortArrayInputThrowsIllegalArgumentException()336   public void testFromByteArrayWithTooShortArrayInputThrowsIllegalArgumentException() {
337     byte[] buffer = MANY_VALUES_PAIRED_STATS.toByteArray();
338     byte[] tooShortByteArray =
339         ByteBuffer.allocate(buffer.length - 1)
340             .order(ByteOrder.LITTLE_ENDIAN)
341             .put(buffer, 0, buffer.length - 1)
342             .array();
343     try {
344       PairedStats.fromByteArray(tooShortByteArray);
345       fail("Expected IllegalArgumentException");
346     } catch (IllegalArgumentException expected) {
347     }
348   }
349 }
350