MatrixXf::Random always returning same matrices
Asked Answered
G

4

13

I just played around with Eigen a bit and noticed that MatrixXf::Random(3,3) always returns the same matrices, first one is always this for example:
0.680375 0.59688 -0.329554
-0.211234 0.823295 0.536459
0.566198 -0.604897 -0.444451

Is that intended behaviour or am i just overseeing something really simple? (My experience with mathematic libraries is close to zero)

Code i used:

for(int i = 0; i < 5; i++) {
        MatrixXf A = MatrixXf::Random(3, 3);
        cout << A <<endl;
}
Garlan answered 22/1, 2014 at 20:7 Comment(0)
M
23

Yes, that's the intended behaviour. Matrix::Random uses the random number generator of the standard library, so you can initialize the random number sequence with srand(unsigned int seed), for instance:

srand((unsigned int) time(0));
Myrlmyrle answered 22/1, 2014 at 21:51 Comment(5)
But this doesn't explain why Matrix::Random is returning the same matrix each time in the loop of wlfbck's original code. Setting the seed will ensure the random results are deterministic, but each call to Matrix::Random should generate a different result.Nostril
@Andrew Medlin, for the code wlfbck posted, I do not get the same matrix each time. I only get his result in the first iteration in the loop. Have you run his code? I get the same matrix repeated if I add the line: srand(1) in the loop.Quicklime
The original question never stated that the returned matrices within the loop are the same but that the sequence, at each run of the program, is the same. This is clear from the first sentence: "[...] first one is always this for example"Myrlmyrle
This is from quite a while ago, but if i remember correctly this was on each run of the program as @Myrlmyrle stated.Garlan
Indeed as @Myrlmyrle said, I misinterpreted the original description. Each loop generates a new result, but they are deterministic due to random seeding. To get your own unique results, use your own random seed. So please ignore my comment of Jul 12, 2018.Nostril
D
28

Instead of srand you can also use a nullary expression together with modern C++11 random number generation:

//see https://en.cppreference.com/w/cpp/numeric/random/uniform_real_distribution
std::random_device rd;
std::mt19937 gen(rd());  //here you could set the seed, but std::random_device already does that
std::uniform_real_distribution<float> dis(-1.0, 1.0);

Eigen::MatrixXf A = Eigen::MatrixXf::NullaryExpr(3,3,[&](){return dis(gen);});

This also allows to use more complex distributions such as a normal distribution.

Dextrose answered 24/11, 2018 at 16:20 Comment(1)
This answer needs some serious upvoting. It rules out all the disadvantages of the legacy rand() functionality.Taken
M
23

Yes, that's the intended behaviour. Matrix::Random uses the random number generator of the standard library, so you can initialize the random number sequence with srand(unsigned int seed), for instance:

srand((unsigned int) time(0));
Myrlmyrle answered 22/1, 2014 at 21:51 Comment(5)
But this doesn't explain why Matrix::Random is returning the same matrix each time in the loop of wlfbck's original code. Setting the seed will ensure the random results are deterministic, but each call to Matrix::Random should generate a different result.Nostril
@Andrew Medlin, for the code wlfbck posted, I do not get the same matrix each time. I only get his result in the first iteration in the loop. Have you run his code? I get the same matrix repeated if I add the line: srand(1) in the loop.Quicklime
The original question never stated that the returned matrices within the loop are the same but that the sequence, at each run of the program, is the same. This is clear from the first sentence: "[...] first one is always this for example"Myrlmyrle
This is from quite a while ago, but if i remember correctly this was on each run of the program as @Myrlmyrle stated.Garlan
Indeed as @Myrlmyrle said, I misinterpreted the original description. Each loop generates a new result, but they are deterministic due to random seeding. To get your own unique results, use your own random seed. So please ignore my comment of Jul 12, 2018.Nostril
P
2

@orian:

std::srand(unsigned seed) is not an Eigen function. The complete code should work like that:

    std::srand((unsigned int) time(0));
    for(int i = 0; i < 5; i++) {   
            MatrixXf A = MatrixXf::Random(3, 3);
            cout << A <<endl;
        }
Pyrene answered 29/9, 2015 at 5:6 Comment(1)
Putting the seeding of the rng into the loop will guarantee that you get the same matrix each time, which is the opposite of what I believe the original poster wanted. To get random matrices which are deterministic, the call to std::srand should be OUTSIDE the loop.Nostril
T
1

How about this way?

#include<iostream>
#include<random>
#include <Eigen/Dense>



int main(){

  std::random_device rd;
  std::mt19937 gen(rd());  
  std::uniform_real_distribution<float> dis(0, 1);

  Eigen::MatrixXf m = Eigen::MatrixXf::Zero(10,10).unaryExpr([&](float dummy){return dis(gen);});
  cout<<"Uniform random matrix:\n"<<m<<endl;
  cout<<"Mean: "<<m.mean()<<endl;

  return 0;
}
Turquoise answered 5/6, 2019 at 11:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.