001/* Base class for Colt Random Sources. 002 003 Copyright (c) 2004-2016 The Regents of the University of California. 004 All rights reserved. 005 Permission is hereby granted, without written agreement and without 006 license or royalty fees, to use, copy, modify, and distribute this 007 software and its documentation for any purpose, provided that the above 008 copyright notice and the following two paragraphs appear in all copies 009 of this software. 010 011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 015 SUCH DAMAGE. 016 017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 022 ENHANCEMENTS, OR MODIFICATIONS. 023 024 PT_COPYRIGHT_VERSION_2 025 COPYRIGHTENDKEY 026 027 */ 028package ptolemy.actor.lib.colt; 029 030import java.util.Random; 031 032import cern.jet.random.engine.DRand; 033import cern.jet.random.engine.MersenneTwister; 034import edu.cornell.lassp.houle.RngPack.RandomElement; 035import edu.cornell.lassp.houle.RngPack.Ranecu; 036import edu.cornell.lassp.houle.RngPack.Ranlux; 037import edu.cornell.lassp.houle.RngPack.Ranmar; 038import ptolemy.actor.lib.RandomSource; 039import ptolemy.actor.parameters.SharedParameter; 040import ptolemy.data.LongToken; 041import ptolemy.data.StringToken; 042import ptolemy.data.Token; 043import ptolemy.kernel.CompositeEntity; 044import ptolemy.kernel.util.Attribute; 045import ptolemy.kernel.util.IllegalActionException; 046import ptolemy.kernel.util.NameDuplicationException; 047 048/////////////////////////////////////////////////////////////////// 049//// ColtRandomSource 050 051/** Base class for Colt random sources. 052 This base class manages the choice of 053 random number generator class. When the random number 054 generator class is set for any one actor in a model, 055 it gets set to match in all other actors within the 056 same top-level container (unless this actor is within 057 an EntityLibrary). 058 059 @author David Bauer, Kostas Oikonomou, and Edward A. Lee 060 @version $Id$ 061 @since Ptolemy II 4.1 062 @Pt.ProposedRating Yellow (eal) 063 @Pt.AcceptedRating Red (cxh) 064 */ 065public abstract class ColtRandomSource extends RandomSource { 066 /** Construct an actor with the given container and name. 067 * @param container The container. 068 * @param name The name of this actor. 069 * @exception IllegalActionException If the actor cannot be contained 070 * by the proposed container. 071 * @exception NameDuplicationException If the container already has an 072 * actor with this name. 073 */ 074 public ColtRandomSource(CompositeEntity container, String name) 075 throws NameDuplicationException, IllegalActionException { 076 super(container, name); 077 078 generatorClass = new SharedParameter(this, "generatorClass", 079 ColtRandomSource.class, "DRand"); 080 generatorClass.setStringMode(true); 081 082 generatorClass.addChoice("DRand"); 083 generatorClass.addChoice("MersenneTwister (MT19937)"); 084 generatorClass.addChoice("Ranecu"); 085 generatorClass.addChoice("Ranlux"); 086 generatorClass.addChoice("Ranmar"); 087 } 088 089 /////////////////////////////////////////////////////////////////// 090 //// ports and parameter //// 091 092 /** The low-level random number generator (RNG) class name. 093 * This is a string that defaults to "DRand". 094 * Below are possible values for this parameter and links 095 * to pages that define the meaning of the parameter. 096 * This is a "shared parameter", which means that 097 * changing this parameter in any one actor will cause 098 * a similar change to be applied to all other Colt 099 * actors within the same top level (unless this is in 100 * a library). 101 * <menu> 102 * <li><code>"DRand"</code> 103 * (<a href="http://hoschek.home.cern.ch/hoschek/colt/V1.0.3/doc/cern/jet/random/engine/DRand.html#in_browser">Definition</a>) 104 * <li><code>"MersenneTwister (MT19937)"</code> 105 * (<a href="http://hoschek.home.cern.ch/hoschek/colt/V1.0.3/doc/cern/jet/random/engine/MersenneTwister.html#in_browser">Definition</a>) 106 * <li><code>"Ranecu""</code> 107 * (<a href="http://hoschek.home.cern.ch/hoschek/colt/V1.0.3/doc/edu/cornell/lassp/houle/RngPack/Ranecu.html#in_browser">Definition</a>) 108 * <li><code>"Ranlux"</code> 109 * (<a href="http://hoschek.home.cern.ch/hoschek/colt/V1.0.3/doc/cern/jet/random/engine/Ranlux.html#in_browser">Definition</a>) 110 * <li><code>"Ranmar"</code> 111 * (<a href="http://hoschek.home.cern.ch/hoschek/colt/V1.0.3/doc/cern/jet/random/engine/Ranmar.html#in_browser">Definition</a>) 112 * </menu> 113 */ 114 public SharedParameter generatorClass; 115 116 /////////////////////////////////////////////////////////////////// 117 //// public methods //// 118 119 /** If the attribute is <i>generatorClass</i> 120 * then create the base random number generator. 121 * @param attribute The attribute that changed. 122 * @exception IllegalActionException If the change is not acceptable 123 * to this container (not thrown in this base class). 124 */ 125 @Override 126 public void attributeChanged(Attribute attribute) 127 throws IllegalActionException { 128 if (attribute == generatorClass) { 129 String generatorClassValue = ((StringToken) generatorClass 130 .getToken()).stringValue(); 131 132 if (generatorClassValue != null 133 && !generatorClassValue.equals(_generatorClassName)) { 134 _needNewGenerator = true; 135 } 136 } else { 137 super.attributeChanged(attribute); 138 } 139 } 140 141 /////////////////////////////////////////////////////////////////// 142 //// protected methods //// 143 144 /** Method that is called after _randomNumberGenerator is changed. */ 145 protected abstract void _createdNewRandomNumberGenerator(); 146 147 /** Create the random number generator using current parameter values. */ 148 @Override 149 protected void _createGenerator() throws IllegalActionException { 150 long seedValue = ((LongToken) seed.getToken()).longValue(); 151 Token token = privateSeed.getToken(); 152 if (token != null) { 153 seedValue = ((LongToken) token).longValue(); 154 _generatorSeed = seedValue; 155 } else { 156 _generatorSeed = seedValue; 157 if (seedValue == 0L) { 158 seedValue = System.currentTimeMillis() + hashCode(); 159 } else { 160 // BTW - the reason to use the full name here is so that 161 // each random number generator generates a sequence 162 // of different random numbers. If we use just the 163 // display name, then two actors that have the same 164 // name will generate the same sequence of numbers which 165 // is bad for Monte Carlo simulations. 166 // See privateSeed in RandomSource for an alternate 167 // way to set seeds. 168 seedValue = seedValue + getFullName().hashCode(); 169 } 170 } 171 172 StringToken generatorToken = (StringToken) generatorClass.getToken(); 173 String generatorClassValue = null; 174 175 if (generatorToken != null) { 176 generatorClassValue = generatorToken.stringValue(); 177 } 178 179 _generatorClassName = generatorClassValue; 180 181 if (generatorClassValue == null 182 || generatorClassValue.equals("DRand")) { 183 _randomNumberGenerator = new DRand((int) seedValue); 184 } else if (generatorClassValue.equals("MersenneTwister (MT19937)")) { 185 _randomNumberGenerator = new MersenneTwister((int) seedValue); 186 } else if (generatorClassValue.equals("Ranecu")) { 187 _randomNumberGenerator = new Ranecu((int) seedValue); 188 } else if (generatorClassValue.equals("Ranlux")) { 189 _randomNumberGenerator = new Ranlux((int) seedValue); 190 } else if (generatorClassValue.equals("Ranmar")) { 191 _randomNumberGenerator = new Ranmar((int) seedValue); 192 } 193 194 // In the base class, if _random is null, then initialize() 195 // will re-run this method. We don't want this, so even though 196 // we don't need it, we create an instance of Random. 197 _random = new Random(); 198 _needNewGenerator = false; 199 _needNew = true; 200 201 _createdNewRandomNumberGenerator(); 202 } 203 204 /////////////////////////////////////////////////////////////////// 205 //// protected variables //// 206 207 /** The low-level random number generator. 208 */ 209 protected RandomElement _randomNumberGenerator; 210 211 /////////////////////////////////////////////////////////////////// 212 //// private variables //// 213 214 /** The class name of the current _randomNumberGenerator. 215 */ 216 private String _generatorClassName; 217}