6

Is quaternion comparison possible? I'm writing a Java class of Quaternions and I want to implement the Comparable interface to use the Collections.sort(List<Quaternion>) facility. I'm not expert at math, I really don't understand the things I read about Quaternions. So, can anyone tell me can I override the compareTo method for Quaternions and how?

My class declarition:

public class Quaternion implements Serializable, Comparable<Quaternion> {

    private double s; // scalar part
    private double i, j, k; // vectorel part


    public Quaternion() {
        super();
    }

    public Quaternion(double s, double i, double j, double k) {
        super();
        this.s = s;
        this.i = i;
        this.j = j;
        this.k = k;
    }
Cœur
  • 37,241
  • 25
  • 195
  • 267
anarhikos
  • 1,415
  • 3
  • 15
  • 19
  • 3
    This is a math question and not a programming one. Ask a math expert and, if you have trouble with implementing that solution, ask here for help in implementation. – SJuan76 Apr 27 '11 at 12:00

7 Answers7

2

You can implement compareTo, by comparing its fields. However, you need to determine what you want the order to be like. AFAIK, there is no standard definition of what comes before or after for complex numbers let alone a quaternion.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
2

You certainly can compare them; whether the comparison is meaningful or not is open to debate. Since a quaternion can represented by four real numbers, you'd just do something like (pseudocode)

if (q1.a != q2.a)
    return q1.a - q2.a;
else if (q1.b != q2.b)
    return q1.b - q2.b;
else if (q1.c != q2.c)
    return q1.c - q2.c;
else
    return q1.d - q2.d;

Since the values are real numbers, you might use an epsilon-based comparison, and you need to convert small positive and negative differences into positive and negative integers. But you get the idea.

Ernest Friedman-Hill
  • 80,601
  • 10
  • 150
  • 186
1

There is no reason why you can't compare two quaternions. Assuming that you want to compare magnitudes, compute and compare the Quaternion Norms. Your Quaternion class should have a norm (magnitude) method allowing a toCompare to be something like the following:

int compareTo(Quaternion o){
  return (int)(this.norm() - o.norm());
}

A better version would be:

int compareTo(Quaternion o){
  // return (int)(this.norm() - o.norm());
  double tNorm = this.norm;
  double oNorm = o.norm;
  int retVal = 0;

  if (tNorm < oNorm){
    retVal = -1;
  } else if (tNorm > oNorm){
    retVal = 1;
  }

  return retVal;
}
John Percival Hackworth
  • 11,395
  • 2
  • 29
  • 38
  • 1
    I would recommend against using `-` in `compareTo` (due to potential overflows). Use `<` or delegate to `Integer.compareTo`. – aioobe Apr 27 '11 at 12:02
  • Yes, I've implemented the norm method, and it seems most meaningful comparison. Thanks – anarhikos Apr 27 '11 at 12:26
  • 2
    There is a reason why you should NOT compare quaternions: They can not be ordered. You can define how to compare two quaternions, but there are some downsides. The most serious one when using the norm is that (as Klas mentioned) two quaternions, which are not equal, can have equal norms. This also violates the [definition of the compareTo-method](http://download.oracle.com/javase/6/docs/api/java/lang/Comparable.html), which states that it should return 0 only if the two objects are equal. – martin Apr 27 '11 at 12:53
  • @martin: the real reason why you don't compare quaternions in math is that you cannot have (a < b => a + c < b + c) and (a > 0 and b > 0 => ab > 0) since this would imply -1 < 0 and -1 > 0. Those axioms are required to do anything meaningful with the ordering. When it comes to storing quaternions in a tree, lexicographic order is perfectly fine. I agree however that comparing by norm is foolish since it will break silently many algorithms which rely on (not(a < b) and not(a > b) => a == b). – Alexandre C. Apr 27 '11 at 14:01
  • 1
    -1 Your ordering is inconsistent with `equals`, which is not recommended for implementations of the `Comparable` interface. – starblue Apr 27 '11 at 14:06
  • @martin Of course the quaternions can be ordered. The question is whether any of the infinite number of possible orderings is useful enough to stand out as being *the* implementation for a quaternion library. I really don't think so. – sigfpe Apr 28 '11 at 19:21
  • Lexical orderings for n-vectors of floating-point are workable in principle, but - especially in the face of inevitable rounding errors - have little meaning. Consider: A tiny change to one element in an 'ordered' list could result in it moving many places away in the list, even though it may also be that no two elements in the list are close together, by any reasonable distance metric. – greggo Mar 01 '17 at 18:32
1

A quaternion is a kind of 4-dimensional vector. How do you want to order them? The most reasonable way would be to use the norm.

public int compareTo(Object o) {
  if (o instanceOf Quaternion) {
    // Compute the difference between the square of the norm
    double result = s*s + i*i + j*j + k*k - o.s*o.s - o.i*o.i - o.j*o.j - o.k*o.k;
    if (result > 0) { return 1; }
    if (result < 0) { return -1; }
    return 0;
  }
}

Note that using the norm will make quaternions of equal length but pointing in different directions equal, and some algorithms will not be able to distinguish between them. Sorting algorithms may well throw away "duplicates". Just a friendly warning.

Klas Lindbäck
  • 33,105
  • 5
  • 57
  • 82
0

Think about quaternions as a tuple (ordered list) of four floating-point numbers. Defining equality is pretty straightforward, but how would you define total order? In other words, how do you want to define greater-than relationship between two four-number sequences?

In fact, there is no common greater-than relationship even between complex numbers and quaternions can be considered as a pair of complex numbers. Easy comparison is only possible in one-dimensional space. Complex numbers are two-dimensional, quaternions - four.

Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674
0

You can, but I don't think you should.

The argument is the same as for complex numbers. Given two quaternions, they are either equal or not, there is no way to say which one is greater than the other. The quaternions form a division algebra, which is not ordered (unlike the field of the real numbers for example). The only (reasonable) way, I can think of, comparing two quaternions is by using the norm.

double norm = Math.sqrt(s*s + i*i + j*j + k*k);

In that case you could define, that a quaternion a is greater than a quaternion b iff the norm of a is greater than the norm of b. But that is definitely not a standard definition. I would be careful in making quaternions or complex numbers comparable. However, it depends on your use case. Just take into account, that there is no standard way of sorting such numbers.

See this google search for some good links about comparing complex numbers. The argument for quaternions is basically the same.

Another way to compare quaternions would be to use a lexicographic order.

martin
  • 2,150
  • 1
  • 34
  • 48
  • The argument is simple. Axioms for ordered rings (http://en.wikipedia.org/wiki/Ordered_ring ) that we **do not require here** imply that if i > 0, i * i > 0, so -1 > 0. But 1 > 0, since 1 = 1 * 1 and therefore 0 > -1 (by adding -1 on both sides). Note also that a field is ordered iff -1 is not a sum of squares. – Alexandre C. Apr 27 '11 at 14:18
0

There is no mathematical standard ordering for quaternions or for complex numbers.

You may nevertheless want to implement the Comparable interface, for conveniently sorting and for storing them in TreeSet and TreeMap collections.

To make clear that the ordering is arbitrary I'd use the lexicographic combination of the components of the quaternion. This also ensures that the ordering is consistent with equals, and that the algorithms work as desired.

For a more natural ordering, for example one that takes the norm into account, you can always explicitly define a comparator.

starblue
  • 55,348
  • 14
  • 97
  • 151
  • Bear in mind, if you then want to look up a quaternion value in that tree, and it doesn't exactly match one already in the tree, you could easily wind up beside a leaf node which is not the 'closest' value (via distance metric). There could easily be a leaf node, which is much closer via distance metric, but which falls some ways away in the lexical sort order. So it raises the question of how the structure is used, given that floating point calculations always have some 'fuzz'... – greggo Mar 01 '17 at 18:41
  • 1
    You can't avoid that once you have two or more dimensions. The best you can do is the converse, so that values which are close in your ordering are also close in the space, via some space-filing curve. An application in a two-dimensional space is for example to order by distance from some chosen point first, then lexicographically to break ties ("find me a hotel close to P"). – starblue Mar 01 '17 at 18:56