Eigen Sparse valuePtr is displaing zeros, while leaving out valid values - c++

I don't understand the result I get when I try to iterate over valuePtr of a sparse matrix. Here is my code.
#include <iostream>
#include <vector>
#include <Eigen/Sparse>
using namespace Eigen;
int main()
{
SparseMatrix<double> sm(4,5);
std::vector<int> cols = {0,1,4,0,4,0,4};
std::vector<int> rows = {0,0,0,2,2,3,3};
std::vector<double> values = {0.2,0.4,0.6,0.3,0.7,0.9,0.2};
for(int i=0; i < cols.size(); i++)
sm.insert(rows[i], cols[i]) = values[i];
std::cout << sm << std::endl;
int nz = sm.nonZeros();
std::cout << "non_zeros : " << nz << std::endl;
for (auto it = sm.valuePtr(); it != sm.valuePtr() + nz; ++it)
std::cout << *it << std::endl;
return 0;
}
Output:
0.2 0.4 0 0 0.6 // The values are in the matrix
0 0 0 0 0
0.3 0 0 0 0.7
0.9 0 0 0 0.2
non_zeros : 7
0.2 // but valuePtr() does not point to them
0.3 // I expected: 0.2, 0.3, 0.9, 0.4, 0.6, 0.7, 0.2
0.9
0
0.4
0
0
I don't understand why I am getting zeros, what's going on here?

According to the documentation for SparseMatrix:
Unlike the compressed format, there might be extra space inbetween the
nonzeros of two successive columns (resp. rows) such that insertion of
new non-zero can be done with limited memory reallocation and copies.
[...]
A call to the function makeCompressed() turns the matrix into the standard compressed format compatible with many library.
For example:
This storage scheme is better explained on an example. The following
matrix
0 3 0 0 0
22 0 0 0 17
7 5 0 1 0
0 0 0 0 0
0 0 14 0 8
and one of its possible sparse, column major representation:
Values: 22 7 _ 3 5 14 _ _ 1 _ 17 8
InnerIndices: 1 2 _ 0 2 4 _ _ 2 _ 1 4
[...]
The "_" indicates available free space to quickly insert new elements.
Since valuePtr() simply return a pointer to the Values array, you'll see the empty spaces (the zeroes that got printed) unless you make the matrix compressed.

Related

std::vector.data(), &std::vector[0] and &std::vector.front() returning wrong values

I'm having a little issue that i don't know how to fix. I'm trying to send a std::vector<float*> to the GPU, and in order to do that, I have to return the elements from the array as values instead of pointers.
This float-pointer vector just for testing is storing 2 squares with 4 vertices each, having a total of 8 elements in the vector:
int main()
{
//Start up code goes here
Model m(//position, rotation, scale);
RendererCore::AddModel(m);
//...
}
void RendererCore::AddModel(Model& m)
{
for (int i = 0; i < m.vertices.size(); i++)
{
allVerts.push_back(&m.vertices[i].position.x);
std::cout << *allVerts.back() << std::endl;
allVerts.push_back(&m.vertices[i].position.y);
std::cout << *allVerts.back() << std::endl;
allVerts.push_back(&m.vertices[i].position.z);
std::cout << *allVerts.back() << std::endl;
}
}
When I print them after that, it seems that everything is fine!
-1.5
0.5
1
-1.5
-0.5
1
-0.5
-0.5
1
-0.5
0.5
1
-0.5
0.5
0
-0.5
-0.5
0
0.5
-0.5
0
0.5
0.5
0
But now, when I try to pass them to values like this:
float* result = *&allVerts[0];
//Print data just to test
for(int i = 0; i < allVerts.size(); i++)
{
std::cout << result[i] << std::endl;
}
And print the elements from the "float array", it shows the wrong values!
-1.5
0.5
1
1
1
1
1
1
-1.5
-0.5
1
1
1
1
1
1
-0.5
-0.5
1
1
1
1
1
1
This also happens with *&allVerts.front() and allVerts.data().
A workaround for this is doing a for loop and push the elements one by one, but probably the more models the vector will have, the more it will cost compared to passing the elements to value from the memory address (correct me if I'm wrong, maybe it takes the same amount of time?), so I want to stick with fixing the issue.
The basic problem is that you have a vector of pointers, which don't necessarily all point to contiguous memory. So you can't treat them as such.
In order to get your values into a contiguous array of floats, you'll need to copy them into a contiguous array of floats. Something like
std::vector<float *> allVerts;
std::vector<float> copy;
copy.clear();
for (float *p : allVerts)
copy.push_back(*p);
Now you can use copy.data() (or &copy[0]) to get a pointer to the contiguous array of float values.

How to generate this matrix with armadillo in c++?

I would like to generate a matrix in C ++ using armadillo that behaves like a "truth table", for example:
0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1
I was thinking of a cycle of this kind, but I'm not very practical with armadillo and its data structures.
imat A = zeros<imat>(8, 3);
/* fill each row */
for(int i=0; i < 8; i++)
{
A.row(i) = (i/(pow(2, i)))%2 * ones<ivec>(3).t(); //
}
cout << "A = \n" << A << endl;
Any ideas?
If you need a large size truth table matrix (~2^30 x 30) as you said here, from the memory point of view, you should implement a function which quickly calculates the values you want rather than storing them on a matrix.
This is easily done using std::bitset as follows.
Note that N must be determined at compile-time in this method.
Then you can get the value of your A(i,j) by matrix<3>(i,j):
DEMO
#include <bitset>
template <std::size_t N>
std::size_t matrix(std::size_t i, std::size_t j)
{
return std::bitset<N>(i)[N-j-1];
}

Ordering an array based on 2D array of relations (higher, lower, doesn't matter)

I have been stuck with this problem for two days and I still can't get it right.
Basically, I have a 2D array with relations between certain numbers (in given range):
0 = the order doesn't matter
1 = the first number (number in left column) should be first
2 = the second number (number in upper row) should be first
So, I have some 2D array, for example this:
0 1 2 3 4 5 6
0 0 0 1 0 0 0 2
1 0 0 2 0 0 0 0
2 2 1 0 0 1 0 0
3 0 0 0 0 0 0 0
4 0 0 2 0 0 0 0
5 0 0 0 0 0 0 0
6 1 0 0 0 0 0 0
And my goal is to create a new array of given numbers (0 - 6) in such a way that it is following the rules from the 2D array (e.g. 0 is before 2 but it is after 6). I probably also have to check if such array exists and then create the array. And get something like this:
6 0 2 1 4 5
My Code
(It doesn't really matter, but I prefer c++)
So far I tried to start with ordered array 0123456 and then swap elements according to the table (but that obviously can't work). I also tried inserting the number in front of the other number according to the table, but it doesn't seem to work either.
// My code example
// I have:
// relArr[n][n] - array of relations
// resArr = {1, 2, ... , n} - result array
for (int i = 0; i < n; i++) {
for (int x = 0; x < n; x++) {
if (relArr[i][x] == 1) {
// Finding indexes of first (i) and second (x) number
int iI = 0;
int iX = 0;
while (resArr[iX] != x)
iX++;
while (resArr[iI] != i)
iI++;
// Placing the (i) before (x) and shifting array
int tmp, insert = iX+1;
if (iX < iI) {
tmp = resArr[iX];
resArr[iX] = resArr[iI];
while (insert < iI+1) {
int tt = resArr[insert];
resArr[insert] = tmp;
tmp = tt;
insert++;
}
}
} else if (relArr[i][x] == 2) {
int iI = 0;
int iX = 0;
while (resArr[iX] != x)
iX++;
while (resArr[iI] != i)
iI++;
int tmp, insert = iX-1;
if (iX > iI) {
tmp = resArr[iX];
resArr[iX] = resArr[iI];
while (insert > iI-1) {
int tt = resArr[insert];
resArr[insert] = tmp;
tmp = tt;
insert--;
}
}
}
}
}
I probably miss correct way how to check whether or not it is possible to create the array. Feel free to use vectors if you prefer them.
Thanks in advance for your help.
You seem to be re-ordering the output at the same time as you're reading the input. I think you should parse the input into a set of rules, process the rules a bit, then re-order the output at the end.
What are the constraints of the problem? If the input says that 0 goes before 1:
| 0 1
--+----
0 | 1
1 |
does it also guarantee that it will say that 1 comes after 0?
| 0 1
--+----
0 |
1 | 2
If so you can forget about the 2s and look only at the 1s:
| 0 1 2 3 4 5 6
--+--------------
0 | 1
1 |
2 | 1 1
3 |
4 |
5 |
6 | 1
From reading the input I would store a list of rules. I'd use std::vector<std::pair<int,int>> for this. It has the nice feature that yourPair.first comes before yourPair.second :)
0 before 2
2 before 1
2 before 4
6 before 0
You can discard any rules where the second value is never the first value of a different rule.
0 before 2
6 before 0
This list would then need to be sorted so that "... before x" and "x before ..." are guaranteed to be in that order.
6 before 0
0 before 2
Then move 6, 0, and 2 to the front of the list 0123456, giving you 6021345.
Does that help?
Thanks for the suggestion.
As suggested, only ones 1 are important in 2D array. I used them to create vector of directed edges and then I implemented Topological Sort. I decide to use this Topological Sorting Algorithm. It is basically Topological Sort, but it also checks for the cycle.
This successfully solved my problem.

SparseMatrix in Eigen

If I set the value of a SparseMatrix entry in Eigen as follows:
sparse_matrix->coeffref(10, 10) = 0;
Would this actually shrink the storage required by the matrix or would it try and store a 0 and use up 4 bytes there (assuming integer type)?
if the answer is the latter, how can I set columns to 0, so that it does not use any extra space?
Also, what about something like this:
typedef Eigen::Triplet<double> TripletType;
std::vector<TripletType> t;
for (int i = 0; i < some_value; ++i) {
for (int j = 0; j < some_value; ++j) {
t->push_back(TripletType(i, j, 0);
}
}
sparse_matrix->setFromTriplets(t);
Would this result in explicit zeros in the sparse matrix?
After insertion with coeffRef you can prune the sparse matrix like:
Eigen::SparseMatrix<double, Eigen::ColMajor> A(5,5);
// fill A
A.insert(0,0)=9.;
A.insert(1,0)=3.0/2.0;
A.insert(0,1)=3.0/2.0;
A.insert(2,0)=6.0;
A.insert(0,2)=6.0;
A.insert(3,0)=3.0/4.0;
A.insert(0,3)=3.0/4.0;
A.insert(4,0)=3.0;
A.insert(0,4)=3.0;
A.insert(1,1)=1.0/2.0;
A.insert(2,2)=12.0;
A.insert(3,3)=5.0/8.0;
A.insert(4,4)=16.0;
std::cout << A << std::endl;
std::cout << A.data().size() << std::endl;
A.coeffRef(3,0) = 0;
A.prune(0,0); // Suppresses all nonzeros which are much smaller than reference under the tolerence epsilon
std::cout << A << std::endl;
std::cout << A.data().size() << std::endl;`
Output:
Nonzero entries:
(9,0) (1.5,1) (6,2) (0.75,3) (3,4) (_,_) (_,_) (_,_) (1.5,0) (0.5,1) (6,0) (12,2
) (0.75,0) (0.625,3) (3,0) (16,4)
Outer pointers:
0 8 10 12 14 $
Inner non zeros:
5 2 2 2 2 $
9 1.5 6 0.75 3
1.5 0.5 0 0 0
6 0 12 0 0
0.75 0 0 0.625 0
3 0 0 0 16
16
Nonzero entries:
(9,0) (1.5,1) (6,2) (3,4) (1.5,0) (0.5,1) (6,0) (12,2) (0.75,0) (0.625,3) (3,0)
(16,4)
Outer pointers:
0 4 6 8 10 $
9 1.5 6 0.75 3
1.5 0.5 0 0 0
6 0 12 0 0
0 0 0 0.625 0
3 0 0 0 16
12
You can see that the size has changed from 16 to 12, as also the three (_,_) are removed.
I didn't check with sizeof() if memory storage that is needed is really less.

How to create undirected graph out of adjancency matrix?

Hello everywhere there is an explanation by drawings hot to create graph out of adj. matrix. However, i need simple pseudo code or algorithym for that .... I know how to draw it out of adj. matrix and dont know why nobody no where explains how to actually put it in code. I dont mean actual code but at least algorithm ... Many say .. 1 is if there is an edge i know that.. I have created the adj. matrix and dont know how to transfer it to graph. My vertices dont have names they are just indexes of the matrix. for example 1-9 are the "names of my matrix"
1 2 3 4 5 6 7 8 9
1 0 1 0 0 1 0 0 0 0
2 1 0 1 0 0 0 0 0 0
3 0 1 0 1 0 0 0 0 0
4 0 0 1 0 0 1 0 0 0
5 1 0 0 0 0 0 1 0 0
6 0 0 0 1 0 0 0 0 1
7 0 0 0 0 1 0 0 1 0
8 0 0 0 0 0 0 1 0 0
9 0 0 0 0 0 1 0 0 0
that was originaly a maze ... have to mark row1 col4 as start and row7 col8 end ...
Nobody ever told me how to implement graph out of matrix (without pen) :Pp
thanks
Nature of symmetry
Adjancency matrix is a representation of a graph. For undirected graph, its matrix is symmetrical. For instance, if there is an edge from vertex i to vertex j, there must also be an edge from vertex j to vertex i. That is the same edge actually.
*
*
* A'
A *
*
*
Algorithm
Noticing this nature, you can implement your algorithm as simple as:
void drawGraph(vertices[nRows][nCols])
{
for (unsigned int i = 0; i < nRows; ++i)
{
for (unsigned int j = i; j < nCols; ++j)
{
drawLine(i, j);
}
}
}
You can convert a graph from an adjacency matrix representation to a node-based representation like this:
#include <iostream>
#include <vector>
using namespace std;
const int adjmatrix[9][9] = {
{0,1,0,0,1,0,0,0,0},
{1,0,1,0,0,0,0,0,0},
{0,1,0,1,0,0,0,0,0},
{0,0,1,0,0,1,0,0,0},
{1,0,0,0,0,0,1,0,0},
{0,0,0,1,0,0,0,0,1},
{0,0,0,0,1,0,0,1,0},
{0,0,0,0,0,0,1,0,0},
{0,0,0,0,0,1,0,0,0}
};
struct Node {
vector<Node*> neighbours;
/* optional additional node information */
};
int main (int argc, char const *argv[])
{
/* initialize nodes */
vector<Node> nodes(9);
/* add pointers to neighbouring nodes */
int i,j;
for (i=0;i<9;++i) {
for (j=0;j<9;++j) {
if (adjmatrix[i][j]==0) continue;
nodes[i].neighbours.push_back(&nodes[j]);
}
}
/* print number of neighbours */
for (i=0;i<9;++i) {
cout << "Node " << i
<< " has " << nodes[i].neighbours.size() <<" outbound edges." << endl;
}
return 0;
}
Here, the graph is represented as an array of nodes with pointers to reachable neighbouring nodes. After setting up the nodes and their neighbour pointers you use this data structure to perform the graph algorithms you want, in this (trivial) example print out the number of outbound directed edges each node has.