In [1]:
using SymPy

In [2]:
SymPy.sympy.__version__


Out[2]:
"1.3"

In [3]:
using PyCall

In [4]:
const ga = PyCall.PyNULL()
copy!(ga, PyCall.pyimport_conda("galgebra.ga", "galgebra"))
const mv = PyCall.PyNULL()
copy!(mv, PyCall.pyimport_conda("galgebra.mv", "galgebra"))
const printer = PyCall.PyNULL()
copy!(printer, PyCall.pyimport_conda("galgebra.printer", "galgebra"))
ga


Out[4]:
PyObject <module 'galgebra.ga' from '/Users/utensil/projects/galgebra/galgebra/ga.py'>

In [5]:
printer.Format()

In [6]:
mutable struct Mv
    o::PyCall.PyObject
end

Base.convert(::Type{Mv}, o::PyCall.PyObject) = Mv(o)

pytype_mapping(mv.Mv, Mv)


Out[6]:
9-element Array{Tuple{PyObject,Type},1}:
 (PyObject <class 'sympy.combinatorics.permutations.Permutation'>, SymPermutation)         
 (PyObject <class 'sympy.combinatorics.perm_groups.PermutationGroup'>, SymPermutationGroup)
 (PyObject <class 'sympy.polys.polytools.Poly'>, Sym)                                      
 (PyObject <class 'sympy.matrices.dense.MutableDenseMatrix'>, Array{Sym,N} where N)        
 (PyObject <class 'sympy.matrices.matrices.MatrixBase'>, Array{Sym,N} where N)             
 (PyObject <class 'sympy.core.basic.Basic'>, Sym)                                          
 (PyObject <class 'mpmath.ctx_mp_python.mpf'>, BigFloat)                                   
 (PyObject <class 'mpmath.ctx_mp_python.mpc'>, Complex{BigFloat})                          
 (PyObject <class 'galgebra.mv.Mv'>, Mv)                                                   

In [7]:
macro define_op(type, op, method)
    @eval begin
        $op(x::$type, y::$type) = x.o.$method(y.o)
    end
end


Out[7]:
@define_op (macro with 1 method)

In [8]:
macro define_lop(type, rtype, op, lmethod)
    @eval begin
        $op(x::$type, y::$rtype) = x.o.$lmethod(y)
    end
end
                
macro define_rop(type, ltype, op, rmethod)
    @eval begin
        $op(x::$ltype, y::$type) = y.o.$rmethod(x)
    end
end


Out[8]:
@define_rop (macro with 1 method)

In [9]:
import Base: +,-,*,/,^,==
@define_op(Mv, +, __add__)
@define_op(Mv, -, __sub__)
# Geometric product: *
@define_op(Mv, *, __mul__)
@define_op(Mv, /, __div__)
@define_op(Mv, ^, __pow__)
@define_op(Mv, ==, __eq__)

# Wedge product: \wedge
@define_op(Mv, , __xor__)
# Hestene's inner product: \cdot
@define_op(Mv, , __or__)
# Left contraction: \rfloor
@define_op(Mv, <<, __lt__)
@define_op(Mv, , __lt__)
# Right contraction: \lfloor
@define_op(Mv, >>, __rt__)
@define_op(Mv, , __rt__)


Out[9]:
⊢ (generic function with 1 method)

In [10]:
@define_lop(Mv, Sym, +, __add__)
@define_rop(Mv, Sym, +, __radd__)
@define_lop(Mv, Sym, -, __sub__)
@define_rop(Mv, Sym, -, __rsub__)
@define_lop(Mv, Sym, *, __mul__)
@define_rop(Mv, Sym, *, __rmul__)
@define_lop(Mv, Sym, /, __div__)
@define_rop(Mv, Sym, /, __rdiv__)

@define_lop(Mv, Number, +, __add__)
@define_rop(Mv, Number, +, __radd__)
@define_lop(Mv, Number, -, __sub__)
@define_rop(Mv, Number, -, __rsub__)
@define_lop(Mv, Number, *, __mul__)
@define_rop(Mv, Number, *, __rmul__)
@define_lop(Mv, Number, /, __div__)
@define_rop(Mv, Number, /, __rdiv__)


Out[10]:
/ (generic function with 112 methods)

In [11]:
-(x::Mv) = x.o.__neg__()


Out[11]:
- (generic function with 188 methods)

In [12]:
py"""
def vector(ga, components):
    bases = ga.mv()
    return sum([components[i] * e for i, e in enumerate(bases)])
"""
const vector = py"vector"


Out[12]:
PyObject <function vector at 0x134460840>

In [13]:
macro define_show(type)
    @eval begin
        Base.show(io::IO, x::$type) = print(io, pystr(x.o))
        Base.show(io::IO, ::MIME"text/plain", x::$type) = print(io, pystr(x.o))
        Base.show(io::IO, ::MIME"text/latex", x::$type) = print(io, "\\begin{align*}" * printer.latex(x.o) * "\\end{align*}")
    end
end


Out[13]:
@define_show (macro with 1 method)

In [14]:
@define_show(Mv)

In [15]:
(x, y, z) = xyz = symbols("x,y,z",real=true)


Out[15]:
(x, y, z)

In [16]:
(o3d, ex, ey, ez) = ga.Ga.build("e_x e_y e_z", g=[1, 1, 1], coords=xyz)


Out[16]:
(PyObject <galgebra.ga.Ga object at 0x1256866a0>,  \boldsymbol{e}_{x},  \boldsymbol{e}_{y},  \boldsymbol{e}_{z})

In [17]:
ex


Out[17]:
\begin{align*} \boldsymbol{e}_{x}\end{align*}

In [18]:
ey


Out[18]:
\begin{align*} \boldsymbol{e}_{y}\end{align*}

In [19]:
ez


Out[19]:
\begin{align*} \boldsymbol{e}_{z}\end{align*}

In [20]:
const V = o3d


Out[20]:
PyObject <galgebra.ga.Ga object at 0x1256866a0>

In [21]:
a = V.mv("a", "scalar")
b = V.mv("b", "scalar")
c = V.mv("c", "scalar")
d = V.mv("d", "scalar")
u = V.mv("u", "vector")
v = V.mv("v", "vector")
w = V.mv("w", "vector")


Out[21]:
\begin{align*}w^{x} \boldsymbol{e}_{x} + w^{y} \boldsymbol{e}_{y} + w^{z} \boldsymbol{e}_{z}\end{align*}

In [22]:
v + w == w + v


Out[22]:
true

In [23]:
(u + v) + w == u + (v + w)


Out[23]:
true

In [24]:
v + Sym(0) == v


Out[24]:
true

In [25]:
# TODO Why can't == work?
Sym(0) * v - Sym(0)


Out[25]:
\begin{align*} 0 \end{align*}

In [26]:
Sym(1) * v == v


Out[26]:
true

In [27]:
a * (b * v) == (a * b) * v


Out[27]:
true

In [28]:
a * (v + w) == a * v + a * w


Out[28]:
true

In [29]:
(a + b) * v ==  a * v + b * v


Out[29]:
true

In [30]:
uu = vector(V, [1, 2, 3])
vv = vector(V, [4, 5, 6])
ww = vector(V, [5, 6, 7])


Out[30]:
\begin{align*}5 \boldsymbol{e}_{x} + 6 \boldsymbol{e}_{y} + 7 \boldsymbol{e}_{z}\end{align*}

In [31]:
uu + vv


Out[31]:
\begin{align*}5 \boldsymbol{e}_{x} + 7 \boldsymbol{e}_{y} + 9 \boldsymbol{e}_{z}\end{align*}

In [32]:
7 * uu + 2 * ww


Out[32]:
\begin{align*}17 \boldsymbol{e}_{x} + 26 \boldsymbol{e}_{y} + 35 \boldsymbol{e}_{z}\end{align*}

In [33]:
7 * uu - 2 * ww


Out[33]:
\begin{align*}-3 \boldsymbol{e}_{x} + 2 \boldsymbol{e}_{y} + 7 \boldsymbol{e}_{z}\end{align*}

In [34]:
3 * uu + 2 * vv + ww


Out[34]:
\begin{align*}16 \boldsymbol{e}_{x} + 22 \boldsymbol{e}_{y} + 28 \boldsymbol{e}_{z}\end{align*}

In [35]:
v + ga.S(-1) * v


Out[35]:
\begin{align*} 0 \end{align*}

In [36]:
v0 = vector(V, [0, 0, 0])


Out[36]:
\begin{align*} 0 \end{align*}

In [37]:
a * v0 == v0


Out[37]:
true

In [38]:
(-a) * v == a * (-v)


Out[38]:
true

In [39]:
(-a) * v == - a * v


Out[39]:
true

In [40]:
SymPy.sqrt(2)


Out[40]:
1.4142135623730951

In [41]:
SymPy.sqrt(Sym(2))


Out[41]:
\begin{equation*}\sqrt{2}\end{equation*}

In [42]:
SymPy.Rational(2, 3)


Out[42]:
2//3

In [43]:
Sym(SymPy.Rational(2, 3))


Out[43]:
\begin{equation*}\frac{2}{3}\end{equation*}

In [44]:
SymPy.sqrt(2) * u + SymPy.Rational(2, 3) * v


Out[44]:
\begin{align*}\left ( 1.4142135623731 u^{x} + 0.666666666666667 v^{x}\right ) \boldsymbol{e}_{x} + \left ( 1.4142135623731 u^{y} + 0.666666666666667 v^{y}\right ) \boldsymbol{e}_{y} + \left ( 1.4142135623731 u^{z} + 0.666666666666667 v^{z}\right ) \boldsymbol{e}_{z}\end{align*}

In [45]:
SymPy.sqrt(Sym(2)) * u + Sym(SymPy.Rational(2, 3)) * v


Out[45]:
\begin{align*}\left ( \sqrt{2} u^{x} + \frac{2 v^{x}}{3}\right ) \boldsymbol{e}_{x} + \left ( \sqrt{2} u^{y} + \frac{2 v^{y}}{3}\right ) \boldsymbol{e}_{y} + \left ( \sqrt{2} u^{z} + \frac{2 v^{z}}{3}\right ) \boldsymbol{e}_{z}\end{align*}

In [ ]: