📄 empiricaldistributionimpl.java
字号:
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package org.apache.commons.math.random;import java.io.EOFException;import java.io.Serializable;import java.io.BufferedReader;import java.io.FileReader;import java.io.File;import java.io.IOException;import java.io.InputStreamReader;import java.net.URL;import java.util.ArrayList;import java.util.List;import org.apache.commons.math.stat.descriptive.SummaryStatistics;import org.apache.commons.math.stat.descriptive.StatisticalSummary;/** * Implements <code>EmpiricalDistribution</code> interface. This implementation * uses what amounts to the * <a href="http://nedwww.ipac.caltech.edu/level5/March02/Silverman/Silver2_6.html"> * Variable Kernel Method</a> with Gaussian smoothing:<p> * <strong>Digesting the input file</strong> * <ol><li>Pass the file once to compute min and max.</li> * <li>Divide the range from min-max into <code>binCount</code> "bins."</li> * <li>Pass the data file again, computing bin counts and univariate * statistics (mean, std dev.) for each of the bins </li> * <li>Divide the interval (0,1) into subintervals associated with the bins, * with the length of a bin's subinterval proportional to its count.</li></ol> * <strong>Generating random values from the distribution</strong><ol> * <li>Generate a uniformly distributed value in (0,1) </li> * <li>Select the subinterval to which the value belongs. * <li>Generate a random Gaussian value with mean = mean of the associated * bin and std dev = std dev of associated bin.</li></ol></p><p> *<strong>USAGE NOTES:</strong><ul> *<li>The <code>binCount</code> is set by default to 1000. A good rule of thumb * is to set the bin count to approximately the length of the input file divided * by 10. </li> *<li>The input file <i>must</i> be a plain text file containing one valid numeric * entry per line.</li> * </ul></p> * * @version $Revision: 617850 $ $Date: 2008-02-02 11:01:29 -0700 (Sat, 02 Feb 2008) $ */public class EmpiricalDistributionImpl implements Serializable, EmpiricalDistribution { /** Serializable version identifier */ private static final long serialVersionUID = -6773236347582113490L; /** List of SummaryStatistics objects characterizing the bins */ private ArrayList binStats = null; /** Sample statistics */ private SummaryStatistics sampleStats = null; /** number of bins */ private int binCount = 1000; /** is the distribution loaded? */ private boolean loaded = false; /** upper bounds of subintervals in (0,1) "belonging" to the bins */ private double[] upperBounds = null; /** RandomData instance to use in repeated calls to getNext() */ private RandomData randomData = new RandomDataImpl(); /** * Creates a new EmpiricalDistribution with the default bin count. */ public EmpiricalDistributionImpl() { binStats = new ArrayList(); } /** * Creates a new EmpiricalDistribution with the specified bin count. * * @param binCount number of bins */ public EmpiricalDistributionImpl(int binCount) { this.binCount = binCount; binStats = new ArrayList(); } /** * Computes the empirical distribution from the provided * array of numbers. * * @param in the input data array */ public void load(double[] in) { DataAdapter da = new ArrayDataAdapter(in); try { da.computeStats(); fillBinStats(in); } catch (Exception e) { throw new RuntimeException(e.getMessage()); } loaded = true; } /** * Computes the empirical distribution using data read from a URL. * @param url url of the input file * * @throws IOException if an IO error occurs */ public void load(URL url) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream())); try { DataAdapter da = new StreamDataAdapter(in); try { da.computeStats(); } catch (Exception e) { throw new IOException(e.getMessage()); } if (sampleStats.getN() == 0) { throw new EOFException("URL " + url + " contains no data"); } in = new BufferedReader(new InputStreamReader(url.openStream())); fillBinStats(in); loaded = true; } finally { if (in != null) { try { in.close(); } catch (Exception ex) { // ignore } } } } /** * Computes the empirical distribution from the input file. * * @param file the input file * @throws IOException if an IO error occurs */ public void load(File file) throws IOException { BufferedReader in = new BufferedReader(new FileReader(file)); try { DataAdapter da = new StreamDataAdapter(in); try { da.computeStats(); } catch (Exception e) { throw new IOException(e.getMessage()); } in = new BufferedReader(new FileReader(file)); fillBinStats(in); loaded = true; } finally { if (in != null) { try { in.close(); } catch (Exception ex) { // ignore } } } } /** * Provides methods for computing <code>sampleStats</code> and * <code>beanStats</code> abstracting the source of data. */ private abstract class DataAdapter{ /** * Compute bin stats. * * @param min minimum value * @param delta grid size * @throws Exception if an error occurs computing bin stats */ public abstract void computeBinStats(double min, double delta) throws Exception; /** * Compute sample statistics. * * @throws Exception if an error occurs computing sample stats */ public abstract void computeStats() throws Exception; } /** * Factory of <code>DataAdapter</code> objects. For every supported source * of data (array of doubles, file, etc.) an instance of the proper object * is returned. */ private class DataAdapterFactory{ /** * Creates a DataAdapter from a data object * * @param in object providing access to the data * @return DataAdapter instance */ public DataAdapter getAdapter(Object in) { if (in instanceof BufferedReader) { BufferedReader inputStream = (BufferedReader) in; return new StreamDataAdapter(inputStream); } else if (in instanceof double[]) { double[] inputArray = (double[]) in; return new ArrayDataAdapter(inputArray); } else { throw new IllegalArgumentException( "Input data comes from the" + " unsupported source"); } } } /** * <code>DataAdapter</code> for data provided through some input stream */ private class StreamDataAdapter extends DataAdapter{ /** Input stream providng access to the data */ private BufferedReader inputStream; /** * Create a StreamDataAdapter from a BufferedReader * * @param in BufferedReader input stream */ public StreamDataAdapter(BufferedReader in){ super(); inputStream = in;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -