001    /*
002    Galois, a framework to exploit amorphous data-parallelism in irregular
003    programs.
004    
005    Copyright (C) 2010, The University of Texas at Austin. All rights reserved.
006    UNIVERSITY EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES CONCERNING THIS SOFTWARE
007    AND DOCUMENTATION, INCLUDING ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR ANY
008    PARTICULAR PURPOSE, NON-INFRINGEMENT AND WARRANTIES OF PERFORMANCE, AND ANY
009    WARRANTY THAT MIGHT OTHERWISE ARISE FROM COURSE OF DEALING OR USAGE OF TRADE.
010    NO WARRANTY IS EITHER EXPRESS OR IMPLIED WITH RESPECT TO THE USE OF THE
011    SOFTWARE OR DOCUMENTATION. Under no circumstances shall University be liable
012    for incidental, special, indirect, direct or consequential damages or loss of
013    profits, interruption of business, or related expenses which may arise from use
014    of Software or Documentation, including but not limited to those resulting from
015    defects in Software and/or Documentation, or loss or inaccuracy of data of any
016    kind.
017    
018    File: Statistics.java 
019    
020     */
021    
022    package util;
023    
024    import java.io.PrintStream;
025    import java.util.ArrayList;
026    import java.util.Collection;
027    import java.util.Collections;
028    import java.util.List;
029    
030    import util.fn.FnIterable;
031    import util.fn.Lambda;
032    
033    /**
034     * Abstract class for encapsulating statistics collected by the
035     * runtime system.
036     * 
037     *
038     */
039    public abstract class Statistics {
040      /**
041       * Prints a summary of the statistics. The output should be short and,
042       * in most cases, at most one line long.
043       * 
044       * @param out output stream
045       */
046      public abstract void dumpSummary(PrintStream out);
047    
048      /**
049       * Prints the full results for the statistics.
050       * 
051       * @param out output stream
052       */
053      public abstract void dumpFull(PrintStream out);
054    
055      /**
056       * Merge two of the same type of statistics together. Used to aggregate
057       * statistics together.
058       * 
059       * @param other another statistics object of the same type to be merged with
060       */
061      public abstract void merge(Object other);
062    
063      /**
064       * Prints out appropriately formatted header for {@link #dumpFull(PrintStream)} output.
065       * 
066       * @param out    output stream
067       * @param header header to print
068       */
069      protected final void printFullHeader(PrintStream out, String header) {
070        out.printf("==== %s ====\n", header);
071      }
072    
073      /**
074       * Prints out appropriately formatted for {@link #dumpSummary(PrintStream)} output.
075       * 
076       * @param out
077       * @param header
078       */
079      protected final void printSummaryHeader(PrintStream out, String header) {
080        out.printf("%s: ", header);
081      }
082    
083      /**
084       * Prints out mean, min, max, and stdev of a collection of integers.
085       * 
086       * @param out    output stream
087       * @param list   collection of integers
088       * @param prefix string to prefix the output
089       */
090      protected final void summarizeInts(PrintStream out, Collection<Integer> list, String prefix) {
091        summarizeInts(out, list, 0, prefix);
092      }
093    
094      /**
095       * Prints out mean, min, max, and stdev of a collection of integers.
096       * 
097       * @param out    output stream
098       * @param list   collection of integers
099       * @param drop   exclude the first <code>drop</code> integers from the output
100       * @param prefix string to prefix the output
101       */
102      protected final void summarizeInts(PrintStream out, Collection<Integer> list, int drop, String prefix) {
103        float[] stats = summarizeInts(list, drop);
104        if (stats == null) {
105          return;
106        }
107    
108        if (stats[4] != list.size()) {
109          prefix = String.format("%sDrop first %.0f: ", prefix, list.size() - stats[4]);
110        }
111    
112        out.printf("%smean: %.2f min: %.0f max: %.0f stdev: %.2f\n", prefix, stats[0], stats[1], stats[2], Math
113            .sqrt(stats[3]));
114      }
115    
116      /**
117       * Returns mean, min, max, and variance of a collection of integers. This method
118       * takes a drop parameter that drops the first <i>N</i> integers before computing
119       * the summary statistics.
120       * 
121       * @param list collection of integers
122       * @param drop exclude the first <code>drop</code> integers from the results
123       * @return     an array of {mean, min, max, variance, number of dropped integers}
124       */
125      protected final float[] summarizeInts(Collection<Integer> list, int drop) {
126        if (list.isEmpty()) {
127          return null;
128        }
129    
130        if (list.size() <= 1 + drop) {
131          drop = 0;
132        }
133    
134        List<Integer> retain = new ArrayList<Integer>(list).subList(drop, list.size());
135        final float mean = CollectionMath.sumInteger(retain) / (float) retain.size();
136        int min = Collections.min(retain);
137        int max = Collections.max(retain);
138    
139        float var = CollectionMath.sumFloat(FnIterable.from(retain).map(new Lambda<Integer, Float>() {
140          @Override
141          public Float call(Integer x) {
142            return (x - mean) * (x - mean);
143          }
144        })) / (retain.size() - 1);
145    
146        float[] retval = new float[] { mean, min, max, var, retain.size() };
147    
148        return retval;
149      }
150    
151      /**
152       * Prints out mean, min, max, and stdev of a collection of longs.
153       * 
154       * @param out    output stream
155       * @param list   collection of longs
156       * @param prefix string to prefix the output
157       */
158      protected final void summarizeLongs(PrintStream out, Collection<Long> list, String prefix) {
159        summarizeLongs(out, list, 0, prefix);
160      }
161    
162      /**
163       * Prints out mean, min, max, and stdev of a collection of longs.
164       * 
165       * @param out    output stream
166       * @param list   collection of longs
167       * @param drop   exclude the first <code>drop</code> longs from the output
168       * @param prefix string to prefix the output
169       */
170      protected final void summarizeLongs(PrintStream out, Collection<Long> list, int drop, String prefix) {
171        summarizeLongs(out, list, drop, prefix, false);
172      }
173    
174      /**
175       * Prints out mean, min, max, and stdev of a collection of longs.
176       * 
177       * @param out     output stream
178       * @param list    collection of longs
179       * @param drop    exclude the first <code>drop</code> longs from the output
180       * @param prefix  string to prefix the output
181       * @param newLine suppress trailing newline
182       */
183      protected final void summarizeLongs(PrintStream out, Collection<Long> list, int drop, String prefix,
184          boolean suppressNewline) {
185        float[] stats = summarizeLongs(list, drop);
186        if (stats == null) {
187          return;
188        }
189    
190        if (stats[4] != list.size()) {
191          prefix = String.format("%sDrop first %.0f: ", prefix, list.size() - stats[4]);
192        }
193    
194        out.printf("%smean: %.2f min: %.0f max: %.0f stdev: %.2f", prefix, stats[0], stats[1], stats[2], Math
195            .sqrt(stats[3]));
196    
197        if (!suppressNewline)
198          out.println();
199      }
200    
201      /**
202       * Returns mean, min, max, and variance of a collection of longs. This method
203       * takes a drop parameter that drops the first <i>N</i> longs before computing
204       * the summary statistics.
205       * 
206       * @param list collection of longs
207       * @param drop exclude the first <code>drop</code> longs from the results
208       * @return     an array of {mean, min, max, variance, number of dropped longs}
209       */
210      protected final float[] summarizeLongs(Collection<Long> list, int drop) {
211        if (list.isEmpty()) {
212          return null;
213        }
214    
215        if (list.size() <= 1 + drop) {
216          drop = 0;
217        }
218    
219        List<Long> retain = new ArrayList<Long>(list).subList(drop, list.size());
220        final float mean = CollectionMath.sumLong(retain) / (float) retain.size();
221        long min = Collections.min(retain);
222        long max = Collections.max(retain);
223    
224        float var = CollectionMath.sumFloat(FnIterable.from(retain).map(new Lambda<Long, Float>() {
225          @Override
226          public Float call(Long x) {
227            return (x - mean) * (x - mean);
228          }
229        })) / (retain.size() - 1);
230    
231        float[] retval = new float[5];
232        retval[0] = mean;
233        retval[1] = min;
234        retval[2] = max;
235        retval[3] = var;
236        retval[4] = retain.size();
237    
238        return retval;
239      }
240    
241      /**
242       * Prints out mean, min, max, and stdev of a collection of floats.
243       * 
244       * @param out    output stream
245       * @param list   collection of floats
246       * @param prefix string to prefix the output
247       */
248      protected final void summarizeFloats(PrintStream out, Collection<Float> list, String prefix) {
249        summarizeFloats(out, list, 0, prefix);
250      }
251    
252      /**
253       * Prints out mean, min, max, and stdev of a collection of floats.
254       * 
255       * @param out    output stream
256       * @param list   collection of floats
257       * @param drop   exclude the first <code>drop</code> floats from the output
258       * @param prefix string to prefix the output
259       */
260      protected final void summarizeFloats(PrintStream out, Collection<Float> list, int drop, String prefix) {
261        float[] stats = summarizeFloats(list, drop);
262        if (stats == null) {
263          return;
264        }
265    
266        if (stats[4] != list.size()) {
267          prefix = String.format("%sDrop first %d: ", prefix, list.size() - stats[4]);
268        }
269    
270        out.printf("%smean: %.4f min: %.4f max: %.4f stdev: %.3f\n", prefix, stats[0], stats[1], stats[2], Math
271            .sqrt(stats[3]));
272      }
273    
274      /**
275       * Returns mean, min, max, and variance of a collection of floats. This method
276       * takes a drop parameter that drops the first <i>N</i> floats before computing
277       * the summary statistics.
278       * 
279       * @param list collection of floats
280       * @param drop exclude the first <code>drop</code> floats from the results
281       * @return     an array of {mean, min, max, variance, number of dropped floats}
282       */
283      protected final float[] summarizeFloats(Collection<Float> list, int drop) {
284        if (list.isEmpty()) {
285          return null;
286        }
287    
288        if (list.size() <= 1 + drop) {
289          drop = 0;
290        }
291    
292        List<Float> retain = new ArrayList<Float>(list).subList(drop, list.size());
293        final float mean = CollectionMath.sumFloat(retain) / (float) retain.size();
294        float min = Collections.min(retain);
295        float max = Collections.max(retain);
296    
297        float var = CollectionMath.sumFloat(FnIterable.from(retain).map(new Lambda<Float, Float>() {
298          @Override
299          public Float call(Float x) {
300            return (x - mean) * (x - mean);
301          }
302        })) / (retain.size() - 1);
303    
304        float[] retval = new float[5];
305        retval[0] = mean;
306        retval[1] = min;
307        retval[2] = max;
308        retval[3] = var;
309        retval[4] = retain.size();
310    
311        return retval;
312      }
313    }