def simplexInCenter(vs): print " in simplexInCenter" n = len(vs) nDims = len(vs[0]) # 5 points in 2 dims is hopeless if n >= nDims+3: print " hopeless!" print " out simplexInCenter" return None weights = [] for i in xrange(n): oppositeFacet = Mat([vs[j] for j in xrange(n) if j != i]) #do('oppositeFacet') M = Mat([v-oppositeFacet[0] for v in oppositeFacet[1:]]) #do('M') M2 = M * M.transposed() #do('M2') det = M2.det() #do('det') oppositeFacetContent = sqrt(det) weights.append(oppositeFacetContent) weights = Vec(weights) weights /= sum(weights) answer = Vec(weights) * Mat(vs) do('answer') print " out simplexInCenter" return answer
class HyperbolicIsometry: @staticmethod def identity(nDims): return HyperbolicIsometry(Mat.identity(nDims), [0]*nDims) def __init__(self,R=None,t=None): # R and t can't both be None, or we wouldn't know the dimension if R == None: R = Mat.identity(len(t)) if t == None: t = [0]*len(R) self.R = Mat(R) self.t = Vec(t) def apply(self,p): return translate(p * self.R, self.t) def applyInverse(self,p): return self.R * translate(p,-self.t) # R * p = p * R^-1 since R is orthogonal # Return f such that for all p, # f(p) = rhs(self(p)) def compose(self,rhs): lhs = self nDims = len(self.t) t = rhs.apply(self.t) # = rhs(lhs(0)) if True: R = Mat.identity(nDims) for i in xrange(nDims): R[i] = translate(rhs.apply(lhs.apply(R[i])), -t) # R[i] = Isometry(I,t)^-1(rhs(lhs(I[i]))) R = Mat(R) else: # Argh, I thought this was right, but it's not?? wtf? R = self.R * rhs.R return HyperbolicIsometry(R,t) def inverse(self): return HyperbolicIsometry(None,-self.t).compose(HyperbolicIsometry(self.R.transposed(),None)) def dist2(self,rhs): return (rhs.R-self.R).length2() + (rhs.t-self.t).length2() def __repr__(self): return 'HyperbolicIsometry('+`self.R`+','+`self.t`+')' def __str__(self): return self.__repr__() # # Operator notation: # f(p) = f.apply(p) # p*f = f.apply(p) # f0*f1 = f0.compose(f1) # note that # (f0*f1)*f2 == f0*(f1*f2) # and (p*f0)*f1 == p*(f0*f1) # def __call__(self,p): return self.apply(p) def __rmul__(self,lhs): # actually relies on fact that Vec's __mul__ # explicitly calls rhs.__rmul__ when rhs is unrecognized type return self.apply(lhs) def __mul__(self,rhs): return self.compose(rhs) def __pow__(self,rhs): assert type(rhs) == int if rhs == -1: # most common case return self.inverse() if rhs < 0: # either of the following work if True: return (self^-rhs).inverse() else: return self.inverse()^-rhs if rhs > 1: return self**int(rhs/2) * self**(rhs-int(rhs/2)) if rhs == 1: return self assert rhs == 0 return HyperbolicIsometry.identity(len(self.t)) # XXX TODO: I think this is a bad idea, since ^ binds looser than * and even + def __xor__(self,rhs): return self.__pow__(rhs)