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
Comparison of complex numbers #837
Comments
Thanks Gulfaraz, yeah, so far we've simply don't do ordering of complex numbers. It could make sense to implement it. Not sure which of the two solutions is preferable. Can you explain a little bit more about your use case, why you need this? |
I was porting the fmincg (conjugate gradient) function to javascript from the ml-class by Andrew Ng. The function goes through a bunch of iterations where the numbers keep changing (yes, this is my existing knowledge on machine learning or numerical calculations - have a lot to learn). During these iterations some of the matrices start to hold complex numbers and along comes a condition of I had used If I was porting the code from MATLAB - I would've implemented the MATLAB implementation. It wasn't a calculated preference but merely a "try to replicate as much as possible" decision making. Apparently, MATLAB is used much more extensively when compared to octave. It would be wise to find out what python libraries do - a bit of googling showed me there is at least one user trying to solve the problem. Reasoning to compare with python -> While moving to programming from MATLAB and Octave - python is the language of choice. Should also checkout R which was also mentioned in the course. TL;DR - I do not think the choice of implementation matters as long as the calculations don't break. |
Thanks for the extra explanation. Ok then let's implement ordering for complex numbers. I still need a bit more time to consider what would be the most appropriate way of ordering: by real value or by absolute value. Any extra arguments for one or the other are welcome. |
I made a PR assuming the real value based on this stackoverflow post I chose the MATLAB's approach was for its popularity over Octave and also because it's easier to change the code to take real parts Please review the changes and if I've missed some dependency. |
That's odd... Three days ago when I reviewed your PR I also entered a reply here about the choice for the way of ordering, but apparently I didn't press the "Comment" button or something. I'm not really convinced that ordering by real value is the best solution. To me, comparing the absolute value sounds way more logical. The stackoverflow article you link to gives performance as argument. That can be a good reason. There are also issues though with this choice of Matlab (see this discussion): In this case I find consistency and logical behavior more important than staying compatible with Matlab (and apparently Octave thought the same - though they weigh Matlab compatibility much higher that mathjs does). What do you think? |
I'm not sure if there is a best solution here. I believe the application use case defines the Although, consistency should be prioritized higher than being compatible with any other software. If On searching for articles on I am fine with sticking to the absolute values unless anyone can think of a scenario where calculations/comparisons might break as a result of this assumption. |
I just noticed this issue, sorry for a late comment. To me ordering of complex numbers is very strange, it has no mathematical basis and if implemented, it would be nice to have an option to turn it off. |
Here are my two cents. Ordering by absolute value will lead to these unexpected results:
|
If we order by real part, then a user could apply a transform to each side of the inequality to achieve any behavior:
But I'm not sure that will work with functions like |
@ericman314 nice examples of counter-intuitive results. I'm afraid that any option we choose has "unexpected results", but maybe comparing by real part isn't that bad after all. At least the behavior should be consistend for the relational operators Comparing complex numbers is indeed weird. If I understand it correctly the reason is not to see which of two complex numbers is largest, but to be able to order a list of complex numbers in "some" deterministic way. I'm still looking for more use cases. Maybe in set theory or something? @gulfaraz wouldn't your initial issue of From a practical point of view: it is currently already possible to implement the comparison of your choice yourself, like:
It's also possible to override the built-in error that you get right now when comparing complex numbers: // override default implementation of comparing complex numbers (which throws an error)
math.import ({
smaller: math.typed({ 'Complex,Complex': function (a, b) { return a.re < b.re } }),
smallerEq: math.typed({ 'Complex,Complex': function (a, b) { return a.re <= b.re } }),
larger: math.typed({ 'Complex,Complex': function (a, b) { return a.re > b.re } }),
largerEq: math.typed({ 'Complex,Complex': function (a, b) { return a.re >= b.re } })
}, { override: true });
// then:
math.eval('2+3i < 3+1i') // returns true |
From A New Approach To Ordering Complex Numbers published in 2008, the suggested approach is summarized in 6.7
The paper also lists the alternatives And this link which concludes with it is impossible to (sensibly) order complex numbers. At this point, I want to refer to the first post on this issue where the sensibility of the ordering isn't the priority. But the exception in the calculations because maths itself has no mathematical rule (similar to the case of We could choose to
Is there another alternative ? |
Thanks for doing this research @gulfaraz. Since the original issue has been solved with |
Works for me 👍 |
👍 |
Ok then... Time to reopen this issue already :D Ordering of complex numbers is indeed needed for set operations. We could do without but that will lead to inefficient code, See #858. We figured that both sorting by real part or absolute value will not work though: this will not uniquely sort differing values like I think that's a really interesting and simple idea, which gives uniquely ordered values which are probably way easier to reason about for a human being too. |
@josdejong should I reopen the PR and implement this approach ? |
Thanks @gulfaraz, yes that would be great! Thanks |
support to compare complex numbers #837
Is it absolutely necessary to change the default comparison functions for this very specific use case? |
That's a good point. From a pragmatic point of view it's nice to have this "just" working, but indeed there is no mathematical meaning for this. So then the question then is: will it do harm? Does it do harm in for example Matlab and Octave which each have their own implementation? I tend to think that it does do little harm whilst it's very convenient to have when you need it (and very unpractical if it isn't there). I don't think "special internal behavior" would be the right solution either: if we need it now internally, you can be sure that someone will need it externally as well. An other option that you suggested before is to make this behavior configurable. We could do that though I'm careful with introducing more configuration as that complicates the library. Anyone else any thoughts on this? |
Just thinking aloud: maybe we could only do sorting of complex numbers in the |
'Does it do harm?' 'Matlab and Octave'? There is a lot of legacy in such environments. I do not know why those people chose to implement such nonsense, but blindly copying suspicious behavior seems foolish to me. Sorry for the wording, I am quite passionate about this one... :) |
@josdejong |
Thanks for the feedback. Appreciate your concerns Paál. We've made decisions to go a different route than Matlab before and indeed try to make a good choice and not blindly follow the big guys. This is a great discussion :). There is no mathematical definition for comparing complex numbers. We also don't have concrete use cases except sorting a list in a deterministic order (for the new set functions). It's easy to add features but hard to remove them later on, so from that point of view it's safer to wait until there are actual use cases. So, if everybody agrees, I think it's ultimately better to remove the complex number implementations for We do need a solution though to be able to sort a list with values including complex numbers for the set functions. We could implement support for ordering complex numbers in the |
The problem we're trying to solve is deterministic iteration. Sets are unordered. But we may want a reproduce-able way to iterate over a set. This maps directly to the problem of ordering tuples--there are multiple orderings. Consider the natural ordering of comparing tuples element by element. Since complex numbers are (real, imaginary) this would be: |
@josdejong The set functions support string arrays. However, if I have a set which contains strings and other types, the functions fail, because sorting between numbers and strings are not supported. Now, I know it's a math library, but sets can contain strings, in my opinion. With a This way we don't do any harm to complex numbers, but we can solve my problem and also provide an additional feature to the library, which can be useful in some cases. What do you guys think? |
At the risk of going full circle, a comparator is more general. And a comparator can order arrays or heaps or whatever. Since a comparator is an object, it can take options (e.g., ignore case, convertStringToNumber, etc.). With a comparator we can sort everything, not only sets. |
@firepick1 very well said. This natural ordering is indeed what we're looking for (and the current implementation in the You're indeed going full circle by suggesting to solve this with a comparator. Ideally:
Creating a clearly separate function for this ordering makes most sense to me so far. The naming of this new function is very important, users must understand that it's not sorting in ascending, mathematical order. I like the "natural" naming that Karl proposes. We could introduce this
What I like about this solution is that it does not introduce a new function, and it makes very clear that it's sorting behavior is not mathematical ascending order. |
@josdejong Can it work with mixed data types? For example, a set can contain numbers and complexs, or numbers and letters. |
Well it's up to us to define the exact behavior of the natural sorting, but I think in general it should accept a list containing any type of data including mixed data types. It could for example first order by type (string, number, complex, unit, ...), and then for each type order the items in a natural way. We can start simple by adding support for complex numbers, and changing the ordering of strings to natural sorting. Later on we can also add support for ordering objects and maybe also nested arrays. |
Sorters and comparators are different. Separation of concerns allows sorters to focus on algortihms (e.g., heapsort, binarysort, etc.) and comparators to focus on comparison: var cmp = new mathjs.Comparator({tuples: "natural"}); Since JS defines Set as iterable following insertion order, the above creates an ordered set as defined by the ordering of the customizable cmp comparator. |
Yes that's true. The current |
math.compareNatural would also allow us to merge infinite streams, which are not sortable in our lifetime |
…ural sort in set functions (See #837)
I've made a start with implementing The function is a WIP, and needs to be worked out further:
|
Oddly, this issue crisscrosses with the null issue. Consider: |
I think the How about:
|
hm, I just realize that we can't put numeric types in the same group, and that in order to give deterministic results, the comparator should not consider So I think we have to fine another name for this comparator comparing anything, name it |
Thinking about it, we can generalize this comparator even more. What the set functions need is just "any" sorting as long as it is strict and deterministic. It basically boils down to needing a deep strict comparator. Similar to for example |
Re numeric types, one could compare first based on the numerical value and second on the type. E.g.
|
That's, a smart idea Harry, thanks |
I've experimented with a sort of So I will continue working out the |
I've now fully implemented hope to do a release today. (finally...) |
|
So I should update the set functions? |
@Nekomajin42 I already updated the set functions to use |
The following is the output when comparing complex numbers.
Which is mathematically accurate, but was of little use in implementing logistic regression.
A few searches later I found this comment --
-- which made sense and confirmed that I would need to find a workaround in order to proceed with my calculations.
I took octave as the reference and implemented their partial ordering logic
I looked up MATLAB's implementation for complex comparison and they only compare the real parts of the numbers - which is different from octave's implementation mentioned above. Either implementation could or could not be the preferred partial ordering for the user but it's not a show stopper.
I feel the library should implement some sort of default partial ordering instead of an absolute error which halts the program. Either of the above implementations or a different partial ordering altogether so that the calculations don't completely halt.
I used the following code to work around the problem.
Which resulted in
It would be nice to have a default solution out of the box. That's my 2 cents.
Also, thank you for the awesome library.
The text was updated successfully, but these errors were encountered: