def linrep(G, verbose=False): gen = G.gen simple = G.simple #print "simple:", simple # Simple vectors in the Euclidean (standard) basis. S = array(simple) #print shortstr(S) #print shortstr(dot(S.transpose(), S)) I = identity(G.n) # T maps vectors in the Euclidean basis to vectors in the Simple basis. Tt = solve(S, identity(G.n), check=True) T = Tt.transpose() assert eq(dot(S, Tt), I) As = [] # As for generators for g in gen: # A is the matrix representation of g in the simple root basis. #print "A:", [g(s) for s in simple] rows = [] for s in simple: r = g(s) r = dot(T, r) #print shortstr(r) rows.append(r) A = array(rows).transpose() assert eq(dot(A, A), I) As.append(A) return As
def order(g): n = 1 a = dot(g, g) while not eq(a, g): a = dot(a, g) n += 1 #print(n, end=' ') return n
def test(): perms = [[0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 1, 0], [2, 0, 1]] signss = [(a, b, c) for a in [-1, 1] for b in [-1, 1] for c in [-1, 1]] ops = [Op(perm, signs) for perm in perms for signs in signss] for A in ops: for B in ops: lhs = (A * B).todense() rhs = ((dot(A.todense(), B.todense()))) assert eq(lhs, rhs) print(len(ops))
def check_simple(self): """ A set of simple roots for a root system \Phi is a set of roots that form a basis for the Euclidean space spanned by \Phi with the special property that each root has components with respect to this basis that are either all nonnegative or all nonpositive. https://en.wikipedia.org/wiki/E8_(mathematics)#Simple_roots """ simple = self.simple n = len(simple) U = array(simple) #print "simple:" #print U V = solve(U, identity(len(U)), check=True) #print "inverse:" #print V #print "UV:" #print dot(U, V) roots = self.roots gen = self.gen n = len(simple) for i in range(n): root = simple[i] assert gen[i](root) == rscale(-1, root) #print root, gen[i](root) for i in range(n): for j in range(i + 1, n): assert rdot(simple[i], simple[j]) <= 0 for root in roots: nroot = rscale(-1, root) for g in gen: if g(root) == nroot: assert root in simple or rscale(-1, root) in simple if root in simple or nroot in simple: continue a = dot(root, V) #print "root:", shortstr(root, a) pos = (a >= 0).astype(int) neg = (a <= 0).astype(int) #assert pos.sum() == n or neg.sum() == n if pos.sum() != n and neg.sum() != n: assert 0, "FAIL"
def mulclose(gen, maxsize=None, verbose=False): found = set(str(g) for g in gen) els = list(gen) changed = True while changed: if verbose: print("mulclose:", len(els)) changed = False _els = list(els) for A in _els: for B in _els: C = dot(A, B) if str(C) not in found: els.append(C) found.add(str(C)) if maxsize and len(els) >= maxsize: return list(els) changed = True return els
def representation(G, verbose=False): gen = G.gen simple = G.simple #print "simple:", simple # Simple vectors in the Euclidean (standard) basis. S = array(simple) print("S:") print(shortstr(S)) I = identity(G.n) # T maps vectors in the Euclidean basis to vectors in the Simple basis. Tt = solve(S, identity(G.n), check=True) T = Tt.transpose() print("T:") print(shortstr(T)) print('--' * 10) assert eq(dot(S, Tt), I) Ws = [] # weight spaces As = [] # As for generators for g in gen: # A is the matrix representation of g in the simple root basis. #print "A:", [g(s) for s in simple] rows = [] for s in simple: r = g(s) r = dot(T, r) #print shortstr(r) rows.append(r) A = array(rows).transpose() assert eq(dot(A, A), identity(len(A))) # reflection As.append(A) print("A:") print(shortstr(A)) print("St*A*T:") print(shortstr(dotx(S.transpose(), A, T))) # W is the fixed space of A, expressed as vectors in the Euclidean basis. # These vectors (rows of W) lie on the "mirror" that is A. W = [] for root in simple: groot = g(root) if groot == rscale(-1, root): continue w = array(root) + array(groot) # easy! W.append(w) assert numpy.abs(w).sum() #u = solve(S.transpose(), w) #v = dot(S.transpose(), u) #assert eq(v, w) W = array(W) Ws.append(W) print("W:") print(shortstr(W)) B = dotx((A - identity(len(A))), T, W.transpose()) #print "A*T*Wt:" #print shortstr(dotx(A, T, W.transpose())) #print "(A-I)*T*Wt:" #print shortstr(B) assert numpy.abs(B).sum() == 0 #B = dotx(S.transpose(), A, T) #print "B:" #print shortstr(B) print('--' * 10) Ws = [Subspace(W) for W in Ws] for W in Ws: print("W:") print(W) print('--' * 10) # not needed... # W0 = Subspace(S) # Ws = [W.intersect(W0) for W in Ws] # Each of these weights will lie on all but one of the A mirrors weights = [] for i in range(G.n): Ws1 = list(Ws) Ws1.pop(i) W = Ws1[0] for j in range(1, len(Ws1)): W = W.intersect(Ws1[j]) print("weight:") print(W) W = W.W # get the numpy array assert len(W) == 1 W.shape = W.shape[1], A = As[i] B = dotx(S.transpose(), A, T) w = W.transpose() Bw = dot(B, w) assert not eq(Bw, w) v = Bw - w # we will scale w so that this delta will be equal to S[i] v = v.transpose() # row vector s = S[i] r = None for j in range(len(v)): assert (v[j] == 0) == (s[j] == 0) if v[j] == 0: continue assert r is None or r == s[j] / v[j] r = s[j] / v[j] w = r * w #print shortstr(w) v = dot(B, w) - w assert eq(v, s) weights.append(w) W = array(weights) print("W:") print(shortstr(W)) Wt = W.transpose() St = S.transpose() # What combination of weights gives the (simple) roots? U = solve(Wt, St) print("U:") print(shortstr(U)) # What combination of roots gives the weights? V = solve(St, Wt) print("V:") print(shortstr(V)) print('--' * 10) #for A in As: weyl = G.generate() # entire weyl group, sorted by word length print("weyl:", len(weyl)) I = weyl[0] assert I.word == '' # identity rows = [] for s in simple: r = I(s) r = dot(T, r) #print shortstr(r) rows.append(r) A0 = array(rows).transpose() for g in weyl: rows = [] for s in simple: r = g(s) r = dot(T, r) #print shortstr(r) rows.append(r) A = array(rows).transpose() #print "A:" #print shortstr(A) print(g.word or 'I') D = dot(A - A0, V).transpose() print(shortstr(D))
def main(): X, Z = build(2) I = dot(X, X) #print(I) #print(X) #print(Z) II = tensor(I, I) P2 = [tensor(X, I), tensor(Z, I), tensor(I, X), tensor(I, Z)] found = set() for g in mulclose(P2): s = shortstr(g) found.add(s) assert len(found) == 32 assert shortstr(II) in found if 0: G = mulclose(P2) for g in G: A = numpy.array(g, dtype=numpy.float) vals = numpy.linalg.eigvals(A) print(vals) # all +1, -1 d = argv.get("d", 4) gen = build(d) n = (2**d) * factorial(d) assert len(mulclose(gen)) == n # slow... G = mulclose(gen, n) print("orders:") for g in G: print(order(g), end=' ') print() if 0: for g in G: A = numpy.array(g, dtype=numpy.float) vals = numpy.linalg.eigvals(A) print(vals) # all kinds of stuff.. if d == 4: assert len([g for g in G if shortstr(g) in found]) == 32 pairs = [] c_comm = 0 c_anti = 0 total = 0 for i in range(len(G)): for j in range(len(G)): g = G[i] h = G[j] gh = dot(g, h) hg = dot(h, g) total += 1 if eq(gh, -hg): c_anti += 1 elif eq(gh, hg): c_comm += 1 if shortstr(g) in found or shortstr(h) in found: continue if eq(gh, -hg) and i < j: #assert order(g)==2 print(order(g), end=' ') #print(g) #print(h) #print(eq(g, g.transpose()), end=' ') #print(eq(h, h.transpose())) if eq(g, g.transpose()) and eq(h, h.transpose()) and i < j: pairs.append((g, h)) #print(".", end='') #print() #print(c_comm, c_anti, total) print("pairs:", len(pairs)) ops = {} for (g, h) in pairs: ops[shortstr(g)] = g ops[shortstr(h)] = h ops = list(ops.values()) print(len(ops)) for g in ops: for h in ops: a = eq(dot(g, h), dot(h, g)) b = eq(dot(g, h), -dot(h, g)) if a == b == False: s = ' ' elif a: s = '+ ' elif b: s = '- ' print(s, end=' ') print() return A, B, C, D = gen pairs = [ s.split() for s in ("ABDA CBDC", "BACB DCDA", "BACB DCDC", "BACDBCBADCBC DCABDCDABACD") ] for l, r in pairs: left = [eval(s) for s in l] right = [eval(s) for s in r] left = dotx(*left) right = dotx(*right) if 1: print(shortstr(left)) print(shortstr(left) in found) print() print(shortstr(right)) print(shortstr(right) in found) print() print(shortstr(dotx(left, right))) print() print() assert eq((dotx(right, left)), -(dotx(left, right)))