I'm working on a neural networks project and I have 2 classes like this:
public class Net
{
// Net object is made of neurons
public List<Neuron> Neurons = new List<Neuron>();
// neurons are created in Net class constructor
public Net(int neuronCount, int neuronInputs)
{
for (int n = 0; n < neuronCount; n++)
{
Neurons.Add(new Neuron(n, neuronInputs));
}
}
}
public class Neuron
{
public int index; // neuron has index
public List<double> weights = new List<double>(); // and list of weights
// Neuron constructor is supposed to add random weights to new neuron
public Neuron(int neuronIndex, int neuronInputs)
{
Random rnd = new Random();
for (int i = 0; i < neuronInputs; i++)
{
this.index = neuronIndex;
this.weights.Add(rnd.NextDouble());
}
}
When I try to create network and display it's "contents":
Neuro.Net Network = new Neuro.Net(4, 4); // creating network with 4 neurons with 4 weights each
// dgv is a DataGridView for weights preview
dgv.Rows.Clear();
dgv.Columns.Clear();
// creating columns
foreach (Neuro.Neuron neuron in Network.Neurons)
{
dgv.Columns.Add("colN" + neuron.index, "N" + neuron.index);
}
dgv.Rows.Add(Network.Neurons[0].weights.Count());
for (int n = 0; n < Network.Neurons.Count(); n++)
{
for (int w = 0; w < Network.Neurons[n].weights.Count(); w++)
{
dgv.Rows[w].Cells[n].Value = Network.Neurons[n].weights[w];
}
}
When I run that code - I'm getting something like this (all weights are identical):
When I saw it - I tried to debug and find my mistake. However, when I put breakpoint in the neuron constructor - my network initializes as I want (weights are different):
I tried to use Debug and Release configurations - same results.
Can someone explain what is going on here?
Magic?
However, when I put breakpoint in neuron constructor - my network
initializes as I want (neurons are diffrent):
Presumably, the breakpoint introduces enough of a delay for Random() to be seeded with a different number. The delay can be caused by you pausing in the code (obviously) or even the non-matching evaluation of a conditional breakpoint (which slows execution slightly).
It would be better to have:
private static readonly Random _random = new Random();
And call _random.Next() without creating a new instance, such as:
public Neuron(int neuronIndex, int neuronInputs)
{
for (int i = 0; i < neuronInputs; i++)
{
this.index = neuronIndex;
this.weights.Add(_random.NextDouble());
}
}
The parameterless constructor of Random uses Environment.TickCount (hence the difference when a delay is introduced). You could also provide your own seed if you must create a new instance every time.
This behavior is documented here, specifically:
...because the clock has finite resolution, using the parameterless
constructor to create different Random objects in close succession
creates random number generators that produce identical sequences of
random numbers. [...] This problem can be avoided by creating a single
Random object rather than multiple ones.
Alternatively, you could use System.Security.Cryptography.RNGCryptoServiceProvider.
Random numbers are generated using current system time.
When you are debugging, you allow sometime between each generation. When you run, the code, it runs so fast that the seed is the same, thus, the generated randoms are equal.
Solution: declare a class member to contain the random instance and for every new random, call .Next() method.
private static rnd = new Random();
remove this line:
Random rnd = new Random();
and you are done
create a static instance of Random class.
since within constructor, Random is initialized each time, hence the possibility of similar numbers!
private static readonly Random rnd = new Random();
public Neuron(int neuronIndex, int neuronInputs)
{
private static readonly rnd = new Random();
for (int i = 0; i < neuronInputs; i++)
{
this.index = neuronIndex;
this.weights.Add(rnd.NextDouble());
}
}
Related
I want to make 2 different Random objects in 2 consecutive lines of code. The parameterless constructer of the Random class is like this:
public Random()
: this(Environment.TickCount) {
}
It uses Environment.TickCount as the seed. TickCount represents the amount of time that has passed since the OS is switched on, right?
I tried the following:
Random r1 = new Random ();
Random r2 = new Random ();
And I found out that the 2 Random objects had the same seed because their Next methods return the same number each time. I was surprised by how fast a line of code can be executed. Then I tried:
long tick1 = Environment.TickCount;
for (int i = 0 ; i < 100000 ; i++) {
}
long tick2 = Environment.TickCount;
Console.WriteLine (tick2 - tick1);
And I get 0. So I iterated 100000 times and still, not even 1 millisecond has passed?
I just want to ask how can I create 2 different Random objects or is there another way to generate random numbers?
Base on #PankajMishra's answer, try this one:
//Function to get random number
private static readonly Random getrandom = new Random();
private static readonly object syncLock = new object();
public static int GetRandomNumber(int min, int max)
{
lock(syncLock) { // synchronize
return getrandom.Next(min, max);
}
}
lock block is effective when you use it in a multi-threading program, if you sure just one thread use it, so you can prevent lock to increase your code performance.
To me, it seems like an XY problem, because you don't need two separate Random instances - you can use the same one to generate all your random number, can't you? Just call Next again and that's it:
var rnd = new Random();
int firstRandomInt = rnd.Next();
int secondRandomInt = rnd.Next();
However, you really need 2 Random instances, you can use the first one to seed the second one:
var rnd = new Random();
var rnd2 = new Random(rnd.Next());
This question already has answers here:
Random String Generator Returning Same String [duplicate]
(30 answers)
Closed 8 years ago.
First off I have my "Deck" class here. I've just put in the some basic methods, for testing purposes. It's my first go at creating a "card" program.
public class Deck
{
private int deckCounter = 0;
private List<Card> deckSize = new List<Card>();
private List<Card> shuffledDeck = new List<Card>();
private Random random = new Random();
public Deck()
{
}
public void Build()
{
for (int i = 1; i < 5; i++)
{
for (int k = 1; k < 14; k++)
{
deckSize.Add(new Card(k.ToString(), i));
}
}
}
public void Add(Card card)
{
deckSize.Add(card);
deckCounter++;
}
public Card RemoveCard()
{
Card cardToRemove = deckSize.First();
deckSize.RemoveAt(0);
return cardToRemove;
}
public void ShowContainedCards()
{
int cardCount = 0;
foreach (Card c in deckSize)
{
Console.WriteLine(c.ReturnCardInfo());
cardCount++;
}
Console.WriteLine(cardCount);
}
public void Shuffle()
{
while (deckSize.Count != 0)
{
int i = random.Next(deckSize.Count);
shuffledDeck.Add(deckSize[i]);
deckSize.RemoveAt(i);
}
deckSize = shuffledDeck;
}
public bool IsEmpty()
{
if (deckSize.Any())
{
return false;
}
else return true;
}
public List<Card> GetCardList()
{
return deckSize;
}
}
Basicly, what I do is, this:
Deck deck1 = new Deck();
Deck deck2 = new Deck();
deck1.Build();
deck1.Shuffle();
deck2.Build();
deck2.Shuffle();
After that, I get the exact same shuffle, for deck1 and deck2. Why is that? Also, I'm a newb at this, if you couldn't tell :)
Use the same Random class instance in both deck instances:
Random random = new Random();
Deck deck1 = new Deck(random);
Deck deck2 = new Deck(random);
So, in the constructor:
public class Deck
{
private int deckCounter = 0;
private List<Card> deckSize = new List<Card>();
private List<Card> shuffledDeck = new List<Card>();
private Random random;
public Deck(Random random)
{
this.random = random;
}
The current problem with your code, is that the two instances of Random that are created are seeded the same. This causes them to produce the same results. Using the same instance of Random means the second shuffle will build on top of the seeded results of the first shuffle.
From the docs:
The default seed value is derived from the system clock and has finite resolution. As a result, different Random objects that are created in close succession by a call to the default constructor will have identical default seed values and, therefore, will produce identical sets of random numbers.
The same docs also suggest a solution:
This problem can be avoided by using a single Random object to generate all random numbers.
Hence, one possible solution would be to make your random generator static, so all of your Deck instances share the same Random instance:
private static Random random = new Random();
That way, you would even avoid changing any part of the public interface of your Deck class.
Computers are inherently not random, so any random number generator will actually be using an algorithm to produce output that looks random. The thing with this is that there's always a starting point, and if you know where it' starting from, you can predict the outcome. Random number generators therefore have a "seed" which tells it where to start. The same seed will always give the same sequence of "random" numbers.
Both times, you're using new Random(), which uses the default seed. In some languages, you'd be advised to pass the current time as a seed, but C# does that for you. However, if you create two Random objects close together, they're likely to get the same time, which is what's happening here.
If you made your Random static, then all your random numbers would come from the same source, so the two decks would get successive random numbers, not the same ones in parallel.
My program needs to:
a. Generate an array of 20 random integers from zero to nine. Search for the first occurrence, if any, of the number 7, and report its position in the array.
b. Repeat the computation of part a 1000 times, and for each position in the array, report the number of times that the first occurrence of a 7 in the array is at that position
However whenever I run the program I get strange results (different every time) such as:
No sevens found at any position
1000 sevens found at one position and no sevens found anywhere else
Hundreds of sevens found in 2 positions, and none found anywhere else.
Does anyone have an idea what is wrong with my program?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Week_6_Project_2
{
class Program
{
static int intArrayLength = 20;
static int[] resultsArray = new int[intArrayLength];
public static Array generateRandomArray() {
int[] randomNumberArray = new int[intArrayLength];
Random random = new Random();
int popcounter = 0;
while (popcounter < intArrayLength) {
randomNumberArray[popcounter] = random.Next(0, 10);
popcounter += 1;
}
return randomNumberArray;
}
public static void searchForSevens()
{
int counter = 0;
int[] randomArray = (int[])generateRandomArray();
while (counter < intArrayLength)
{
if (randomArray[counter] == 7)
{
resultsArray[counter] += 1;
counter = intArrayLength;
}
counter += 1;
}
}
static void Main()
{
int searchCounter = 0;
while (searchCounter < 1000)
{
searchForSevens();
searchCounter += 1;
}
int displayCounter = 0;
while (displayCounter < intArrayLength)
{
Console.WriteLine("Number of first occurrence of 7 at position {0} = {1}", displayCounter, resultsArray[displayCounter]);
displayCounter += 1;
}
Console.ReadLine();
}
}
}
Your main problem is that each searchForSevens() test only takes a small fraction of time and the Random class uses auto-seeding from the clock. The clock however has a limited resolution. The result is that many (sometimes all) of your random sequences will be the same. And at most you will have 2 or 3 different result sets.
The simple fix for this single-threaded program is to use 1 static instance of Random.
You're instantiating a new instance of Random every time you call the generateRandomArray method. Since the random number generator uses the current time as a seed, instantiating two Random instances at the same time results in the same numbers being generated, which explains your unexpected results.
To solve your problem, you should only instantiate one Random instance, store it in private field, and reuse it every time you call the Next method.
The problem I assume stems from the fact, that Random() uses current time as seed. And the computation happens so fast, that each time new Random() is called, it uses same time. So you get same sequence of numbers.
To fix this, you simply need to set seed by yourself, incremmenting it every cycle should be enough.
long base = DateTime.Now.TotalMilliseconds;
Random rand = new Random(base+searchCounter);
.. something like that.
I will not answer but will try to give an analogy for the people that think that they need more then one Random instance...
Suppose that you need to fill 6 sheets of paper with random numbers from 1-6. Ask yourself this: do you need 6 dices or one to do the job? If you answer that you need more than one dice, ask yourself this: how different or more random is throwing different dice instead of same dice every time?
I mean, if you throw ONE on a dice, next throw of a dice won't have any less chance to be ONE again than it would be any other number. It goes against intuition, but it is mathematically and statistically so.
In your original code, you're calling the Random method in rapid succession [broken example based on OP's original code], thus seeding the method with the same number, resulting in duplicate "random" numbers. Creating a static member will ensure randomness simply because you're only creating a single instance of it.
Try creating a single static instance of random like this. [static member example].
static readonly Random Random = new Random();
Based on this, here's how I would solve your particular problem.
using System;
namespace Week_6_Project_2
{
class Program
{
// ******************************************
// THIS IS A SINGLE INSTANCE OF Random.
// read below as to why I'm seeding the instantiation of Random();
static readonly Random Random = new Random(Guid.NewGuid().GetHashCode());
// ******************************************
private const int IntArrayLength = 20;
static readonly int[] ResultsArray = new int[IntArrayLength];
public static Array GenerateRandomArray()
{
var randomNumberArray = new int[IntArrayLength];
var popcounter = 0;
while (popcounter < IntArrayLength)
{
randomNumberArray[popcounter] = Random.Next(0, 10);
popcounter += 1;
}
return randomNumberArray;
}
public static void SearchForSevens()
{
var counter = 0;
var randomArray = (int[])GenerateRandomArray();
while (counter < IntArrayLength)
{
if (randomArray[counter] == 7)
{
ResultsArray[counter] += 1;
counter = IntArrayLength;
}
counter += 1;
}
}
static void Main()
{
var searchCounter = 0;
while (searchCounter < 1000)
{
SearchForSevens();
searchCounter += 1;
}
var displayCounter = 0;
while (displayCounter < IntArrayLength)
{
Console.WriteLine("Number of first occurrence of 7 at position {0} = {1}", displayCounter, ResultsArray[displayCounter]);
displayCounter += 1;
}
Console.ReadLine();
}
}
}
Further reading about Random()
Beyond the answer above, sometimes it is necessary to seed Random(int); (I like to use the HashCode of a Guid) to ensure further randomness. This is because the default seed uses the clock which from the docs [microsoft] has a finite resolution. If your class is instantiated multiple times in quick succession (< 16ms), you will get the same seed from the clock... this breaks stuff.
[example of seeded Random(int) run in rapid succession with random results]
"using the parameterless constructor to create different Random objects in close succession creates random number generators that produce identical sequences of random numbers."
hear me when I say that you should NOT instantiate a new Random on every iteration of a loop -- use a static member
Another valid reason to implement your own seed is when you want to recreate a random sequence [example of two identical lists based on same seed]. Re-using the same seed will recreate the sequence since the sequence is based on the seed.
note: others might say that seeding it is not necessary [link], but I personally believe that for the additional few keystrokes and the microscopic hit on the clock, you might as well increase the probability of a unique seed. It doesn't hurt anything, and in some situations it can help.
I know there are many questions on the net about it ,but I would like to know why my method fails
What Am i Doing wrong?
public class Generator
{
private static readonly Random random = new Random();
private static readonly object SyncLock = new object();
public static int GetRandomNumber(int min, int max)
{
lock (SyncLock)
{
return random.Next(min, max);
}
}
}
[TestFixture]
public class Class1
{
[Test]
public void SimpleTest()
{
var numbers=new List<int>();
for (int i = 1; i < 10000; i++)
{
var random = Generator.GetRandomNumber(1,10000);
numbers.Add(random);
}
CollectionAssert.AllItemsAreUnique(numbers);
}
}
EDIT
Test method is failing!! Sorry for not mentioning
Thanks for your time and suggestions
How can you possibly expect a sequence of 10,000 random numbers from a set of 10,000 possible values to be all unique unless you are extremely lucky? What you are expecting is wrong.
Flip a coin twice. Do you truly expect TH and HT to be the only possible sequences?
What makes you think random numbers should work any differently?
This output from a random number generator is possible:
1, 1, 1, 1, 1, 1, ..., 1
So is this:
1, 2, 3, 4, 5, 6, ..., 10000
In fact, both of those sequences are equally likely!
You seem to be under the misapprehension that the Random class generates a sequence of unique, though apparently random numbers. This is simply not the case; randomness implies that the next number could be any of the possible choices, not just any except one I've seen before.
That being the case, it is entirely unsurprising that your test fails: the probability that 10000 randomly generated integers (between 1 and 10000 no less) are unique is minuscule.
Random != Unique
The point here is that your code should model your problem and yours really doesn't. Random is not equal to unique. If you want unique, you need to get your set of values and shuffle them.
If you truly want random numbers, you can't expect them to be unique. If your (P)RNG offers an even distribution, then over many trials you should see similar counts of every value (see the Law of Large Numbers). Cases may show up that seem "wrong" but you can't discount that you hit that case by chance.
public static void FisherYatesShuffle<T>(T[] array)
{
Random r = new Random();
for (int i = array.Length - 1; i > 0; i--)
{
int j = r.Next(0, i + 1);
T temp = array[j];
array[j] = array[i];
array[i] = temp;
}
}
int[] array = new int[10000];
for (int i = 0; i < array.Length; i++) array[i] = i;
FisherYatesShuffle(array);
I think you failed to mention that your test method is failing.
It is failing because your random generator is not producing Unique numbers. I'm not sure how it would under it's current condition.
I made this code to load about 8 different textures to a list of objects with a texture property.
I have a folder with textures named "1.png, 2.png, 3.png,.......,46.png" and I want the 8 different objects to be loaded with randomly chosen textures.
DockedFruitsList = new List<Fruit>(8);
for (int i = 0; i < 8; i++)
{
Fruit temp = new Fruit();
temp = new Fruit();
temp.Position = AvailablePositions[i];
int random=(new Random().Next(0, 4600) % 46);
temp.Texture = Content.Load<Texture2D>(#"Fruits/" + random);
DockedFruitsList.Add(temp);
}
The thing is, despite the random always generates a different number, the result of draw is always the same texture, it changes from a run to another run, but it's always the same for all the 8 textures
spriteBatch.Begin();
for (int i = 0; i < DockedFruitsList.Count; i++)
{
spriteBatch.Draw(DockedFruitsList[i].Texture, DockedFruitsList[i].Position, Color.White);
}
spriteBatch.End();
Try this out:
for (int i = 0; i < 100; i++)
Console.WriteLine(new Random().Next(0, 10));
Odds are you'll get an output like this:
5
5
5
.
.
.
This is because the seed of the Random class is initialized with a time-based value. If you initialize many instances of the Random class near the same point in time, then they will all end up with the same seed, and so the values they will produce will all be the same.
What you really want to do is to create one Random instance and use that for all your random values. The values generated will have no relation to each other:
var r = new Random();
for (int i = 0; i < 100; i++)
Console.WriteLine(r.Next(0, 10));
Output:
2
8
0
.
.
.
From the msdn:
The random number generation starts from a seed value.
If the same seed is used repeatedly, the same series of numbers is generated.
By default, the parameterless constructor of the Random class uses the system clock to generate its seed value
System clock it uses only changes its value every few milliseconds, so if you call new Random() very quickly it'll get seeded with the same number, thus the calls to Next... will yield identical results.
Note that if you debugged it, stepping through the code gave the system clock time to advance, thus you won't get the error unless it runs through the loop without you breaking / stepping through.
Create the Random object once, and reuse it (note i'm now converting random to string and i've called a different method on random too):
var rand = new Random();
DockedFruitsList = new List<Fruit>(8);
for (int i = 0; i < 8; i++)
{
Fruit temp = new Fruit();
temp = new Fruit();
temp.Position = AvailablePositions[i];
int random=(rand.Next(46) + 1);
temp.Texture = Content.Load<Texture2D>(#"Fruits/" + random.ToString());
DockedFruitsList.Add(temp);
}
new Random().Next(0, 4600)
means you initialize the rng every time (maybe with the same seed?)
Move the new outside the method (static member or similar).
Random is seeded by the time(GetTickCount()), the time changes only every few milliseconds. So all instances of random created within that interval will return the same sequence. The correct thing is only creating a single instance of Random outside the loop.
DockedFruitsList = new List<Fruit>(8);
Random rand = new Random();
for (int i = 0; i < 8; i++)
{
Fruit temp = new Fruit();
temp = new Fruit();
temp.Position = AvailablePositions[i];
int random=(rand.Next(1, 46));
temp.Texture = Content.Load<Texture2D>(#"Fruits/" + random);
DockedFruitsList.Add(temp);
}
Check Revisiting randomness for more details.
There is also no reason to use rand.Next(0, 4600)%46. You can use rand.Next(0,46) directly.
Note that this code will still return duplicate entries. If you want to avoid that entirely you can use:
Random rand=new Random();
foreach(int randomFruid in Range(1,46).Shuffle(rand).Take(8))
{
...
}
With Shuffle from Is using Random and OrderBy a good shuffle algorithm?