I need a random number generator that generates various number between n and m, but no with a equal probability. I want to set a value x between n and m where the possibility is the highest:
Is there an easy way to do that using the Random class? The likelihood should have the form of a binominal distribution or something similar (it is not important that its an exact binominal distributon, rough approximations are also ok)
EDIT
Maybe I have to clarify: I'm not looking for a binominal or gaussian distribution but also for something like this:
I want to to define the value x where the highest likelihood should be.
EDIT
Unfortunately the previously accepted answer does not seem to work how i suspected. So I'm still looking for an answer!
You can use the Box-Muller transform to generate a sequence of psuedorandom normally distributed numbers from a sequence of numbers uniformally distributed between 0 and 1.
Java SDK has good implementation Random.nextGaussian (taken from http://download.oracle.com/javase/1.4.2/docs/api/java/util/Random.html#nextGaussian())
I hope it is rather clear how to parse from java source to c#
synchronized public double nextGaussian() {
if (haveNextNextGaussian) {
haveNextNextGaussian = false;
return nextNextGaussian;
} else {
double v1, v2, s;
do {
v1 = 2 * nextDouble() - 1; // between -1.0 and 1.0
v2 = 2 * nextDouble() - 1; // between -1.0 and 1.0
s = v1 * v1 + v2 * v2;
} while (s >= 1 || s == 0);
double multiplier = Math.sqrt(-2 * Math.log(s)/s);
nextNextGaussian = v2 * multiplier;
haveNextNextGaussian = true;
return v1 * multiplier;
}
}
UPDATE: How I've made shift of median:
public static float gaussianInRange(float from, float mean, float to)
{
if( !(from < mean && mean < to) )
throw new IllegalArgumentException(MessageFormat.format("RandomRange.gaussianInRange({0}, {1}, {2})", from, mean, to));
int p = _staticRndGen.nextInt(100);
float retval;
if (p < (mean*Math.abs(from - to)))
{
double interval1 = (_staticRndGen.nextGaussian() * (mean - from));
retval = from + (float) (interval1);
}
else
{
double interval2 = (_staticRndGen.nextGaussian() * (to - mean));
retval = mean + (float) (interval2);
}
while (retval < from || retval > to)
{
if (retval < from)
retval = (from - retval) + from;
if (retval > to)
retval = to - (retval - to);
}
return retval;
}
You need a generator working on a "Normal Distribution". Have a look here:
http://www.csharpcity.com/reusable-code/random-number-generators/
smth relatively simple.
You can generate 2 random numbers:
1st defines how close to x the 2nd random number would be.
You can use any breakpoint/function levels you like.
Related
I have an array of numbers(double) and I want to implement a recursive method in C# to calculate a running average for a given position in the array using the following algorithm:
µn+1 = (n * µn)/(n+1) + Xn+1/n
where µn+1 is the average at the position I'm interested in,
µn is the average of the prior iteration and Xn+1 is the nth element of the array.
I have been able to do it with an averaging function and an iterative function but not recursion:
static double Flow(double[] A, int n)
{
double U = (A[0] + A[1]) / 2.0;
if (n == 2) { return U; }
else if (n == 1) { return A[0]; }
else
{
for (int i = 3; i <= n; i++)
{
U = Avg(A, U, i);
}
}
return U;
}
static double Avg(double[] A, double M, int n)
{
double a =(n - 1) * M / (n);
double b = A[n - 1] / (n);
return a + b;
}
You need to define µ1, whatever your initial value of the first average is, for your algorithm to work. Also, variable i is not involved in your expression so what's it? Since Xn+1 is divided by n, I presume it can't be zero. Then the function should look like this:
double Avg(double[] array, int n)
{
if (n = 2)
{
return u1/2+array[2]; //u1 is a set value.
}
return (n-1)*Avg(array, n-1)/n+array[n]/(n-1);
}
Last but not least, it's more convenient to express recursive algorithm in µn = ... µ(n-1) instead of µ(n+1)=...µn.
I'm trying to write an implementation of the parking lot test for random number generators. Here are the sources that I'm getting my information about the test from: Intel math library documentation and Page 4 of this paper along with the phi function for probability density listed here.
I wrote an implementation of the test in C#. It uses a 100x100 grid whose values are initially set to null. I then use the random number generator to generate random integers for x and y. If that index of the grid and it's neighbors are empty, that index gets set to 1. Otherwise, nothing happens because there was a "crash".
I ran it using C# System.Random generator. I don't believe the results are correct because I always get very near 3079 points parked, which is about 500 short of the average I'm supposed to get. It's also yields a p-value of 2.21829146215425E-90.
My code is below. Does anyone have any experience with this or can anyone see something that I might be doing incorrectly in my implementation? Any help would be greatly appreciated.
private void RunParkingLotTest()
{
points = new int?[100,100];
int parked = 0;
for (int i = 0; i < 12000; i++)
{
int x = random.Next(100);
int y = random.Next(100);
if (IsSafeToPark(x, y))
{
points[x, y] = 1;
parked++;
}
}
Console.WriteLine("Parked: " + parked + "\nP value: " + PhiFunction((parked-3523)/21.9));
}
private bool IsSafeToPark(int x, int y)
{
return PointIsEmpty(x, y)
&& LeftOfPointIsEmpty(x, y)
&& RightOfPointIsEmpty(x, y)
&& BelowPointIsEmpty(x, y)
&& AbovePointIsEmpty(x, y);
}
private bool AbovePointIsEmpty(int x, int y)
{
if (y == 99)
{
return true;
}
else
return points[x, y + 1] == null;
}
private bool BelowPointIsEmpty(int x, int y)
{
if (y == 0)
{
return true;
}
else
return points[x, y - 1] == null;
}
private bool RightOfPointIsEmpty(int x, int y)
{
if (x == 99)
{
return true;
}
else
return points[x + 1, y] == null;
}
private bool LeftOfPointIsEmpty(int x, int y)
{
if (x == 0)
{
return true;
}
else
return points[x - 1, y] == null;
}
private bool PointIsEmpty(int x, int y)
{
return points[x, y] == null;
}
private double PhiFunction(double x)
{
//ϕ(x) = (2π)−½e−x2/2
return ((1 / Math.Sqrt(2 * Math.PI)) * Math.Exp(-(Math.Pow(x, 2)) / 2));
}
edit - The problems with my original implementation were
I was plotting squares instead of disks
I only plotted points at integer values. I should have used decimal values instead.
As a result of the above two, I needed to change my distance check
Thanks to Chris Sinclair and mine z for help in figuring this out. The final code is posted below.
I'm going to take a stab at this, and admittedly, I have not attempted any such test, so forgive me if I'm way off. In general though, the .NET Random implementation is pretty good and I've never had issues with it, so I wouldn't suspect that initially especially since you're properly reusing the same instance instead of creating new ones.
Reading from the parking.pdf, and from the Intel documentation, it seems that they're using discs, and compute the distance from their centre points. Your implementation is using squares (array of 1 distance between spots) and thus ignoring diagonals.
From the pdf:
If disks were being used, the distance between the particles r =
p(x(i) − z)2 + (y(i) − z)2 would need to be less than or equal to one.
Does it matter whether one uses disks or squares? An indication of the
importance of which geometric figure is parked can be obtained by
comparing the area occupied by a square of side 1.0 to the area of a
disk of diameter 1.0. The ratio of the areas, disk to square, is π/4.
Therefore, it would be anticipated that more disks could be placed in
a box than squares in the same number of tries.
And the Intel doc:
The test assumes a next random point (x, y) successfully ”parked”, if
it is far enough from every previous successfully ”parked” point. The
sufficient distance between the points (x1, y1) and (x2, y2) is
min(|x1 - x2|,|y1 - y2|) > 1.
I'm guessing that the π/4 disk to square ratio and the differences between how many discs can fit vs squares might be why you're seeing a different number. (although right now I fail to see a directly relationship between 3523 and 3070 and π/4. 3523 * π/4 = 2767, which is close, but I'm sure if there's a relationship it's slightly more complex than just simple multiplication.)
Not a great answer, but my best guess.
EDIT: Interestingly enough, I did a quick implementation using discs with 1 unit diameter and getting results around 4000 parked. So maybe there's a bit more to this than my untrained self can grasp (or maybe .NET's Random doesn't pass the test?) Anyway, here's my disc implementation:
List<Point> parkedCars = new List<Point>();
Random random = new Random();
void Main()
{
int parked = 0;
for (int i = 0; i < 12000; i++)
{
double x = random.NextDouble() * 100;
double y = random.NextDouble() * 100;
Point pointToPark = new Point(x, y);
if (IsSafeToPark(pointToPark))
{
parkedCars.Add(pointToPark);
parked++;
}
}
Console.WriteLine("Parked: " + parked);
}
private bool IsSafeToPark(Point pointToPark)
{
//make sure it's "inside" the box
if (pointToPark.X < 0.5 || pointToPark.X > 99.5
|| pointToPark.Y < 0.5 || pointToPark.Y > 99.5)
return false;
if (parkedCars.Any(p => Distance(pointToPark, p) <= 1))
return false;
return true;
}
private double Distance(Point p1, Point p2)
{
return Math.Sqrt((p1.X - p2.X) * (p1.X - p2.X) + (p1.Y - p2.Y) * (p1.Y - p2.Y));
}
Using my likely too simple application of the π/4 ratio yields about 3142. A bit closer, but it seems very incorrect.
EDIT: As #mike z pointed out, my test using directly distance is incorrect. According to the parameters of the test, which I forgot about, just checks that the X and Y distance are greater than 1. Changing my Distance check to:
Math.Max(Math.Abs(p1.X - p2.X), Math.Abs(p1.Y - p2.Y))
Yields a much closer result around 3450, which is pretty close. If I take out my "//make sure it's "inside" the box" check, averaged over 10 tries gets 3531!
So my final, "working" code is:
public struct Point
{
public double X,Y;
public Point(double x, double y)
{
this.X = x;
this.Y = y;
}
}
List<Point> parkedCars = new List<Point>();
Random random = new Random();
void Main()
{
int parked = 0;
for (int i = 0; i < 12000; i++)
{
double x = random.NextDouble() * 100;
double y = random.NextDouble() * 100;
Point pointToPark = new Point(x, y);
if (IsSafeToPark(pointToPark))
{
parkedCars.Add(pointToPark);
parked++;
}
}
Console.WriteLine("Parked: " + parked);
}
private bool IsSafeToPark(Point pointToPark)
{
if (parkedCars.Any(p => Distance(pointToPark, p) <= 1))
return false;
return true;
}
private double Distance(Point p1, Point p2)
{
return Math.Max(Math.Abs(p1.X - p2.X), Math.Abs(p1.Y - p2.Y));
}
EDIT: I ran the test 100 times twice, and averaged the results to 3521.29 and 3526.74 respectively. Not sure if this means there still something slightly more to this, but perhaps this is just indicative of rounding or floating point precision differences between .NET and Fortran.
How can I compute a base 2 logarithm without using the built-in math functions in C#?
I use Math.Log and BigInteger.Log repeatedly in an application millions of times and it becomes painfully slow.
I am interested in alternatives that use binary manipulation to achieve the same. Please bear in mind that I can make do with Log approximations in case that helps speed up execution times.
Assuming you're only interested in the integral part of the logarithm, you can do something like that:
static int LogBase2(uint value)
{
int log = 31;
while (log >= 0)
{
uint mask = (1 << log);
if ((mask & value) != 0)
return (uint)log;
log--;
}
return -1;
}
(note that the return value for 0 is wrong; it should be negative infinity, but there is no such value for integral datatypes so I return -1 instead)
http://graphics.stanford.edu/~seander/bithacks.html
For the BigInteger you could use the toByteArray() method and then manually find the most significant 1 and count the number of zeroes afterward. This would give you the base-2 logarithm with integer precision.
The bit hacks page is useful for things like this.
Find the log base 2 of an integer with a lookup table
The code there is in C, but the basic idea will work in C# too.
If you can make due with approximations then use a trick that Intel chips use: precalculate the values into an array of suitable size and then reference that array. You can make the array start and end with any min/max values, and you can create as many in-between values as you need to achieve the desired accuracy.
You can try this C algorithm to get the binary logarithm (base 2) of a double N :
static double native_log_computation(const double n) {
// Basic logarithm computation.
static const double euler = 2.7182818284590452354 ;
unsigned a = 0, d;
double b, c, e, f;
if (n > 0) {
for (c = n < 1 ? 1 / n : n; (c /= euler) > 1; ++a);
c = 1 / (c * euler - 1), c = c + c + 1, f = c * c, b = 0;
for (d = 1, c /= 2; e = b, b += 1 / (d * c), b - e /* > 0.0000001 */ ;)
d += 2, c *= f;
} else b = (n == 0) / 0.;
return n < 1 ? -(a + b) : a + b;
}
static inline double native_ln(const double n) {
// Returns the natural logarithm (base e) of N.
return native_log_computation(n) ;
}
static inline double native_log_base(const double n, const double base) {
// Returns the logarithm (base b) of N.
// Right hand side can be precomputed to 2.
return native_log_computation(n) / native_log_computation(base) ;
}
Source
I have a path that is evaluate at time 't' and returns an orientation and position based on the path type.
The value for time is affected by the path type:
switch (type)
{
case PathType.Closed:
time = ToolBox.Wrap(time, StartTime, EndTime);
break; // Wrap time around the path time to loop
case PathType.Open:
time = ToolBox.Min(time, EndTime);
break; // Clamp the time value to the max path time range
case PathType.Oscillating:
break;
}
The missing link is oscillating.
My question is what is a good, efficient way for oscillating between two values?
For example (2, 7). If time reaches 7 it reverses and decrements towards to 2 and once it reaches 2 it reverses and increases towards 7.
The algorithm should know whether to increase/decrease the value based on the original value so if the value is 9 it knows the answer is 7 - (Abs(7 - 9). If the value is 14 the value has wrapped around so it will result in an increase of 1.
Higher values will also increase or decrease the value depending on the number of times it wraps around the original range.
I hope that makes sense as I'm finding it difficult to explain.
EDIT:
Doesn't oscillate with floating point values:
for (float i = 0; i < 100; i += 0.1f)
{
Console.WriteLine("{0} {1}", i, Oscillate(2.5f, 7.5f, i));
}
private float Oscillate(float min, float max, float value)
{
float range = max - min;
float multiple = value / range;
bool ascending = multiple % 2 == 0;
float modulus = value % range;
return ascending ? modulus + min : max - modulus;
}
Here is what I came up with:
public static int Oscillate(int input, int min, int max)
{
int range = max - min ;
return min + Math.Abs(((input + range) % (range * 2)) - range);
}
I'm assuming input will be a counter starting at 0.
Ideally, you should be abstracting this functionality into some kind of a class and not be concerned about how the implementation actually works when you're using it. Here's an initial take on what that would look like in C++ (my C# is a little rusty). I think you can work it into C# with only little difficulty.
class oscillator
{
private:
float min;
float max;
static float mod(float num, float div)
{
float ratio = num / div;
return div * (ratio - std::floor(ratio));
}
public:
oscillator(float a, float b)
: min(a < b ? a : b), max(a > b ? a : b) {}
float range() ( return max-min; }
float cycle_length() { return 2*range(); }
float normalize(float val)
{
float state = mod(val-min, cycle_length());
if (state > range())
state = cycle_length()-state;
return state + min;
}
};
This will oscillate your numbers between 2 & 7, in this example, time is an int:
bool isIncreasing = time <= 7;
for (int i = 0; i < 20; i++) //some random loop
{
time = time + (isIncreasing ? 1 : -1);
if (time >= 7 || time <= 2) isIncreasing = !isIncreasing;
}
New answer to account for float values:
// Note: Increase FACTOR depending on how many decimal places of accuracy you need.
private const float FACTOR = 10;
public void Test()
{
for (float i = 0; i < 1000; i += 0.1F)
{
Console.WriteLine("{0} {1}", i, Oscillate(2.5F, 7.5F, i));
}
}
private float Oscillate(float min, float max, float time)
{
return (float)(Oscillate_Aux(Upscale(min), Upscale(max), Upscale(time))) / FACTOR;
}
private int Upscale(float value)
{
return (int)(value * FACTOR);
}
private int Oscillate_Aux(int min, int max, int time)
{
int range = max - min;
int multiple = time / range;
bool ascending = multiple % 2 == 0;
int modulus = time % range;
return ascending ? modulus + min : max - modulus;
}
What you're describing sounds a lot like periodic linear interpolation between two values. Consider using XNA's MathHelper.Lerp function as the basis for your oscillation.
Note that it uses a percentage to control the oscillation as its third parameter. You'll have to figure out how to translate your time t value into a percentile, but you could start with ex. sin(t) to see how things work.
If you're reluctant to import XNA into your project, the core equation is very simple:
value1 + (value2 - value1) * amount
Edit: If your question, at its heart, really is "What is a good, efficient way for oscillating between two values?", then Math.Sin(t) (or Cos) can provide you with regular oscillation between 0 and 1.
I want to use a random number generator that creates random numbers in a gaussian range where I can define the median by myself. I already asked a similar question here and now I'm using this code:
class RandomGaussian
{
private static Random random = new Random();
private static bool haveNextNextGaussian;
private static double nextNextGaussian;
public static double gaussianInRange(double from, double mean, double to)
{
if (!(from < mean && mean < to))
throw new ArgumentOutOfRangeException();
int p = Convert.ToInt32(random.NextDouble() * 100);
double retval;
if (p < (mean * Math.Abs(from - to)))
{
double interval1 = (NextGaussian() * (mean - from));
retval = from + (float)(interval1);
}
else
{
double interval2 = (NextGaussian() * (to - mean));
retval = mean + (float)(interval2);
}
while (retval < from || retval > to)
{
if (retval < from)
retval = (from - retval) + from;
if (retval > to)
retval = to - (retval - to);
}
return retval;
}
private static double NextGaussian()
{
if (haveNextNextGaussian)
{
haveNextNextGaussian = false;
return nextNextGaussian;
}
else
{
double v1, v2, s;
do
{
v1 = 2 * random.NextDouble() - 1;
v2 = 2 * random.NextDouble() - 1;
s = v1 * v1 + v2 * v2;
} while (s >= 1 || s == 0);
double multiplier = Math.Sqrt(-2 * Math.Log(s) / s);
nextNextGaussian = v2 * multiplier;
haveNextNextGaussian = true;
return v1 * multiplier;
}
}
}
Then to verify the results I plotted them with gaussianInRange(0, 0.5, 1) for n=100000000
As one can see the median is really at 0.5 but there isn't really a curve visible. So what I'm doing wrong?
EDIT
What i want is something like this where I can set the highest probability by myself by passing a value.
The simplest way to draw normal deviates conditional on them being in a particular range is with rejection sampling:
do {
retval = NextGaussian() * stdev + mean;
} while (retval < from || to < retval);
The same sort of thing is used when you draw coordinates (v1, v2) in a circle in your unconditional normal generator.
Simply folding in values outside the range doesn't produce the same distribution.
Also, if you have a good implementation of the error function and its inverse, you can calculate the values directly using an inverse CDF. The CDF of a normal distribution is
F(retval) = (1 + erf((retval-mean) / (stdev*sqrt(2)))) / 2
The CDF of a censored distribution is
C(retval) = (F(retval) - F(from)) / (F(to) - F(from)), from ≤ x < to
To draw a random number using a CDF, you draw v from a uniform distribution on [0, 1] and solve C(retval) = v. This gives
double v = random.NextDouble();
double t1 = erf((from - mean) / (stdev*sqrt(2)));
t2 = erf((to - mean) / (stdev*sqrt(2)));
double retval = mean + stdev * sqrt(2) * erf_inv(t1*(1-v) + t2*v);
You can precalculate t1 and t2 for specific parameters. The advantage of this approach is that there is no rejection sampling, so you only need a single NextDouble() per draw. If the [from, to] interval is small this will be faster.
However, it sounds like you might want the binomial distribution instead.
I have similar methods in my Graph generator (had to modify it a bit):
Returns a random floating-point number using a generator function with a specific range:
private double NextFunctional(Func<double, double> func, double from, double to, double height, out double x)
{
double halfWidth = (to - from) / 2;
double distance = halfWidth + from;
x = this.rand.NextDouble() * 2 - 1;// -1 .. 1
double y = func(x);
x = halfWidth * x + distance;
y *= height;
return y;
}
Gaussian function:
private double Gauss(double x)
{
// Graph should look better with double-x scale.
x *= 2;
double σ = 1 / Math.Sqrt(2 * Math.PI);
double variance = Math.Pow(σ, 2);
double exp = -0.5 * Math.Pow(x, 2) / variance;
double y = 1 / Math.Sqrt(2 * Math.PI * variance) * Math.Pow(Math.E, exp);
return y;
}
A method that generates a graph using the random numbers:
private void PlotGraph(Graphics g, Pen p, double from, double to, double height)
{
for (int i = 0; i < 1000; i++)
{
double x;
double y = this.NextFunctional(this.Gauss, from, to, height, out x);
this.DrawPoint(g, p, x, y);
}
}
I would rather used a cosine function - it is much faster and pretty close to the gaussian function for your needs:
double x;
double y = this.NextFunctional(a => Math.Cos(a * Math.PI), from, to, height, out x);
The out double x parameter in the NextFunctional() method is there so you can easily test it on your graphs (I use an iterator in my method).