galgebra icon indicating copy to clipboard operation
galgebra copied to clipboard

`.is_versor()` method in class `Mv` of module mv.py uses an incorrect algorithm

Open Greg1950 opened this issue 11 months ago • 4 comments

The multivector method .is_versor() purports to follow the test on p. 533 of Leo Dorst's Geometric Algebra for Computer Science. But:

  1. Dorst's test itself, as it appears in GACS, is incorrect, as shown by a simple counterexample.
  2. The algorithm used in .is_versor() does not faithfully implement Dorst's test.
  3. The algorithm used in .is_versor() has a simple counterexample.

I have devised four conditions satisfied by versors which, if satisfied, also imply that a multivector is a versor. I am currently checking with Dorst as to his opinion, but I'm pretty confident in my reasoning.

Let V be a multivector, and let V.rev() and V.g_invol() be its reverse and grade involute. Let x be a generic 1-vector. Then V will be a versor if and only if it meets each of the following conditions:

  1. V * V.rev() and V.rev() * V are both scalars.
  2. V * V.rev() is not zero.
  3. V.g_invol() * V.rev() is a scalar.
  4. V.g_invol() * x * V.rev() is a vector.

The counterexamples, if anyone's interested, are these:

  • To Dorst's test as it appears in GACS: Let V = 1 + I where I = e0 e1 e2 e3 is the unit pseudoscalar of the spacetime algebra G(1,3). Then V meets the conditions described by GACS, but the geometric product V (reverse of V) is not a scalar, showing that V cannot be a versor.
  • To the algorithm currently used in .is_versor(): Let V = e1 + e2 e3 in the algebra G(3,0) of Euclidean 3-space. Then V passes the test in .is_versor(), but V cannot be a versor as it is a mixture of odd and even grades.

I will post further after hearing back from Dorst. In the meanwhile, I have a proposed rewrite of the .is_versor() method that I am testing. Once my testing is satisfied, I'll post my rewrite here.

Greg Grunberg [email protected] 2025 March 04

Greg1950 avatar Mar 05 '25 04:03 Greg1950

Greg, many thanks for sharing this with the community, also, thanks for your previous work that merged into GAlgebra main branch in #510 .

utensil avatar Mar 07 '25 11:03 utensil

Given that V * V.rev() is a nonzero scalar, the requirement that V.rev() * V be a scalar becomes superfluous, for then V.rev() * V will equal V * V.rev(). Instead of the four conditions listed in my original issue statement, the sufficient conditions for V to be a versor may be taken to be

  1. V * V.rev() is a nonzero scalar.
  2. V.g_invol() * V.rev() is a scalar.
  3. V.g_invol() * x * V.rev() is a vector whenever x is a vector.

I have written a detailed mathematical proof that those three conditions are equivalent to V being a versor. Email me a request and I'll gladly provide a PDF of the proof.

Greg Grunberg [email protected] 2025 March 09

Greg1950 avatar Mar 09 '25 16:03 Greg1950

I have eliminated as superfluous one of the three tests for versorhood mentioned in my post of 2025 March 09. It's necessary to show only that

  1. V * V.rev() is a nonzero scalar.
  2. V.g_invol() * x * V.rev() is a vector whenever x is a 1-vector.

Again, a PDF is available.

Greg Grunberg [email protected] 2025 March 12

My initial attempt at actual Python code for the test follows. Be cautioned that I have not yet tried out that code. I am aware that its computation of self * reverse twice is an inefficiency.

    def is_versor(self) -> bool:
        """
        Tests for versor status of `self`, where a versor is defined as 
        a geometric product of finitely-many nonnull vectors.
        Sets self.versor_flg and returns its value.
        """
        if self.versor_flg is not None:
            return self.versor_flg
        self.characterise_Mv()
        reverse = self.rev()
        involute = self.g_invol()    # self's grade involute
        self.versor_flg = (self * reverse).is_scalar() \
            and not (self * reverse).is_zero() \
            and (involute * self.Ga._XOX * reverse).is_vector()
            # self.Ga._XOX is a generic vector in self's geometric algebra 
        return self.versor_flg

Greg1950 avatar Mar 12 '25 20:03 Greg1950

Hi @Greg1950 , sorry for the delay, I've created a PR #536 for this, along with some test cases from the top of my head. Can you review the code and tests? Thanks!

utensil avatar Mar 25 '25 04:03 utensil