How to compare if two tensors are equal in Eigen? - c++

There is this:
https://codeyarns.com/2016/02/16/how-to-compare-eigen-matrices-for-equality/
But there is no isApprox for tensors.
The following doesn't do what I want:
#include <Eigen/Core>
#include <unsupported/Eigen/CXX11/Tensor>
#include <array>
#include <iostream>
using namespace Eigen;
using namespace std;
int main()
{
// Create 2 matrices using tensors of rank 2
Eigen::Tensor<int, 2> a(2, 3);
Eigen::Tensor<int, 2>* b = &a;
cerr<<(*b==*b)<<endl;
}
because it does coordinate wise comparison and returns a tensor of the same dimension instead of a true/false vale.
How do I check if two tensors are identical? No isApprox for tensors.
I could write my own function, but I want to be able to use GPU power when available, and it seems like Eigen has built-in GPU support.

For an exact comparison of 2 tensors A and B, you can use the comparison operator followed by a boolean reduction:
Tensor<bool, 0> eq = (A==B).all();
This will return a tensor of rank 0 (i.e. a scalar) that contains a boolean value that's true iff each coefficient of A is equal to the corresponding coefficient of B.
There is no approximate comparison at the moment, although it wouldn't be difficult to add.

You can always use a couple of Eigen::Maps to do the isApprox checks.
#include <iostream>
#include <unsupported/Eigen/CXX11/Tensor>
using namespace Eigen;
int main()
{
Tensor<double, 3> t(2, 3, 4);
Tensor<double, 3> r(2, 3, 4);
t.setConstant(2.1);
r.setConstant(2.1);
t(1, 2, 3) = 2.2;
std::cout << "Size: " << r.size() << "\n";
std::cout << "t: " << t << "\n";
std::cout << "r: " << r << "\n";
Map<VectorXd> mt(t.data(), t.size());
Map<VectorXd> mr(r.data(), r.size());
std::cout << "Default isApprox: " << mt.isApprox(mr) << "\n";
std::cout << "Coarse isApprox: " << mt.isApprox(mr, 0.11) << "\n";
return 0;
}
P.S./N.B. Regarding Eigen's built in GPU support... Last I checked it is fairly limited and with good reason. It is/was limited to fixed size matrices as dynamic allocation on a GPU is really something you want to avoid like the common cold (if not like the plague). I take it back. It looks like the Tensor module supports GPUs pretty well.

Related

CGAL normalize vector

I want to normalize the vectors, yet I could not understand how to do such a basic operation. There does not exist a direct method like Vector_3::normalize().
I call squared_length() and then CGAL::sqr_root() to find the vector length. Then when I want to divide my vector to its length, compiler does not permit since CGAL types are not compatible. Where am I wrong?
I'm expanding here the comment by #MarcGlisse.
There are two scenarios - you want exact calculations or you don't. In the first case you can use the Exact_predicates_exact_constructions_kernel_with_sqrt and the normalized vector will be exact.
In the second case you can use many kernels, but the normalized vector will probably have the length, slightly different from 1. Also some kernels don't have the function CGAL::sqrt at all - however you can always convert squared distances to the double type, using the function CGAL::to_double. Another way is to use a function CGAL::approximate_sqrt, which automatically does this conversion if it's necessary. These conversions make calculations not exact. Please see the example below:
#include <iostream>
#include <CGAL/Exact_predicates_exact_constructions_kernel_with_sqrt.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Simple_cartesian.h>
using KernelExactWithSqrt = CGAL::Exact_predicates_exact_constructions_kernel_with_sqrt;
using KernelExact = CGAL::Exact_predicates_exact_constructions_kernel;
using KernelInexact = CGAL::Simple_cartesian<double>;
template <typename T>
auto normalize(T const& V)
{
auto const slen = V.squared_length();
auto const d = CGAL::approximate_sqrt(slen);
return V / d;
}
template <typename T>
auto check()
{
typename T::Point_2 const p{0, 0}, q{1, 1};
auto const n = normalize(typename T::Vector_2{p, q});
return n.squared_length() == 1;
}
int main()
{
std::cout << "====== Exact kernel with square root ======" << std::endl;
std::cout << check<KernelExactWithSqrt>() << std::endl;
std::cout << "====== Inexact kernel ======" << std::endl;
std::cout << check<KernelInexact>() << std::endl;
std::cout << "====== Exact kernel with automatic conversion to double ======" << std::endl;
std::cout << check<KernelExact>() << std::endl;
}
The output:
====== Exact kernel with square root ======
1
====== Inexact kernel ======
0
====== Exact kernel with automatic conversion to double ======
0
So, this example shows that the Exact_predicates_exact_constructions_kernel_with_sqrt guarantees you that the normalized vector will be what you expect.

Armadillo element-wise operations only on diagonal

Does armadillo offer functions that apply element-wise operations only on the diagonal elements of a matrix? Say I want to run an inverse on it then I get infs on off-diagonals. I know that I can get it with arma::inv(m), but for diagonal matrices it seems faster to run it element-wise.
Minimal example:
#include <iostream>
#include <armadillo>
int main() {
arma::Col<double> v = {1.2, 3.14, 2.71, 0.1};
arma::Mat<double> m = arma::diagmat(v);
std::cout << " A diagonal matrix:\n" << m << "\n\n";
std::cout << " It's elemenet-wise inverse:\n" << 1.0/m << std::endl;
return 0;
}

eigen: create Vector-like Replicate (access with one index, LinearAccessBit)

I want to create an Eigen::Replicate object that can be accessed like a vector, i.e. with a single index. I got that to work with the fixed-size replicate<Index,Index>(), which I can't use in reality, the non-one factor is not a compile-time constant. It also works when manually creating a Replicate object, but I feel like I'm just overlooking the obvious way of using a replicate function to achieve this:
#include <Eigen/Dense>
#include <iostream>
using namespace Eigen;
int main(){
Vector3i v (3);
v << 0,1,2;
constexpr int nReplications {2};
auto replDynamic { v.replicate(nReplications, 1) };
/* with a dynamic replication, two indexes are required to access a coeff */
std::cout << "5th entry: " << replDynamic(4,0) << '\n';
auto replFixed { v.replicate<nReplications, 1>() };
/* I want to use only one index, but I require the number of replications
* in one dimension to be dynamic */
std::cout << "5th entry: " << replFixed(4) << '\n';
/* don't know how to access the VectorwiseOp variant */
// auto replVector { v.replicate(nReplications) };
// std::cout << "5th entry: " << replVector(4) << '\n';
/* this function doesn't exist */
// auto replDefined { v.replicate<Dynamic,1>(nReplications, 1) };
// std::cout << "5th entry: " << replDefined(4) << '\n';
/* I'd rather not define it manually (it's not the intended way), but it works */
Replicate<Vector3i,Dynamic,1> replManual { v, nReplications, 1 };
std::cout << "5th entry: " << replManual(4) << '\n';
return 0;
}
The source code shows VectorwiseOp<...>::replicate(Index factor) in line 134, which sounds like what I need, but I don't seem to be able to access it.
And a function such as replicate<Index,Index>(Index,Index) doesn't exist.
Assuming I understand what you are asking, since a Vector3i is a one column Eigen::Matrix, you can get a VectorwiseOp<...> expression template from a Vector3i (say) by using the colwise() function and then call the one argument replicate with that.
That is,
#include <Eigen/Dense>
#include <iostream>
using namespace Eigen;
int main() {
Vector3i v(3);
v << 0, 1, 2;
auto foo = v.colwise().replicate(2);
std::cout << "5th entry: " << foo(4) << '\n';
return 0;
}
Note though that using type deduction on a expression template, or "pseudo expression" as they are called in the Eigen documentation, is generally a bad idea i.e. writing Eigen::Matrix<int, 6, 1> foo = v.colwise().replicate(2) is safer; the Eigen documentation mentions the issue here.
By adding a .reshaped() after the replicate(...) call, the ColsAtCompileTime are set to 1, and therefore, the resulting object can be accessed like a vector:
#include <Eigen/Dense>
#include <iostream>
using namespace Eigen;
int main(){
Vector3i v (3);
v << 0,1,2;
constexpr int nReplications {2};
auto replReshaped { v.replicate(nReplications, 1).reshaped() };
std::cout << "5th entry: " << replReshaped(4) << '\n';
return 0;
}

computing lpNorm column wise in Eigen

When I try to call lpNorm<1> with colwise() in Eigen I get the error:
error: 'Eigen::DenseBase > >::ColwiseReturnType' has no member named 'lpNorm'
Instead norm() and squaredNorm() work fine calling them colwise.
example
#include <Eigen/Dense>
#include <iostream>
using namespace std;
using namespace Eigen;
int main()
{
MatrixXf m(2,2), n(2,2);
m << 1,-2,
-3,4;
cout << "m.colwise().squaredNorm() = " << m.colwise().squaredNorm() << endl;
cout << "m.lpNorm<1>() = " << m.lpNorm<1>() << endl;
// cout << "m.colwise().lpNorm<1>() = " << m.colwise().lpNorm<1>() << endl;
}
works fine giving
m.colwise().squaredNorm() = 10 20
m.lpNorm<1>() = 10
If I uncomment the last line I get the error.
Can someone help?
It is not implemented for colwise in Eigen <=3.2.9. You have two options:
Upgrade to Eigen 3.3 (beta)
Loop over all columns and calculate the lp norms one by one.
You may by-pass it that way:
m.cwiseAbs().colwise().sum()
Unfortunately it only works in case of L1 norm (which is equivalent of an absolute value).

Boost Polygon: Issue with euclidean_distance

I have the following code which is supposed to compute the Euclidean distance between two rectangles. I compiled using GCC 4.7.3 and Boost v1.58.0
#include <iostream>
#include <cmath>
#include <boost/polygon/polygon.hpp>
#include <boost/geometry.hpp>
namespace gtl = boost::polygon;
using namespace boost::polygon::operators;
typedef gtl::rectangle_data<int> LayoutRectangle;
int main(int argc, char** argv)
{
LayoutRectangle t(16740130,29759232,16740350,29760652);
LayoutRectangle n(16808130,29980632,16808350,29982052);
std::cout << gtl::euclidean_distance(t, n) << std::endl;
std::cout << gtl::euclidean_distance(t, n, gtl::HORIZONTAL) << " "
<< gtl::euclidean_distance(t, n, gtl::VERTICAL) << std::endl;
std::cout << gtl::square_euclidean_distance(t, n) << std::endl;
std::cout << std::sqrt(gtl::square_euclidean_distance(t, n)) << std::endl;
std::cout << (int) std::sqrt(gtl::square_euclidean_distance(t, n)) << std::endl;
return 0;
}
The code above produced the following output:
38022.6
67780 219980
52985328800
230185
230185
The correct answer is 230185. Now if I go look at the implementation of euclidean_distance() in the boost polygon library, I see this:
template <typename rectangle_type, typename rectangle_type_2>
typename enable_if< typename gtl_and_3<y_r_edist2, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type,
typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type,
typename rectangle_distance_type<rectangle_type>::type>::type
euclidean_distance(const rectangle_type& lvalue, const rectangle_type_2& rvalue) {
double val = (int)square_euclidean_distance(lvalue, rvalue);
return std::sqrt(val);
}
This looks identical to the std::sqrt(gtl::square_eclidean_distance(t,n)) line in my code which gives the correct answer (230185). So why am I getting 38022.6 with gtl::euclidean_distance()? What am I not seeing here?
Looks like the internal computation is overflowing.
I don't think this is a library bug, the library is used incorrectly with the underlying (unchecked) int type.
(However, there is a different bug in the library that I mention at the end.)
Try using a smaller "integer representation" of the problem:
For example:
LayoutRectangle t(167402,297592,167404,297607);
LayoutRectangle n(168082,299806,168084,299821);
Unfortunately there is no general solution of the problem in integer arithmetic, except 0) using higher precision can buy you something, 1) scaling the problem 2) using multiprecision, 3) using rational arithmetic and integer part
(For floating point the solution is simply normalizing the components, this is how std::abs for std::complex<double> works to avoid floating point overflow)
It is good to use large integers to represent a geometric problem BUT
for this reason, as a workaround, use coordinates that span distance of at most (int)std::sqrt((double)std::numeric_limits<int>::max()/2) = 2^15 = 32768.
Which is a surprisingly small number.
Complete code:
#include <iostream>
#include <cmath>
#include <boost/polygon/polygon.hpp>
#include <boost/geometry.hpp>
int main(){
namespace gtl = boost::polygon;
using namespace boost::polygon::operators;
typedef gtl::rectangle_data<int> LayoutRectangle;
LayoutRectangle t(167401,297592,167403,297606);
LayoutRectangle n(168081,299806,168083,299820);
std::cout << gtl::euclidean_distance(t, n) << std::endl;
std::cout << gtl::euclidean_distance(t, n, gtl::HORIZONTAL) << " "
<< gtl::euclidean_distance(t, n, gtl::VERTICAL) << std::endl;
std::cout << gtl::square_euclidean_distance(t, n) << std::endl;
std::cout << std::sqrt(gtl::square_euclidean_distance(t, n)) << std::endl;
std::cout << (int) std::sqrt(gtl::square_euclidean_distance(t, n)) << std::endl;
}
Output:
2302.1
678 2200
5299684
2302.1
2302
Which is the expected result.
Looking at the code, it seems that there is a bug in the library, not because it gives overflow but because an internal computation is casted to int and not the the underlying generic integer data type. This means that probably even if you use multiprecision integers the results will overflow.