/* @(#)PolyaExperiment.java Copyright (C) 2001-2008 Kyle Siegrist Department of Mathematical Sciences University of Alabama in Huntsville This program is part of Virtual Laboratories in Probability and Statistics, http://www.math.uah.edu/stat/, a project partially supported by the National Science Foundation under grant number DUE-0089377. This program is licensed under a Creative Commons License. Basically, you are free to copy, distribute, and modify this program, and to make commercial use of the program. However you must give proper attribution. See http://creativecommons.org/licenses/by/2.0/ for more information. */ package edu.uah.math.experiments; import java.awt.FlowLayout; import java.awt.Color; import java.io.Serializable; import java.awt.Dimension; import java.awt.event.ItemEvent; import java.awt.event.ActionEvent; import javax.swing.JToolBar; import javax.swing.JComboBox; import javax.swing.Timer; import javax.swing.event.ChangeEvent; import edu.uah.math.devices.RecordTable; import edu.uah.math.devices.Urn; import edu.uah.math.devices.Ball; import edu.uah.math.devices.Parameter; import edu.uah.math.devices.RandomVariableGraph; import edu.uah.math.devices.RandomVariableTable; import edu.uah.math.distributions.PolyaDistribution; import edu.uah.math.distributions.RandomVariable; /** * This class defines a the Polya urn scheme. An urn initially contains a specified * number of red and green balls. On each trial a ball is chosen at random and then . * replaced along with a specified number of new balls of the same color. * the population size, sample size, and number of red balls. * The random variable of interest is the number of red balls in the sample. * @author Kyle Siegrist * @version June, 2009 */ public class PolyaExperiment extends Experiment implements Serializable{ //Variables private int red = 1, green = 1, step = 1, trials = 10, sum, trial; private double proportion; //Objects private RecordTable recordTable = new RecordTable(new String[]{"Run", "Y", "M"}); private Urn urn = new Urn(trials, 26); private JToolBar toolBar = new JToolBar("Parameter Toolbar"); private PolyaDistribution distribution = new PolyaDistribution(red, green, step, trials); private RandomVariable rvSum = new RandomVariable(distribution, "Y"); private RandomVariableGraph sumGraph = new RandomVariableGraph(rvSum); private RandomVariableTable sumTable = new RandomVariableTable(rvSum); //Scrollbars and labels private Parameter redScroll = new Parameter(1, 50, 1, red, "Initial red balls", "a"); private Parameter greenScroll = new Parameter(1, 50, 1, green, "Initial green balls", "b"); private Parameter stepScroll = new Parameter(0, 50, 1, step, "Number of balls added", "c"); private Parameter trialsScroll = new Parameter(1, 70, 1, trials, "Sample size", "n"); //Timer private Timer timer = new Timer(100, this); /** * This method initialize the experiment, including the record table, the sliders * the tool bar, the urn, and the graph and table for the number of red balls. */ public void init(){ super.init(); setName("Polya's Urn Experiment"); //Initial red ball slider redScroll.setWidth(140); redScroll.getSlider().addChangeListener(this); //Initial green ball slider greenScroll.setWidth(140); greenScroll.getSlider().addChangeListener(this); //Step slider stepScroll.setWidth(140); stepScroll.getSlider().addChangeListener(this); //Sample size slider trialsScroll.setWidth(140); trialsScroll.getSlider().addChangeListener(this); //Toolbar toolBar.setLayout(new FlowLayout(FlowLayout.LEFT)); toolBar.add(redScroll); toolBar.add(greenScroll); toolBar.add(stepScroll); toolBar.add(trialsScroll); addToolBar(toolBar); //Graphs urn.setMinimumSize(new Dimension(100, 100)); addComponent(urn, 0, 0, 1, 1); sumGraph.setMinimumSize(new Dimension(100, 100)); addComponent(sumGraph, 1, 0, 1, 1); //Tables recordTable.setDescription("Y: Number of red balls in the sample; M: Proportion of red balls in the sample"); addComponent(recordTable, 0, 1, 1, 1); addComponent(sumTable, 1, 1, 1, 1); //Final actions validate(); reset(); } /** * This method returns basic information about the applet, including copyright * information, descriptive informaion, and instructions. */ public String getAppletInfo(){ return super.getAppletInfo() + "\n\n" + "Visit http://www.math.uah.edu/stat/applets/PolyaExperiment.xhtml for more information\n" + "about the applet and for a mathematical discussion of Polya's experiment"; } /** * This method handles the slider events associated with changing the parameters * (the number of red balls, the number of green balls, the number of balls added, * and the sample size). * @param e the change event */ public void stateChanged(ChangeEvent e){ if (e.getSource() == redScroll.getSlider()){ red = (int)redScroll.getValue(); setParameters(); } else if (e.getSource() == greenScroll.getSlider()){ green = (int)greenScroll.getValue(); setParameters(); } else if (e.getSource() == stepScroll.getSlider()){ step = (int)stepScroll.getValue(); setParameters(); } else if (e.getSource() == trialsScroll.getSlider()){ trials = (int)trialsScroll.getValue(); urn.setBallCount(trials); setParameters(); } } /** * This method sets the distribution for the random variable in terms of * the parameters (the number of balls, the number of red balls, and the * sample size. */ public void setParameters(){ distribution.setParameters(red, green, step, trials); rvSum.setDistribution(distribution); reset(); } /** * This method defines the experment. The balls are chosen at random * and the number of red balls in the sample computed. */ public void doExperiment(){ int totalRed = red, totalGreen = green; double probability; Ball ball; sum = 0; super.doExperiment(); for (int i = 0; i < trials; i++){ probability = (double)totalRed / (totalRed + totalGreen); ball = urn.getBall(i); if (Math.random() < probability) { sum++; ball.setBallColor(RED); ball.setValue((int)Math.ceil(Math.random() * totalRed)); totalRed = totalRed + step; } else{ ball.setBallColor(GREEN); ball.setValue((int)Math.ceil(Math.random() * totalGreen)); totalGreen = totalGreen + step; } } proportion = (double)sum / trials; rvSum.setValue(sum); } /** * This method updates the display, including the urn, the random variable * graph and table, and the record table. */ public void update(){ super.update(); urn.setDrawn(true); sumGraph.repaint(); recordTable.addRecord(new double[]{getTime(), sum, proportion}); sumTable.repaint(); } /** * This method runs the experiment one time, with additional annimation and sound.. */ public void step(){ stop(); doExperiment(); trial = 0; urn.setDrawn(false); timer.start(); } /** * This method stops the step process, if necessary, and then calls the usual run method. */ public void run(){ timer.stop(); super.run(); } /** * This method stops the step process, if necessary, and then calls the usual stop method. */ public void stop(){ timer.stop(); super.stop(); } /** * This method resets the experiment, including the urn, the random variable, * the random variable graph and table, and the record table. */ public void reset(){ timer.stop(); //Initialize variables super.reset(); recordTable.reset(); urn.setDrawn(false); rvSum.reset(); sumGraph.reset(); sumTable.reset(); } /** * This method handles the events associated with the timer. The balls are shown one at a time. */ public void actionPerformed(ActionEvent e){ Ball ball; if (e.getSource() == timer){ if (trial < trials){ ball = urn.getBall(trial); ball.setDrawn(true); if (ball.getBallColor() == Color.red) playNote(1); else playNote(0); trial++; } else{ timer.stop(); sumGraph.repaint(); recordTable.addRecord(new double[]{getTime(), sum, proportion}); sumTable.repaint(); } } else super.actionPerformed(e); } }