All Downloads are FREE. Search and download functionalities are using the official Maven repository.

umontreal.iro.lecuyer.stat.list.ListOfTallies Maven / Gradle / Ivy

Go to download

SSJ is a Java library for stochastic simulation, developed under the direction of Pierre L'Ecuyer, in the Département d'Informatique et de Recherche Opérationnelle (DIRO), at the Université de Montréal. It provides facilities for generating uniform and nonuniform random variates, computing different measures related to probability distributions, performing goodness-of-fit tests, applying quasi-Monte Carlo methods, collecting (elementary) statistics, and programming discrete-event simulations with both events and processes.

The newest version!


/*
 * Class:        ListOfTallies
 * Description:  List of statistical collectors.
 * Environment:  Java
 * Software:     SSJ 
 * Copyright (C) 2001  Pierre L'Ecuyer and Université de Montréal
 * Organization: DIRO, Université de Montréal
 * @author       Éric Buist 
 * @since        2007

 * SSJ is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License (GPL) as published by the
 * Free Software Foundation, either version 3 of the License, or
 * any later version.

 * SSJ is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * A copy of the GNU General Public License is available at
   GPL licence site.
 */

package umontreal.iro.lecuyer.stat.list;

import umontreal.iro.lecuyer.util.PrintfFormat;
import cern.colt.list.DoubleArrayList;
import cern.colt.matrix.DoubleMatrix1D;
import cern.colt.matrix.DoubleMatrix2D;

import umontreal.iro.lecuyer.stat.Tally;
import umontreal.iro.lecuyer.stat.TallyStore;



/**
 * Represents a list of tally statistical collectors.
 * Each element of the list is an instance of {@link umontreal.iro.lecuyer.stat.Tally Tally},
 * and a vector of observations can be added with
 * the {@link #add((double[])) add} method.
 * This class defines factory methods to fill a newly-constructed list
 * with Tally or TallyStore instances.
 * 
 */
public class ListOfTallies extends ListOfStatProbes {



   /**
    * Constructs a new empty list of tallies.
    * 
    */
   public ListOfTallies() {
      super();
   }


   /**
    * Constructs a new empty list of tallies with name name.
    * 
    * @param name the name of the new list.
    * 
    * 
    */
   public ListOfTallies (String name) {
      super (name);
   }


   /**
    * This factory method constructs and returns a list of tallies with size instances of
    *    {@link Tally}.
    * 
    * @param size the size of the list.
    * 
    *    @return the created list.
    * 
    */
   public static ListOfTallies createWithTally (int size) {
      ListOfTallies list = new ListOfTallies();
      for (int i = 0; i < size; i++)
         list.add (new Tally());
      return list;
   }


   /**
    * This factory method constructs and returns a list of tallies with size instances of
    *    {@link TallyStore}.
    * 
    * @param size the size of the list.
    * 
    *    @return the created list.
    * 
    */
   public static ListOfTallies createWithTallyStore (int size) {
      ListOfTallies list = new ListOfTallies();
      for (int i = 0; i < size; i++)
         list.add (new TallyStore());
      return list;
   }


   /**
    * Adds the observation x[i] in
    *  tally i of this list, for i = 0,..., size() - 1.
    *  No observation is added if the value is Double.NaN,
    *  or if collecting is turned OFF.
    *  If broadcasting is ON, the given array is notified
    *  to all registered observers.
    *  The given array x not being stored by this object,
    *  it can be freely used and modified after the call to this method.
    * 
    * @param x the array of observations.
    * 
    *    @exception NullPointerException if x is null.
    * 
    *    @exception IllegalArgumentException if the length of
    *     x does not correspond to size().
    * 
    * 
    */
   public void add (double[] x) {
      int l = size();
      if (x.length != l)
         throw new IllegalArgumentException
            ("Incompatible array length: given " +
            x.length + ", required " + l);
      if (collect)
         for (int i = 0; i < l; i++) {
            double v = x[i];
            Tally ta = get (i);
            if (!Double.isNaN (v) && ta != null)
               ta.add (v);
         }
         notifyListeners (x);
   }


   /**
    * Assuming that each tally in this list contains
    *  the same number of observations, returns
    *  the number of observations in tally 0, or
    *   0 if this list is empty.
    * 
    * @return the number of observations.
    * 
    */
   public int numberObs() {
      if (size() == 0)
         return 0;
      Tally t0 = get (0);
      return t0 == null ? 0 : t0.numberObs();
   }


   /**
    * Tests that every tally in this list contains the
    *  same number of observations.
    *  This returns true if and only if all
    *  tallies have the same number of observations, or if this list is empty.
    *  If observations are always added using the
    *  {@link #add((double[])) add} method from this class, and not
    *  {@link umontreal.iro.lecuyer.stat.Tally#add((double)) add} from
    *    {@link Tally}, this method always  returns true.
    * 
    * @return the success indicator of the test.
    * 
    */
   public boolean areAllNumberObsEqual() {
      final int l = size();
      int n = numberObs();
      for (int i = 1; i < l; i++) {
         Tally t = get (i);
         if (t.numberObs() != n)
            return false;
      }
      return true;
   }


   /**
    * Computes the average for each tally
    *  in this list, and stores the averages in the array r.
    *  If the tally i has no observation,
    *  the Double.NaN value is stored
    *  in the array, at index i.
    * 
    */
   public void average (double[] r) {
      final int l = size();
      for (int i = 0; i < l; i++) {
          // Manual check to avoid repetitive logs when all tallies
          // have 0 observation.
         Tally ta = get (i);
         double v = ta == null || ta.numberObs() == 0 ? Double.NaN : ta.average();
         r[i] = v;
      }
   }


   /**
    * For each tally in this list, computes
    *  the sample variance, and stores the variances into the array v.
    *  If, for some tally i, there are not enough
    *  observations for estimating the variance,
    *  Double.NaN is stored in the array.
    * 
    * @param v the array to be filled with sample variances.
    * 
    *    @exception NullPointerException if v is null.
    * 
    *    @exception IllegalArgumentException if v.length
    *     does not correspond to {@link umontreal.iro.lecuyer.stat.list.ListOfStatProbes#size(()) size}.
    * 
    * 
    */
   public void variance (double[] v) {
      if (size() != v.length)
         throw new IllegalArgumentException
            ("Invalid length of given array");
      for (int i = 0; i < v.length; i++) {
         Tally tally = get (i);
         if (tally == null || tally.numberObs() < 2)
            v[i] = Double.NaN;
         else
            v[i] = tally.variance();
      }
   }


   /**
    * For each tally in this list, computes
    *  the sample standard deviation, and stores the standard deviations
    *  into the array std.
    *  This is equivalent to calling {@link #variance((double[])) variance} and
    *  performing a square root on every element
    *  of the filled array.
    * 
    * @param std the array to be filled with standard deviations.
    * 
    *    @exception NullPointerException if std is null.
    * 
    *    @exception IllegalArgumentException if std.length
    *     does not correspond to size().
    * 
    * 
    */
   public void standardDeviation (double[] std) {
      if (size() != std.length)
         throw new IllegalArgumentException
            ("Invalid length of given array");
      for (int i = 0; i < std.length; i++) {
         Tally tally = get (i);
         if (tally == null || tally.numberObs() < 2)
            std[i] = Double.NaN;
         else
            std[i] = tally.standardDeviation();
      }
   }


   /**
    * Returns the empirical covariance of the observations in tallies
    *  with indices i and j.  If 
    * x1,…, xn represent the
    *  observations in tally i whereas 
    * y1,…, yn represent the
    *  observations in tally j, then the covariance is given by
    *  
    * 

*
* SX, Y = $\displaystyle {\frac{{1}}{{n-1}}}$k=1n(xk - bar(X)n)(yk - bar(Y)n) = [tex2html_wrap_indisplay273](∑k=1nxkyk - $\displaystyle {\frac{{1}}{{n}}}$k=1nxkr=1nyr). *

* This returns Double.NaN * if the tallies do not contain the same number of observations, or * if they contain less than two observations. * This method throws an exception if the * underlying tallies are not capable of storing * observations, i.e. if the tallies are not TallyStores. * The {@link ListOfTalliesWithCovariance} * subclass provides an alternative implementation * of this method which does not require the * observations to be stored. * * @param i the index of the first tally. * * @param j the index of the second tally. * * @return the value of the covariance. * @exception ArrayIndexOutOfBoundsException if one or both * indices are out of bounds. * * */ public double covariance (int i, int j) { if (i == j) return get (i).variance(); TallyStore tallyi = (TallyStore)get (i); TallyStore tallyj = (TallyStore)get (j); return tallyi.covariance (tallyj); } /** * Returns the empirical correlation between * the observations in tallies with indices i and j. * If the tally i contains a sample of the random * variate X and the tally j contains a sample of Y, * this corresponds to * *

*
* Cor(X, Y) = Cov(X, Y)/((X)(Y))1/2. *

* *

* This method uses {@link #covariance((int, int)) covariance} * to obtain an estimate of the covariance, and * {@link umontreal.iro.lecuyer.stat.Tally#variance(()) variance} in * class {@link Tally} to obtain the sample variances. * * @param i the index of the first tally. * * @param j the index of the second tally. * * @return the value of the correlation. * @exception ArrayIndexOutOfBoundsException if one or both * indices are out of bounds. * * */ public double correlation (int i, int j) { if (i == j) return 1.0; double cov = covariance (i, j); Tally tallyi = get (i); Tally tallyj = get (j); if (tallyi == null || tallyj == null) return Double.NaN; return cov/Math.sqrt (tallyi.variance()*tallyj.variance()); } /** * Constructs and returns the sample covariance matrix * for the tallies in this list. The given d×d matrix c, * where d = size(), * is filled with the computed sample covariances. * Element c.get (i, j) corresponds to * the result of * covariance (i, j). * * @param c the matrix to be filled with the sample covariances. * * @exception NullPointerException if c is null. * * @exception IllegalArgumentException if the number of rows or columns * in c does not correspond to size(). * * */ public void covariance (DoubleMatrix2D c) { int l = size(); if (c.rows() != l) throw new IllegalArgumentException ("Invalid number of rows in covariance matrix"); if (c.columns() != l) throw new IllegalArgumentException ("Invalid number of columns in covariance matrix"); for (int i1 = 0; i1 < l; i1++) c.setQuick (i1, i1, get (i1).variance()); for (int i1 = 0; i1 < l - 1; i1++) for (int i2 = i1 + 1; i2 < l; i2++) { double cov = covariance (i1, i2); c.setQuick (i1, i2, cov); c.setQuick (i2, i1, cov); } } /** * Similar to {@link #covariance((DoubleMatrix2D)) covariance} for computing * the sample correlation matrix. * * @param c the matrix to be filled with the correlations. * * @exception NullPointerException if c is null. * * @exception IllegalArgumentException if the number of rows or columns in c * does not correspond to {@link umontreal.iro.lecuyer.stat.list.ListOfStatProbes#size(()) size}. * * */ public void correlation (DoubleMatrix2D c) { int l = size(); if (c.rows() != l) throw new IllegalArgumentException ("Invalid number of rows in correlation matrix"); if (c.columns() != l) throw new IllegalArgumentException ("Invalid number of columns in correlation matrix"); for (int i1 = 0; i1 < l; i1++) c.setQuick (i1, i1, 1.0); for (int i1 = 0; i1 < l - 1; i1++) for (int i2 = i1 + 1; i2 < l; i2++) { double cor = correlation (i1, i2); c.setQuick (i1, i2, cor); c.setQuick (i2, i1, cor); } } /** * Clones this object. This makes a shallow copy * of this list, i.e., this does not clone all the tallies in the list. * The created clone is modifiable, even if the original list is unmodifiable. * */ public ListOfTallies clone() { return (ListOfTallies)super.clone(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy