• 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 
51 import com.google.common.collect.ImmutableList;
52 import com.google.common.math.StatsTesting.ManyValues;
53 import com.google.common.testing.EqualsTester;
54 import com.google.common.testing.SerializableTester;
55 import java.nio.ByteBuffer;
56 import java.nio.ByteOrder;
57 import junit.framework.TestCase;
58 
59 /**
60  * Tests for {@link PairedStats}. This tests instances created by {@link
61  * PairedStatsAccumulator#snapshot}.
62  *
63  * @author Pete Gillin
64  */
65 public class PairedStatsTest extends TestCase {
66 
testCount()67   public void testCount() {
68     assertThat(EMPTY_PAIRED_STATS.count()).isEqualTo(0);
69     assertThat(ONE_VALUE_PAIRED_STATS.count()).isEqualTo(1);
70     assertThat(TWO_VALUES_PAIRED_STATS.count()).isEqualTo(2);
71     assertThat(MANY_VALUES_PAIRED_STATS.count()).isEqualTo(MANY_VALUES_COUNT);
72   }
73 
testXStats()74   public void testXStats() {
75     assertStatsApproxEqual(EMPTY_STATS_ITERABLE, EMPTY_PAIRED_STATS.xStats());
76     assertStatsApproxEqual(ONE_VALUE_STATS, ONE_VALUE_PAIRED_STATS.xStats());
77     assertStatsApproxEqual(TWO_VALUES_STATS, TWO_VALUES_PAIRED_STATS.xStats());
78     assertStatsApproxEqual(MANY_VALUES_STATS_ITERABLE, MANY_VALUES_PAIRED_STATS.xStats());
79   }
80 
testYStats()81   public void testYStats() {
82     assertStatsApproxEqual(EMPTY_STATS_ITERABLE, EMPTY_PAIRED_STATS.yStats());
83     assertStatsApproxEqual(OTHER_ONE_VALUE_STATS, ONE_VALUE_PAIRED_STATS.yStats());
84     assertStatsApproxEqual(OTHER_TWO_VALUES_STATS, TWO_VALUES_PAIRED_STATS.yStats());
85     assertStatsApproxEqual(OTHER_MANY_VALUES_STATS, MANY_VALUES_PAIRED_STATS.yStats());
86   }
87 
testPopulationCovariance()88   public void testPopulationCovariance() {
89     try {
90       EMPTY_PAIRED_STATS.populationCovariance();
91       fail("Expected IllegalStateException");
92     } catch (IllegalStateException expected) {
93     }
94     assertThat(ONE_VALUE_PAIRED_STATS.populationCovariance()).isWithin(0.0).of(0.0);
95     assertThat(createSingleStats(Double.POSITIVE_INFINITY, 1.23).populationCovariance()).isNaN();
96     assertThat(createSingleStats(Double.NEGATIVE_INFINITY, 1.23).populationCovariance()).isNaN();
97     assertThat(createSingleStats(Double.NaN, 1.23).populationCovariance()).isNaN();
98     assertThat(TWO_VALUES_PAIRED_STATS.populationCovariance())
99         .isWithin(ALLOWED_ERROR)
100         .of(TWO_VALUES_SUM_OF_PRODUCTS_OF_DELTAS / 2);
101     // For datasets of many double values, we test many combinations of finite and non-finite
102     // x-values:
103     for (ManyValues values : ALL_MANY_VALUES) {
104       PairedStats stats = createPairedStatsOf(values.asIterable(), OTHER_MANY_VALUES);
105       double populationCovariance = stats.populationCovariance();
106       if (values.hasAnyNonFinite()) {
107         assertThat(populationCovariance).named("population covariance of " + values).isNaN();
108       } else {
109         assertThat(populationCovariance)
110             .named("population covariance of " + values)
111             .isWithin(ALLOWED_ERROR)
112             .of(MANY_VALUES_SUM_OF_PRODUCTS_OF_DELTAS / MANY_VALUES_COUNT);
113       }
114     }
115     assertThat(HORIZONTAL_VALUES_PAIRED_STATS.populationCovariance())
116         .isWithin(ALLOWED_ERROR)
117         .of(0.0);
118     assertThat(VERTICAL_VALUES_PAIRED_STATS.populationCovariance()).isWithin(ALLOWED_ERROR).of(0.0);
119     assertThat(CONSTANT_VALUES_PAIRED_STATS.populationCovariance()).isWithin(ALLOWED_ERROR).of(0.0);
120   }
121 
testSampleCovariance()122   public void testSampleCovariance() {
123     try {
124       EMPTY_PAIRED_STATS.sampleCovariance();
125       fail("Expected IllegalStateException");
126     } catch (IllegalStateException expected) {
127     }
128     try {
129       ONE_VALUE_PAIRED_STATS.sampleCovariance();
130       fail("Expected IllegalStateException");
131     } catch (IllegalStateException expected) {
132     }
133     assertThat(TWO_VALUES_PAIRED_STATS.sampleCovariance())
134         .isWithin(ALLOWED_ERROR)
135         .of(TWO_VALUES_SUM_OF_PRODUCTS_OF_DELTAS);
136     assertThat(MANY_VALUES_PAIRED_STATS.sampleCovariance())
137         .isWithin(ALLOWED_ERROR)
138         .of(MANY_VALUES_SUM_OF_PRODUCTS_OF_DELTAS / (MANY_VALUES_COUNT - 1));
139     assertThat(HORIZONTAL_VALUES_PAIRED_STATS.sampleCovariance()).isWithin(ALLOWED_ERROR).of(0.0);
140     assertThat(VERTICAL_VALUES_PAIRED_STATS.sampleCovariance()).isWithin(ALLOWED_ERROR).of(0.0);
141     assertThat(CONSTANT_VALUES_PAIRED_STATS.sampleCovariance()).isWithin(ALLOWED_ERROR).of(0.0);
142   }
143 
testPearsonsCorrelationCoefficient()144   public void testPearsonsCorrelationCoefficient() {
145     try {
146       EMPTY_PAIRED_STATS.pearsonsCorrelationCoefficient();
147       fail("Expected IllegalStateException");
148     } catch (IllegalStateException expected) {
149     }
150     try {
151       ONE_VALUE_PAIRED_STATS.pearsonsCorrelationCoefficient();
152       fail("Expected IllegalStateException");
153     } catch (IllegalStateException expected) {
154     }
155     try {
156       createSingleStats(Double.POSITIVE_INFINITY, 1.23).pearsonsCorrelationCoefficient();
157       fail("Expected IllegalStateException");
158     } catch (IllegalStateException expected) {
159     }
160     assertThat(TWO_VALUES_PAIRED_STATS.pearsonsCorrelationCoefficient())
161         .isWithin(ALLOWED_ERROR)
162         .of(
163             TWO_VALUES_PAIRED_STATS.populationCovariance()
164                 / (TWO_VALUES_PAIRED_STATS.xStats().populationStandardDeviation()
165                     * TWO_VALUES_PAIRED_STATS.yStats().populationStandardDeviation()));
166     // For datasets of many double values, we test many combinations of finite and non-finite
167     // y-values:
168     for (ManyValues values : ALL_MANY_VALUES) {
169       PairedStats stats = createPairedStatsOf(MANY_VALUES, values.asIterable());
170       double pearsonsCorrelationCoefficient = stats.pearsonsCorrelationCoefficient();
171       if (values.hasAnyNonFinite()) {
172         assertThat(pearsonsCorrelationCoefficient)
173             .named("Pearson's correlation coefficient of " + values)
174             .isNaN();
175       } else {
176         assertThat(pearsonsCorrelationCoefficient)
177             .named("Pearson's correlation coefficient of " + values)
178             .isWithin(ALLOWED_ERROR)
179             .of(
180                 stats.populationCovariance()
181                     / (stats.xStats().populationStandardDeviation()
182                         * stats.yStats().populationStandardDeviation()));
183       }
184     }
185     try {
186       HORIZONTAL_VALUES_PAIRED_STATS.pearsonsCorrelationCoefficient();
187       fail("Expected IllegalStateException");
188     } catch (IllegalStateException expected) {
189     }
190     try {
191       VERTICAL_VALUES_PAIRED_STATS.pearsonsCorrelationCoefficient();
192       fail("Expected IllegalStateException");
193     } catch (IllegalStateException expected) {
194     }
195     try {
196       CONSTANT_VALUES_PAIRED_STATS.pearsonsCorrelationCoefficient();
197       fail("Expected IllegalStateException");
198     } catch (IllegalStateException expected) {
199     }
200   }
201 
testLeastSquaresFit()202   public void testLeastSquaresFit() {
203     try {
204       EMPTY_PAIRED_STATS.leastSquaresFit();
205       fail("Expected IllegalStateException");
206     } catch (IllegalStateException expected) {
207     }
208     try {
209       ONE_VALUE_PAIRED_STATS.leastSquaresFit();
210       fail("Expected IllegalStateException");
211     } catch (IllegalStateException expected) {
212     }
213     try {
214       createSingleStats(Double.POSITIVE_INFINITY, 1.23).leastSquaresFit();
215       fail("Expected IllegalStateException");
216     } catch (IllegalStateException expected) {
217     }
218     assertDiagonalLinearTransformation(
219         TWO_VALUES_PAIRED_STATS.leastSquaresFit(),
220         TWO_VALUES_PAIRED_STATS.xStats().mean(),
221         TWO_VALUES_PAIRED_STATS.yStats().mean(),
222         TWO_VALUES_PAIRED_STATS.xStats().populationVariance(),
223         TWO_VALUES_PAIRED_STATS.populationCovariance());
224     // For datasets of many double values, we test many combinations of finite and non-finite
225     // x-values:
226     for (ManyValues values : ALL_MANY_VALUES) {
227       PairedStats stats = createPairedStatsOf(values.asIterable(), OTHER_MANY_VALUES);
228       LinearTransformation fit = stats.leastSquaresFit();
229       if (values.hasAnyNonFinite()) {
230         assertLinearTransformationNaN(fit);
231       } else {
232         assertDiagonalLinearTransformation(
233             fit,
234             stats.xStats().mean(),
235             stats.yStats().mean(),
236             stats.xStats().populationVariance(),
237             stats.populationCovariance());
238       }
239     }
240     assertHorizontalLinearTransformation(
241         HORIZONTAL_VALUES_PAIRED_STATS.leastSquaresFit(),
242         HORIZONTAL_VALUES_PAIRED_STATS.yStats().mean());
243     assertVerticalLinearTransformation(
244         VERTICAL_VALUES_PAIRED_STATS.leastSquaresFit(),
245         VERTICAL_VALUES_PAIRED_STATS.xStats().mean());
246     try {
247       CONSTANT_VALUES_PAIRED_STATS.leastSquaresFit();
248       fail("Expected IllegalStateException");
249     } catch (IllegalStateException expected) {
250     }
251   }
252 
testEqualsAndHashCode()253   public void testEqualsAndHashCode() {
254     new EqualsTester()
255         .addEqualityGroup(
256             MANY_VALUES_PAIRED_STATS,
257             DUPLICATE_MANY_VALUES_PAIRED_STATS,
258             SerializableTester.reserialize(MANY_VALUES_PAIRED_STATS))
259         .addEqualityGroup(
260             new PairedStats(MANY_VALUES_STATS_ITERABLE, OTHER_MANY_VALUES_STATS, 1.23),
261             new PairedStats(MANY_VALUES_STATS_VARARGS, OTHER_MANY_VALUES_STATS, 1.23))
262         .addEqualityGroup(
263             new PairedStats(OTHER_MANY_VALUES_STATS, MANY_VALUES_STATS_ITERABLE, 1.23))
264         .addEqualityGroup(
265             new PairedStats(MANY_VALUES_STATS_ITERABLE, MANY_VALUES_STATS_ITERABLE, 1.23))
266         .addEqualityGroup(new PairedStats(TWO_VALUES_STATS, MANY_VALUES_STATS_ITERABLE, 1.23))
267         .addEqualityGroup(new PairedStats(MANY_VALUES_STATS_ITERABLE, ONE_VALUE_STATS, 1.23))
268         .addEqualityGroup(
269             new PairedStats(MANY_VALUES_STATS_ITERABLE, MANY_VALUES_STATS_ITERABLE, 1.234))
270         .testEquals();
271   }
272 
testSerializable()273   public void testSerializable() {
274     SerializableTester.reserializeAndAssert(MANY_VALUES_PAIRED_STATS);
275   }
276 
testToString()277   public void testToString() {
278     assertThat(EMPTY_PAIRED_STATS.toString())
279         .isEqualTo("PairedStats{xStats=Stats{count=0}, yStats=Stats{count=0}}");
280     assertThat(MANY_VALUES_PAIRED_STATS.toString())
281         .isEqualTo(
282             "PairedStats{xStats="
283                 + MANY_VALUES_PAIRED_STATS.xStats()
284                 + ", yStats="
285                 + MANY_VALUES_PAIRED_STATS.yStats()
286                 + ", populationCovariance="
287                 + MANY_VALUES_PAIRED_STATS.populationCovariance()
288                 + "}");
289   }
290 
createSingleStats(double x, double y)291   private PairedStats createSingleStats(double x, double y) {
292     return createPairedStatsOf(ImmutableList.of(x), ImmutableList.of(y));
293   }
294 
testToByteArrayAndFromByteArrayRoundTrip()295   public void testToByteArrayAndFromByteArrayRoundTrip() {
296     for (PairedStats pairedStats : ALL_PAIRED_STATS) {
297       byte[] pairedStatsByteArray = pairedStats.toByteArray();
298 
299       // Round trip to byte array and back
300       assertThat(PairedStats.fromByteArray(pairedStatsByteArray)).isEqualTo(pairedStats);
301     }
302   }
303 
testFromByteArray_withNullInputThrowsNullPointerException()304   public void testFromByteArray_withNullInputThrowsNullPointerException() {
305     try {
306       PairedStats.fromByteArray(null);
307       fail("Expected NullPointerException");
308     } catch (NullPointerException expected) {
309     }
310   }
311 
testFromByteArray_withEmptyArrayInputThrowsIllegalArgumentException()312   public void testFromByteArray_withEmptyArrayInputThrowsIllegalArgumentException() {
313     try {
314       PairedStats.fromByteArray(new byte[0]);
315       fail("Expected IllegalArgumentException");
316     } catch (IllegalArgumentException expected) {
317     }
318   }
319 
testFromByteArray_withTooLongArrayInputThrowsIllegalArgumentException()320   public void testFromByteArray_withTooLongArrayInputThrowsIllegalArgumentException() {
321     byte[] buffer = MANY_VALUES_PAIRED_STATS.toByteArray();
322     byte[] tooLongByteArray =
323         ByteBuffer.allocate(buffer.length + 2)
324             .order(ByteOrder.LITTLE_ENDIAN)
325             .put(buffer)
326             .putChar('.')
327             .array();
328     try {
329       PairedStats.fromByteArray(tooLongByteArray);
330       fail("Expected IllegalArgumentException");
331     } catch (IllegalArgumentException expected) {
332     }
333   }
334 
testFromByteArrayWithTooShortArrayInputThrowsIllegalArgumentException()335   public void testFromByteArrayWithTooShortArrayInputThrowsIllegalArgumentException() {
336     byte[] buffer = MANY_VALUES_PAIRED_STATS.toByteArray();
337     byte[] tooShortByteArray =
338         ByteBuffer.allocate(buffer.length - 1)
339             .order(ByteOrder.LITTLE_ENDIAN)
340             .put(buffer, 0, buffer.length - 1)
341             .array();
342     try {
343       PairedStats.fromByteArray(tooShortByteArray);
344       fail("Expected IllegalArgumentException");
345     } catch (IllegalArgumentException expected) {
346     }
347   }
348 }
349