Is there a function in Eigen to compare vectors (matrices) using both relative and absolute tolerance aka numpy.allclose? Standard isApprox fails if one of the vectors is very close to zero.
Asked
Active
Viewed 2.1k times
17
-
See http://eigen.tuxfamily.org/dox-2.0/TutorialCore.html – Mihai8 Feb 24 '13 at 11:58
2 Answers
21
There is no built-in function implementing numpy.allclose, but you easily write one yourself if that's really what you need. However, I'd rather suggest the use of isMuchSmallerThan with reference value:
(a-b).isMuchSmallerThan(ref)
where ref is a representative non zero for your problem.
EDIT: for reference here is a possible implementation of allclose:
template<typename DerivedA, typename DerivedB>
bool allclose(const Eigen::DenseBase<DerivedA>& a,
const Eigen::DenseBase<DerivedB>& b,
const typename DerivedA::RealScalar& rtol
= Eigen::NumTraits<typename DerivedA::RealScalar>::dummy_precision(),
const typename DerivedA::RealScalar& atol
= Eigen::NumTraits<typename DerivedA::RealScalar>::epsilon())
{
return ((a.derived() - b.derived()).array().abs()
<= (atol + rtol * b.derived().array().abs())).all();
}

ggael
- 28,425
- 2
- 65
- 71
-
isMuchSmallerThan can be used for absolute comparison, i.e. (a-b).isMuchSmallerThan(1.0, atol) is equivalent to np.allclose(a, b, 0.0, atol), so to mimic np.allclose we have to do something like this: (a-b).isMuchSmallerThan(1.0, atol) || a.isApprox(b, rtol). Am I correct? – DikobrAz Feb 24 '13 at 13:38
-
5Not exactly because isMuchSmallerThan and isApprox are based on the L2 matrix norm and not element-wise comparisons (infinite norm). – ggael Feb 24 '13 at 16:46
-
It's probably worth mentioning that this, like numpy's `allclose`, is not symmetric, and `b` is expected to be a reference value. If you need a symmetric comparison, multiply `rtol` by `a.derived().array().abs().max(b.derived().array().abs())` instead. – ɲeuroburɳ Aug 31 '21 at 14:51
-
For Quaternions which have a `coeffs()` method to get at the matrix and where negatives are equivelent: `auto e{ atol + rtol * b.coeffs().derived().array().abs() }; return ((a.coeffs().derived() - b.coeffs().derived()).array().abs() <= e).all() || ((a.coeffs().derived() + b.coeffs().derived()).array().abs() <= e).all();` – mheyman Mar 12 '23 at 17:52
4
There is also isApprox function which was not working for me. I am just using ( expect - res).norm() < some small number.

nnrales
- 1,481
- 1
- 17
- 26