I have an Eigen::MatrixXd and I need to modify the value of the elements in its diagonal. In particular I have another Eigen::MatrixXd with one single column and the same number of rows of the first matrix.
I need to subtract to the diagonal of the first matrix the value of the elements of the second matrix.
Example:
A
1 2 3
4 5 6
7 8 9
B
1
1
1
A'
0 2 3
4 4 6
7 8 8
How can I do?
This works for me:
A_2=A-B.asDiagonal();
The simplest and fastest way to do achieve this is:
Eigen::MatrixXd A1(3,3), B(3,1), A2;
...
A2 = A1;
A2.diagonal() -= B;
of course, better use the VectorXd type for vectors (here for B), and finally if B is constant, then you can use array facilities:
A2.diagonal().array() -= 1;
Matrix manipulation in Eigen works very similar to that of arrays. The indexing starts from zero and it is row major. The documentation (Eigen: The Matrix Class is well written and may help you to solve future problems.
For your stated problem the solution is given below.
#include <iostream>
#include <eigen3/Eigen/Dense>
using Eigen::MatrixXd;
int main()
{
MatrixXd matA(3,3), matB(3,1);
matA<<1,2,3,
4,5,6,
7,8,9;
matB<<1,1,1;
for(int i=0; i<3;i++)
matA(i,i) -= matB(i);
std::cout<<matA<<std::endl;
return 0;
}
However, I would use Matrix3d and Vector3d for the first and second matrix, respectively.
for(int i = 0; i < matrix1.rows(); ++i)
matrix1(i, i) -= matrix2(i, 0);
This code iterates over each row of the matrix (matrix1.rows()) and subtracts the corresponding value of matrix2 (matrix2(i, 0)) from the diagonals in matrix1 (matrix1(i, i)).
Related
I have a Eigen::Matrix2Xf where row are X and Y positions and cols act as list index
I would like to have the sum of the columns (rowwise) where some column condition is true, here some example code:
Eigen::Vector2f computeStuff(Eigen::Matrix2Xf & values, const float max_norm){
const auto mask = values.colwise().norm().array() < max_norm;
return mask.select(values.colwise(), Eigen::Vector2f::Zero()).rowwise().sum();
}
But this code does not compile complaining about the types of the if/else matrices, what is the correct (and computationally faster) way to do it?
Also I know that there are similar question with an answer, but they create a new Eigen::Matrix2Xf with the filtered values given the mask, this code is meant to run inside a #pragma omp parallel for so the basic idea is to do not create a new matrix for maintaining cache coherency
Thanks
The main problem with your code is that .select( ... ) needs at least one of its arguments to have the same shape as the mask. The arguments can be two matrices or a matrix and a scalar or vice-versa, but in all cases the matrices have to be shaped like the mask.
In your code mask is a row vector but values is a 2 by x matrix. One way to handle this is to just replicate the row vector into a two row matrix:
#include <Eigen/Dense>
#include <iostream>
Eigen::Vector2f computeStuff(Eigen::Matrix2Xf& values, const float max_norm) {
auto mask = (values.colwise().norm().array() < max_norm).replicate(2, 1);
return mask.select(values, 0).rowwise().sum();
}
int main() {
Eigen::Matrix2Xf mat(2,4);
mat << 1, 4, 3, 2,
1, 2, 4, 3;
auto val = computeStuff(mat, 5);
std::cout << val;
return 0;
}
In the above mask will be:
1 1 0 1
1 1 0 1
i.e. the row 1 1 0 1 duplicated once. Then mask.select(values, 0) yields
1 4 0 2
1 2 0 3
so the result will be
7
6
which i think is what you want, if I am understanding the question.
I am using C++ and the Eigen library to complete a matching task. However, the result is highly inefficient. The following will describe the task and my current solution.
Task
The task involves two large maps of the same size, mapL and mapR. The matching process occurs row-wise. For example, an element in the r-th row of mapL will match with an element in the r-th row of mapR. The values of the two matching elements may not be exactly the same and therefore I need to look for the element in mapR with the smallest difference.
To compute the difference, I go through the following steps:
Extract an element in the r-th row of mapL.
Extract the r-th row of mapR.
Subtract the row of mapR by the element of mapL).
Repeat the above steps for every element in mapL.
Example
An example would be helpful to understand the above process. Let's say we have
mapL = [ 1 2 3 4, 5;
6 7 8 9 10;
11 12 13 14 15];
mapR = [ 5 4 3 2, 1;
10 9 8 7 6;
15 14 13 12 11];
For the first element in mapL, I would like to obtain a vector difference for some subsequent computations
difference = [5 4 3 2 1] - [1] = [4 3 2 1 0];
Current Solution
When building the C++ code, I tried to vectorize the process by using .replicate and .colwise. The following shows an example code:
int nRow = 1800;
int nCol = 2000;
// Setup two random maps for illustration purposes
MatrixXf mapL = MatrixXf::Random(nRow, nCol);
MatrixXf mapR = MatrixXf::Random(nRow, nCol);
// Initialize some parameters
VectorXf rowL;
MatrixXf rowR(1, nCol);
MatrixXf repeatR;
MatrixXf difference;
// Loop through every row
for (int r = 0; r < nRow; r++) {
// Extract a row from mapL and mapR
rowL = mapL.row(r);
rowR = mapR.row(r);
// Repeat rowR along the col direction
repeatR = rowR.replicate(nCol, 1);
// Compute the difference by .colwise
difference = repeatR.colwise()-=rowL;
/*
Some other codes after the difference is computed
*/
}
Problem
The above code takes around 61s on my machine (VS 2017, Release mode, x64) to iterate through every row. I have implemented a similar code in MATLAB and it only takes around 6s. Is there any way that I can improve the efficiency of the C++ code? I am pretty new to C++ and therefore please let me know if I have missed any important concepts. Thank you very much!
Edit
After some more tests, I found a more efficient way to complete the task. Profiling my original code shows that the .replicate and .colwise operations consume a significant amount of computational power (~90%). Using a nested loop takes < 3s to complete the same task. The new code is as follows:
int nRow = 1800;
int nCol = 2000;
MatrixXf mapL = MatrixXf::Random(nRow, nCol);
MatrixXf mapR = MatrixXf::Random(nRow, nCol);
VectorXf rowL;
ArrayXf rowR(1, nCol);
ArrayXf difference;
for (int r = 0; r < nRow; r++) {
rowL = mapL.row(r);
rowR = mapR.row(r).array();
for (int c = 0; c < nCol; c++) {
difference = rowR - rowL(c);
}
}
Two suggestions:
By default, Eigen stores matrices in column-major order. It would probably help here to use row-major order instead by defining
using RowMajorMatrixXf = Matrix<float, Dynamic, Dynamic, RowMajor>;
and working with that instead of MatrixXf so that the rows are contiguous in memory.
The .row(r) method returns an expression object that does not itself copy memory. But assigning it to VectorXf or ArrayXf makes a copy. You could eliminate the copy by holding on to the expression object like decltype(mapL)::RowXpr rowL = mapL.row(r).
I am finding it difficult to understand two specific implementations which solve this problem on codeforces link.
I understand this is similar to the knapsack problem. However when i solved it myself, i was not aware of the algorithm. I solved it from my own understanding of dynamic programming. My idea is to regard the remaining length of the ribbon as the next state. Here's my code
#include<iostream>
using namespace std;
int main(){
int n,res1=0,res2,x=0;
int a,b,c;
cin >> n >> a >> b >> c;
for(int i=0;i <= n/a; i++){
res2 = -20000;
for(int j=0; j <= (n-(a*i))/b; j++){
x = (n - (a*i) - (b*j));
res2=max(res2,(j + ((x % c) ? -10000 : x/c)));
}
res1=max(res1,i+res2);
}
cout << res1 << endl;
return 0;
Implementation 1:
1 #include <bits/stdc++.h>
2 using namespace std;
3 int main()
4 {
5 int f[4005],n,a,i,j;
6 fill(f+1,f+4005,-1e9);
7 cin>>n;
8 for(;cin>>a;)
9 for(i=a;i<=n;i++)
10 f[i]=max(f[i],f[i-a]+1);
11 cout<<f[n];
12 }
Implementation 2:
1 #include <bits/stdc++.h>
2 int n, a, b, c, ost;
3 std::bitset<4007> mog;
4 main()
5 {
6 std::cin>>n>>a>>b>>c;
7 mog[0]=1;
8 for (int i=1; i<=n; i++)
9 if ((mog=((mog<<a)|(mog<<b)|(mog<<c)))[n])
10 ost=i;
11 std::cout << ost;
12 }
Though i understand the general idea of solving the knapsack problem. I do not have a clear understanding of how lines 8,9,10 in Implementation 1 achieve this. Specifically irrespective of the input values of a,b,c the inner for loop is a single pass over the array for the corresponding value a received.
Similarly, I can see that lines 8,9,10 in implementation 2 does the same thing. But i have no clue at all how this piece of code works.
Please help me understand this. I feel there is some hidden structure to these two solutions which i am not seeing. Thanks in advance.
Implementation 1
This is quite straightforward implementation of dynamic programming.
Outer loop just goes through three values: a, b, and c
8 for(;cin>>a;)
Inner loop visits every element of an array and updates current best known number of cuts for given ribbon length.
9 for(i=a;i<=n;i++)
10 f[i]=max(f[i],f[i-a]+1);
Implementation 2
I don't think that it can be called dynamic programming, but the trick is quite neat.
It allocates array of bits with length equal to max n. Then sets one bit on the left. It means, that ribbon with length of 0 is a valid solution.
On each iteration algorithm shifts given array to the left by a, b, and c. Result of each such shift can be viewed as the new valid sizes of ribbon. By oring result of all 3 shifts, we get all valid sizes after i'th cut. If n'th bit set we know ribbon of size n can be cut i times without remainder.
n = 10
a = 2
b = 3
c = 5
i=1:
0|0000000001 // mog
0|0000000100 // mog<<a
0|0000001000 // mog<<b
0|0000100000 // mog<<c
0|0000101100 // mog=(mog<<a)|(mog<<b)|(mog<<c)
^ here is a bit checked in 'if' statement '(mog=(...))[n]'
i=2:
0|0000101100 // mog
0|0010110000 // mog<<a
0|0101100000 // mog<<b
1|0110000000 // mog<<c // here we have solution with two pieces of size 5
1|0111110000 // (mog<<a)|(mog<<b)|(mog<<c)
^ now bit set, so we have a solution
We know that there is exactly i cuts at that point, so we set ost=i. But we found the worst solution, we have to keep going until we are sure that there is no more solutions.
Eventually we will reach this state:
i=5:
1|1100000000 // mog
1|0000000000 // mog<<a // 5 pieces of size 2
0|0000000000 // mog<<b
0|0000000000 // mog<<c
1|0000000000 // (mog<<a)|(mog<<b)|(mog<<c)
Here it is the last time when bit at position n will be set. So we will set ost=5 and will do some more iterations.
Algorithm uses n as upper bound of possible cuts, but it's obvious that this bound can be improved. For example n / min({a,b,c}) should be sufficient.
I was given the following code to use as part of an exercise. I am instructed to create a 3x3 matrix and assign specific values to it.
Here is the code:
void minput(int* m, int row, int col) {
/* assign 3X3 matrix to following value
8 1 6
3 5 7
4 9 2
*/
*(m+0) = 8;
}
What I am trying to figure out is what this piece of code *(m+0) = 8; is for. I know that adding a * in front of any variable means to "give me whatever is that the address".
What does the +0 do?
*(m+0) is equivalent to m[0]. So the whole statement is assigning 8 to m[0].
it dereferences m (gives you the value at it) I'm guessing it's + 0 so that you can add in different values and get the resulting part of the matrix
Arrays are contiguous in memory, so if you were to add 1 instead of 0, you would set the next value in the matrix to 8.
*(m+0) = 8 is the same as m[0] = 8, it dereferences the pointer to the first element then assigns to it the value 8. In your code you represent the matrix via a one-dimensional array, so you probably want to index your (i,j) component as
m+i*col + j or, equivalently, m[i*col+j], i.e. the line
*(m+i*col+j) = x // can also write is as m[i*col+j] = x
assigns x to the (i,j) component.
How can I find the smallest value of each column in the given set of vectors efficiently ?
For example, consider the following program:
#include <iostream>
#include <vector>
#include <iterator>
#include <cstdlib>
using namespace std;
typedef vector<double> v_t;
int main(){
v_t v1,v2,v3;
for (int i = 1; i<10; i++){
v1.push_back(rand()%10);
v2.push_back(rand()%10);
v3.push_back(rand()%10);
}
copy(v1.begin(), v1.end(), ostream_iterator<double>(cout, " "));
cout << endl;
copy(v2.begin(), v2.end(), ostream_iterator<double>(cout, " "));
cout << endl;
copy(v3.begin(), v3.end(), ostream_iterator<double>(cout, " "));
cout << endl;
}
Let the output be
3 5 6 1 0 6 2 8 2
6 3 2 2 9 0 6 7 0
7 5 9 7 3 6 1 9 2
In this program I want to find the smallest value of every column (of the 3 given vectors) and put it into a vector. In this program I want to define a vector v_t vfinal that will have the values :
3 3 2 1 0 0 1 7 0
Is there an efficient way to do this ? I mention efficient because my program may have to find the smallest values among very large number of vectors. Thank you.
Update:
I'm trying to use something like this which I used in one of my previous programs
int count = std::inner_product(A, A+5, B, 0, std::plus<int>(), std::less<int>());
This counts the number of minimum elements between two arrays A and B. Wouldn't it be efficient enough if I could loop through and use similar kind of function to find the minimal values ? I'm not claiming it can be done or not. It's just an idea that may be improved upon but I don't know how.
You can use std::transform for this. The loops are still there, they're just hidden inside the algorithm. Each additional vector to process is a call to std::transform.
This does your example problem in two linear passes.
typedef std::vector<double> v_t;
int main()
{
v_t v1,v2,v3,vfinal(9); // note: vfinal sized to accept results
for (int i = 1; i < 10; ++i) {
v1.push_back(rand() % 10);
v2.push_back(rand() % 10);
v3.push_back(rand() % 10);
}
std::transform(v1.begin(), v1.end(), v2.begin(), vfinal.begin(), std::min<double>);
std::transform(v3.begin(), v3.end(), vfinal.begin(), vfinal.begin(), std::min<double>);
}
Note: this works in MSVC++ 2010. I had to provide a min functor for gcc 4.3.
I think that the lower bound of your problem is O(n*m), where n is the number of vectors and m the elements of each vector.
The trivial algorithm (comparing the elements at the same index of the different vectors) is as efficient as it can be, I think.
The easiest way to implement it would be to put all your vectors in some data structure (a simple C-like array, or maybe a vector of vectors).
The bst way to do this would be to use a vector of vectors, and just simple looping.
void find_mins(const std::vector<std::vector<int> >& inputs, std::vector<int>& outputs)
{
// Assuming that each vector is the same size, resize the output vector to
// change the size of the output vector to hold enough.
output.resize(inputs[0].size());
for (std::size_t i = 0; i < inputs.size(); ++i)
{
int min = inputs[i][0];
for (std::size_t j = 1; j < inputs[i].size(); ++j)
if (inputs[i][j] < min) min = inputs[i][j];
outputs[i] = min;
}
}
To find the smallest number in a vector, you simply have to examine each element in turn; there's no quicker way, at least from an algorithmic point-of-view.
In terms of practical performance, cache issues may affect you here. As has been mentioned in a comment, it will probably be more cache-efficient if you could store your vectors column-wise rather than row-wise. Alternatively, you may want to do all min searches in parallel, so as to minimise cache misses. i.e. rather than this:
foreach (col)
{
foreach (row)
{
x_min[col] = std::min(x_min[col], x[col][row]);
}
}
you should probably do this:
foreach (row)
{
foreach (col)
{
x_min[col] = std::min(x_min[col], x[col][row]);
}
}
Note that STL already provides a nice function to do this: min_element().