How do you change a Block in Eigen? - c++

I'm having trouble reassigning a Block. In the code below I store the matrix A in two different ways:
as 3 ArrayXds, one for each row
as an ArrayXXd
.
// data
ArrayXXd A (3, 3);
A << 0, 1, 2, 3, 4, 5, 6, 7, 8;
std::vector<ArrayXd> A_rows = {A.row(0), A.row(1), A.row(2)};
// std::vector<ArrayXd> solution
// first row
ArrayXd & current_row = A_rows[0];
// read it, write it, do stuff
// start working with the second row
current_row = std::ref(A_rows[1]);
cout << current_row << endl << endl; // prints 3 4 5
cout << A << endl; // A is unchanged
// Eigen solution
// first row
Block<ArrayXXd, 1, -1> && current_row_block = A.row(0);
// read it, write it, do stuff
// start working with the second row
current_row_block = std::ref(A.row(1)); // doesn't compile
cout << current_row_block << endl;
cout << A << endl;
The error message is:
error: use of deleted function 'void std::ref(const _Tp&&) [with _Tp = Eigen::Block<Eigen::Array<double, -1, -1>, 1, -1, false>]'
current_row_block = std::ref(A.row(1));
^
Is it possible to fix the second approach or should I move to storing the matrix as std::vector<ArrayXd>?
Related question: Passing a reference of a vector element to a threaded function

You don't need a Block<...> to reference a row. You only need an index.
int current_row_id = 0;
std::out << A.row(current_row_id) << std::end;
current_row_id = 1;
std::out << A.row(current_row_id) << std::end;
For your std::vector<ArrayXd> approach, as you are make copies of the rows, you can not change the original A.

Related

How to convert Eigen::eigenvector().col(0).real() to std vector?

I am working on a code in c++ that calulates the eigen vectors of a matrix using the Eigen library. I need only the first column and only the real values of the eigen vector. Is there a way to copy these values to the std::vector data type? Can someone help me with this?
I saw this Converting Eigen::MatrixXf to 2D std::vector post. But I need only the specific values. Moreover, I am not sure what is the type that eigenvector() function returns. In the documentation, it is said as complex Eigen::Matrix type.
This is an example code.
#include<iostream>
#include<Eigen/Eigenvalues>
#include<vector>
using namespace std;
struct eigen
{
float a, b, c;
};
int main()
{
vector<Eigen::Matrix3f> A(1);
A[0] << 1, 2, 3, 2, 4, 5, 3, 5, 6;
Eigen::EigenSolver<Eigen::Matrix3f> handle(A[0]);
cout << "The matrix of eigenvectors, V, is: " << endl << handle.eigenvectors() << endl << endl;
cout << "The real part of first column is : " << endl <<
handle.eigenvectors().col(0).real() << endl << endl;
return 0;
}
The output of the above code is
The matrix of eigenvectors, V, is:
(0.327985,0) (-0.736977,0) (-0.591009,0)
(0.591009,0) (-0.327985,0) (0.736976,0)
(0.736976,0) (0.591009,0) (-0.327985,0)
The real part of the first column is :
0.327985
0.591009
0.736976
I need to copy the values of handle.eigenvectors().col(0).real() to std::vector<eigen>
Map is the answer:
Vector3f::Map(&v[0].a) = handle.eigenvectors().col(0).real();
You can add a constructor and/or an assignment operator to eigen that copies the values.
struct eigen
{
eigen() = default;
template <typename InputIterator, typename = std::iterator_traits<InputIterator>::value_type>
eigen(InputIterator first) : a(*first++), b(*first++), c(*first++) {}
template <typename InputIterator, typename = std::iterator_traits<InputIterator>::value_type>
eigen& operator=(InputIterator first)
{
a = *first++;
b = *first++;
c = *first++;
return *this;
}
float a, b, c;
};
int main()
{
Eigen::Matrix3f A;
A << 1, 2, 3, 2, 4, 5, 3, 5, 6;
Eigen::EigenSolver<Eigen::Matrix3f> handle(A);
std::cout << "The matrix of eigenvectors, V, is: " << std::endl << handle.eigenvectors() << std::endl << std::endl;
std::cout << "The real part of first column is : " << std::endl <<
handle.eigenvectors().col(0).real() << std::endl << std::endl;
eigen e = handle.eigenvectors().col(0).real();
return 0;
}

C++ pass by reference not changing value

Below is the first part of a function meant to analyze a Tic-Tac-Toe board.
The aboutToWin() function returns true if a player is "about to win," ie has two in a row. The board is represented such that if player 1 has made a move in that square, the value in the 3x3 matrix will be 1. Player 2 will be -1. If no one has made a move, it will be 0.
The part that I put in this question is the first part, which checks the negative diagonal (ie positions 1, 5, and 9 on the board).
bool aboutToWin(int squares[3][3], int& position, bool p1)
{
// The value you are looking for is 2 for p1 and -2 for p2
int check = 2;
if (!p1)
{
check = -2;
}
// Check negative diagonal
int sum = 0;
// Go through negative diagonal
for (int i = 0; i < 3; i++)
{
sum += squares[i][i];
// Saves the position of the last checked 0 square
// If check passes, this will be the winning square
// If not, it will get handled and overwritten
if (squares[i][i] == 0)
{
// Calculates position from i
position = 1 + (4 * i);
std::cout << "\nPosition: " << position << "\n";
}
}
// If this diagonal added to check, stop the function and return now
if (sum == check)
return true;
...
}
This is the code that I'm running from the main() function to test this functionality:
int p;
std::cout << p;
int a3[3][3] = {{1, 0, 1},
{0, 0, 0},
{0, 0, 1}};
std::cout << "\nShould be 1, 5: " << aboutToWin(a3, p, true) << ", " << p;
The output is the following:
0
Position: 5
Should be true, 5: 1, 0
Why is this? I can see that the value gets changed during the function, but it doesn't transfer out of the function.
The problem with using:
std::cout << "\nShould be 1, 5: " << aboutToWin(a3, p, true) << ", " << p;
is that the order of the evaluation of the arguments is not defined unless you use C++17.
It looks like p is evaluated first in your setup before the call to aboutToWin.
Separate the calls.
auto ret = aboutToWin(a3, p, true);
std::cout << "\nShould be 1, 5: " << ret << ", " << p;

Point one array value to another value of the same array - C++

Imagine I have the following code:
int* firstArray[4];
fill_n(firstArray, 4, 0);
//firstArray values are: 0, 0, 0, 0
int* secondArray[4];
fill_n(secondArray, 4, 1);
//secondArray values are: 1, 1, 1, 1
Would there be a way to link the first value of firstArray to the first value of secondArray so that if I do:
secondArray[0] = 20;
//secondArray values would be: 20, 1, 1, 1 (because I just changed it)
//firstArray values would be: 20, 0, 0, 0 (because it's pointing to the value I just changed)
As far as I've tested and researched I can't do something along those lines.
P.S.: This is to create a Samurai Sudoku (in which some chunks of numbers are shared), so when I modify a value that 2 sudokus share it would be updated in both.
You are mixing up concepts. You don't even need to declare a second array just do this:
int myarray [20];
int * mypointer;
mypointer = myarray;
// then you can use both mypointer[] myarray[] the same way to access array elements
The concept of arrays is related to that of pointers. In fact, arrays work very much like pointers to their first elements, and, actually, an array can always be implicitly converted to the pointer of the proper type.
The [] operator in arrays acts the same way as a as a de-referencing operator, but with the added ability of automatically advancing the pointer according to the data type. This is why Array[1] references the same value as *(Array+1)
however you are declaring an arrays of pointers to integers, which means that you can't "store" integer values in this array, but rather store the value of the address where the integer is located.
Additionally when you declare an array you are essentially declaring a constant pointer, so you can not "steal" it and make it pointer to another location.
Study this Code and it's output (RUN THIS CODE)
#include <iostream>
using namespace std;
void printarray (int arg[], int length) {
for (int n=0; n<length; ++n)
cout << arg[n] << ' ';
cout << '\n';
}
int main ()
{
int first[] = {5, 10, 15, 14, 13};
printarray (first,3);
// int* third[] = {1,1,1}; Not accepted because int is not int*
// storing the addresses of first as pointers in 2 different arrays
int* third[] = {first,first+2,first+3};
int* forth[] = {first,first+2,first+3};
// the memory adress where the pointers TO first is stored
cout << third << endl;
cout << forth << endl;
cout << &third << endl;
cout << &forth << endl;
// the memory adress where the pointer TO the value of first[0] is stored
cout << *third << endl;
cout << *forth << endl;
cout << third[0] << endl;
cout << forth[0] << endl;
// you are defrencing twice
cout << *third[0] << endl;
cout << *forth[0] << endl;
cout << **third << endl;
cout << **forth << endl;
// assign once
first[0] = 77;
// applys to all values
cout << first[0] << endl;
cout << *third[0] << endl;
cout << *forth[0] << endl;
// better yet declare a int* and use it same way your array
int* second;
second = first;
cout << first[0] << endl;
cout << second[0] << endl;
// again change value and the change is reflected everywhere
second[0] = 99;
cout << first[0] << endl;
cout << second[0] << endl;
cout << *third[0] << endl;
cout << *forth[0] << endl;
}
OUTPUT
5 10 15
0x786378c0b860
0x786378c0b880
0x786378c0b860
0x786378c0b880
0x786378c0b840
0x786378c0b840
0x786378c0b840
0x786378c0b840
5
5
5
5
77
77
77
77
77
99
99
99
99
Store int**s instead of int*s this way you can have each entry in the array point to the same address.
You would initialize the first element lets say as:
int *first = new int;
*first = 1;
firstArray[0] = first;
secondArray[0] = first;
Then if you write *first = 20; both arrays will be updated.
There is a problem with your question that you initialize first to 0 and then to 1. If they were the same address then setting to 1 would overwrite the setting to 0.
You question is not self coherent :
you write int* secondArray[4]; : secondArray is an array of 4 pointers to int
you write secondArray[0] = 20 : here secondArray is an array of 4 int values
Hyp 1 : arrays of 4 int values
&secondArray[1] is &secondArray[0] + 1. Full stop. That the way arrays work in C++. In that case if secondArray[0] is the same as firstArray[0] then the 2 arrays are at same address and are in fact the same array and your example becomes :
int firstArray[4];
fill_n(firstArray, 4, 0);
//firstArray values are: 0, 0, 0, 0
/* int secondArray[4]; first elements could not be related and you should have : */
int *secondArray = firstArray;
fill_n(secondArray, 4, 1);
//secondArray values are: 1, 1, 1, 1
//firstArray values are also: 1, 1, 1, 1
Hyp 2 : arrays of 4 pointers
You can have first element of both array point to same value while the three others are independent
int array[5];
int *firstArray[4];
int *secondArray[4];
firstArray[0] = &(array[0]);
for(int i=1; i<4; i++)
firstArray[i] = secondArray[i] = &(array[1]);
}
secondArray[0] = &(array[4]);
Then :
int* firstArray[4];
fill_n(firstArray, 4, 0);
//firstArray values are: 0, 0, 0, 0
int* secondArray[4];
fill_n(secondArray, 4, 1);
//secondArray values are: 1, 1, 1, 1
//firstArray values are: 1, 0, 0, 0
and
*(secondArray[0]) = 20;
//secondArray values would be: 20, 1, 1, 1 (because I just changed it)
//firstArray values would be: 20, 0, 0, 0 (because it's pointing to the value I just changed)
That is what you asked for, but it is a very unusual requirement and I'm not sure it is really what you need.

Eigen3: Passing fixed size matrix and dynamic size matrix in one data type in template function

I have further question continuing my previous question. Now I want to pass two kinds of Eigen parameters in one type: (1) fixed sized matrix or (2) rows is fixed but cols is dynamic. Both matrices's rows always should be 3. Thy modified function is:
template<typename Derived>
typename Derived::PlainObject bar(const Eigen::MatrixBase<Derived>& v)
{
// EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived);
// EIGEN_STATIC_ASSERT(Derived::RowsAtCompileTime == 3,
// THIS_METHOD_IS_ONLY_FOR_MATRICES_OF_A_SPECIFIC_SIZE);
assert(v.rows() == 3);
typename Derived::PlainObject ret;
std::cout << "v size : " << v.rows() << ", " << v.cols() << std::endl;
std::cout << "ret size: " << ret.rows() << ", " << ret.cols() << std::endl;
return ret;
}
I want to create variable its size is same as the passed parameter v in the function. Passing fixed size matrix is fine, but not for dynamic (column) size matrix. The number of columns of ret for dynamics size matrix is 0.
void main()
{
int n = 1000;
Eigen::Matrix<double, 3, Dynamic> A1 = Eigen::Matrix<double, 3, Dynamic>::Random(3, n);
Eigen::Matrix<double, 3, 1000> B1 = Eigen::Matrix<double, 3, 1000>::Random();
Eigen::Matrix<double, 3, Dynamic> A2 = bar(A1);
Eigen::Matrix<double, 3, 1000> B2 = bar(B1);
}
Output:
v size : 3, 1000
ret size: 3, 0
v size : 3, 1000
ret size: 3, 1000
Is there a consistent way to create variable its size is same as the passed parameter for both of fixed size matrix and dynamic (column) size matrix? Or It is not possible to pass them in one data type?
Thanks in advance!
Since the number of columns is only known at runtime (it's not part of the type), you need to specify it when you create the matrix ret as follow:
template<typename Derived>
typename Derived::PlainObject bar(const Eigen::MatrixBase<Derived>& v)
{
typename Derived::PlainObject ret(v.rows(), v.cols());
std::cout << "v size : " << v.rows() << ", " << v.cols() << std::endl;
std::cout << "ret size: " << ret.rows() << ", " << ret.cols() << std::endl;
return ret;
}
After this change you get the expected answer in both cases:
v size : 3, 1000
ret size: 3, 1000
v size : 3, 1000
ret size: 3, 1000

Pairwise differences between two matrices in Eigen

In matlab/octave pairwise distances between matrices as required for e.g. k-means are calculated by one function call (see cvKmeans.m), to distFunc(Codebook, X) with as arguments two matrices of dimensions KxD.
In Eigen this can be done for a matrix and one vector by using broadcasting, as explained on eigen.tuxfamily.org:
(m.colwise() - v).colwise().squaredNorm().minCoeff(&index);
However, in this case v is not just a vector, but a matrix. What's the equivalent oneliner in Eigen to calculate such pairwise (Euclidean) distances across all entries between two matrices?
I think the appropriate solution is to abstract this functionality into a function. That function may well be templated; and it may well use a loop - the loop will be really short, after all. Many matrix operations are implemented using loops - that's not a problem.
For example, given your example of...
MatrixXd p0(2, 4);
p0 <<
1, 23, 6, 9,
3, 11, 7, 2;
MatrixXd p1(2, 2);
p1 <<
2, 20,
3, 10;
then we can construct a matrix D such that D(i,j) = |p0(i) - p1(j)|2
MatrixXd D(p0.cols(), p0.rows());
for (int i = 0; i < p1.cols(); i++)
D.col(i) = (p0.colwise() - p1.col(i)).colwise().squaredNorm().transpose();
I think this is fine - we can use some broadcasting to avoid 2 levels of nesting: we iterate over p1's points, but not over p0's points, nor over their dimensions.
However, you can make a oneliner if you observe that |p0(i) - p1(j)|2 = |p0(i)|2 + |p1(j)|2 - 2 p0(i)T p1(j). In particular, the last component is just matrix multiplication, so D = -2 p0T p1 + ...
The blank left to be filled is composed of a component that only depends on the row; and a component that only depends on the column: these can be expressed using rowwise and columnwise operations.
The final "oneliner" is then:
D = ( (p0.transpose() * p1 * -2
).colwise() + p0.colwise().squaredNorm().transpose()
).rowwise() + p1.colwise().squaredNorm();
You could also replace the rowwise/colwise trickery with an (outer) product with a 1 vector.
Both methods result in the following (squared) distances:
1 410
505 10
32 205
50 185
You'd have to benchmark which is fastest, but I wouldn't be surprised to see the loop win, and I expect that's more readable too.
Eigen is more of a headache than I thought on first sight.
There is no reshape() functionality for example (and conservativeResize is something else).
It also seems (I'd like to be corrected) to be the case that Map does not just offer a view on the data, but assignments to temporary variables seem to be required.
The minCoeff function after the colwise operator cannot return a minimum element and an index to that element.
It is unclear to me if replicate is actually allocating duplicates of the data. The reason behind broadcasting is that this is not required.
matrix_t data(2,4);
matrix_t means(2,2);
// data points
data << 1, 23, 6, 9,
3, 11, 7, 2;
// means
means << 2, 20,
3, 10;
std::cout << "Data: " << std::endl;
std::cout << data.replicate(2,1) << std::endl;
column_vector_t temp1(4);
temp1 = Eigen::Map<column_vector_t>(means.data(),4);
std::cout << "Means: " << std::endl;
std::cout << temp1.replicate(1,4) << std::endl;
matrix_t temp2(4,4);
temp2 = (data.replicate(2,1) - temp1.replicate(1,4));
std::cout << "Differences: " << std::endl;
std::cout << temp2 << std::endl;
matrix_t temp3(2,8);
temp3 = Eigen::Map<matrix_t>(temp2.data(),2,8);
std::cout << "Remap to 2xF: " << std::endl;
std::cout << temp3 << std::endl;
matrix_t temp4(1,8);
temp4 = temp3.colwise().squaredNorm();
std::cout << "Squared norm: " << std::endl;
std::cout << temp4 << std::endl;//.minCoeff(&index);
matrix_t temp5(2,4);
temp5 = Eigen::Map<matrix_t>(temp4.data(),2,4);
std::cout << "Squared norm result, the distances: " << std::endl;
std::cout << temp5.transpose() << std::endl;
//matrix_t::Index x, y;
std::cout << "Cannot get the indices: " << std::endl;
std::cout << temp5.transpose().colwise().minCoeff() << std::endl; // .minCoeff(&x,&y);
This is not a nice oneliner and seems overkill just to compare every column in data with every column in means and return a matrix with their differences. However, the versatility of Eigen does not seem to be such that this can be written down much shorter.