/** * MonteCarlo.java * * --Copyright notice-- * * Authors: Sim Reaney and Andy Evans. * * This code is also licensed under GPL2 which can be found at * the Open Source Initiative website at... * http://cran.r-project.org/web/licenses/GPL-2 * * --End of Copyright notice-- * **/ import java.io.*; import java.awt.*; import java.util.*; /** * This class gives an object that enacts a Monte Carlo Sampler.
* You need to call its setNumbers method with a filename for * which there is a corresponding datafile. The datafile should have * comma or space delimited text in it. The class will bin the distribution * into a number of bins set in the constructor. To get a value * from the object pulled from the same distribution as the original * data, call the getNumber(double) method with a random number between * zero and one.
* @author Sim Reaney and Andy Evans productions. **/ public class MonteCarlo { double max = 0; double min = 0; double interval = 0; double data[] = null; int numberOfBins = 0; double bins[][] = null; /** * This constructor sets the number of bins.
* Pass in a value corresponding to the number of bins you want. * The value must be greater than zero. * @param Number of bins wanted as an int. **/ MonteCarlo (int numberOfBins) { this.numberOfBins = numberOfBins; bins = new double[2][numberOfBins]; for (int i = 0; i < numberOfBins; i++) { bins [0][i] = 0; bins [1][i] = 0; } } /** * This method will set the frequency distribution of the numbers returned by the sampler.
* You need to call this method with a filename for * which there is a corresponding datafile. The datafile should have * comma or space delimited text in it. The class will bin the distribution * into a number of bins set in the constructor. For file handling, see docs for fileAsArray. * @param Filename of data file. **/ public void setNumbers (String filename) { // Get a datafile as a double array. This also sets max, min, and interval. data = fileAsArray(filename); for(int i = 0; i < numberOfBins; i++) { // Set the value associated with each bin. bins[0][i] = interval + (interval * (i) + min); // Add the cumulative frequency to each bin. // For example, if our frequencies distribution is 2, 10, 3 // our bins will contain 2, 12, 15. for(int j = 0; j < data.length; j++) { if (data[j] < bins[0][i]) bins[1][i]++; } } // Change the cumulative frequencies into cumulative // numbers between 0 and 1. for(int i = 0; i < numberOfBins; i++) { bins[1][i] = (bins[1][i] / data.length); } } // End of setNumbers (String filename). /** * This method returns a number at a rate determined by a preset distribution.
* Calling this method with a random number between zero and one will return * a number. The frequency at which different numbers are returned, and their range * will match the distribution set in setNumbers(String). * @param A random number between 0 and 1. * @return A randomly generated number of a distribution set in setNumbers. * @see MonteCarlo#setNumbers **/ public double getNumber (double random) { // Run through each bin. if the random number is // less than the cumulative frequency in the bin, we return this // bin value. For example, if the values in our bins are // 0.2, 0.8, 1.0 and we give a random number of 0.5, the program will // check the first bin, and continue, then check the second bin and // break, returning the value associated with the second value. double value = 0; for (int i = 0 ; i < numberOfBins; i++) { if (random < bins[1][i]) { value = bins[0][i]; break; } } return value; } // End of getNumber(double random). /** * This method returns a file as a one-dimensional array.
* The file should be comma or space delimited. If the given file * doesn't exist, the user has to pick one. If they cancel, the method * returns null. * @param Filename. * @return File as a one dimensional double array. **/ private double[] fileAsArray(String filename) { File f = null; FileReader fr = null; BufferedReader br = null; // Get the file as a stream. try { fr = new FileReader (filename); br = new BufferedReader (fr); } catch (IOException ioe) { try { FileDialog fd = new FileDialog(new Frame(), "Please pick a data file", FileDialog.LOAD); fd.show(); fr = new FileReader(fd.getDirectory() + fd.getFile()); br = new BufferedReader(fr); } catch (IOException ioe2) { return null; } } String s = null;; int rows = 0; int columns = 0; StringTokenizer st = null; // Calculate the size of the file. try { while ((s = br.readLine()) != null) { rows++; if (rows == 1) { st = new StringTokenizer (s, ","); while (st.hasMoreTokens()) { columns++; } } } } catch (IOException ioe) { System.out.println("Your file Monte Carlo data file could not be read."); return null; } // Make an array of the appropriate size, and read in the file. double dataArray[] = new double[rows * columns]; rows = 0; int position = 0; try { while ( (s = br.readLine ( )) != null) { st = new StringTokenizer (s, ","); position = 0; while (st.hasMoreTokens()) { double temp = (new Double(st.nextToken())).doubleValue(); dataArray[(rows * columns) + position] = temp; // Calculate the min and max values so we can determine the best bin interval size. if ((rows == 0) && (position == 0)) max = min = temp; if (temp > max) max = temp; if (temp < min) min = temp; position++; } rows++; } fr.close ( ); } catch (IOException ioe) { System.out.println("Your file Monte Carlo data file could not be read."); return null; } interval = (max - min) / numberOfBins; return dataArray; } // End of fileAsArray(String filename). // End of MonteCarlo class. }