Skip to content

Commit

Permalink
merging (error due to ipynb )
Browse files Browse the repository at this point in the history
  • Loading branch information
arsenovic committed Sep 4, 2016
2 parents 1aa3de7 + bd3bb72 commit 73de7a7
Show file tree
Hide file tree
Showing 4 changed files with 458 additions and 72 deletions.
116 changes: 68 additions & 48 deletions clifford/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@
multiply scalars with MultiVectors. This can cause problems if
one has code that mixes Python numbers and MultiVectors. If the
code multiplies two values that can each be either type without
checking, one can run into problems as "1 & 2" has a very different
checking, one can run into problems as "1 * 2" has a very different
result from the same multiplication with scalar MultiVectors.
* Taking the inverse of a MultiVector will use a method proposed by
Expand All @@ -158,20 +158,20 @@
to solve this matrix equation for n_k. The laInv method does precisely
that.
The usual, analytic, method for computing inverses [M**-1 = ~M/(M&~M) iff
M&~M == |M|**2] fails for those multivectors where M&~M is not a scalar.
The usual, analytic, method for computing inverses [M**-1 = ~M/(M*~M) iff
M*~M == |M|**2] fails for those multivectors where M*~M is not a scalar.
It is only used if the inv method is manually set to point to normalInv.
My testing suggests that laInv works. In the cases where normalInv works,
laInv returns the same result (within _eps). In all cases,
M & M.laInv() == 1.0 (within _eps). Use whichever you feel comfortable
M * M.laInv() == 1.0 (within _eps). Use whichever you feel comfortable
with.
Of course, a new issue arises with this method. The inverses found
are sometimes dependant on the order of multiplication. That is:
M.laInv() & M == 1.0
M & M.laInv() != 1.0
M.laInv() * M == 1.0
M * M.laInv() != 1.0
XXX Thus, there are two other methods defined, leftInv and rightInv which
point to leftLaInv and rightLaInv. The method inv points to rightInv.
Expand Down Expand Up @@ -235,6 +235,7 @@

# Standard library imports.
import math
import numbers

# Major library imports.
import numpy as np
Expand Down Expand Up @@ -644,15 +645,32 @@ def __init__(self, layout, value=None):
if self.value.shape != (self.layout.gaDims,):
raise ValueError("value must be a sequence of length %s" %
self.layout.gaDims)



def __array_wrap__(self,out_arr, context=None):
uf, objs, huh = context
if uf.__name__ =='multiply':
return objs[1]*objs[0]
if uf.__name__ =='divide':
return objs[1].inv()*objs[0]
elif uf.__name__=='add':
return objs[1]+objs[0]
elif uf.__name__=='subtract':
return -objs[1]+objs[0]
elif uf.__name__ =='exp':
return math.e**(objs[0])

else:
raise ValueError('i dont know what to do')


def _checkOther(self, other, coerce=1):
"""Ensure that the other argument has the same Layout or coerce value if
necessary/requested.
_checkOther(other, coerce=1) --> newOther, isMultiVector
"""

if isinstance(other, (int, float, long)):
if isinstance(other, numbers.Number):
if coerce:
# numeric scalar
newOther = self._newMV()
Expand All @@ -679,10 +697,10 @@ def _newMV(self, newValue=None):
## numeric special methods
# binary

def __and__(self, other):
def __mul__(self, other):
"""Geometric product
M & N --> MN
M * N --> MN
__and__(other) --> MultiVector
"""

Expand All @@ -693,15 +711,17 @@ def __and__(self, other):
other.value))
else:
newValue = other * self.value



return self._newMV(newValue)

def __rand__(self, other):
def __rmul__(self, other):
"""Right-hand geometric product
N & M --> NM
N * M --> NM
__rand__(other) --> MultiVector
"""

other, mv = self._checkOther(other, coerce=0)

if mv:
Expand Down Expand Up @@ -746,10 +766,10 @@ def __rxor__(self, other):

return self._newMV(newValue)

def __mul__(self, other):
def __or__(self, other):
"""Inner product
M * N
M | N
__mul__(other) --> MultiVector
"""

Expand All @@ -763,7 +783,7 @@ def __mul__(self, other):

return self._newMV(newValue)

__rmul__ = __mul__
__ror__ = __or__

def __add__(self, other):
"""Addition
Expand Down Expand Up @@ -806,28 +826,28 @@ def __rsub__(self, other):
def __div__(self, other):
"""Division
-1
M / N --> M & N
M / N --> M * N
__div__(other) --> MultiVector
"""

other, mv = self._checkOther(other, coerce=0)

if mv:
return self & other.inv()
return self * other.inv()
else:
newValue = self.value / other
return self._newMV(newValue)

def __rdiv__(self, other):
"""Right-hand division
-1
N / M --> N & M
N / M --> N * M
__rdiv__(other) --> MultiVector
"""

other, mv = self._checkOther(other)

return other & self.inv()
return other * self.inv()

def __pow__(self, other):
"""Exponentiation of a multivector by an integer
Expand All @@ -850,7 +870,7 @@ def __pow__(self, other):
newMV = self._newMV(np.array(self.value)) # copy

for i in range(1, other):
newMV = newMV & self
newMV = newMV * self

return newMV

Expand All @@ -863,8 +883,8 @@ def __rpow__(self, other):

# Let math.log() check that other is a Python number, not something
# else.
intMV = math.log(other) & self
# pow(x, y) == exp(y & log(x))
intMV = math.log(other) * self
# pow(x, y) == exp(y * log(x))

newMV = self._newMV() # null

Expand All @@ -876,7 +896,7 @@ def __rpow__(self, other):
while nextTerm != 0:
# iterate until the added term is within _eps of 0
newMV << nextTerm
nextTerm = nextTerm & intMV / n
nextTerm = nextTerm * intMV / n
n = n + 1
else:
# squeeze out that extra little bit of accuracy
Expand Down Expand Up @@ -931,15 +951,15 @@ def mag2(self):
Note in mixed signature spaces this may be negative
"""

return (~self & self)[()]
return (~self * self)[()]

def __abs__(self):
"""Magnitude (modulus)
abs(M) --> |M|
__abs__() --> PyFloat
This is sqrt(abs(~M&M)).
This is sqrt(abs(~M*M)).
The abs inside the sqrt is need for spaces of mixed signature
"""
Expand All @@ -950,7 +970,7 @@ def adjoint(self):
"""Adjoint / reversion
_
~M --> M (any one of several conflicting notations)
~(N & M) --> ~M & ~N
~(N * M) --> ~M * ~N
adjoint() --> MultiVector
"""
# The multivector created by reversing all multiplications
Expand Down Expand Up @@ -1362,7 +1382,7 @@ def leftLaInv(self):
"""Return left-inverse using a computational linear algebra method
proposed by Christian Perwass.
-1 -1
M where M & M == 1
M where M * M == 1
leftLaInv() --> MultiVector
"""

Expand All @@ -1383,7 +1403,7 @@ def rightLaInv(self):
"""Return right-inverse using a computational linear algebra method
proposed by Christian Perwass.
-1 -1
M where M & M == 1
M where M * M == 1
rightLaInv() --> MultiVector
"""

Expand All @@ -1400,14 +1420,14 @@ def rightLaInv(self):
return self._newMV(sol)

def normalInv(self):
"""Returns the inverse of itself if M&~M == |M|**2.
"""Returns the inverse of itself if M*~M == |M|**2.
-1
M = ~M / (M & ~M)
M = ~M / (M * ~M)
normalInv() --> MultiVector
"""

Madjoint = ~self
MadjointM = (Madjoint & self)
MadjointM = (Madjoint * self)

if MadjointM.isScalar() and abs(MadjointM[()]) > _eps:
# inverse exists
Expand All @@ -1432,25 +1452,25 @@ def dual(self, I=None):
else:
Iinv = I.inv()

return self * Iinv
return self | Iinv

def commutator(self, other):
"""Returns the commutator product of two multivectors.
[M, N] = M X N = (M&N - N&M)/2
[M, N] = M X N = (M*N - N*M)/2
commutator(other) --> MultiVector
"""

return ((self & other) - (other & self)) / 2
return ((self * other) - (other * self)) / 2

def anticommutator(self, other):
"""Returns the anti-commutator product of two multivectors.
(M&N + N&M)/2
(M*N + N*M)/2
anticommutator(other) --> MultiVector
"""

return ((self & other) + (other & self)) / 2
return ((self * other) + (other * self)) / 2

def gradeInvol(self):
"""Returns the grade involution of the multivector.
Expand Down Expand Up @@ -1480,7 +1500,7 @@ def conjugate(self):
def project(self, other):
"""Projects the multivector onto the subspace represented by this blade.
-1
P (M) = (M _| A) & A
P (M) = (M _| A) * A
A
project(M) --> MultiVector
"""
Expand All @@ -1490,7 +1510,7 @@ def project(self, other):
if not self.isBlade():
raise ValueError, "self is not a blade"

return other.lc(self) & self.inv()
return other.lc(self) * self.inv()

def basis(self):
"""Finds a vector basis of this subspace.
Expand Down Expand Up @@ -1522,7 +1542,7 @@ def basis(self):
# to the point of iteration

for ei in wholeBasis:
Pei = ei.lc(self) & selfInv
Pei = ei.lc(self) * selfInv

J.clean()

Expand Down Expand Up @@ -1558,11 +1578,11 @@ def join(self, other):
return J.normal()

# try something else
M = (other & self.invPS()).lc(self)
M = (other * self.invPS()).lc(self)

if M != 0:
C = M.normal()
J = (self & C.rightInv()) ^ other
J = (self * C.rightInv()) ^ other
return J.normal()

if grSelf[0] >= grOther[0]:
Expand All @@ -1572,7 +1592,7 @@ def join(self, other):
A = other
B = self

if (A & B) == (A * B):
if (A * B) == (A | B):
# B is a subspace of A or the same if grades are equal
return A.normal()

Expand Down Expand Up @@ -1625,7 +1645,7 @@ def meet(self, other, subspace=None):
if subspace is None:
subspace = self.join(other)

return (self & subspace.inv()) * other
return (self * subspace.inv()) | other


def comb(n, k):
Expand Down Expand Up @@ -1839,7 +1859,7 @@ def print_precision(newVal):
def gp(M, N):
"""Geometric product
gp(M,N) = M & N
gp(M,N) = M * N
M and N must be from the same layout
Expand All @@ -1848,10 +1868,10 @@ def gp(M, N):
for example
>>>Ms = [M1,M2,M3] # list of multivectors
>>>reduce(gp, Ms) # == M1&M2&M3
>>>reduce(gp, Ms) # == M1*M2*M3
"""

return M&N
return M*N


4 changes: 2 additions & 2 deletions clifford/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,11 @@ def orthoFrames2Verser2(A,B, eps =1e-6):
rs = [1]*N

for k in range(N):
if abs((A[k]*B[k])-1) <eps:
if abs((A[k]|B[k])-1) <eps:
continue
r = (A[k]-B[k])/abs(A[k]-B[k])
for j in range(k,N):
A[j] = -r&A[j]&r
A[j] = -r*A[j]*r

rs[k] =r

Expand Down

0 comments on commit 73de7a7

Please sign in to comment.