C++ equivalent of Python's scipy.sparse.rand - c++

I need C++ equivalent of Python's scipy.sparse.rand function (https://docs.scipy.org/doc/scipy/reference/generated/scipy.sparse.rand.html). I will input m, n, density parameters and rand() function will generate a matrix (preferably COO matrix) for me. How can I do it?

If you have boost on your hands it might be a good idea to use a combination of boost-ublas and boost-random to do the job.
For this you have to install the boost libraries beforehand.
You might optimize the code if you know beforehand the number of non-zero elements.
You can watch the code work at:
https://coliru.stacked-crooked.com/a/097ea92bb336c774
#include <boost/numeric/ublas/matrix_sparse.hpp>
#include <boost/numeric/ublas/io.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_01.hpp>
int main() {
int rows{ 4 };
int cols{ 4 };
double density{ 0.25 };
boost::random::uniform_01<> dist;
boost::random::mt19937 gen;
boost::numeric::ublas::mapped_matrix<double> m(rows, cols, 3 * 3);
for (unsigned i = 0; i < m.size1(); ++i)
for (unsigned j = 0; j < m.size2(); ++j)
if (dist(gen)>density) m(i, j) = dist(gen);
std::cout << m << std::endl;
}

Related

Program not working for some reason, could someone pls help me fix it [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
Could someone please help me fix my program and explain why it s not working?
It's supposed to generate n points with 2 coordinates, which are both random numbers. The values themselves are random but have to scale the interval from 0 to some chosen value k. All the points have to be apart from each other by some radius which is taken to be 1.
For some reason my program doesn't even start. When I run it, Windows just says that the program is not responding and is trying to diagnose the problem.
Please simplify your explanation as much as possible since I'm a complete beginner and probably won't understand otherwise. Thanks a bunch in advance.
#include <iostream>
#include <vector>
#include <cstdlib>
#include <cmath>
#include <fstream>
using namespace std;
int main()
{
int n=5;
int k=100;
vector<vector<double>> a(n, vector<double> (2));
srand(132);
//a[0][1]=k*((float(rand()))/RAND_MAX);
//a[0][0]=k*((float(rand()))/RAND_MAX);
for(int i=0; i<n;){
a[i][0]=k*((float(rand()))/RAND_MAX);
a[i][1]=k*((float(rand()))/RAND_MAX);
for (int j=0; j<n; j+=1){
if (sqrt(pow((a[i][1]-a[j][1]),2)+pow((a[i][0]-a[j][0]),2))<=1){
i=i;
break;}
else if(j==n-1){
cout << a[i][0] << " " << a[i][1] << endl;
i+=1;}
}}
return 0;
}
Your code lacks structure. That's why it is hard to understand, as you now learned even for you.
I think a good start would be to write a class for point and two functions, one for random points and for point distance then all, especially the double loops, will become much easier to read and debug.
Look at this:
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
struct Point
{
Point() = default;
float x;
float y;
};
float scaled_random(int k)
{
return k*((float(rand()))/RAND_MAX);
}
float distance(const Point& a, const Point& b)
{
return sqrt(pow(a.y-b.y,2)+pow(a.x-b.x,2));
}
int main()
{
int n = 5;
int k = 100;
vector<Point> a(n);
srand(132);
for (int i=0; i<n; ) {
a[i].x = scaled_random(k);
a[i].y = scaled_random(k);
for (int j=0; j<n; j+=1) {
if (distance(a[i], a[j]) <= 1) {
i = i;
break;
} else if (j == n-1) {
cout << a[i].x << " " << a[i].y << endl;
i += 1;
}
}
}
return 0;
}
The issue is still the same, but it has now more structure, better formatting and superfluous includes removed.
Maybe you can see the problem yourself much better this way.
The first time through your code i and j will both be zero, this means a[i][1] - a[j][1] and a[i][0] - a[j][0] are zero, this resets i to 0, breaks the loop and starts again resulting in an infinite loop.
Checking i != j fixes the problem:
if (i != j && sqrt(pow((a[i][1] - a[j][1]), 2) + pow((a[i][0] - a[j][0]), 2)) <= 1) {
Your code might be better structured as:
#include <iostream>
#include <vector>
#include <cstdlib>
#include <cmath>
#include <algorithm>
int main()
{
int n = 5;
int k = 100;
std::vector<std::vector<double>> a(n, std::vector<double>(2));
srand(132);
for (int i = 0; i < n; i++) {
auto end = a.begin() + i;
do
{
a[i][0] = k * ((float(rand())) / RAND_MAX);
a[i][1] = k * ((float(rand())) / RAND_MAX);
}
while (end != std::find_if(a.begin(), end, [&](const std::vector<double>& element)
{
return sqrt(pow((a[i][1] - element[1]), 2) + pow((a[i][0] - element[0]), 2)) <= 1;
}));
std::cout << a[i][0] << " " << a[i][1] << "\n";
}
return 0;
}
Using this code only the values before i are checked each time rather than all of the values.
rand should be avoided in modern c++, see Why is the use of rand() considered bad?
As the elements of your vector always have 2 elements it'd be better to use std::pair or std::array.
pow may be quite an inefficient way to square two numbers. The sqrt could be avoided by squaring your distance instead.
Using the above points your code could become:
#include <iostream>
#include <vector>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <array>
#include <random>
using point = std::array<double, 2>;
double distanceSquared(const point& a, const point& b)
{
auto d0 = a[0] - b[0];
auto d1 = a[1] - b[1];
return d0 * d0 + d1 * d1;
}
int main()
{
int n = 5;
int k = 100;
std::vector<point> a(n);
std::random_device rd;
std::mt19937_64 engine(rd());
std::uniform_real_distribution<double> dist(0, k);
for (int i = 0; i < n; i++) {
auto end = a.begin() + i;
do
{
a[i][0] = dist(engine);
a[i][1] = dist(engine);
}
while (end != std::find_if(a.begin(), end, [&](const point& element)
{
return distanceSquared(a[i], element) <= 1;
}));
std::cout << a[i][0] << " " << a[i][1] << "\n";
}
return 0;
}

Why does vc++ compiler cause this statistical pattern?

I'm running the following program:
#include <iostream>
#include <vector>
#include <cmath>
#include <cstdlib>
#include <chrono>
using namespace std;
const int N = 200; // Number of tests.
const int M = 2000000; // Number of pseudo-random values generated per test.
const int VALS = 2; // Number of possible values (values from 0 to VALS-1).
const int ESP = M / VALS; // Expected number of appearances of each value per test.
int main() {
for (int i = 0; i < N; ++i) {
unsigned seed = chrono::system_clock::now().time_since_epoch().count();
srand(seed);
vector<int> hist(VALS, 0);
for (int j = 0; j < M; ++j) ++hist[rand() % VALS];
int Y = 0;
for (int j = 0; j < VALS; ++j) Y += abs(hist[j] - ESP);
cout << Y << endl;
}
}
This program performs N tests. In each test we generate M numbers between 0 and VALS-1 while we keep counting their appearances in a histogram. Finally, we accumulate in Y the errors, which correspond to the difference between each value of the histogram and the expected value. Since the numbers are generated randomly, each of them would ideally appear M/VALS times per test.
After running my program I analysed the resulting data (i.e., the 200 values of Y) and I realised that some things where happening which I can not explain. I saw that, if the program is compiled with vc++ and given some N and VALS (N = 200 and VALS = 2 in this case), we get different data patterns for different values of M. For some tests the resulting data follows a normal distribution, and for some tests it doesn't. Moreover, this type of results seem to altern as M (the number of pseudo-random values generated in each test) increases:
M = 10K, data is not normal:
M = 100K, data is normal:
and so on:
As you can see, depending on the value of M the resulting data follows a normal distribution or otherwise follows a non-normal distribution (bimodal, dog food or kind of uniform) in which more extreme values of Y have greater presence.
This diversity of results doesn't occur if we compile the program with other C++ compilers (gcc and clang). In this case, it looks like we always obtain a half-normal distribution of Y values:
What are your thoughts on this? What is the explanation?
I carried out the tests through this online compiler: http://rextester.com/l/cpp_online_compiler_visual
The program will generate poorly distributed random numbers (not uniform, independent).
The function rand is a notoriously poor one.
The use of the remainder operator % to bring the numbers into range effectively discards all but the low-order bits.
The RNG is re-seeded every time through the loop.
[edit] I just noticed const int ESP = M / VALS;. You want a floating point number instead.
Try the code below and report back. Using the new &LT;random> is a little tedious. Many people write some small library code to simplify its use.
#include <iostream>
#include <vector>
#include <cmath>
#include <random>
#include <chrono>
using namespace std;
const int N = 200; // Number of tests.
const int M = 2000000; // Number of pseudo-random values generated per test.
const int VALS = 2; // Number of possible values (values from 0 to VALS-1).
const double ESP = (1.0*M)/VALS; // Expected number of appearances of each value per test.
static std::default_random_engine engine;
static void seed() {
std::random_device rd;
engine.seed(rd());
}
static int rand_int(int lo, int hi) {
std::uniform_int_distribution<int> dist (lo, hi - 1);
return dist(engine);
}
int main() {
seed();
for (int i = 0; i < N; ++i) {
vector<int> hist(VALS, 0);
for (int j = 0; j < M; ++j) ++hist[rand_int(0, VALS)];
int Y = 0;
for (int j = 0; j < VALS; ++j) Y += abs(hist[j] - ESP);
cout << Y << endl;
}
}

c++ - Fill a symmetric matrix using an array stored on the heap

I am trying to build a code where I have to declare a large array in the heap.
At the same time I will use the boost library to perform some matrix calculations (as can be seen in Fill a symmetric matrix using an array
).
My limitations here are two : I will deal with large arrays and matrices so I have to declare everything on the heap and I have to work with arrays and not with vectors.
However I am facing a rather trivial for many people problem... When filling the matrix, the last element doesn't get filled in correctly. So although I expect to get
[3,3]((0,1,3),(1,2,4),(3,4,5))
the output of the code is
[3,3]((0,1,3),(1,2,4),(3,4,2.6681e-315))
I am compiling this code in ROOT6. I don't think it's related to that, I am just mentioning it for completion.
A small sample of the code follows
#include <iterator>
#include <iostream>
#include <fstream>
#include </usr/include/boost/numeric/ublas/matrix.hpp>
#include </usr/include/boost/numeric/ublas/matrix_sparse.hpp>
#include </usr/include/boost/numeric/ublas/symmetric.hpp>
#include </usr/include/boost/numeric/ublas/io.hpp>
using namespace std;
int test_boost () {
using namespace boost::numeric::ublas;
symmetric_matrix<double, upper> m_sym1 (3, 3);
float* filler = new float[6];
for (int i = 0; i<6; ++i) filler[i] = i;
float const* in1 = filler;
for (size_t i = 0; i < m_sym1.size1(); ++ i)
for (size_t j = 0; j <= i && in1 != &filler[5]; ++ j)
m_sym1 (i, j) = *in1++;
delete[] filler;
std::cout << m_sym1 << std::endl;
return 0;
}
Any idea on how to solve that?
Arrays and pointers are not objects of class type, they don't have members. You already have a float *, it is filler.
float const* in1 = filler; // adding const is always allowed
I've manged to finally solve it by changing &filler[5] to &filler[6].
So a version that works is seen below
#include <iterator>
#include <iostream>
#include <fstream>
#include </usr/include/boost/numeric/ublas/matrix.hpp>
#include </usr/include/boost/numeric/ublas/matrix_sparse.hpp>
#include </usr/include/boost/numeric/ublas/symmetric.hpp>
#include </usr/include/boost/numeric/ublas/io.hpp>
using namespace std;
int test_boost () {
using namespace boost::numeric::ublas;
symmetric_matrix<double, upper> m_sym1 (3, 3);
float* filler = new float[6];
for (int i = 0; i<6; ++i) filler[i] = i;
float const* in1 = filler;
for (size_t i = 0; i < m_sym1.size1(); ++ i)
for (size_t j = 0; j <= i && in1 != &filler[6]; ++ j)
m_sym1 (i, j) = *in1++;
delete[] filler;
std::cout << m_sym1 << std::endl;
return 0;
}
Running this code yields the following output
[3,3]((0,1,3),(1,2,4),(3,4,5))

c++ random engines not really random

I'm playing a bit with c++ random engines, and something upsets me.
Having noticed that the values I had were roughly of the same order, I did the following test:
#include <random>
#include <functional>
#include <iostream>
int main()
{
auto res = std::random_device()();
std::ranlux24 generator(res);
std::uniform_int_distribution<uint32_t> distribution;
auto roll = std::bind(distribution, generator);
for(int j = 0; j < 30; ++j)
{
double ssum = 0;
for(int i = 0; i< 300; ++i)
{
ssum += std::log10(roll());
}
std::cout << ssum / 300. << std::endl;
}
return 0;
}
and the values I printed were all about 9.2 looking more like a normal distribution, whatever the engine I used.
Is there something I have not understood correctly?
Thanks,
Guillaume
Having noticed that the values I had were roughly of the same order
This is exactly what you'd expect with a uniform random number generator. There are 9 times as many integers in the range [10^(n-1),10^n) as there are in the range [0,10^(n-1)).

Vector inside vector (creating chromosomes)

I'm attempting to build a genetic algorithm that can take a certain amount of variables (say 4), and use these in a way so that you could have 2a + 3b + c*c + d = 16. I realise there are more efficient ways to calculate this, but I want to try and build a genetic algorithm to expand later.
I'm starting by trying to create "organisms" that can compete later. What I've done is this:
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <random>
// Set population size
const int population_size = 10;
const int number_of_variables = 4;
int main()
{
// Generate random number
std::random_device rd;
std::mt19937 rng(rd()); // random-number engine (Mersenne-Twister in this case)
std::uniform_int_distribution<int> uni(-10, 10);
// Set gene values.
std::vector<int>chromosome;
std::vector<int>variables;
for (int i = 0; i < number_of_variables; ++i)
{
double rand_num = uni(rng);
variables.push_back (rand_num);
std::cout << variables[i] << "\n";
}
return 0;
}
What happens is it will fill up the number_of_variables vector, and output these just because that makes it clear for me that it's actually doing what I intend for it to do. What I want it to do however is to fill up each "chromosome" with one variables vector, so that for example chromosome 0 would have the values {1, 5, -5, 9} etc.
The following code obviously isn't working, but this is what I'd like it to do:
for (int j = 0; j < population_size; ++j)
{
for (int i = 0; i < number_of_variables; ++i)
{
double rand_num = uni(rng);
variables.push_back(rand_num);
}
chromosome.push_back(variables[j]);
std::cout << chromosome[j] << "\n";
}
Meaning it'd fill up the variables randomly, then chromosome1 would take those 4 values that "variables" took, and repeat. What actually happens is that (I think) it only takes the first value from "variables" and copies that into "chromosome" rather than all 4.
If anyone could help it'd be very much appreciated, I realise this might be simply a rookie mistake that is laughably simply in the eyes of someone more experienced with vectors (which would probably be 99% of the people on this website, hah).
Anyway, thanks :)
#include <iostream>
#include <vector>
#include <random>
// Set population size
const int population_size = 10;
const int number_of_variables = 4;
int main()
{
// Generate random number
std::random_device rd;
std::mt19937 rng(rd()); // random-number engine (Mersenne-Twister in this case)
std::uniform_int_distribution<int> uni(-10, 10);
// Set gene values.
std::vector< std::vector<int>>chromosome;
for( int kp = 0; kp < population_size; kp++ )
{
std::vector<int>variables;
for (int i = 0; i < number_of_variables; ++i)
{
double rand_num = uni(rng);
variables.push_back (rand_num);
}
chromosome.push_back( variables );
}
// display entire population
for( auto c : chromosome )
{
for( auto v : c )
{
std::cout << v << " ";
}
std::cout << "\n";
}
// display 4th member of population
for( auto v : chromosone[ 3 ] )
{
std::cout << v << " ";
}
std::cout << "\n";
return 0;
}
http://ideone.com/2jastJ
You can place a vector inside a vector with the syntax:
std::vector<std::vector<int>>
but you will need to make the outer vector large enough for num_variables.
#include <vector>
#include <cstdlib>
using Individual = std::vector<int>;
using Population = std::vector<Individual>;
// short for std::vector<std::vector<int>>;
const size_t number_of_variables = 8;
int main() {
Population population(10);
for (auto& individual : population) {
individual.resize(number_of_variables);
for (size_t j = 0; j < number_of_variables; ++j) {
individual[j] = j; // replace with random number
}
}
}
Live demo: http://ideone.com/pfufGt