Advertisement
dspwhite

Random walk for paytables

Sep 25th, 2015
243
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 15.67 KB | None | 0 0
  1. public void main() {
  2.     double[] probability;
  3.     double[] payout;
  4.     //string csv=@"0.5  -1
  5.     //0.5   1";
  6.     string csv=@"0.75 -1
  7.     0.1 0.5
  8.     0.15 4.5";
  9.  
  10.     convertCSVtoPayoutTable(csv, out probability, out payout);  // this just populates the probability and payout arrays from the CSV.
  11.     double output = travel(probability, payout, 10000, 20000);  // Process paytable to find travel
  12.     label1.Text = "Average travel (simulation): "+ output;              // Print out final answer
  13. }
  14.  
  15.  
  16.  
  17. public double travel(double[] probability, double[] payout, long runs, long universes) {
  18.     Roulette r = new Roulette(probability);
  19.     double coin;
  20.     double tn=0;
  21.  
  22.     for (long u=0; u<universes; u++){
  23.         coin=0;            
  24.         for(long n=0; n<runs; n++){
  25.             int s = r.spin();
  26.             coin+= payout[s];
  27.         }
  28.         //if(coin>0) {  // This is the line you wanted me to add.
  29.             tn+=Math.Abs(coin);
  30.         //}
  31.     }
  32.     return tn/(universes*1.0);
  33. }
  34.  
  35.  
  36. public void convertCSVtoPayoutTable(string csv, out double[] probability, out double[] payout)
  37. {
  38.     string[] lines = csv.Split(new string[] { "\n", "\r\n", "\r" }, StringSplitOptions.RemoveEmptyEntries);
  39.     probability = new double[lines.Length];
  40.     payout = new double[lines.Length];
  41.     for (int i=0; i<lines.Length; i++)
  42.     {
  43.         string[] s = lines[i].Split(new char[] { ',', '\t',' ' },StringSplitOptions.RemoveEmptyEntries);
  44.         bool success1,success2;            
  45.         if(s.Length==2) {
  46.         success1= Double.TryParse(s[0], out probability[i]);
  47.         success2 = Double.TryParse(s[1], out payout[i]);
  48.         } else {
  49.             success1=false;
  50.             success2=false;
  51.         }
  52.         if(!success1 || !success2) {
  53.             probability=null;
  54.             payout=null;
  55.             return;
  56.         }
  57.     }
  58. }
  59.  
  60.  
  61.  
  62.  
  63.  
  64. public static class math
  65. {
  66.     public static double standardDeviation(double[] profit, double[] probability) {
  67.         double ep = expectedPayout(profit,probability);        
  68.         double d=0;
  69.         for(int i=0; i<profit.Length; i++)  {
  70.             d+=probability[i] *Math.Pow(profit[i]-ep,2);
  71.         }
  72.         return Math.Sqrt(d);
  73.     }
  74.  
  75.     public static double variance(double[] profit, double[] probability) {
  76.         double ep = expectedPayout(profit,probability);
  77.         double d=0;
  78.         for(int i=0; i<profit.Length; i++)  {
  79.             d+=probability[i] *Math.Pow(profit[i]-ep,2);
  80.         }
  81.         return d;
  82.     }
  83.  
  84.     public static double expectedPayout(double[] profit, double[] probability) {
  85.         double he=0;
  86.         for (int i = 0; i < probability.Length; i++)    {
  87.             he += probability[i] * profit[i];
  88.         }
  89.         return he;
  90.     }
  91. }
  92.  
  93.  
  94.  
  95.  
  96. public class Roulette
  97. {
  98.     public int ispin;
  99.     double[] c;
  100.     double total;
  101.     FastRandom random;
  102.  
  103.     public Roulette(double[] n) {
  104.         random = new FastRandom();  // Feel free to use your own Random function rather than this one.
  105.         total = 0;
  106.         c = new double[n.Length + 1];
  107.         c[0] = 0;
  108.         // Create cumulative values for later:
  109.         for (int i = 0; i < n.Length; i++)      {
  110.             c[i + 1] = c[i] + n[i];
  111.             total += n[i];
  112.         }
  113.     }
  114.  
  115.     public int spin()   {
  116.         ispin++;
  117.         double r = random.NextDouble() * total;     // Create a random number between 0 and 1 and times by the total we calculated earlier.        
  118.         //// Binary search for efficiency. Objective is to find index of the number just above r:
  119.         int a = 0;
  120.         int b = c.Length - 1;
  121.         while (b - a > 1)   {
  122.             int mid = (a + b) / 2;
  123.             if (c[mid] > r) b = mid;
  124.             else a = mid;
  125.         }
  126.         return a;
  127.     }
  128.  
  129. }
  130.  
  131.  
  132.  
  133.  
  134.  
  135.  
  136.  
  137. // http://www.codeproject.com/Articles/9187/A-fast-equivalent-for-System-Random
  138.  
  139.  
  140. /// <summary>
  141. /// A fast random number generator for .NET
  142. /// Colin Green, January 2005
  143. ///
  144. /// September 4th 2005
  145.  ///  Added NextBytesUnsafe() - commented out by default.
  146.  ///  Fixed bug in Reinitialise() - y,z and w variables were not being reset.
  147.  ///
  148.  /// Key points:
  149.  ///  1) Based on a simple and fast xor-shift pseudo random number generator (RNG) specified in:
  150.  ///  Marsaglia, George. (2003). Xorshift RNGs.
  151.  ///  http://www.jstatsoft.org/v08/i14/xorshift.pdf
  152.  ///  
  153.  ///  This particular implementation of xorshift has a period of 2^128-1. See the above paper to see
  154.  ///  how this can be easily extened if you need a longer period. At the time of writing I could find no
  155.  ///  information on the period of System.Random for comparison.
  156.  ///
  157.  ///  2) Faster than System.Random. Up to 8x faster, depending on which methods are called.
  158.  ///
  159.  ///  3) Direct replacement for System.Random. This class implements all of the methods that System.Random
  160.  ///  does plus some additional methods. The like named methods are functionally equivalent.
  161.  ///  
  162.  ///  4) Allows fast re-initialisation with a seed, unlike System.Random which accepts a seed at construction
  163.  ///  time which then executes a relatively expensive initialisation routine. This provides a vast speed improvement
  164.  ///  if you need to reset the pseudo-random number sequence many times, e.g. if you want to re-generate the same
  165.  ///  sequence many times. An alternative might be to cache random numbers in an array, but that approach is limited
  166.  ///  by memory capacity and the fact that you may also want a large number of different sequences cached. Each sequence
  167.  ///  can each be represented by a single seed value (int) when using FastRandom.
  168.  ///  
  169.  ///  Notes.
  170.  ///  A further performance improvement can be obtained by declaring local variables as static, thus avoiding
  171.  ///  re-allocation of variables on each call. However care should be taken if multiple instances of
  172.  ///  FastRandom are in use or if being used in a multi-threaded environment.
  173.  ///
  174.  /// </summary>
  175.  public class FastRandom
  176.  {
  177.      // The +1 ensures NextDouble doesn't generate 1.0
  178.      const double REAL_UNIT_INT = 1.0/((double)int.MaxValue+1.0);
  179.      const double REAL_UNIT_UINT = 1.0/((double)uint.MaxValue+1.0);
  180.      const uint Y=842502087, Z=3579807591, W=273326509;
  181.  
  182.      uint x, y, z, w;
  183.  
  184.      #region Constructors
  185.  
  186.      /// <summary>
  187.      /// Initialises a new instance using time dependent seed.
  188.      /// </summary>
  189.      public FastRandom()
  190.      {
  191.          // Initialise using the system tick count.
  192.          Reinitialise((int)Environment.TickCount);
  193.      }
  194.  
  195.      /// <summary>
  196.      /// Initialises a new instance using an int value as seed.
  197.      /// This constructor signature is provided to maintain compatibility with
  198.      /// System.Random
  199.      /// </summary>
  200.      public FastRandom(int seed)
  201.      {
  202.          Reinitialise(seed);
  203.      }
  204.  
  205.      #endregion
  206.  
  207.      #region Public Methods [Reinitialisation]
  208.  
  209.      /// <summary>
  210.      /// Reinitialises using an int value as a seed.
  211.      /// </summary>
  212.      /// <param name="seed"></param>
  213.      public void Reinitialise(int seed)
  214.      {
  215.          // The only stipulation stated for the xorshift RNG is that at least one of
  216.          // the seeds x,y,z,w is non-zero. We fulfill that requirement by only allowing
  217.          // resetting of the x seed
  218.          x = (uint)seed;
  219.          y = Y;
  220.          z = Z;
  221.          w = W;
  222.      }
  223.  
  224.      #endregion
  225.  
  226.      #region Public Methods [System.Random functionally equivalent methods]
  227.  
  228.      /// <summary>
  229.      /// Generates a random int over the range 0 to int.MaxValue-1.
  230.      /// MaxValue is not generated in order to remain functionally equivalent to System.Random.Next().
  231.      /// This does slightly eat into some of the performance gain over System.Random, but not much.
  232.      /// For better performance see:
  233.      ///
  234.      /// Call NextInt() for an int over the range 0 to int.MaxValue.
  235.       ///
  236.       /// Call NextUInt() and cast the result to an int to generate an int over the full Int32 value range
  237.       /// including negative values.
  238.       /// </summary>
  239.       /// <returns></returns>
  240.       public int Next()
  241.       {
  242.           uint t=(x^(x<<11));
  243.           x=y; y=z; z=w;
  244.           w=(w^(w>>19))^(t^(t>>8));
  245.  
  246.           // Handle the special case where the value int.MaxValue is generated. This is outside of
  247.           // the range of permitted values, so we therefore call Next() to try again.
  248.           uint rtn = w&0x7FFFFFFF;
  249.           if(rtn==0x7FFFFFFF)
  250.               return Next();
  251.           return (int)rtn;            
  252.       }
  253.  
  254.       /// <summary>
  255.       /// Generates a random int over the range 0 to upperBound-1, and not including upperBound.
  256.       /// </summary>
  257.       /// <param name="upperBound"></param>
  258.       /// <returns></returns>
  259.       public int Next(int upperBound)
  260.       {
  261.           if(upperBound<0)
  262.               throw new ArgumentOutOfRangeException("upperBound", upperBound, "upperBound must be >=0");
  263.  
  264.           uint t=(x^(x<<11));
  265.           x=y; y=z; z=w;
  266.  
  267.           // The explicit int cast before the first multiplication gives better performance.
  268.           // See comments in NextDouble.
  269.           return (int)((REAL_UNIT_INT*(int)(0x7FFFFFFF&(w=(w^(w>>19))^(t^(t>>8)))))*upperBound);
  270.       }
  271.  
  272.       /// <summary>
  273.       /// Generates a random int over the range lowerBound to upperBound-1, and not including upperBound.
  274.       /// upperBound must be >= lowerBound. lowerBound may be negative.
  275.       /// </summary>
  276.       /// <param name="lowerBound"></param>
  277.       /// <param name="upperBound"></param>
  278.       /// <returns></returns>
  279.       public int Next(int lowerBound, int upperBound)
  280.       {
  281.           if(lowerBound>upperBound)
  282.               throw new ArgumentOutOfRangeException("upperBound", upperBound, "upperBound must be >=lowerBound");
  283.  
  284.           uint t=(x^(x<<11));
  285.           x=y; y=z; z=w;
  286.  
  287.           // The explicit int cast before the first multiplication gives better performance.
  288.           // See comments in NextDouble.
  289.           int range = upperBound-lowerBound;
  290.           if(range<0)
  291.           {   // If range is <0 then an overflow has occured and must resort to using long integer arithmetic instead (slower).
  292.               // We also must use all 32 bits of precision, instead of the normal 31, which again is slower.  
  293.               return lowerBound+(int)((REAL_UNIT_UINT*(double)(w=(w^(w>>19))^(t^(t>>8))))*(double)((long)upperBound-(long)lowerBound));
  294.           }
  295.              
  296.           // 31 bits of precision will suffice if range<=int.MaxValue. This allows us to cast to an int and gain
  297.           // a little more performance.
  298.           return lowerBound+(int)((REAL_UNIT_INT*(double)(int)(0x7FFFFFFF&(w=(w^(w>>19))^(t^(t>>8)))))*(double)range);
  299.       }
  300.  
  301.       /// <summary>
  302.       /// Generates a random double. Values returned are from 0.0 up to but not including 1.0.
  303.       /// </summary>
  304.       /// <returns></returns>
  305.       public double NextDouble()
  306.       {  
  307.           uint t=(x^(x<<11));
  308.           x=y; y=z; z=w;
  309.  
  310.           // Here we can gain a 2x speed improvement by generating a value that can be cast to
  311.           // an int instead of the more easily available uint. If we then explicitly cast to an
  312.           // int the compiler will then cast the int to a double to perform the multiplication,
  313.           // this final cast is a lot faster than casting from a uint to a double. The extra cast
  314.           // to an int is very fast (the allocated bits remain the same) and so the overall effect
  315.           // of the extra cast is a significant performance improvement.
  316.           //
  317.           // Also note that the loss of one bit of precision is equivalent to what occurs within
  318.           // System.Random.
  319.           return (REAL_UNIT_INT*(int)(0x7FFFFFFF&(w=(w^(w>>19))^(t^(t>>8)))));            
  320.       }
  321.  
  322.  
  323.       /// <summary>
  324.       /// Fills the provided byte array with random bytes.
  325.       /// This method is functionally equivalent to System.Random.NextBytes().
  326.       /// </summary>
  327.       /// <param name="buffer"></param>
  328.       public void NextBytes(byte[] buffer)
  329.       {
  330.           // Fill up the bulk of the buffer in chunks of 4 bytes at a time.
  331.           uint x=this.x, y=this.y, z=this.z, w=this.w;
  332.           int i=0;
  333.           uint t;
  334.           for(int bound=buffer.Length-3; i<bound;)
  335.           {  
  336.               // Generate 4 bytes.
  337.               // Increased performance is achieved by generating 4 random bytes per loop.
  338.               // Also note that no mask needs to be applied to zero out the higher order bytes before
  339.               // casting because the cast ignores thos bytes. Thanks to Stefan Trosch?tz for pointing this out.
  340.               t=(x^(x<<11));
  341.               x=y; y=z; z=w;
  342.               w=(w^(w>>19))^(t^(t>>8));
  343.  
  344.               buffer[i++] = (byte)w;
  345.               buffer[i++] = (byte)(w>>8);
  346.               buffer[i++] = (byte)(w>>16);
  347.               buffer[i++] = (byte)(w>>24);
  348.           }
  349.  
  350.           // Fill up any remaining bytes in the buffer.
  351.           if(i<buffer.Length)
  352.           {
  353.               // Generate 4 bytes.
  354.               t=(x^(x<<11));
  355.               x=y; y=z; z=w;
  356.               w=(w^(w>>19))^(t^(t>>8));
  357.  
  358.               buffer[i++] = (byte)w;
  359.               if(i<buffer.Length)
  360.               {
  361.                   buffer[i++]=(byte)(w>>8);
  362.                   if(i<buffer.Length)
  363.                   {  
  364.                       buffer[i++] = (byte)(w>>16);
  365.                       if(i<buffer.Length)
  366.                       {  
  367.                           buffer[i] = (byte)(w>>24);
  368.                       }
  369.                   }
  370.               }
  371.           }
  372.           this.x=x; this.y=y; this.z=z; this.w=w;
  373.       }
  374.  
  375.  
  376. //      /// <summary>
  377. //      /// A version of NextBytes that uses a pointer to set 4 bytes of the byte buffer in one operation
  378. //      /// thus providing a nice speedup. The loop is also partially unrolled to allow out-of-order-execution,
  379. //      /// this results in about a x2 speedup on an AMD Athlon. Thus performance may vary wildly on different CPUs
  380. //      /// depending on the number of execution units available.
  381. //      ///
  382. //      /// Another significant speedup is obtained by setting the 4 bytes by indexing pDWord (e.g. pDWord[i++]=w)
  383. //      /// instead of adjusting it dereferencing it (e.g. *pDWord++=w).
  384. //      ///
  385. //      /// Note that this routine requires the unsafe compilation flag to be specified and so is commented out by default.
  386. //      /// </summary>
  387. //      /// <param name="buffer"></param>
  388. //      public unsafe void NextBytesUnsafe(byte[] buffer)
  389. //      {
  390. //          if(buffer.Length % 8 != 0)
  391. //              throw new ArgumentException("Buffer length must be divisible by 8", "buffer");
  392. //
  393. //          uint x=this.x, y=this.y, z=this.z, w=this.w;
  394. //          
  395. //          fixed(byte* pByte0 = buffer)
  396. //          {
  397. //              uint* pDWord = (uint*)pByte0;
  398. //              for(int i=0, len=buffer.Length>>2; i < len; i+=2)
  399. //              {
  400. //                  uint t=(x^(x<<11));
  401. //                  x=y; y=z; z=w;
  402. //                  pDWord[i] = w = (w^(w>>19))^(t^(t>>8));
  403. //
  404. //                  t=(x^(x<<11));
  405. //                  x=y; y=z; z=w;
  406. //                  pDWord[i+1] = w = (w^(w>>19))^(t^(t>>8));
  407. //              }
  408. //          }
  409. //
  410. //          this.x=x; this.y=y; this.z=z; this.w=w;
  411. //      }
  412.  
  413.       #endregion
  414.  
  415.       #region Public Methods [Methods not present on System.Random]
  416.  
  417.       /// <summary>
  418.       /// Generates a uint. Values returned are over the full range of a uint,
  419.       /// uint.MinValue to uint.MaxValue, inclusive.
  420.       ///
  421.       /// This is the fastest method for generating a single random number because the underlying
  422.       /// random number generator algorithm generates 32 random bits that can be cast directly to
  423.       /// a uint.
  424.       /// </summary>
  425.       /// <returns></returns>
  426.       public uint NextUInt()
  427.       {
  428.           uint t=(x^(x<<11));
  429.           x=y; y=z; z=w;
  430.           return (w=(w^(w>>19))^(t^(t>>8)));
  431.       }
  432.  
  433.       /// <summary>
  434.       /// Generates a random int over the range 0 to int.MaxValue, inclusive.
  435.       /// This method differs from Next() only in that the range is 0 to int.MaxValue
  436.       /// and not 0 to int.MaxValue-1.
  437.       ///
  438.       /// The slight difference in range means this method is slightly faster than Next()
  439.       /// but is not functionally equivalent to System.Random.Next().
  440.       /// </summary>
  441.       /// <returns></returns>
  442.       public int NextInt()
  443.       {
  444.           uint t=(x^(x<<11));
  445.           x=y; y=z; z=w;
  446.           return (int)(0x7FFFFFFF&(w=(w^(w>>19))^(t^(t>>8))));
  447.       }
  448.  
  449.  
  450.       // Buffer 32 bits in bitBuffer, return 1 at a time, keep track of how many have been returned
  451.       // with bitBufferIdx.
  452.       uint bitBuffer;
  453.       uint bitMask=1;
  454.  
  455.       /// <summary>
  456.       /// Generates a single random bit.
  457.       /// This method's performance is improved by generating 32 bits in one operation and storing them
  458.       /// ready for future calls.
  459.       /// </summary>
  460.       /// <returns></returns>
  461.       public bool NextBool()
  462.       {
  463.           if(bitMask==1)
  464.           {  
  465.               // Generate 32 more bits.
  466.               uint t=(x^(x<<11));
  467.               x=y; y=z; z=w;
  468.               bitBuffer=w=(w^(w>>19))^(t^(t>>8));
  469.  
  470.               // Reset the bitMask that tells us which bit to read next.
  471.               bitMask = 0x80000000;
  472.               return (bitBuffer & bitMask)==0;
  473.           }
  474.  
  475.           return (bitBuffer & (bitMask>>=1))==0;
  476.       }
  477.  
  478.       #endregion
  479. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement