Calling a member function that produces random numbers does not give completely random numbers

I am creating a wxWidget application with C ++, where at the beginning of the program I want the application window to contain pixels with random colors as follows:

Random color pixels

There are 3600 pixels (60 x 60) in the above application, and I gave each pixel a random RGB color with uniform_int_distribution

The colors for the pixels in the image above are currently generated using the following function in my code:

 void random_colors(int ctable[][3], int n) { // construct a trivial random generator engine from a time-based seed: unsigned seed = std::chrono::system_clock::now().time_since_epoch().count(); std::default_random_engine generator (seed); std::uniform_int_distribution<int> distribution(0,255); for(int i=0; i<n; i++) { for(int j=0; j<3; j++) { ctable[i][j] = distribution(generator); } } } 

I do this by providing this function with a 3600 x 3 table and this function will populate the values ​​for the colors.

This method, however, is not what I want. I want to create a class called somNode , where each somNode object represents a pixel in the picture (with RGB values ​​as an attribute of an array of elements). In this somNode class, I have a member function using uniform_int_distribution to give when each somNode created its own random RGB color. This is a function that creates a random color for each somNode :

 void rand_node_colour(int nodeWeights[]) { // construct a trivial random generator engine from a time-based seed: unsigned seed = std::chrono::system_clock::now().time_since_epoch().count(); std::default_random_engine generator (seed); std::uniform_int_distribution<int> distribution(0,255); for(int i=0; i<3; i++) { nodeWeights[i] = distribution(generator); } } 

an array of nodeWeights elements represents the RGB value for somNode . Now, when I create this "som-grid", which I have in the image above (3600 pixels, corresponding to 3600 somNode s), I use the following code (look at som-constructor):

 #include "somNode.h" #include <vector> class som { public: double learning_rate; std::vector<somNode> somGrid; public: som(double lrate); void epoch(); void trainOnce(); }; /* * Initialize the som grid */ som::som(double lrate) { learning_rate = lrate; // Create the som grid for(int i=0; i<60; i++) { for(int j=0; j<60; j++) { int xL = j*10; int xR = (j+1)*10; int yT = i*10; int yB = (i+1)*10; somGrid.push_back(somNode(xL, xR, yB, yT)); } } } // Train som by one epoch void som::epoch() { } // Train som by one color void som::trainOnce() { } 

So, I have a vector<somNode> somGrid where I click all these 3600 somNode when I create them. When constructing each node, the somNode rand_node_colour member somNode rand_node_colour , which creates an RGB value.

When I implement this code instead of the one I used, I get this result first:

enter image description here

You can see that there is a clear outline, so something is wrong here. My question is: what happens in random number generation when creating somNodes? Why doesn't it give the same result as the code I used above?

PS here is somNode.cpp :

 #include <random> #include <iostream> #include <chrono> #include<cmath> void rand_node_colour(int nodeWeights[]); /* * This class represent a node in the som-grid */ class somNode { public: // Weight of the node representing the color int nodeWeights[3]; // Position in the grid double X, Y; // corner coorinates for drawing the node on the grid int x_Left, x_Right, y_Bottom, y_Top; public: // Constructor somNode(int xL, int xR, int yB, int yT); void editWeights(int r, int g, int b); double getDistance(int r, int g, int b); }; somNode::somNode(int xL, int xR, int yB, int yT) { // Set the corner points x_Left = xL; x_Right = xR; y_Bottom = yB; y_Top = yT; // Initialize random weights for node rand_node_colour(nodeWeights); // Calculate the node position (center coordinate) X = x_Left + (double)((x_Right - x_Left)/double(2)); Y = y_Bottom + (double)((y_Top - y_Bottom)/double(2)); } void somNode::editWeights(int r, int g, int b) { nodeWeights[0] = r; nodeWeights[1] = g; nodeWeights[2] = b; } double somNode::getDistance(int r, int g, int b) { return sqrt(pow(nodeWeights[0]-r, 2) + pow(nodeWeights[1]-g, 2) + pow(nodeWeights[2]-b, 2)); } void rand_node_colour(int nodeWeights[]) { // construct a trivial random generator engine from a time-based seed: unsigned seed = std::chrono::system_clock::now().time_since_epoch().count(); std::default_random_engine generator (seed); std::uniform_int_distribution<int> distribution(0,255); for(int i=0; i<3; i++) { nodeWeights[i] = distribution(generator); } } 
+7
c ++ random wxwidgets
source share
1 answer

The problem is that you constantly recreate and sow the random number generator in rand_node_colour . You call it a tight loop so you can get the same time, which means that the seed will be the same, which means that the generated random numbers will be the same.

What you need to do is split the generator once and then continue to use its random output. An easy way to fix your code would be to make it static in the sos function, it will be initialized only once, and each subsequent function call will continue, and not run the generator throughout. If we do this, the code will become

 void rand_node_colour(int nodeWeights[]) { // construct a trivial random generator engine from a time-based seed: static std::default_random_engine generator (std::chrono::system_clock::now().time_since_epoch().count()); std::uniform_int_distribution<int> distribution(0,255); for(int i=0; i<3; i++) { nodeWeights[i] = distribution(generator); } } 
+6
source share

All Articles