How to add a block matrix onto a sparse matrix in Eigen - c++

For example I have a 10x10 SparseMatrix A, and I want to add a 3x3 identity matrix to the upper left corner of A.
A is known to be already non-zero in those 3 entries.
If I have to add the values one by one it is ok too, but I didn't find the method to manipulate on elements of a Sparse Matrix in Eigen.
Did I miss something?

If all you want is to apply an operation to a specific element at a time, you can use coeffRef like so:
typedef Eigen::Triplet<double> T;
std::vector<T> coefficients;
for (int i = 0; i < 9; i++) coefficients.push_back(T(i, i, (i % 3) + 1));
Eigen::SparseMatrix<double> A(10, 10);
A.setFromTriplets(coefficients.begin(), coefficients.end());
std::cout << A << "\n\n";
for (int i = 0; i < 3; i++) A.coeffRef(i,i) += 1;
std::cout << A << "\n\n";

Related

Program for finding the transpose of given matrix

I was thinking the approach to finding the transpose of a matrix and
below is the algorithm but it is not giving me proper output , so
anyone can tell me where I have done mistake and what should be proper
algorithm ? And how can I improve it ?
// m is the number of rows and n is the number of columns in a matrix
for (int i = 0; i < m; i++) // For swapping the non-diagonal elements
{
for (int j = 0; j < n; j++)
{
if (i != j)
{
int temp = 0;
temp = a[i][j];
a[i][j] = a[j][i];
a[j][i] = temp;
}
}
}
cout << "Elements of transpose matrix of a is: " << endl;
for (int i = 0; i < m; i++) // printing the elements after transpose
{
for (int j = 0; j < n; j++)
{
cout << a[i][j] << " ";
}
cout << endl;
You made the same mistake one can make while reversing a 1D array, hence I will use that as a simpler example:
#include <vector>
#include <iostream>
#include <utility>
std::vector<int> reverse_broken(std::vector<int> x){
for (size_t i=0;i< x.size(); ++i){
std::swap(x[i],x[x.size()-1-i]);
}
return x;
}
int main(){
auto x = reverse_broken({1,2,3,4});
for (const auto& e : x) std::cout << e << " ";
}
output:
1 2 3 4
reverse_broken iterates all elements and swaps them with the respective reversed element. However, once the first has been swapped with the last, the last has already been swapped. Later swapping the last with the first puts them in the original order again.
Same with your transpose. Once you swapped an element above the diagonal with one below the diagonal, they are already transposed. You don't need to swap them again.
I'll show you the fix for the reverse_broken and leave it to you to apply same fix to your transpose:
std::vector<int> reverse(std::vector<int> x){
for (size_t i=0;i< x.size()/2; ++i){
// stop in the middle ^^ because then all elements have been swapped
std::swap(x[i],x[x.size()-1-i]);
}
return x;
}
You should also consider to not transpose the matrix at all. Depending on how often you access swapped elements and how you populate it, it will be cheaper to either populate it in right order from the start, or just swapping the indices on access:
// normal access:
auto x = a[i][j];
// transposed access:
auto y = a[j][i];
PS: I used reverse only for illustration. To reverse a container you should actually use std::reverse. Also note that you can and should use std::swap. And last but not least, only a square matrix can be transposed in place. For a non square matrix you need to construct a new one with different dimensions.

Removing zero columns or rows using eigen

I was wondering if there is a more efficient way to remove columns or rows that are all zero elements. I am sure there is using the functions in the eigen library but I do not know how.
Right now I am doing it like so, with the idea of the while loop being used in case there are multiple rows/columns that sum to zero I dont want to exceed range limits or pass any zero rows.
void removeZeroRows() {
int16_t index = 0;
int16_t num_rows = rows();
while (index < num_rows) {
double sum = row(index).sum();
// I use a better test if zero but use this for demonstration purposes
if (sum == 0.0) {
removeRow(index);
}
else {
index++;
}
num_rows = rows();
}
}
Currently (Eigen 3.3), there is no direct functionality for this (though it is planned for Eigen 3.4).
Meanwhile can use something like this (of course, row and col can be interchanged, and output is just for illustration):
Eigen::MatrixXd A;
A.setRandom(4,4);
A.col(2).setZero();
// find non-zero columns:
Eigen::Matrix<bool, 1, Eigen::Dynamic> non_zeros = A.cast<bool>().colwise().any();
std::cout << "A:\n" << A << "\nnon_zeros:\n" << non_zeros << "\n\n";
// allocate result matrix:
Eigen::MatrixXd res(A.rows(), non_zeros.count());
// fill result matrix:
Eigen::Index j=0;
for(Eigen::Index i=0; i<A.cols(); ++i)
{
if(non_zeros(i))
res.col(j++) = A.col(i);
}
std::cout << "res:\n" << res << "\n\n";
Generally, you should avoid resizing a matrix at every iteration, but resize it to the final size as soon as possible.
With Eigen 3.4 something similar to this will be possible (syntax is not final yet):
Eigen::MatrixXd res = A("", A.cast<bool>().colwise().any());
Which would be equivalent to Matlab/Octave:
res = A(:, any(A));

Sampling from a boolean matrix in Eigen

I have a matrix A of this form:
Eigen::Matrix<bool, n, m> A(n, m)
and I want to obtain a random element among the ones that are 'true'. The silly way to do that would be to obtain the number of 'true' elements t, generate a random number between 1 and t and iterate:
//r = random number
int k = 0;
for (int i = 0; i < A.rows(); ++i)
for (int j = 0; j < A.cols(); ++j)
{
if (A(i, j))
++k;
if (k == r)
std::cout << "(" << i << ", " << j << ")" << std::endl;
}
This solution is incredibly slow when multiple samples are needed and the matrix is big. Any suggestion as to how I should go about this?
In short: I'd like to find an efficient way to obtain the i-th 'true' element of the above matrix.
You could use Eigen::SparseMatrix instead.
Eigen::SparseMatrix<bool> A(n, m);
With its compressed (or not) column/row storage scheme, you could find the r-th non-zero element in O(m)/O(n) time, or O(log(m)) with binary search.
You could use the COO format utility Eigen::Triplet to find the r-th non-zero element in O(1) time.
std::vector<Eigen::Triplet<bool> > a(num_nonzeros);
And yes, since it's a bool matrix, storing the values is unnecessary too.

Using Eigen/Sparse library in c++, is there a way to delete columns from a sparse matrix?

I have built a matrix which is n rows by n+4 columns, there are four specific columns which I would need to delete to make this into a square. Is there a way to do this with eigen? I have had a look at their Docs and I can't seem to find anything.
Thanks all,
Nick
You can use matrix multiplication, e.g.
SparseMatrix<double> X(10,14);
for (int i = 0; i<14; i++) X.coeffRef(0, i) += (double) (i+1);
SparseMatrix<double> Y(14, 10);
for (int i = 0; i<10; i++) Y.coeffRef(i, i) += 1.0;
cout << X*Y << endl << endl;

Matrix Circular Shift

Does anyone know an efficient way to right circular-shift a matrix? Btw, the matrix is binary but a method to solve a non-binary matrix is also fine.
Right now, I'm thinking of implementing a circular array for the rows of my matrix and updating each row whenever a shift operation is required.
Another method, I was considering was implementing a vector of pointers to columns (of the matrix) represented by vectors and swapping them around when a shift operation occurs.
E.g.
1 2 3
4 5 6
7 8 9
Right-shift
3 1 2
6 4 5
9 7 8
Another problem arises with all these solutions if I need to shift the matrix down as well. To implement both operations efficiently, is completely beyond me.
Down-shift
9 7 8
3 1 2
6 4 5
Something like this perhaps,
class matrix {
std::vector<bool> elements;
int rows, cols, row_ofs, col_ofs;
std::size_t index(int r, int c) {
r = (r + row_ofs) % rows;
c = (c + col_ofs) % cols;
return std::size_t(r)*cols + c; // row major layout
}
public:
matrix() : rows(0), cols(0) {}
matrix(int r, int c)
: elements(std::size_t(r)*c), rows(r), cols(c) {}
int num_rows() const { return rows; }
int num_cols() const { return cols; }
std::vector<bool>::reference operator()(int r, int c) {
return elements.at(index(r,c));
}
bool operator()(int r, int c) const {
return elements.at(index(r,c));
}
void rotate_left() { col_ofs = (col_ofs+1 ) % cols; }
void rotate_right() { col_ofs = (col_ofs+cols-1) % cols; }
void rotate_up() { row_ofs = (row_ofs+1 ) % rows; }
void rotate_down() { row_ofs = (row_ofs+rows-1) % rows; }
};
(untested)
Edit: Here's an alternative: Use std::deque<std::deque<T> > internally. ;-)
Yes, it does support random access. A deque is not a list. Plus, you don't need to bother anymore with the modulo arithmetic.
Not sure what you mean exactly. Usually right-shift is applied to a buffer or row vector. The answer will depend on how your matrix is stored.
An efficient way to rotate an array, if the memory layout allows it, is to copy the first value to the end of the array and then move the pointer to the array up one element. This will only work if you allocate enough room for the array and don't rotate too many times.
Or, you can just keep the array in place and have an extra pointer to the "left end", taking care to handle all the wrapping around correctly in your other operations.
Otherwise, you will probably have to perform a lot of memcopying.
Edit: I see you just updated the question to include this answer.
Other edit: From the examples, you don't seem to need to shift the rows and columns independently. If that is the case, then you just need to store the coordinates of the "top left" index and modify all the matrix operations to lookup values in the data structure appropriately.
The issue for you then becomes a question of where you want the efficiency. Are you going to be performing many shift operations? If not, then it might not be worth slowing down all the multiplication operations with an extra lookup.
And if you do use the lookup idea, definitely DO NOT use a mod operator. It is incredibly inefficient. Instead, for a shift, just test for greater than row or column length and subtract the length when needed.
Another method, I was considering was implementing a vector of pointers to columns (of the matrix) represented by vectors and swapping them around when a shift operation occurs.
I would do this for the columns (horizontal shift) and another vector for the rows (vertical shift).
I would also create a Matrix object to encapsulate your "real" matrix and these two vectors. The getters/setters of your object would reference those two vectors to access data in your "real" matrix and you would have methods like "horizontalShift(...)" and "verticalShift(...)" that only swap values in your two vectors, like you suggested.
Would it be the fastest implementation ? There one more indirection to access the data (still O(1) though) and the swapping would be O(m) for horizontal shift and O(n) for vertical shift (for a n by m matrix) using vectors.
There are methods that make doing the shift itself very fast, but result in inefficiencies when trying to 'use' the matrix, e.g. print, dot\cross products.
For example, if I had a matrix defined like "int m[3][2];" I might just use an index to define the first column index. Thus a shift is just an add\subtract of that one index (no modification of the data).
Another example; if you want to restrict the matrix to being binary, you could pack the matrix into a single variable and use bit shifts (rotate left\right).
Both of these methods would make other operations more complex however.
I guess it all depends on the scope of how the matrix is going to be used and how generic you want it to be.
Using Eigen library it is very simple:
Eigen::Matrix<int, 3, 3> A;
A << 1, 2, 3,
4, 5, 6,
7, 8, 9;
std::cout << A << std::endl << std::endl;
// Right-shift:
A.col(0).swap(A.col(1));
A.col(0).swap(A.col(2));
std::cout << A << std::endl << std::endl;
// Down-shift:
A.row(0).swap(A.row(1));
A.row(0).swap(A.row(2));
std::cout << A << std::endl << std::endl;
There is a very useful reference guide for Eigen-MATLAB correspondence.
I implemented a recursion C++ version by anti clock wise shift:
// rotateMatrix.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
using namespace std;
void rotatematrix(int M[][3], int row, int col, int rowLen, int colLen)
{
//rowLen & colLen are always the orginal matrix total length
// playRows & playCols are the size for the current recuision
// row & col are the starting position related to the original matrix(0,0)
int playRows = rowLen - 2*row ;
int playCols = colLen - 2*col;
if (playCols <= 1 || playRows <= 1)
return;
//row,col is the starting point pointing to the top left corner element
if (rowLen <= 1 || colLen <= 1) return;
int tmp = M[row][col];
//left shift the top row by one element
for (int j = col; j <= playCols + col - 2; ++j)
M[row][j] = M[row][j + 1];
// up shift the right colunm by one position
for (int i = row; i <= playRows + row - 2; ++i)
M[i][col + playCols - 1] = M[i + 1][col + playCols - 1];
//right shift the bottom row by one
for (int j = col + playCols - 2; j >= col; --j)
M[row+playRows-1][j+1] = M[row+playRows-1][j];
// down shift the left col by one
for (int i = row + playRows - 2; i >= row; --i)
M[i+1][col] = M[i][col];
M[row + 1][col] = tmp;
rotatematrix(M, ++row, ++col, rowLen, colLen);
}
int _tmain(int argc, _TCHAR* argv[])
{
// Test Case 1
/*
int a[4][4] = { { 1, 2, 3, 4 },
{ 5, 6, 7, 8 },
{ 9, 10, 11, 12 },
{ 13, 14, 15, 16 } };
int R = 4, C = 4;*/
// Tese Case 2
int R = 3, C = 3;
int a[3][3] = {{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
for (int i = 0; i<R; i++)
{
for (int j = 0; j<C; j++)
cout << a[i][j] << " ";
cout << endl;
}
rotatematrix(a, 0, 0, 3, 3);
// Print rotated matrix
for (int i = 0; i<R; i++)
{
for (int j = 0; j<C; j++)
cout << a[i][j] << " ";
cout << endl;
}
return 0;
}
I have made code for rotating an array in circular fashion layer by layer.
#include<stdio.h>
#include<stdlib.h>
int main()
{
int n;
int value=1;
scanf("%d",&n);
int arr[n][n];
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
arr[i][j]=value++;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
printf("%d\t",arr[i][j]);
printf("\n");
}
for(int r1=0,r2=n-1,c1=0,c2=n-1;r1<=r2;r1++,r2--,c1++,c2--)
{
int temp=arr[c1][r2];
for(int i=r2;i>r1;i--)
arr[c1][i]=arr[c1][i-1];
int temp2=arr[c2][r2];
for(int i=c2;i>c1;i--)
if(i!=c1+1)
arr[i][r2]=arr[i-1][r2];
else
arr[i][r2]=temp;
temp=arr[c2][r1];
for(int i=r1;i<r2;i++)
if(i!=r2-1)
arr[c2][i]=arr[c2][i+1];
else
arr[c2][i]=temp2;
for(int i=c1;i<c2;i++)
if(i!=c2-1)
arr[i][r1]=arr[i+1][r1];
else
arr[i][r1]=temp;
}
printf("\n\n");
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
printf("%d\t",arr[i][j]);
printf("\n");
}
return 0;
}
Sample code working: