c++ use 1D Array with 2D Data - c++

I do not use any matrix library, but instead plain std::vector for my matrix data.
To fill it with 2D data I use this code:
data[iy + dataPointsY * ix] = value;
I would like to know is this is correct or if it must be the other way (ix first).
To my understanding fftw needs 'Row-major Format'. Since I use it the formula should be according to row-major format.

Assuming you want row major format for fftw, what you want is:
data[ix + iy*dataPointsY]
The point of row-major is, when the combined index increased by 1, the corresponding row index would be same (assuming not overflowing to the next row).
double m[4][4];
mp = (double*)m;
mp[1+2*3] == m[2][1]; //true
mp[2+2*3] == m[2][2]; //true
mp[2+2*3] == m[3][1]; //false
In general, there's no "right" way to store a matrix. Row major format is also called "C-style" matrix, while column major is called "fortran-style" matrix. The naming is due to different multidimensional array indexing scheme between the two language.

Related

efficiently updating inplace certain blocks of a large sparse matrix in Eigen?

Suppose that I have a large sparse matrix with the following pattern:
the number of nonzeros per column and their locations are fixed
only matrix block A and B will change and the rest of the matrix stays static; (blocks A and B themselves are also sparse with fixed nonzero locations)
As instructed in the document, i've initialized the above matrix by
reserving the exact number of nonzeros per column for the column major sparse matrix
inserting column by column
inserting from the smallest row index per column
In later part of the program, it's natural to reuse the matrix and only updates the A, B blocks inplace. Possible ways are:
accessing existing entries by coeffRef, would introduce binary search so not preferred here.
iterating over the outer and inner dimensions as documented here
However, it seems a bit unnecessary to iterate over all nonzero entries since most part of the sparse matrix stays the same.
Is it possible to update A, B inplace without iterating over all nonzeros in the matrix?
From what I can tell, the InnerIterator can be used used for this and runs in constant time.
Eigen::Index col = 1;
Eigen::Index offset_in_col = 1;
using SparseMatrixD = Eigen::SparseMatrix<double>;
SparseMatrixD mat = ...;
SparseMatrixD::InnerIterator i =
SparseMatrixD::InnerIterator(mat, col) + offset_in_col;
assert(i.row() == 1);
assert(i.col() == 1);
assert(i.value() == C);
This should access the value C. All you need to know is how many nonzero elements are per column (or inner dimension in general). You don't need to know how many nonzero columns (outer dimensions) are stored because that array (SparseMatrix.outerIndexPtr()) has one entry per column.

Armadillo Sparse Matrix Size in Bytes

I would like to assess how large Armadillo sparse matrices are. The question is related to this answer regarding dense matrices.
Consider the following example:
void some_function(unsigned int matrix_size) {
arma::sp_mat x(matrix_size, matrix_size);
// Steps entering some non-zero values
std::cout << sizeof(x) << std::endl;
}
Unfortunately, sizeof does, as in the dense matrix case, not return the size of the matrix itself, but rather the size of a pointer or some other small object. The size of the sparse matrix should not simply be the number of non-zero elements times the data type's size. Armadillo stores sparse matrices in a compressed format. And on top of the cell values, there should also be a matrix or vectors storing the cell indices. And I guess that the matrix also has a header storing information about the object.
There are three key properties:
n_rows
n_cols and
n_nonzero
The last value represents the number of cells 0 <= n_nonzero <= (n_rows*n_cols) which have a value.
You can use this to know the density (which is also displayed as a percentage with .print, e.g.
[matrix size: 3x3; n_nonzero: 4; density: 44.44%]
(1, 0) 0.2505
(0, 1) 0.9467
(0, 2) 0.2513
(2, 2) 0.5206
I used these properties to implement sp_matrix serialization before: How to serialize sparse matrix in Armadillo and use with mpi implementation of boost?
The actual number of bytes allocated will be roughly correlating to n_nonzero, but you have to account for /some/ overhead. In practice the best way to measure actual allocations is by using instrumented allocators, or (the logical extension of that idea) memory profilers. See e.g. How to find the memory occupied by a boost::dynamic_bitset?

Replacing all negative elements with zero eigen3 c++

As said I want to replace all < 0 elements in a eigen3 matrix in C++ with zero in most efficient manner.
I check that there are negative elements using:
(result.array() < 0).any()
A nicer and more efficient way than your proposed method would be to use the select method.
result = (result.array() < 0).select(0, result);
I found a way:
Create a matrix of zeros of same shape,
zero_matrix.setZero();
And find coeff wise maximum between zero matrix and your matrix.
result = result.array().max(zero_matrix.array());

How to auto-generate and assign variables corresponding to elements in a matrix?

I am working on a binary linear program problem.
I am not really familiar with any computer language(just learned Java and C++ for a few months), but I may have to use computer anyway since the problem is quite complicated.
The first step is to declare variables m_ij for every entry in (at least 8 X 8) a matrix M.
Then I assign corresponding values of each element of a matrix to each of these variables.
The next is to generate other sets of variables, x_ij1, x_ij2, x_ij3, x_ij4, and x_ij5, whenever the value of m_ij is not 0.
The value of x_ijk variable is either 0 or 1, and I do not have to assign values for x_ijk variables.
Probably the simplest way to do it is to declare and assign a value to each variable, e.g.
int* m_11 = 5, int* m_12 = 2, int* m_13 = 0, ... int* m_1n = 1
int* m_21 = 3, int* m_12 = 1, int* m_13 = 2, ... int* m_2n = 3
and then pick variables, the value of which is not 0, and declare x_ij1 ~ x_ij5 accordingly.
But this might be too much work, especially since I am going to consider many different matrices for this problem.
Is there any way to do this automatically?
I know a little bit of Java and C++, and I am considering using lp_solve package in C++(to solve binary integer linear program problem), but I am willing to use any other language or program if I could do this easily.
I am sure there must be some way to do this(probably using loops, I guess?), and this is a very simple task, but I just don't know about it because I do not have much programming language.
One of my cohort wrote a program for generating a random matrix satisfying some condition we need, so if I could use that matrix as my input, it might be ideal, but just any way to do this would be okay as of now.
Say, if there is a way to do it with MS excel, like putting matrix entries to the cells in an excel file, and import it to C++ and automatically generate variables and assign values to them, then this would simplify the task by a great deal!
Matlab indeed seems very suitable for the task. Though the example offered by #Dr_Sam will indeed create the matrices on the fly, I would recommend you to initialize them before you assign the values. This way your code still ends up with the right variable if something with the same name already existed in the workspace and also your variable will always have the expected size.
Assuming you want to define a square 8x8 matrix:
m = zeros(8)
Now in general, if you want to initialize a three dimensional matrixh of size imax,jmax,kmax:
imax = 8;
jmax = 8;
kmax = 5;
x = zeros(imax,jmax,kmax);
Now assigning to or reading from these matrices is very easy, note that length and with of m have been chosen the same as the first dimensions of x:
m(3,4) = 4; %Assign a value
myvalue = m(3,4) %read the value
m(:,1) = 1:8 *Assign the values 1 through 8 to the first column
x(2,4,5) = 12; %Assign a single value to the three dimensional matrix
x(:,:,2) = m+1; Assign the entire matrix plus one to one of the planes in x.
In C++ you could use a std::vector of vectors, like
std::vector<std::vector<int>> matrix;
You don't need to use separate variables for the matrix values, why would you when you have the matrix?
I don't understand the reason you need to get all values where you evaluate true or false. Instead just put directly into a std::vector the coordinates where your condition evaluates to true:
std::vector<std::pair<int, int> true_values;
for (int i = 0; i < matrix.size(); i++)
{
for (int j = 0; j < matrix[i].size(); j++)
{
if (some_condition_for_this_matrix_value(matrix[i][j], i, j) == true)
true_values.emplace_back(std::make_pair(i, j));
}
}
Now you have a vector of all matrix coordinates where your condition is true.
If you really want to have both true and false values, you could use a std::unordered_map with a std::pair containing the matrix coordinates as key and bool as value:
// Create a type alias, as this type will be used multiple times
typedef std::map<std::pair<int, int>, bool> bool_map_type;
bool_map_type bool_map;
Insert into this map all values from the matrix, with the coordinates of the matrix as the key, and the map value as true or false depending on whatever condition you have.
To get a list of all entries from the bool_map you can remove any false entries with std::remove_if:
std::remove_if(bool_map.begin(), bool_map.end(),
[](const bool_map_type::value_type& value) {
return value.second == false;
};
Now you have a map containing only entries with their value as true. Iterate over this map to get the coordinates to the matrix
Of course, I may totally have misunderstood your problem, in which case you of course are free to disregard this answer. :)
I know both C++ and Matlab (not Python) and in your case, I would really go for Matlab because it's way easier to use when you start programming (but don't forget to come back to C++ when you will find the limitations to Matlab).
In Matlab, you can define matrices very easily: just type the name of the matrix and the index you want to set:
m(1,1) = 1
m(2,2) = 1
gives you a 2x2 identity matrix (indices start with 1 in Matlab and entries are 0 by default). You can also define 3d matrices the same way:
x(1,2,3) = 2
For the import from Excel, it is possible if you save your excel file in CSV format, you can use the function dlmread to read it in Matlab. You could also try later to implement your algorithm directly in Matlab.
Finally, if you want to solve your binary integer programm, there is already a built-in function in Matlab, called bintprog which can solve it for you.
Hope it helps!

Accessing elements of a cv::Mat with at<float>(i, j). Is it (x,y) or (row,col)?

When we access specific elements of a cv::Mat structure, we can use mat.at(i,j) to access the element at position i,j. What is not immediately clear, however, whether (i,j) refers to the x,y coordinate in the matrix, or the ith row and the jth column.
OpenCV, like many other libraries, treat matrix access in row-major order. That means every access is defined as (row, column). Note that if you're working with x and y coordinates of an image, this becomes (y, x), if y is your vertical axis.
Most matrix libraries are the same in that regards, the access is (row, col) as well in, for example, Matlab or Eigen (a C++ matrix library).
Where these applications and libraries do differ however is how the data is actually stored in memory. OpenCV stores the data in row-major order in memory (i.e. the rows come first), while for example Matlab stores the data in column-major order in memory. But if you're just a user of these libraries, and accessing the data via a (row, col) accessor, you'll never actually see this difference in memory storage order.
So OpenCV handles this a bit strange. OpenCV stores the Mat in row major order, but addressing it over the methood Mat::at() falsely suggests column major order. I think the Opencv documentation is misleading in this case. I had to write this testcase to make sure for myself.
cv::Mat m(3,3,CV_32FC1,0.0f);
m.at<float>(1,0) = 2;
cout << m << endl;
So addressing is done with Mat::at(y,x) :
[0, 0, 0;
2, 0, 0;
0, 0, 0]
But raw pointer access reveals that it is actually stored row major, e.g. the "2" is in the 4th position. If it were stored in column major order, it would be in the 2nd position.
float* mp = &m.at<float>(0);
for(int i=0;i<9;i++)
cout << mp[i] << " ";
0 0 0 2 0 0 0 0 0
As a side remark: Matlab stores and addresses a matrix in column major order. It might be annoying, but at least it is consistent.
OpenCV, like may other libraries, treat matrices (and images) in row-major order. That means every access is defined as (row, column).
Notable exceptions from this general rule are Matlab and Eigen libraries.
From what I've read in the documentation, it's at(y, x) (i.e. row, col).
Since cv::Mat is actually a general matrix, with images being just a special case, it follows matrix indexing and therefore the row (y) comes before the column (x):
mat.at(i, j) = mat.at(row, col) = mat.at(y, x)