find rowwise maxCoeff and Index of maxCoeff in Eigen - eigen

I want to find the maximum values and indices by row of a matrix. I based this on an example on the eigen website (example 7).
#include <iostream>
#include <Eigen/Dense>
using namespace std;
using namespace Eigen;
int main()
{
MatrixXf mat(2,4);
mat << 1, 2, 6, 9,
3, 1, 7, 2;
MatrixXf::Index maxIndex;
VectorXf maxVal = mat.rowwise().maxCoeff(&maxIndex);
std::cout << "Maxima at positions " << endl;
std::cout << maxIndex << std::endl;
std::cout << "maxVal " << maxVal << endl;
}
Problem here is that my line
VectorXf maxVal = mat.rowwise().maxCoeff(&maxIndex);
is wrong. The original example has
float maxNorm = mat.rowwise().sum().maxCoeff(&maxIndex);
i.e. there is an additional reduction .sum() involved. any suggestions? I guess I just want the eigen equivalent to what in matlab I would write as
[maxval maxind] = max(mymatrix,[],2)
i.e. find maximum value and it's index over the second dimension of mymatrix and return in a (nrow(mymatrix),2) matrix.
thanks!
(sent to the eigen list as well, sorry for cross-posting.)

My guess is that this is not possible without using a for loop using the current api. As you said yourself, you can get the vector of maximum row values using
VectorXf maxVal = mat.rowwise().maxCoeff();
As far as I can tell from the API Documentation for maxCoeff() it will only write back a single index value. Following code (untested) should give you what you want:
MatrixXf::Index maxIndex[2];
VectorXf maxVal(2);
for(int i=0;i<2;++i)
maxVal(i) = mat.row(i).maxCoeff( &maxIndex[i] );

Besides the "for loop" solution by Jakob, you could also use libigl's igl::mat_max which functions like MATLAB's row-/column-wise max
Eigen::MatrixXf mat(2,4);
mat << 1, 2, 6, 9,
3, 1, 7, 2;
Eigen::VectorXi maxIndices;
Eigen::VectorXf maxVals;
igl::mat_max(mat,2,maxVals,maxIndices);
Then maxVals would contain [9;7] and maxIndices would contain [3;2].

Related

Construct SimplicialLLT object from provided L matrix

I performed LLT factorization of a sparse matrix (SimplicialLLT) and modified the L matrix to Lmod (EDIT: I made a copy of the matrix with some modifications). I would like to construct a new SimplicialLLT object from this modified matrix Lmod so that I can directly use it to obtain a solution of system (Lmod*Lmod')x = B. Is this somehow possible in Eigen? Here is a short code example:
#include <iostream>
#include <Eigen/Dense>
#include <Eigen/Sparse>
using namespace Eigen;
using namespace std;
int main()
{
// Initial system A0 x0 = B
// Create dense matrix first
MatrixXd A0dense(5, 5);
A0dense << 1,0,0,0,0,0,2,-1,0,0,0,-1,2,-1,0,0,0,-1,1,0,0,0,0,0,1;
// Convert it to sparse
SparseMatrix<double> A0;
A0 = A0dense.sparseView();
// Create LLT decomposition od A0
SimplicialLLT<SparseMatrix<double>, Lower, NaturalOrdering<int>> LLTofA0(A0);
// Extract the L matrix
SparseMatrix<double> L0 = LLTofA0.matrixL();
cout << "L0 =" << endl << L0 << endl;
// RHS vector B
VectorXd B(5);
B << 0, 0, 0, 1, 1;
// Create a copy of L0 with some modifications
vector<Triplet<double>> Triplets; // Vector of triplets
for (int k = 0; k < L0.outerSize(); ++k)
{
for (SparseMatrix<double>::InnerIterator it(L0, k); it; ++it) // Iterate over nonzero entries of L0
{
if (it.col() != 2)
{
// If the column is unequal to 2, store the location and value
Triplet<double> T(it.row(), it.col(), it.value());
Triplets.push_back(T);
}
}
}
// Create modified Lmod matrix from the stored triplets
SparseMatrix<double> Lmod(L0.outerSize(), L0.outerSize());
Lmod.setFromTriplets(Triplets.begin(), Triplets.end());
cout << "Lmod =" << endl << Lmod << endl;
// Now I want to solve different system (Lmod*Lmod') x = B and use the matrix Lmod for it
}

What's the best algorithm to find a missing number between two sorted numbers?

Okay, so here's an example:
We have an array [1, 2, 3, 6, 7, 9, 15]
And we need to find the number that would fit between two numbers if this were sorted. It should help create a sequence of 3 numbers in the array, at the very least. We can assume there's only one missing number.
The answer in this case would be 8. I got an idea as to how to brute force this in python using the in operator, but it's not very efficient.
def find_missing_number(arr):
for num in arr:
if (
num in arr and
num + 1 not in arr and
num + 2 in arr
):
return num + 1
Any language solutions are appreciated.
Here is a solution in C++ 17,
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
vector<int> v1 {1, 2, 3, 6, 7, 9, 15};
auto const it = std::adjacent_find(v1.begin(), v1.end(),
[] (auto const a, auto const b) {
return b - a == 2;
} );
if (it == v1.end()) {
std::cout << "no matching\n";
} else {
std::cout << "the missing number: " << 1 + *it << '\n';
}
}
Look for consecutive numbers with a distance of two:
def find_missing_number(arr):
arr = sorted(arr) # you'll only need this, if arr is not yet sorted
for a, b in zip(arr, arr[1:]):
if b - a == 2:
return a + 1
You could make it fast by using a set. And remove the pointless num in arr check (that's always true, since you're doing for num in arr).
def find_missing_number(arr):
s = set(arr)
for num in arr:
if (num + 1 not in s) and (num + 2 in s):
return num + 1
Logic that I would suggest is same.
For num = least to max least = 1 and max = 15 in this example
Iterate and see if the loop , and loop + 2 are in the array and loop+1 is not in the array

Get a number value from Vector positions

I'm new here and actually
I've got a problem in my mind, and it's like this:
I get an input of a vector of any size, but for this case, let's take this one:
vetor = {1, 2, 3, 4}
Now, all I want to do is to take this numbers and sum each one (considering it's unity, tens, hundred, thousand) and register the result into a integer variable, for the case, 'int vec_value'.
Considering the vector stated above, the answer should be: vec_value = 4321.
I will leave the main.cpp attached to the post, however I will tell you how I calculated the result, but it gave me the wrong answer.
vetor[0] = 1
vetor[1] = 2
vetor[2] = 3
vetor[3] = 4
the result should be = (1*10^0)+(2*10^1)+(3*10^2)+(4*10^3) = 1 + 20 +
300 + 4000 = 4321.
The program is giving me the solution as 4320, and if I change the values randomly, the answer follows the new values, but with wrong numbers still.
If anyone could take a look at my code to see what I'm doing wrong I'd appreciate it a lot!
Thanks..
There's a link to a picture at the end of the post showing an example of wrong result.
Keep in mind that sometimes the program gives me the right answer (what leaves me more confused)
Code:
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <vector>
#include <cmath>
using namespace std;
int main()
{
vector<int> vetor;
srand(time(NULL));
int lim = rand() % 2 + 3; //the minimum size must be 3 and the maximum must be 4
int value;
for(int i=0; i<lim; i++)
{
value = rand() % 8 + 1; // I'm giving random values to each position of the vector
vetor.push_back(value);
cout << "\nPos [" << i << "]: " << vetor[i]; //just to keep in mind what are the elements inside the vector
}
int vec_value=0;
for(int i=0; i<lim; i++)
{
vec_value += vetor[i] * pow(10, i); //here i wrote the formula to sum each element of the vector with the correspondent unity, tens, hundreds or thousands
}
cout << "\n\nValor final: " << vec_value; //to see what result the program will give me
return 0;
}
Example of the program
Try this for the main loop:
int power = 1;
for(int i=0; i<lim; i++)
{
vec_value += vetor[i] * power;
power *= 10;
}
This way, all the computations are in integers, you are not affected by floating point rounding.

Conversion of data type using auto in C++

I have 2 vector container which contains 2 different kind of value with data type uint32_t. I want to print both of them together.
Like this is what I have
vector<uint32_t> data1;
vector<uint32_t> data2;
Now I know a method for single data like below
for(auto const& d1: data1)
cout<< d1 << endl;
But I want to print both data together like this,
cout<< d1 << "\t" << d2 << endl;
How can I do this using auto? (where d2 is auto converted value from data2)
You could use a normal for loop over the index:
for (auto i = 0u; i != n; ++i)
std::cout << data1[i] << "\t" << data2[i] << "\n";
Edit: if you want to convert the uint32_t to an int, for example, you could do:
auto d1 = static_cast<int>(data1[i]);
but it is up to you to ensure the conversion is safe. i.e the value fits in the target type.
Use the Boost Zip Iterator, which will let you have a range of pairs rather than two ranges of the vectors' data types. Something along the lines of:
#include <boost/iterator/zip_iterator.hpp>
#include <boost/range.hpp>
#include <stdint.h>
#include <vector>
#include <iostream>
template <typename... TContainer>
auto zip(TContainer&... containers) -> boost::iterator_range<boost::zip_iterator<decltype(boost::make_tuple(std::begin(containers)...))>> {
auto zip_begin = boost::make_zip_iterator(boost::make_tuple(std::begin(containers)...));
auto zip_end = boost::make_zip_iterator(boost::make_tuple(std::end(containers)...));
return boost::make_iterator_range(zip_begin, zip_end);
}
int main()
{
std::vector<uint32_t> data1( { 11, 22, 33 } );
std::vector<uint32_t> data2( { 44, 55, 66 } );
for (auto t : zip(data1, data2)) {
std::cout << boost::get<0>(t) << "\t" << boost::get<1>(t) << "\n";
}
}
The zip() function is due to this question and you can put it in a separate header file since it's not specific to your case.
If possible (and plausible for your use case): work with a container of pairs
If your application is not in a bind w.r.t. computer resources, and you know that you will be working with the values of your two containers as pairs (assuming same-length containers, as in your example), it might be useful to actually work with a container of pairs, which also ease the use of the neat range-based for loops ( >= C++11).
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
std::vector<uint32_t> data1 = {1, 2, 3};
std::vector<uint32_t> data2 = {4, 5, 6};
// construct container of (int, int) pairs
std::vector<std::pair<int, int>> data;
data.reserve(data1.size());
std::transform(data1.begin(), data1.end(), data2.begin(), std::back_inserter(data),
[](uint32_t first, uint32_t second) {
return std::make_pair(static_cast<int>(first), static_cast<int>(second));
}); /* as noted in accepted answer: you're responsible for
ensuring that the conversion here is safe */
// easily use range-based for loops to traverse of the
// pairs of your container
for(const auto& pair: data) {
std::cout << pair.first << " " << pair.second << "\n";
} /* 1 4
2 5
3 6 */
return 0;
}

Eigen Library Euler Order Sequencing

I'm trying to understand the Eigen library's "eulerAngles" function, and I have some test code that doesn't make sense.
My testing includes determining if the Euler function call "eulerAngles(0, 1, 2)" corresponds to a "XYZ" Euler sequence of the static frame. For Eigen's column major matrix multiplication, it should correspond to "Z * Y * X". I have confirmed that with some simple tests, but for negative angles around the X axis I don't understand the results. Instead of using a Euler 3 Angle constructor, I'm using the "AngleAxisd" function:
rot3x3 = AngleAxisd( -M_PI, Vector3d::UnitX() );
Vector3d vec = rot3x3.eulerAngles(0, 1, 2);
For positive angles around the X axis, it works the way I expect. For the -M_PI angle (equivalent to 180 degrees), I'm seeing the following:
Euler angles: -0, 3.14159, -3.14159
I expect the first element in the array to be near -π, and the other two to be near zero. I expect the range of the first and last angles to be ±π, and the middle angle to be ±π/2. The middle angle is out of range.
The program is below:
#include "stdafx.h"
#include <iostream>
#include "<Eigen\Dense"
#include "<unsupported\Eigen\MatrixFunctions"
using namespace std;
using namespace Eigen;
int main(int argc, char* argv[])
{
Matrix3d rot3x3;
rot3x3 = AngleAxisd( -M_PI, Vector3d::UnitX() );
cout << "Here is rot3x3:" << endl << rot3x3 << endl << endl;
Vector3d vec = rot3x3.eulerAngles(0, 1, 2); // => 1-2-3 => XYZ => Z*Y*X
cout << "Euler angles: " << vec.x() << ", "
<< vec.y() << ", "
<< vec.z() << endl << endl;
system("pause");
return 0;
}
The output is:
Here is rot3x3:
1 0 0
0 -1 1.22465e-016
0 -1.22465e-016 -1
Euler angles: -0, 3.14159, -3.14159
This result is equivalent to a -π around the X axis (and it is the same as a positive π rotation around the X axis as well). Shouldn't the middle angle though be in the range that is equivalent to ±90 degrees?
Euler angles are not uniquely defined. In case of ambiguity, eulerAngles always pick the solution that minimizes the first angles. See also the following bug entries for related discussions: 609, 801, 947.

Resources