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

umontreal.iro.lecuyer.stat.list.ListOfTalliesWithCovariance 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:        ListOfTalliesWithCovariance
 * Description:  List of tallies with covariance
 * 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.stat.Tally;
import umontreal.iro.lecuyer.stat.TallyStore;
import java.util.logging.Level;
import java.util.logging.Logger;
import cern.colt.matrix.DoubleMatrix1D;



/**
 * Extends {@link ListOfTallies} to add support for the computation
 * of the sample covariance between each pair of elements
 * in a list, without storing all observations.
 * This list of tallies contains internal structures to keep track of
 * 
 * bar(X)n, i for 
 * i = 0,…, d - 1, and
 * 
 * k=0n-1(Xi, k - bar(X)k, i)(Xj, k - bar(X)k, j)/n, for
 * 
 * i = 0,…, d - 2 and 
 * j = 1,…, d - 1, with j > i.
 * Here, 
 * bar(X)n, i is the ith component of 
 * bar(X)n, the average vector,
 * and 
 * bar(X)0, i = 0 for 
 * i = 0,…, d - 1.
 * The value Xi, k corresponds to the ith component of the kth observation
 * Xk.
 * These sums are updated every time a vector is added to this list, and
 * are used to estimate the covariances.
 * 
 * 

* Note: the size of the list of tallies must remain fixed because of the * data structures used for computing sample covariances. * As a result, the first call to init makes this list * unmodifiable. * *

* Note: for the sample covariance to be computed between a pair * of tallies, the number of observations in each tally * should be the same. It is therefore recommended to always * add complete vectors of observations to this list. * Moreover, one must use * the {@link #add add} method in this class to add vectors of observations for * the sums used for covariance estimation to be updated correctly. * Failure to use this method, e.g., adding observations * to each individual tally in the list, will result in an incorrect * estimate of the covariances, unless the tallies * in the list can store observations. * For example, the following code, which adds the vector v in * the list of tallies list, works correctly only if the list * contains instances of {@link TallyStore}: * *

* * for (int i = 0; i < v.length; i++) *
      list.get (i).add (v[i]); *
*
* But the following code is always correct: * *
* * list.add (v); *
*
* */ public class ListOfTalliesWithCovariance extends ListOfTallies { private double[] tempArray; private double[][] sxy; // Determines if we use a numerically stable covariance // formula. private boolean isStable = true; // The average of the first observations, for each tally private double[] curAverages; // The sum (xi - average)(yi - average) of the first observations private double[][] curSum2; private Logger log = Logger.getLogger ("umontreal.iro.lecuyer.stat.list"); /** * Creates an empty list of tallies with covariance support. * One must fill the list with tallies, and call {@link #init init} before * adding any observation. * */ public ListOfTalliesWithCovariance() { super(); } /** * Creates an empty list of tallies with covariance * support and name name. * One must fill the list with tallies, and call {@link #init init} before * adding any observation. * * @param name the name of the new list. * * */ public ListOfTalliesWithCovariance (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 ListOfTalliesWithCovariance createWithTally (int size) { ListOfTalliesWithCovariance list = new ListOfTalliesWithCovariance(); for (int i = 0; i < size; i++) list.add (new Tally()); list.init(); 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 ListOfTalliesWithCovariance createWithTallyStore (int size) { ListOfTalliesWithCovariance list = new ListOfTalliesWithCovariance(); for (int i = 0; i < size; i++) list.add (new TallyStore()); list.init(); return list; } private void createSxy() { int l = size(); if (isStable) { curAverages = new double[l]; curSum2 = new double[l-1][]; for (int i = 0; i < l - 1; i++) curSum2[i] = new double[l - 1 - i]; } else { sxy = new double[l - 1][]; for (int i = 0; i < l - 1; i++) sxy[i] = new double[l - 1 - i]; } tempArray = new double[l]; } public void init() { super.init(); if (isModifiable()) { setUnmodifiable(); createSxy(); } if (isStable) { for (int i = 0; i < curAverages.length; i++) curAverages[i] = 0; for (int i = 0; i < curSum2.length; i++) for (int j = 0; j < curSum2[i].length; j++) curSum2[i][j] = 0; } else for (int i = 0; i < sxy.length; i++) for (int j = 0; j < sxy[i].length; j++) sxy[i][j] = 0; } /** * Adds a new vector of observations x to this * list of tallies, and updates the internal data structures computing * averages, and sums of products. * One must use this method instead of adding observations to * individual tallies to get a covariance estimate. * * @param x the new vector of observations. * * */ public void add (double[] x) { int l = size(); int structSize = 0; structSize = (isStable) ? curSum2.length : sxy.length; if (structSize != l - 1) throw new IllegalArgumentException ("The structure's size mismatches the list's size"); super.add (x); if (isStable) { int numObs = get (0).numberObs(); // get (i1).average() would return the average over the n // observations, but we need the average over the last n-1 observations. for (int i1 = 0; i1 < l - 1; i1++) for (int i2 = i1 + 1; i2 < l; i2++) curSum2[i1][i2 - i1 - 1] += (numObs - 1)* (x[i1] - curAverages[i1])*(x[i2] - curAverages[i2])/numObs; for (int i = 0; i < l; i++) curAverages[i] += (x[i] - curAverages[i])/numObs; // Now, curAverages[i] == get (i).average() } else for (int i1 = 0; i1 < l - 1; i1++) for (int i2 = i1 + 1; i2 < l; i2++) sxy[i1][i2 - i1 - 1] += x[i1]*x[i2]; } public void add (DoubleMatrix1D x) { x.toArray (tempArray); add (tempArray); } public double covariance (int i, int j) { if (i == j) return get (i).variance(); if (i > j) { // Make sure that i1 < i2, to have a single case int tmp = i; i = j; j = tmp; } Tally tallyi = get (i); Tally tallyj = get (j); if (tallyi == null || tallyj == null) return Double.NaN; int n = tallyi.numberObs(); if (n != tallyj.numberObs()) { log.logp (Level.WARNING, "ListOfTalliesWithCovariance", "covariance", "Tally " + i + ", with name " + tallyi.getName() + ", contains " + n + " observations while " + "tally " + j + ", with name " + tallyj.getName() + ", contains " + tallyj.numberObs() + "observations"); return Double.NaN; } if (n < 2) { log.logp (Level.WARNING, "ListOfTalliesWithCovariance", "covariance", "Tally " + i + ", with name " + tallyi.getName() + ", contains " + n + " observation"); return Double.NaN; } if (tallyi instanceof TallyStore && tallyj instanceof TallyStore) return ((TallyStore) tallyi).covariance ((TallyStore) tallyj); else if (isStable) return curSum2[i][j - i - 1]/(n-1); else { double sum1 = tallyi.sum(); double sum2 = tallyj.sum(); double sum12 = sxy[i][j - i - 1]; return (sum12 - sum1*sum2/n)/(n-1); } } /** * Clones this object. * This clones the list of tallies and the data structures holding the sums of products but * not the tallies comprising the list. * The created clone is modifiable, even though the original list is unmodifiable. * */ public ListOfTalliesWithCovariance clone() { ListOfTalliesWithCovariance ta = (ListOfTalliesWithCovariance)super.clone(); ta.tempArray = new double[size()]; if (curAverages != null) ta.curAverages = curAverages.clone(); if (sxy != null) { ta.sxy = new double[sxy.length][]; for (int i = 0; i < sxy.length; i++) ta.sxy[i] = sxy[i].clone(); } if (curSum2 != null) { ta.curSum2 = new double[curSum2.length][]; for (int i = 0; i < curSum2.length; i++) ta.curSum2[i] = curSum2[i].clone(); } return ta; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy