/* @(#)BernoulliLaplace.java Copyright (C) 2005-2009 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.event.MouseEvent; import java.awt.Color; import java.io.Serializable; import javax.swing.JToolBar; import javax.swing.event.ChangeEvent; import java.awt.event.ItemEvent; import java.awt.Dimension; import edu.uah.math.distributions.Domain; import edu.uah.math.distributions.HypergeometricDistribution; import edu.uah.math.distributions.RandomVariable; import edu.uah.math.devices.RecordTable; import edu.uah.math.devices.Timeline; import edu.uah.math.devices.RandomVariableGraph; import edu.uah.math.devices.RandomVariableTable; import edu.uah.math.devices.Parameter; /** * This class models the Bernoulli-Laplace Markov chain. The model consists of two urns: * with j balls in urn 0 and k balls in urn 1. Of the j + k balls, r are red. At each * discrete time unit, a ball is chosen at random from urn 0, a ball is chosen at random * from urn 1 and the balls are switched. The number of balls in the two urns can be * varied, as well as the number of red balls. The initial state can be specified by * clicking on a state when the time is 0. The graph and table show the proportion of * time spent in each state. As time increases, these proportions converge to the * steady-state probabilities of the chain. * @author Dawn Duehring * @author Kyle Siegrist * @version May, 2006 */ public class BernoulliLaplaceExperiment extends Experiment{ //Variables private int urn0Balls = 10, urn1Balls = 10, redBalls = 10, initialState = 0, currentState = 0; private int minState = Math.max(0, redBalls - urn0Balls), maxState = Math.min(urn1Balls, redBalls); //Objects private RecordTable recordTable = new RecordTable(new String[] {"Time", "X"}); private Timeline chain = new Timeline(new Domain(minState, maxState, 1, Domain.DISCRETE), "x"); private JToolBar toolBar = new JToolBar("Parameter Toolbar"); private HypergeometricDistribution limitDistribution = new HypergeometricDistribution(urn0Balls + urn1Balls, redBalls, urn1Balls); private RandomVariable state = new RandomVariable(limitDistribution, "X"); private RandomVariableGraph stateGraph = new RandomVariableGraph(state); private RandomVariableTable stateTable = new RandomVariableTable(state); //Scrollbars and labels private Parameter urn0Scroll = new Parameter(1, 100, 1, urn0Balls, "Number of balls in urn 0", "j"), urn1Scroll = new Parameter(1, 100, 1, urn1Balls, "Number of balls in urn 1", "k"), redScroll = new Parameter(0, urn0Balls + urn1Balls, 1, redBalls, "Number of red balls", "r"); /** * This method initialize the experiment, including the toolbar, record table, Markov chain, * histogram, and data table. */ public void init(){ super.init(); setName("BernoulliLaplace Experiment"); //Scrollbar urn0Scroll.getSlider().addChangeListener(this); urn1Scroll.getSlider().addChangeListener(this); redScroll.getSlider().addChangeListener(this); //Toolbar toolBar.setLayout(new FlowLayout(FlowLayout.LEFT)); toolBar.add(urn0Scroll); toolBar.add(urn1Scroll); toolBar.add(redScroll); addToolBar(toolBar); //Urn Chain state.setValue(currentState); chain.setToolTipText("Markov chain: at time 0, click to set the initial state"); chain.setPointSize(6); chain.setMargins(35, 20, 20, 20); chain.setMinimumSize(new Dimension(100, 30)); chain.addMouseListener(this); chain.setCurrentTimeColor(Color.red); addComponent(chain, 0, 0, 2, 1, 10, 0); //Random variable graph addComponent(stateGraph, 0, 1, 2, 1); //Record Table recordTable.setDescription("X: state"); addComponent(recordTable, 0, 2, 1, 1); //Data Table addComponent(stateTable, 1, 2, 1, 1); //Final actions validate(); reset(); } /** * This method returns basic information about the applet, including copyright * information, descriptive information, and instructions. * @return applet infomration */ public String getAppletInfo(){ return super.getAppletInfo() + "\n\n" + "Visit http://www.math.uah.edu/stat/applets/BernoulliLaplace.xhtml for more information\n" + "about the applet and for a mathematical discussion of the Bernoulli-Laplace experiment."; } /** * This method handles the scrollbar events for changing the number of states. * @param e the change event */ public void stateChanged(ChangeEvent e){ int maxRed; if (e.getSource() == urn0Scroll.getSlider()){ urn0Balls = (int)urn0Scroll.getValue(); maxRed = urn0Balls + urn1Balls; if (redBalls > maxRed) redBalls = maxRed; redScroll.setRange(1, maxRed, 1, redBalls); } else if (e.getSource() == urn1Scroll.getSlider()){ urn1Balls = (int)urn1Scroll.getValue(); maxRed = urn0Balls + urn1Balls; if (redBalls > maxRed) redBalls = maxRed; redScroll.setRange(1, maxRed, 1, redBalls); } else if (e.getSource() == redScroll.getSlider()){ redBalls = (int)redScroll.getValue(); } minState = Math.max(0, redBalls - urn0Balls); maxState = Math.min(urn1Balls, redBalls); chain.setDomain(new Domain(minState, maxState, 1, Domain.DISCRETE)); limitDistribution.setParameters(urn0Balls + urn1Balls, redBalls, urn1Balls); if (initialState > maxState) initialState = maxState; else if (initialState < minState) initialState = minState; reset(); } /** * This method sets the initial state when the user clicks on a ball. * @param e the mouse event */ public void mouseClicked(MouseEvent e){ if (e.getSource() == chain && getTime() == 0){ int x = (int)Math.rint(chain.getXScale(e.getX())); if (x < minState) x = minState; else if (x > maxState) x = maxState; initialState = x; reset(); } } /** * This method performs the next step in the process. A note is played, depending on * the state. */ public void step(){ doExperiment(); playNote(currentState); update(); } /** * This method resets the experiment, including the Markov chain, the record table * the histogram and data table. */ public void reset(){ super.reset(); currentState = initialState; chain.resetData(); chain.addTime(currentState, Color.red); chain.setCurrentTime(currentState); recordTable.reset(); recordTable.addRecord(new double[]{getTime(), initialState}); state.reset(); stateGraph.reset(); stateTable.reset(); } /** * This method defines the experiment. The Markov chain moves to the next state. */ public void doExperiment(){ super.doExperiment(); move(); } /** * This method updates the experiment, including the record table, Markov chain, * histogram, and data table. */ public void update(){ super.update(); recordTable.addRecord(new double[]{getTime(), currentState}); chain.resetData(); chain.addTime(initialState, Color.blue); chain.addTime(currentState, Color.red); chain.setCurrentTime(currentState); stateGraph.repaint(); stateTable.repaint(); } /** * This method sets the transition probabilities */ public void move(){ double p = Math.random(), m = (double)(urn0Balls * urn1Balls); double p1 = (currentState * (urn0Balls - redBalls + currentState)) / m; double p2 = (currentState * (redBalls - currentState) + (urn1Balls - currentState) * (urn0Balls - redBalls + currentState)) / m; if (p <= p1) currentState = currentState - 1; else if (p > p1 + p2) currentState = currentState + 1; state.setValue(currentState); } }