Exemple #1
0
    def test_innermorphic(self):
        for p, q in [(2, 0), (3, 0), (4, 0)]:
            layout, blades = Cl(p, q)

            A = Frame(layout.randomV(p+q))
            R = layout.randomRotor()
            B = Frame([R*a*~R for a in A])
            self.assertTrue(A.is_innermorphic_to(B))
Exemple #2
0
    def checkit(self, p, q):
        # p, q =4,0
        N = p + q
        # eps(1e-4)
        layout, blades = Cl(p, q)

        # create frame
        A = layout.randomV(n=N)
        # create Rotor
        R = 5.*layout.randomRotor()
        # create rotated frame
        B = [R*a*~R for a in A]

        # find verser from both frames
        R_found, rs = of2v(A, B)

        # Rotor is determiend correctly, within a sign
        self.assertTrue(R == R_found or R == -R_found)

        # Determined Verser implements desired transformation
        self.assertTrue([R_found*a*~R_found for a in A] == B)
Exemple #3
0
    def test_layout_comparison_operators(self, g3, g4):
        l3a = g3
        l3b, _ = Cl(3)  # need a new copy here
        l4 = g4

        assert operator.eq(l3a, l3b) is True
        assert operator.eq(l3a, l4) is False
        assert operator.eq(l3a, None) is False

        assert operator.ne(l3a, l3b) is False
        assert operator.ne(l3a, l4) is True
        assert operator.ne(l3a, None) is True
class TestInitialisation:
    def test_speed(self):
        algebras = range(2, 9)
        print()  # So that the first number is on a new line
        for i in algebras:
            t_start = time.time()
            Cl(i)
            t_end = time.time()
            print(i, t_end - t_start)

    @pytest.mark.parametrize('algebra',
                             [Cl(i) for i in [4]] + [conformalize(Cl(3)[0])],
                             ids=['Cl(4)', 'conformalize(Cl(3))'])
    def test_sparse_multiply(self, algebra):
        layout = algebra[0]
        # Make two random multivectors
        a = layout.randomMV()
        b = layout.randomMV()
        # Project the multivectors to the grades required
        grades_possibilities = []
        for r in range(1, len(layout.sig)):
            possible_grades = [
                list(m) for m in list(
                    itertools.combinations(range(len(layout.sig)), r))
            ]
            grades_possibilities += possible_grades
        for i, grades_a in enumerate(grades_possibilities):
            sparse_mv_a = sum([a(k) for k in grades_a])
            for j, grades_b in enumerate(grades_possibilities):
                sparse_mv_b = sum([b(k) for k in grades_b])
                # Compute results
                gp = layout.gmt_func_generator(grades_a=grades_a,
                                               grades_b=grades_b)
                result_sparse = gp(sparse_mv_a.value, sparse_mv_b.value)
                result_dense = (sparse_mv_a * sparse_mv_b).value
                # Check they are the same
                np.testing.assert_almost_equal(result_sparse, result_dense)
                print(j + i * len(grades_possibilities),
                      len(grades_possibilities)**2)
Exemple #5
0
    def test_metric(self):
        layout = Cl(4, 1)[0]
        e1 = layout.blades['e1']
        e2 = layout.blades['e2']
        e3 = layout.blades['e3']
        e4 = layout.blades['e4']
        e5 = layout.blades['e5']

        assert (e1 * e1)[0] == 1
        assert (e2 * e2)[0] == 1
        assert (e3 * e3)[0] == 1
        assert (e4 * e4)[0] == 1
        assert (e5 * e5)[0] == -1
class TestInitialisation:
    @pytest.mark.parametrize(
        "n", [x for x in range(2, 7)] +
        [pytest.param(x, marks=too_slow_without_jit) for x in range(7, 9)])
    def test_speed(self, n, benchmark):
        benchmark(Cl, n)

    @too_slow_without_jit
    @pytest.mark.veryslow
    @pytest.mark.parametrize('algebra',
                             [Cl(i) for i in [4]] + [conformalize(Cl(3)[0])],
                             ids=['Cl(4)', 'conformalize(Cl(3))'])
    def test_sparse_multiply(self, algebra):
        layout = algebra[0]
        # Make two random multivectors
        a = layout.randomMV()
        b = layout.randomMV()

        # Choose the grades we care about.
        # We skip the cases of:
        #  - all grades
        #  - no grades
        #  - any multiplications including the pseudoscalar
        grades_possibilities = list(_powerset(range(layout.dims)))[1:-1]

        for i, grades_a in enumerate(grades_possibilities):
            sparse_mv_a = sum([a(k) for k in grades_a], layout.MultiVector())
            for j, grades_b in enumerate(grades_possibilities):
                sparse_mv_b = sum([b(k) for k in grades_b],
                                  layout.MultiVector())
                # Compute results
                gp = layout.gmt_func_generator(grades_a=grades_a,
                                               grades_b=grades_b)
                result_sparse = gp(sparse_mv_a.value, sparse_mv_b.value)
                result_dense = (sparse_mv_a * sparse_mv_b).value
                # Check they are the same
                np.testing.assert_almost_equal(result_sparse, result_dense)
                print(j + i * len(grades_possibilities),
                      len(grades_possibilities)**2)
Exemple #7
0
    def test_metric(self):
        layout = Cl(4, 1)[0]
        e1 = layout.blades['e1']
        e2 = layout.blades['e2']
        e3 = layout.blades['e3']
        e4 = layout.blades['e4']
        e5 = layout.blades['e5']

        self.assertAlmostEqual((e1 * e1)[0], 1)
        self.assertAlmostEqual((e2 * e2)[0], 1)
        self.assertAlmostEqual((e3 * e3)[0], 1)
        self.assertAlmostEqual((e4 * e4)[0], 1)
        self.assertAlmostEqual((e5 * e5)[0], -1)
 def test_sparse_multiply(self):
     algebras = [Cl(i) for i in [3, 4]] + [conformalize(Cl(3)[0])]
     # For all the algebras we are interested in
     for alg in algebras:
         layout = alg[0]
         # Make two random multivectors
         a = layout.randomMV()
         b = layout.randomMV()
         # Project the multivectors to the grades required
         grades_possibilities = []
         for r in range(1,len(layout.sig)):
             possible_grades = [list(m) for m in list(itertools.combinations(range(len(layout.sig)), r))]
             grades_possibilities += possible_grades
         for i,grades_a in enumerate(grades_possibilities):
             sparse_mv_a = sum([a(k) for k in grades_a])
             for j,grades_b in enumerate(grades_possibilities):
                 sparse_mv_b = sum([b(k) for k in grades_b])
                 # Compute results
                 gp = get_mult_function(layout.gmt,layout.gaDims,layout.gradeList,grades_a=grades_a,grades_b=grades_b)
                 result_sparse = gp(sparse_mv_a.value,sparse_mv_b.value)
                 result_dense = (sparse_mv_a*sparse_mv_b).value
                 # Check they are the same
                 testing.assert_almost_equal(result_sparse, result_dense)
                 print(j+i*len(grades_possibilities),len(grades_possibilities)**2)
Exemple #9
0
    def test_inv_g4(self):
        '''
        a numerical test for the inverse of a MV. truth was
        generated by results of clifford v0.82
        '''
        layout, blades = Cl(4)
        valA = np.array([
            -0.3184271488037198,
            -0.8751064635010213,  # noqa
            -1.5011710376191947,
            1.7946332649746224,  # noqa
            -0.8899576254164621,
            -0.3297631748225678,  # noqa
            0.04310366054166925,
            1.3970365638677635,  # noqa
            -1.545423393858595,
            1.7790215501876614,  # noqa
            0.4785341530609175,
            -1.32279679741638,  # noqa
            0.5874769077573831,
            -1.0227287710873676,  # noqa
            1.779673249468527,
            -1.5415648119743852  # noqa
        ])

        valAinv = np.array([
            0.06673424072253006,
            -0.005709960252678998,  # noqa
            -0.10758540037163118,
            0.1805895938775471,  # noqa
            0.13919236400967427,
            0.04123255613093294,  # noqa
            -0.015395162562329407,
            -0.1388977308136247,  # noqa
            -0.1462160646855434,
            -0.1183453106997158,  # noqa
            -0.06961956152268277,
            0.1396713851886765,  # noqa
            -0.02572904638749348,
            0.02079613649197489,  # noqa
            -0.06933660606043765,
            -0.05436077710009021  # noqa
        ])

        A = MultiVector(layout=layout, value=valA)
        Ainv = MultiVector(layout=layout, value=valAinv)

        np.testing.assert_almost_equal(A.inv().value, Ainv.value)
Exemple #10
0
    def test_mv_str(self):
        """ Test the __str__ magic method """
        layout, blades = Cl(3)
        e1 = blades['e1']
        e2 = blades['e2']
        e12 = blades['e12']

        assert str(e1) == "(1^e1)"
        assert str(1 + e1) == "1 + (1^e1)"
        assert str(-e1) == "-(1^e1)"
        assert str(1 - e1) == "1 - (1^e1)"

        mv = layout.scalar * 1.0
        mv[(1,)] = float('nan')
        mv[(1, 2)] = float('nan')
        assert str(mv) == "1.0 + (nan^e1) + (nan^e12)"
Exemple #11
0
    def test_exp_g4(self):
        '''
        a numerical test for the exponential of a bivector. truth was
        generated by results of clifford v0.82
        '''
        layout, blades = Cl(4)

        valB = np.array([
            -0.,
            0.,  # noqa
            0.,
            -0.,  # noqa
            -0.,
            -1.9546896043012914,  # noqa
            0.7069828848351363,
            -0.22839793693302957,  # noqa
            1.0226966962560002,
            1.8673816483342143,  # noqa
            -1.7694566455296474,
            -0.,  # noqa
            -0.,
            0.,  # noqa
            -0.,
            -0.  # noqa
        ])
        valexpB = np.array([
            -0.8154675764311629,
            0.,  # noqa
            0.,
            0.,  # noqa
            0.,
            0.3393508714682218,  # noqa
            0.22959588097548828,
            -0.1331099867581965,  # noqa
            -0.01536404898029994,
            0.012688721722814184,  # noqa
            0.35678394795928464,
            0.,  # noqa
            0.,
            0.,  # noqa
            0.,
            -0.14740840378445502  # noqa
        ])

        B = MultiVector(layout=layout, value=valB)
        expB = MultiVector(layout=layout, value=valexpB)
        np.testing.assert_almost_equal(np.exp(B)[0].value, expB.value)
Exemple #12
0
    def test_comparison_operators(self):
        layout, blades = Cl(3)
        e1 = blades['e1']
        e2 = blades['e2']

        pytest.raises(TypeError, operator.lt, e1, e2)
        pytest.raises(TypeError, operator.le, e1, e2)
        pytest.raises(TypeError, operator.gt, e1, e2)
        pytest.raises(TypeError, operator.ge, e1, e2)

        assert operator.eq(e1, e1) is True
        assert operator.eq(e1, e2) is False
        assert operator.ne(e1, e1) is False
        assert operator.ne(e1, e2) is True

        assert operator.eq(e1, None) is False
        assert operator.ne(e1, None) is True
Exemple #13
0
    def test_factorise(self):
        layout_a = Cl(3)[0]
        layout,blades,stuff = conformalize(layout_a)
        e1 = layout.blades['e1']
        e2 = layout.blades['e2']
        e3 = layout.blades['e3']
        e4 = layout.blades['e4']
        e5 = layout.blades['e5']

        up = stuff['up']

        blade = up(e1 + 3*e2 + 4*e3)^up(5*e1 + 3.3*e2 + 10*e3)^up(-13.1*e1)

        basis, scale = blade.factorise()
        new_blade = (reduce(lambda a, b: a^b, basis)*scale)
        print(new_blade)
        print(blade)
        np.testing.assert_almost_equal(new_blade.value, blade.value, 5)
Exemple #14
0
    def test_normalInv(self):
        layout, blades = Cl(3)
        e1 = layout.blades['e1']
        e2 = layout.blades['e2']
        e3 = layout.blades['e3']
        assert (2*e1).normalInv() == (0.5*e1)

        with pytest.raises(ValueError):
            (0*e1).normalInv()  # divide by 0

        with pytest.raises(ValueError):
            (1 + e1 + e2).normalInv()  # mixed even and odd grades

        # produces garbage, but doesn't crash
        (1 + e1 + e2).normalInv(check=False)

        # check that not requiring normalInv works fine
        assert (1 + e1 + e2).inv() == -1 + e1 + e2
Exemple #15
0
    def test_vee(self):
        layout_a = Cl(3)[0]
        layout, blades, stuff = conformalize(layout_a)
        e1 = layout.blades['e1']
        e2 = layout.blades['e2']
        e3 = layout.blades['e3']
        up = layout.up

        A = up(e1)
        B = up(e2)
        C = up(-e1)
        D = up(e3)

        sph = A^B^C^D
        pl = A^B^C^layout.einf

        assert sph & pl == 2*(A^B^C)
        assert pl & sph == -2*(A^B^C)
Exemple #16
0
    def test_gp_op_ip(self):
        layout = Cl(4, 1)[0]
        e1 = layout.blades['e1']
        e2 = layout.blades['e2']
        e3 = layout.blades['e3']
        e4 = layout.blades['e4']
        e5 = layout.blades['e5']

        e123 = layout.blades['e123']
        np.testing.assert_almost_equal(e123.value, (e1 ^ e2 ^ e3).value)
        np.testing.assert_almost_equal(e123.value, (e1 * e2 * e3).value)

        e12345 = layout.blades['e12345']
        np.testing.assert_almost_equal(e12345.value, (e1 ^ e2 ^ e3 ^ e4 ^ e5).value)
        np.testing.assert_almost_equal(e12345.value, (e1 * e2 * e3 * e4 * e5).value)

        e12 = layout.blades['e12']
        np.testing.assert_almost_equal(-e12.value, (e2 ^ e1).value)

        t = np.zeros(32)
        t[0] = -1
        np.testing.assert_almost_equal(t, (e12*e12).value)
Exemple #17
0
    def test_array_control(self):
        '''
        test methods to take control addition from numpy arrays
        '''
        layout, blades = Cl(3)
        e1 = blades['e1']
        e3 = blades['e3']
        e12 = blades['e12']

        for i in range(100):

            number_array = np.random.rand(4)

            output = e12 + (e1 * number_array)
            output2 = MVArray([e12 + (e1 * n) for n in number_array])
            np.testing.assert_almost_equal(output, output2)

            output = e12 + (e1 * number_array)
            output2 = MVArray([e12 + (e1 * n) for n in number_array])
            np.testing.assert_almost_equal(output, output2)

            output = (number_array * e1) + e12
            output2 = MVArray([(n * e1) + e12 for n in number_array])
            np.testing.assert_almost_equal(output, output2)

            output = number_array / e12
            output2 = MVArray([n / e12 for n in number_array])
            np.testing.assert_almost_equal(output, output2)

            output = (e1 / number_array)
            output2 = MVArray([(e1 / n) for n in number_array])
            np.testing.assert_almost_equal(output, output2)

            output = ((e1 / number_array) * e3) / e12
            output2 = MVArray([((e1 / n) * e3) / e12 for n in number_array])
            np.testing.assert_almost_equal(output, output2)
Exemple #18
0
def g3():
    return Cl(3)[0]
Exemple #19
0
def g2():
    return Cl(2)[0]
Exemple #20
0
 def setUp(self):
     self.algebras = [Cl(i) for i in [3, 4, 5]] # we should make this a dict, so we know what dimension it is
Exemple #21
0
 def test_frame_inv(self):
     for p, q in [(2, 0), (3, 0), (4, 0)]:
         layout, blades = Cl(p, q)
         A = Frame(layout.randomV(p + q))
         self.check_inv(A)
Exemple #22
0
def g7():
    return Cl(7)[0]
Exemple #23
0
def g4_1():
    return Cl(4, 1)[0]
Exemple #24
0
def g4():
    return Cl(4)[0]
Exemple #25
0
 def algebra(self, request):
     return Cl(request.param)
Exemple #26
0
class TestPGA:
    layout, _ = Cl(3, 0, 1, firstIdx=0)

    def test_right_complement(self):
        for b in self.layout.blades_list:
            assert b ^ b.right_complement() == self.layout.pseudoScalar

    def test_left_complement(self):
        for b in self.layout.blades_list:
            assert b.left_complement() ^ b == self.layout.pseudoScalar

    def test_vee(self):
        blades = self.layout.blades

        e0 = blades['e0']
        e1 = blades['e1']
        e2 = blades['e2']
        e3 = blades['e3']

        e01 = blades['e01']
        e02 = blades['e02']
        e03 = blades['e03']
        e12 = blades['e12']
        e13 = blades['e13']
        e23 = blades['e23']

        e123 = e1 ^ e2 ^ e3
        e032 = e0 ^ e3 ^ e2
        e013 = e0 ^ e1 ^ e3
        e021 = e0 ^ e2 ^ e1

        # PGA points are trivectors.
        # A point is just a homogeneous point, euclidean coordinates plus the origin
        def POINT(x, y, z):
            return e123 + x * e032 + y * e013 + z * e021

        P1 = POINT(0, 0, 1)
        P2 = POINT(3, 4, 0)
        L = P1 & P2
        assert L == -(4 ^ e01) + (3 ^ e02) - (1 ^ e12) - (4 ^ e13) + (3 ^ e23)

    def test_no_crash(self):
        """ TODO: This doesn't actually do any asserts! """
        layout = self.layout
        blades = layout.blades
        print(blades)

        # A rotor (Euclidean line) and translator (Ideal line)
        def rotor(angle, line):
            return math.cos(
                angle / 2.0) + math.sin(angle / 2.0) * line.normal()

        def translator(dist, line):
            return 1.0 + dist / 2.0 * line

        # PGA is plane based. Vectors are planes. (think linear functionals)
        E0 = blades['e0']  # ideal plane
        E1 = blades['e1']  # x=0 plane
        E2 = blades['e2']  # y=0 plane
        E3 = blades['e3']  # z=0 plane

        # A plane is defined using its homogenous equation ax + by + cz + d = 0
        def PLANE(a, b, c, d):
            return a * E1 + b * E2 + c * E3 + d * E0

        # PGA points are trivectors.
        E123 = E1 ^ E2 ^ E3
        E032 = E0 ^ E3 ^ E2
        E013 = E0 ^ E1 ^ E3
        E021 = E0 ^ E2 ^ E1

        # A point is just a homogeneous point, euclidean coordinates plus the origin
        def POINT(x, y, z):
            return E123 + x * E032 + y * E013 + z * E021

        # for our toy problem (generate points on the surface of a torus)
        # we start with a function that generates motors.
        # circle(t) with t going from 0 to 1.
        def CIRCLE(t, radius, line):
            return rotor(t * math.pi * 2.0, line) * translator(radius, E1 * E0)

        # a torus is now the product of two circles.
        def TORUS(s, t, r1, l1, r2, l2):
            return CIRCLE(s, r2, l2) * CIRCLE(t, r1, l1)

        # sample the torus points by sandwich with the origin
        def POINT_ON_TORUS(s, t):
            to = TORUS(s, t, 0.25, E1 * E2, 0.6, E1 * E3)
            return to * E123 * ~to

        # Elements of the even subalgebra (scalar + bivector + pss) of unit length are motors
        ROT = rotor(math.pi / 2.0, E1 * E2)

        # The outer product ^ is the MEET. Here we intersect the yz (x=0) and xz (y=0) planes.
        AXZ = E1 ^ E2  # x=0, y=0 -> z-axis line

        # line and plane meet in point. We intersect the line along the z-axis (x=0, y=0) with the xy (z=0) plane.
        ORIG = AXZ ^ E3  # x=0, y=0, z=0 -> origin

        # We can also easily create points and join them into a line using the regressive (vee, &) product.
        PX = POINT(1, 0, 0)
        LINE = (ORIG.dual() ^ PX.dual()
                ).dual()  # & = regressive product, JOIN, here, x-axis line.

        # Lets also create the plane with equation 2x + z - 3 = 0
        P = PLANE(2, 0, 1, -3)

        # rotations work on all elements ..
        ROTATED_LINE = ROT * LINE * ~ROT
        ROTATED_POINT = ROT * PX * ~ROT
        ROTATED_PLANE = ROT * P * ~ROT

        # See the 3D PGA Cheat sheet for a huge collection of useful formulas
        POINT_ON_PLANE = (P | PX) * P

        # output some numbers.
        print("a point       :", str(PX))
        print("a line        :", str(LINE))
        print("a plane       :", str(P))
        print("a rotor       :", str(ROT))
        print("rotated line  :", str(ROTATED_LINE))
        print("rotated point :", str(ROTATED_POINT))
        print("rotated plane :", str(ROTATED_PLANE))
        print("point on plane:", str(POINT_ON_PLANE.normal()))
        print("point on torus:", str(POINT_ON_TORUS(0.0, 0.0)))
Exemple #27
0
 def test_frame_inv(self):
     for p, q in [(2, 0), (3, 0), (4, 0)]:
         layout, blades = Cl(p, q)
         A = Frame(layout.randomV(p + q))
         self.check_inv(A)
Exemple #28
0
 def setUp(self):
     self.algebras = [Cl(i) for i in [3, 4, 5]]
Exemple #29
0
def g3c():
    return conformalize(Cl(3)[0])[0]
Exemple #30
0
def g5():
    return Cl(5)[0]
Exemple #31
0
 def test_unary_op_preserves_dtype(self, func):
     """ test that simple unary ops on blades do not promote types """
     layout, blades = Cl(3)
     e1 = blades['e1']
     assert func(e1).value.dtype == e1.value.dtype
Exemple #32
0
 def test_frame_inv(self, p, q):
     layout, blades = Cl(p, q)
     A = Frame(layout.randomV(p + q))
     self.check_inv(A)
Exemple #33
0
 def setUp(self):
     self.algebras = [Cl(3, 0, 1, firstIdx=0), Cl(4, 0, 1, firstIdx=0)]