Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an overload of equals #43

Closed
martin-drozdik opened this issue Dec 15, 2017 · 4 comments
Closed

Add an overload of equals #43

martin-drozdik opened this issue Dec 15, 2017 · 4 comments

Comments

@martin-drozdik
Copy link

This program:

import koma.eye

fun main(args: Array<String>)
{
    val a = eye(3)
    val b = eye(3)
    println(a == b)
}

Produces false, because it just compares whether a and b refer to the same Kotlin object.

It would be very useful to have an overload that would compare matrices in the mathematical sense. That is, two matrices are the same if they have the same dimensions and each element of one matrix is equal to the element in the other matrix in the same column and row.

@kyonifer
Copy link
Owner

Agreed. One can simply use === if they need referential equality, so == should do something useful (i.e. elementwise equality as you suggest).

One thing to consider here is that floating point equality will rarely behave as one expects, because numerical issues can cause things that should be equal to be slightly different. Thus it may make sense to admit an optional epsilon be set somewhere similar to assertMatrixEquals, perhaps a new property in options. Alternatively, == could check for true equality and another method could allow tolerances, such as how numpy does it with allclose.

@martin-drozdik
Copy link
Author

Indeed floating point equality is something that may incur a great level of frustration, especially for people new to floating point arithmetic. However, Kotlin prescribes a fairly strict floating point standard (unlike e.g. C++) and therefore I believe that the user should be able to demand a strict floating point comparison. Therefore I suggest the second option:

Alternatively, == could check for true equality and another method could allow tolerances, such as how numpy does it with allclose.

@JosephCatrambone
Copy link
Contributor

Numpy has an operation numpy.allclose(a, b, some_epsilon) which returns true if abs(a-b) < eps for all a,b. Unfortunately it's not possible to pass an epsilon value to the equals operator and still have it be overloadable, so @OverRide fun equals(b, epsilon=1e-6) isn't doable, but maybe a static class-level float that can be set in advance and tweaked according to needs? Or, barring that, do something like AdaGrad and takes the magnitude of the global vector and returns true if all values are within 1% of the standard deviation. I'm not as keen on the second approach because it's more computationally expensive AND it doesn't always behave as one might expect. [0, 1, 0] and [0, 1.1, 0] could sometimes turn out to be close. That doesn't seem acceptable to me.

Perhaps instead of adding what I think of as a kinda' gross global epsilon we can just add a method called 'allclose' to match Numpy? Or we can default to something like 1e-8 and take that as good enough.

@kyonifer
Copy link
Owner

kyonifer commented Jan 6, 2018

It sounds like everyone is on board with going the allclose route and reserving == for true equality. I was leaning that way myself, so lets go with that.

Numpy has an operation numpy.allclose(a, b, some_epsilon) which returns true if abs(a-b) < eps for all a,b.

allclose actually has two tolerance values, to deal with the relative tolerance and an absolute tolerance, so they can compare on an arbitrary scale but not let large differences ever be equal. Check out the link in my first reply-- implementing that verbatim probably makes sense.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants