75 KiB
75 KiB
In [1]:
from sage.structure.parent import Parent from sage.structure.element import Element #from sage.structure.unique_representation import UniqueRepresentation #from sage.categories.rings import Rings from sage.structure.richcmp import rich_to_bool, op_EQ, op_NE, op_LT, op_LE, op_GT, op_GE #from sage.categories.morphism import Morphism #from sage.rings.rational_field import QQ #from sage.algebras.commutative_dga import GradedCommutativeAlgebra #from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing #from sage.functions.other import factorial import itertools import copy import random
Simplicial Complex¶
In [2]:
S1 = SimplicialComplex([[0,1,2],[0,1,3],[0,2,3],[1,2,3],[3,4],[3,5],[4,5]],is_mutable=False)
In [3]:
S2 = SimplicialComplex([[0,1,2],[0,1,3],[0,2,3],[1,2,3],[3,4,5],[3,4,6],[3,5,6],[4,5,6]],is_mutable=False)
In [4]:
def cohomology_gens(S,n): gens = {} basis = S.cohomology_ring().basis() for k in basis.keys(): if k[0] == n: gens[k] = basis[k] return gens
In [5]:
gens = cohomology_gens(S2,2) gens
Out[5]:
{(2, 0): h^{2,0}, (2, 1): h^{2,1}}
In [6]:
v = gens[(2,1)] c = v.to_cycle() c
Out[6]:
\chi_(4, 5, 6)
In [7]:
def lift_cohomology_generator(S, g): cycle = g.to_cycle() cochain = {} for n in range(S.dimension()+1): for simplex in S._n_cells_sorted(n): cochain[simplex.tuple()] = 0 for i in cycle: #print(type(i[0].tuple())) cochain[i[0].tuple()] = i[1] return cochain
In [8]:
lift_cohomology_generator(S2,gens[(2,1)])
Out[8]:
{(0,): 0,
(1,): 0,
(2,): 0,
(3,): 0,
(4,): 0,
(5,): 0,
(6,): 0,
(0, 1): 0,
(0, 2): 0,
(0, 3): 0,
(1, 2): 0,
(1, 3): 0,
(2, 3): 0,
(3, 4): 0,
(3, 5): 0,
(3, 6): 0,
(4, 5): 0,
(4, 6): 0,
(5, 6): 0,
(0, 1, 2): 0,
(0, 1, 3): 0,
(0, 2, 3): 0,
(1, 2, 3): 0,
(3, 4, 5): 0,
(3, 4, 6): 0,
(3, 5, 6): 0,
(4, 5, 6): 1}
Apln¶
In [2]:
class Apln(UniqueRepresentation): def __init__(self,n): self.n = n self.algebras = [] self.relations = [] for i in range(n+1): [cdga, relations] = self._cdga(i) self.algebras.append(cdga) self.relations.append(relations) def _cdga(self,n): ts = ['t'+str(t) for t in range(n+1)] ys = ['y'+str(t) for t in range(n+1)] degrees = tuple((n+1)*[(0,2)])+tuple((n+1)*[(1,2)]) gca = GradedCommutativeAlgebra(QQ, names=ts+ys, degrees=degrees) t_relation = -1 y_relation = 0 #t_relation = sum(self.gca.gens()[:n])-1 #y_relation = sum(self.gca.gens()[n:]) for i in range(n+1): t_relation += gca.gens()[i] y_relation += gca.gens()[n+1+i] #gca_with_relations = self.gca.quotient(self.gca.ideal(t_relation,y_relation),check=False) dfs = {gca.gens_dict()[ts[i]]:gca.gens_dict()[ys[i]] for i in range(n+1)} return [gca.cdg_algebra(dfs),[t_relation,y_relation]] def __repr__(self): return "Simplicial algebra of dimension %s" % self.n def inject_variables(self, n): self.algebras[n].inject_variables() def generators(self, n): return self.algebras[n].gens() def get_multidegree(self, p): a3 = p.parent() n = len(a3.gens())/2 multidegrees = {} for k in p.dict().keys(): multideg = vector(QQ,n*[0]) for i in range(n): multideg[i] = k[i]+k[i+n] multidegrees[k] = multideg return multidegrees def face(self,i,n): if(self.n==0): return 0 domain = self.algebras[n] codomain = self.algebras[n-1] tImages = [] yImages = [] n = len(domain.gens())//2 for k in range(n): if(k<i): tImages.append(codomain.gens()[k]) yImages.append(codomain.gens()[n-1+k]) elif(k==i): tImages.append(0) yImages.append(0) elif(k>i): tImages.append(codomain.gens()[k-1]) yImages.append(codomain.gens()[n+k-2]) images = tImages+yImages return domain.hom(codomain=codomain,im_gens=images) def reduce_polynomial(self,p): ## Input: # - p: polynomial in variables t_0,..t_n,y_0,...,y_n ## Output: # - The polynomial after applying the corresponding relations to reduce the variables t_0, y_0 apl = p.parent() dim = len(apl.gens())//2-1 return p.reduce(self.relations[dim]) def _convert_integrable_polynomial(self,p): ## Input: # - p: polynomial in variables t_1,..t_n,y_1,...,y_n ## Output: # - A polynomial in the ring Q<t_1,..t_n>. # (After reducing the variables t_{0},y_{0} by the corresponding relations, # the algorithm removes the variables y_{1},..,y_{n}). apl = p.parent() n = len(apl.gens())//2 pol = self.reduce_polynomial(p) relations = [] for i in range(n): relations.append(apl.gens()[n+i]-1) return pol.reduce(relations) def integral(self,p): ## Input: # - p: polynomial in variables t_0,..t_n,y_0,...,y_n ## Output: # - the integral of the polynomial after reducing the variables t_0, y_0 by the corresponding relations # apl = p.parent() n = len(apl.gens())//2-1 pol = self._convert_integrable_polynomial(p) result = 0 for k in pol.dict().keys(): # k is a monomial numerator = 1 denominator = n for e in k: # e is an exponents numerator *= factorial(e) denominator += e coef = pol.dict()[k] result += coef*numerator/factorial(denominator) return ((-1)**(n*(n-1)/2))*result def lift(self, value, n): apl = self.algebras[n] gens = apl.gens() return value*((-1)**(n*(n-1)/2))*factorial(n)*prod(gens[n+2:]) def homogeneous_part(self,pol,degree): parts = [pol.homogeneous_parts()[k] for k in pol.homogeneous_parts() if list(k)[0]==degree] return sum(parts) def propagate(self, face_list, n): """ - face_list: indexes of the elements that form the face of the simplex we want to propagate - EXAMPLE: p = a.propagate([0,3,4],5) t4*y0*y3 - t3*y0*y4 + t0*y3*y4 """ simplex_dim = len(face_list)-1 indexes = list(range(simplex_dim+1)) apl = self.algebras[n] y_gens = [apl.gens()[n+1+i] for i in face_list] t_gens = [apl.gens()[i] for i in face_list] result = apl(0) for i in reversed(indexes): t = t_gens[i] y_prod = copy.deepcopy(y_gens) del y_prod[i] y_prod = prod(y_prod) result += ((-1)**i)*t*y_prod#((-1)**(simplex_dim+i))*t*y_prod return result
In [3]:
# Funciones añadidas
In [4]:
def get_multidegree(self, p): a3 = p.parent() n = len(a3.gens())/2 multidegrees = {} for k in p.dict().keys(): multideg = vector(QQ,n*[0]) for i in range(n): multideg[i] = k[i]+k[i+n] multidegrees[k] = multideg return multidegrees
In [ ]:
In [5]:
a = Apln(5) a.inject_variables(3) p = t2*y0*y1-t1*y0*y2+t0*y1*y2 q = a.face(1,3)(p) ared = a.reduce_polynomial(q) ared
Defining t0, t1, t2, t3, y0, y1, y2, y3
Out[5]:
0
Empiezan celdas de pruebas¶
In [6]:
p = 5*t2^2*y0*y1-t1*y0*y2+t0*y1*y2 p.dict()
Out[6]:
{(0, 0, 2, 0, 1, 1, 0, 0): 5,
(0, 1, 0, 0, 1, 0, 1, 0): -1,
(1, 0, 0, 0, 0, 1, 1, 0): 1}
In [ ]:
In [7]:
apl = Apln(5) apl.inject_variables(3) d=1 c=d b=2*d-1/2 a=2*d-1/2 w1=a*(t0*t1^2*t2*t3*y0)+b*(t0^2*t1*t2*t3*y1)+c*(t0^2*t1^2*t3*y2)+d*(t0^2*t1^2*t2*y3) d=5 c=d b=2*d-1/2 a=2*d-1/2 w2=a*(t0*t1^2*t2*t3*y0)+b*(t0^2*t1*t2*t3*y1)+c*(t0^2*t1^2*t3*y2)+d*(t0^2*t1^2*t2*y3) w1.differential()==w2.differential()
Defining t0, t1, t2, t3, y0, y1, y2, y3
Out[7]:
True
In [8]:
m0 = p.monomials() m0
Out[8]:
[t2^2*y0*y1, t1*y0*y2, t0*y1*y2]
In [9]:
p = (5*t2^2 + 5)*y0*y1 p
Out[9]:
5*t2^2*y0*y1 + 5*y0*y1
In [10]:
p = 5*t2^2*y0*y1-t1*y0*y2+t0*y1*y2 p.dict()
Out[10]:
{(0, 0, 2, 0, 1, 1, 0, 0): 5,
(0, 1, 0, 0, 1, 0, 1, 0): -1,
(1, 0, 0, 0, 0, 1, 1, 0): 1}
In [ ]:
In [ ]:
In [ ]:
In [11]:
def get_term(coef, exp, gens): return coef*prod(list(map(lambda exp, gen: gen^exp, exp, gens))) def get_terms(p): a = p.parent() n = len(a.gens())/2 ts_only_gens = a.gens()[:n]+tuple(n*[1]) ys_only_gens = tuple(n*[1])+a.gens()[n:] terms = {} pol = p.dict() for exp in pol.keys(): key = get_term(1, exp,ys_only_gens) if key not in terms.keys(): coef = get_term(pol[exp],exp,ts_only_gens) terms[key] = coef else: coef = get_term(pol[exp],exp,ts_only_gens) terms[key] += coef return terms
In [12]:
p = 5*t2^2*y0*y1-t1*y0*y2+t0*y1*y2+3*y0*y1 print(p) terms = get_terms(p) terms
5*t2^2*y0*y1 - t1*y0*y2 + t0*y1*y2 + 3*y0*y1
Out[12]:
{y0*y1: 5*t2^2 + 3, y0*y2: -t1, y1*y2: t0}
In [13]:
# comprobamos que la suma de los términos nos da el polinomio original p2 = sum([terms[key]*key for key in terms.keys()]) p2==p
Out[13]:
True
In [81]:
Out[81]:
3
In [80]:
lead_term = get_leading_term(p) symbolic_partial_integral(lead_term, 0)
Out[80]:
{y1: 5*t0*t2^2 + 3*t0}
In [114]:
def get_leading_pol(pol): terms = get_terms(pol) keys = list(terms.keys()) keys.sort(reverse=True) return terms[keys[0]]*keys[0] def get_integration_idx(exp): # gets the idx 'i' of the first generator 'y_i' that appears in exp n = len(exp)/2 filter_ts = n*[0]+n*[1] diff_forms = list(map(lambda v, f: v*f, exp, filter_ts)) return next((i for i, x in enumerate(list(diff_forms)) if x), None)-n def symbolic_partial_monomial_integral(monomial, idx): exp = list(monomial.dict().keys())[0] coef = monomial.dict()[exp] n = len(exp)/2 if (exp[n+idx]==0): raise IndexError("El término no se puede integrar respecto a esa variable") integral = list(copy.deepcopy(exp)) integral[n+idx] = 0 integral[idx] += 1 new_coef = coef/integral[idx] a = monomial.parent() return get_term(new_coef, integral, a.gens()) def symbolic_partial_integral(polynomial): # necessary condition: all monomials have apl.gens[n+integration_idx] factor exp = list(polynomial.dict().keys())[0] integration_idx = get_integration_idx(exp) aGens = polynomial.parent().gens() integral = 0 for exp in polynomial.dict().keys(): coef = polynomial.dict()[exp] monomial = get_term(coef, exp, aGens) integral += symbolic_partial_monomial_integral(monomial, integration_idx) terms = get_terms(integral) result = sum([terms[key]*key for key in terms.keys()]) return result
In [115]:
symbolic_partial_integral(terms[y0*y1]*y0*y1)
Out[115]:
5*t0*t2^2*y1 + 3*t0*y1
In [143]:
def find_preimage_diff(pol): if pol.differential()!=0 : raise ValueError("This polynomial is not in the kernel of the differential") lead_pol = get_leading_pol(pol) w = symbolic_partial_integral(lead_pol) theta = pol - w.differential() if (theta == 0): return w else: return w+find_preimage_diff(theta)
In [144]:
# Ejemplo 1 q = t0*y1+t1*y0 find_preimage_diff(q)
Out[144]:
t0*t1
In [149]:
#Ejemplo 2 q1 = (-1/2)*(t0*t1^2*t2*t3*y0) q2 = (-1/2)*(t0^2*t1*t2*t3*y1) q = q1+q2 dq = q.differential() w = find_preimage_diff(dq) w.differential() == dq
Out[149]:
True
In [157]:
show(q) show(w)
<html></html>
<html></html>
In [177]:
# Ejemplo 3 n=6 a = Apln(n) a.inject_variables(n) q = t5*y1*y2*y3+t2*y0*y1*y3+t3*y3*y4*y6 dq = q.differential() w = find_preimage_diff(dq) print("q = ", q) print("dq = ",dq) print("w = ",w) print("dw = ", w.differential()) w.differential()==dq
Defining t0, t1, t2, t3, t4, t5, t6, y0, y1, y2, y3, y4, y5, y6 q = t2*y0*y1*y3 + t5*y1*y2*y3 + t3*y3*y4*y6 dq = y0*y1*y2*y3 - y1*y2*y3*y5 w = t0*y1*y2*y3 - t1*y2*y3*y5 dw = y0*y1*y2*y3 - y1*y2*y3*y5
Out[177]:
True
In [178]:
# Ejemplo 4 n=6 a = Apln(n) a.inject_variables(n) q = t5*y1*y2+t2*y0*y1+5*y1*y2+t5*y3*y4 dq = q.differential() w = find_preimage_diff(dq) print("q = ", q) print("dq = ",dq) print("w = ",w) print("dw = ", w.differential()) w.differential()==dq
Defining t0, t1, t2, t3, t4, t5, t6, y0, y1, y2, y3, y4, y5, y6 q = t2*y0*y1 + t5*y1*y2 + t5*y3*y4 + 5*y1*y2 dq = y0*y1*y2 + y1*y2*y5 + y3*y4*y5 w = t0*y1*y2 + t1*y2*y5 + t3*y4*y5 dw = y0*y1*y2 + y1*y2*y5 + y3*y4*y5
Out[178]:
True
Terminan celdas de pruebas¶
In [16]:
p = a.propagate([0, 2, 3, 4, 5],5) q = a.face(1,5)(p) ared = a.reduce_polynomial(q) print(q) print(ared)
t4*y0*y1*y2*y3 - t3*y0*y1*y2*y4 + t2*y0*y1*y3*y4 - t1*y0*y2*y3*y4 + t0*y1*y2*y3*y4 y1*y2*y3*y4
In [ ]:
In [17]:
a.algebras[3].gens()[4:-1]
Out[17]:
(y0, y1, y2)
In [18]:
n=3 a = Apln(n) a.inject_variables(n) cdga = a.algebras[n] gens = cdga.gens()[n+1:-1] gens
Defining t0, t1, t2, t3, y0, y1, y2, y3
Out[18]:
(y0, y1, y2)
In [19]:
N = 6 for n in reversed(range(1,N)): print("n = " + str(n)) for face in range(n+1): idx = list(range(N)) del idx[face] r = [perm for perm in itertools.permutations(idx,r=int(n)) if sorted(perm) == list(perm)] #print(r)
n = 5 n = 4 n = 3 n = 2 n = 1
In [ ]:
Apl(K)¶
In [20]:
class AplK(UniqueRepresentation, Parent): def __init__(self,K, category=None): self.K = K self.n = K.dimension() self.apln = Apln(K.dimension()) Parent.__init__(self,category=category ) f = MorphismFromQQToAplK(self) self.register_coercion(f) def _repr_(self): return "Algebra AplK over %s" % self.K def _element_constructor_(self,values): return self.element_class(self,values) def dimension(self): return self.K.dimension() def simplicialComplex(self): return self.K def _n_cells_sorted(self,n): return self.K._n_cells_sorted(n) def lift(self, cochain): # first we find polynomials compatible with the integration value values = {} max_n = 0 for k in cochain.keys(): n = len(k)-1 if n > max_n: max_n = n apl = self.apln.algebras[n] if n>0: values[k] = self.apln.lift(cochain[k],n) else: values[k]= apl(cochain[k]) # second, we propagate the simplicial information simplicial_structure = {} for n in reversed(range(max_n+1)): keys = [k for k in values.keys() if len(k) == n+1] # keys of the n-simplices for k in keys: simplicial_structure[k] = values[k] + self._propagate(cochain, k) #print(simplicial_structure) return AplKElement(self,simplicial_structure) def _faces_of_length(self, simplex, length): return [tuple(e) for e in powerset(simplex) if len(e)==length] def _propagate(self, cochain, simplex): dim = len(simplex)-1 apl = self.apln.algebras[dim] propagation = apl(0) for n in reversed(range(dim+1)): faces = self._faces_of_length(simplex, n) for f in faces: if f in cochain.keys(): dim_face = len(f)-1 value = cochain[f] face_indexes = [simplex.index(i) for i in f] propagation += value*((-1)**(dim_face*(dim_face-1)/2))*factorial(dim_face)*self.apln.propagate(face_indexes, dim) return propagation
In [22]:
# AplK._propagate TEST cochain = {(0,): 0, (1,): 0, (2,):0, (3,): 0, (0,1): 0, (0,2): 0, (1,2): 1, (1,3): 0, (2,3): 0, (0,1,2):0} S = SimplicialComplex([[0,1,2],[1,3],[2,3]],is_mutable=False) A = AplK(S) p = A._propagate(cochain,(0,1,2)) print(p) a = Apln(5) q = a.face(0,2)(p) print(q) ared = a.reduce_polynomial(q) print(ared)
--------------------------------------------------------------------------- KeyError Traceback (most recent call last) ~/Documents/0-PhD/Code/sage-9.2/local/lib/python3.8/site-packages/sage/misc/cachefunc.pyx in sage.misc.cachefunc.CachedFunction.__call__ (build/cythonized/sage/misc/cachefunc.c:5975)() 995 try: --> 996 return self.cache[k] 997 except TypeError: # k is not hashable ~/Documents/0-PhD/Code/sage-9.2/local/lib/python3.8/site-packages/sage/misc/weak_dict.pyx in sage.misc.weak_dict.WeakValueDictionary.__getitem__ (build/cythonized/sage/misc/weak_dict.c:3737)() 703 if wr == NULL: --> 704 raise KeyError(k) 705 out = PyWeakref_GetObject(wr) KeyError: ((<class '__main__.AplK'>, Simplicial complex with vertex set (0, 1, 2, 3) and facets {(1, 3), (2, 3), (0, 1, 2)}), ()) During handling of the above exception, another exception occurred: NameError Traceback (most recent call last) <ipython-input-22-3b31891d9403> in <module> 2 cochain = {(Integer(0),): Integer(0), (Integer(1),): Integer(0), (Integer(2),):Integer(0), (Integer(3),): Integer(0), (Integer(0),Integer(1)): Integer(0), (Integer(0),Integer(2)): Integer(0), (Integer(1),Integer(2)): Integer(1), (Integer(1),Integer(3)): Integer(0), (Integer(2),Integer(3)): Integer(0), (Integer(0),Integer(1),Integer(2)):Integer(0)} 3 S = SimplicialComplex([[Integer(0),Integer(1),Integer(2)],[Integer(1),Integer(3)],[Integer(2),Integer(3)]],is_mutable=False) ----> 4 A = AplK(S) 5 p = A._propagate(cochain,(Integer(0),Integer(1),Integer(2))) 6 print(p) ~/Documents/0-PhD/Code/sage-9.2/local/lib/python3.8/site-packages/sage/misc/classcall_metaclass.pyx in sage.misc.classcall_metaclass.ClasscallMetaclass.__call__ (build/cythonized/sage/misc/classcall_metaclass.c:1762)() 320 """ 321 if cls.classcall is not None: --> 322 return cls.classcall(cls, *args, **kwds) 323 else: 324 # Fast version of type.__call__(cls, *args, **kwds) ~/Documents/0-PhD/Code/sage-9.2/local/lib/python3.8/site-packages/sage/misc/cachefunc.pyx in sage.misc.cachefunc.CachedFunction.__call__ (build/cythonized/sage/misc/cachefunc.c:6101)() 999 return self.cache[k] 1000 except KeyError: -> 1001 w = self.f(*args, **kwds) 1002 self.cache[k] = w 1003 return w ~/Documents/0-PhD/Code/sage-9.2/local/lib/python3.8/site-packages/sage/structure/unique_representation.py in __classcall__(cls, *args, **options) 1006 True 1007 """ -> 1008 instance = typecall(cls, *args, **options) 1009 assert isinstance( instance, cls ) 1010 if instance.__class__.__reduce__ == CachedRepresentation.__reduce__: ~/Documents/0-PhD/Code/sage-9.2/local/lib/python3.8/site-packages/sage/misc/classcall_metaclass.pyx in sage.misc.classcall_metaclass.typecall (build/cythonized/sage/misc/classcall_metaclass.c:2224)() 484 TypeError: Argument 'cls' has incorrect type (expected type, got classobj) 485 """ --> 486 return (<PyTypeObject*>type).tp_call(cls, args, kwds) 487 488 # Class for timing:: <ipython-input-20-57d0fa9f124b> in __init__(self, K, category) 6 self.apln = Apln(K.dimension()) 7 Parent.__init__(self,category=category ) ----> 8 f = MorphismFromQQToAplK(self) 9 self.register_coercion(f) 10 NameError: name 'MorphismFromQQToAplK' is not defined
In [ ]:
S = SimplicialComplex([[0,1,2],[1,3],[2,3]],is_mutable=False) A = AplK(S) cochain = {(0,): 2, (1,): 3, (2,):0, (3,): 0, (0,1): 1, (0,2): 5, (1,2): 1, (1,3): 0, (2,3): 0, (0,1,2):10} p = A.lift(cochain) p
In [ ]:
A.lift(cochain).integral()==cochain
In [ ]:
A.lift(p.integral())==p
In [ ]:
Apl(K) Element¶
In [23]:
class AplKElement(Element): def __init__(self, parent, values): Element.__init__(self,parent) self.apln = Apln(parent.dimension()) self.elements = self.reduce(values) self.check() def reduce(self, values): reduced_values = {} for k in values.keys(): n = len(k)-1 apl = self.apln.algebras[n] reduced_values[k] = self.apln.reduce_polynomial(apl(values[k])) return reduced_values def _repr_(self): return str(self.elements) def dimension(self): return self.parent().dimension() def nullElement(self): C = self.__class__ values = {} for k in self.elements.keys(): values[k]=0 return C(self.parent(),values) def _add_(self,other): C = self.__class__ if(self.elements.keys()!=other.elements.keys()): raise ValueError("error: keys do not match") newValues = {} for k in self.elements.keys(): newValues[k] = self.elements[k]+other.elements[k] return C(self.parent(),newValues) def _sub_(self,other): C = self.__class__ if(self.elements.keys()!=other.elements.keys()): raise ValueError("error: keys do not match") newValues = {} for k in self.elements.keys(): newValues[k] = self.elements[k]-other.elements[k] return C(self.parent(),newValues) def _mul_(self,other): C = self.__class__ if(self.elements.keys()!=other.elements.keys()): raise ValueError("error: keys do not match") newValues = {} for k in self.elements.keys(): newValues[k] = self.elements[k]*other.elements[k] return C(self.parent(),newValues) def _richcmp_(self, other, op): if(op==op_EQ): if(self.elements.keys()!=other.elements.keys()): return False for k in self.elements.keys(): if(self.elements[k]!=other.elements[k]): return False return True elif(op==op_NE): return not self._richcmp_(other,op_EQ) else: raise NotImplementedError("operation not implemented for this element class") def differential(self): C = self.__class__ newValues = {} for k in self.elements.keys(): newValues[k] = self.elements[k].differential() return C(self.parent(),newValues) def check(self): S = self.parent().simplicialComplex() dim = S.dimension() for n in range(1,dim+1): #print("Checking dimension " + str(n)) for simplex in S._n_cells_sorted(n): for f in range(n+1): sFace = tuple(S.face(simplex,f)) aFace = self.apln.face(f,n)(self.elements[simplex.tuple()]) aFace = self.apln.reduce_polynomial(aFace) #print("face: " + str(f),"simplex: " + str(simplex),"sFace: " + str(self.elements[sFace]), "aFace: " + str(aFace)) if(self.elements[sFace] != aFace): raise ValueError("the assignation is not valid") def homogeneous_part(self,degree): C = self.__class__ part = {} for k in self.elements.keys(): part[k] = self.apln.homogeneous_part(self.elements[k],degree) return C(self.parent(),part) def homogeneous_parts(self): parts = {} for n in range(self.dimension()+1): parts[n] = self.homogeneous_part(n) return parts def is_homogeneous(self): isHomogeneous = True for k in self.elements.keys(): isHomogeneous = isHomogeneous and self.elements[k].is_homogeneous() return isHomogeneous def is_closed(self): diff = self.differential() if(diff == self.nullElement()): return True else: return False def _integrable_component(self): C = self.__class__ component = {} for k in self.elements.keys(): degree = len(k)-1 component[k] = self.apln.homogeneous_part(self.elements[k],degree) #component[k] = self.homogeneous_component(dim).elements[k] return component def integral(self): component = self._integrable_component() cochain = {} #integration of each polynomial for k in component.keys(): n = len(k)-1 apl = self.apln.algebras[n] cochain[k] = self.apln.integral(apl(component[k])) return cochain ##################################################################### class MorphismFromQQToAplK(Morphism): def __init__(self, codomain): self.simplicialComplex= codomain.K Morphism.__init__(self, QQ, codomain) def _call_(self, x): S = self.simplicialComplex params1 = {} for d in range(S.dimension()+1): for c in S._n_cells_sorted(d): params1[tuple(c)]=x A = AplK(S) return AplKElement(A, params1)
In [24]:
S = SimplicialComplex([[0, 1, 2]], is_mutable=False) apl = Apln(S.dimension()) A = AplK(S) cochain = {(0,): 0, (1,): 0, (2,):0, (0,1): 0,(0,2): 0, (1,2): 0, (0,1,2): 1} #A.lift(apl, cochain)
In [25]:
q = A.lift(cochain) q
Out[25]:
{(0, 1, 2): -2*y1*y2, (0, 1): 0, (0, 2): 0, (1, 2): 0, (0,): 0, (1,): 0, (2,): 0}
In [ ]:
2*q
In [ ]:
In [ ]:
All together¶
In [ ]:
S1 = SimplicialComplex([[0,1,2],[0,1,3],[0,2,3],[1,2,3],[3,4],[3,5],[4,5]],is_mutable=False) S2 = SimplicialComplex([[0,1,2],[0,1,3],[0,2,3],[1,2,3],[3,4,5],[3,4,6],[3,5,6],[4,5,6]],is_mutable=False) S3 = SimplicialComplex([[0,1,2],[1,3],[2,3]],is_mutable=False) S4 = SimplicialComplex([[0,1,3],[1,2,4],[3,4,5]],is_mutable=False) S5 = simplicial_complexes.Sphere(5) S = S5 apl = Apln(S.dimension()) A = AplK(S)
In [ ]:
n = 5 gens = cohomology_gens(S,n) cochain = lift_cohomology_generator(S,gens[(n,0)])
In [ ]:
gens
In [ ]:
p = A.lift(cochain)
In [ ]:
p.integral()==cochain
Test lift == integral¶
In [26]:
def sublist(lst1, lst2): return set(lst1) <= set(lst2) def sublist_of_lists(list1,list_of_lists): is_sublist = False for list2 in list_of_lists: if sublist(list1,list2): is_sublist = True break return is_sublist def random_simplicial_complex(num_vertices,max_num_facets): vertices = list(range(num_vertices)) simplices = [] partitions = [] for length in range(num_vertices): partitions += [tuple(e) for e in powerset(vertices) if len(e)==length and e] for i in range(max_num_facets+1): r = randint(0,len(partitions)-1) candidate = partitions[r] if not sublist_of_lists(candidate,simplices): simplices.append(candidate) return SimplicialComplex(simplices,is_mutable=False) def random_cochain(S): dim = S.dimension() cochain = {} for n in range(dim+1): for s in S._n_cells_sorted(n): cochain[s.tuple()] = randint(-100,100) return cochain
In [27]:
S = random_simplicial_complex(5,4) S.facets()
Out[27]:
{(0, 1, 4), (0, 1, 3), (0, 1, 2)}
In [ ]:
In [ ]:
In [ ]:
In [ ]:
In [28]:
def test(max_vertices, verbose=False): success = True data = [] for i in range(10): v = randint(2,max_vertices) f = randint(1,v) S = random_simplicial_complex(num_vertices=v,max_num_facets=f) A = AplK(S) cochain = random_cochain(S) #print(cochain) data = [S, cochain] if verbose: print("iteration: " + str(i), "num_vertices: " + str(v), "max_num_facets: " + str(f), "facets: " + str(S.facets())) p = A.lift(cochain) if verbose: print(p) if not p.integral()==cochain: success = False print("Error") break if success: print("success: " + str(success))
In [29]:
test(max_vertices=6, verbose=True)
iteration: 0 num_vertices: 5 max_num_facets: 1 facets: {(1, 3, 4), (0, 4)}
{(1, 3, 4): -168*y1*y2 - 65*t2*y1 + 65*t1*y2 - 71*y1 - 94*y2 - 150*t1 + t2 + 87, (0, 4): -80*y1 + 60*t1 + 28, (1, 3): -71*y1 - 150*t1 + 87, (1, 4): -94*y1 + t1 + 87, (3, 4): 42*y1 + 151*t1 - 63, (0,): 28, (1,): 87, (3,): -63, (4,): 88}
iteration: 1 num_vertices: 4 max_num_facets: 1 facets: {(0, 2, 3), (0, 1, 2)}
{(0, 1, 2): -52*y1*y2 - 65*t2*y1 + 65*t1*y2 + 54*y1 + 81*y2 - 64*t1 - 58*t2 + 70, (0, 2, 3): 82*y1*y2 + 45*t2*y1 - 45*t1*y2 + 81*y1 + 71*y2 - 58*t1 - 95*t2 + 70, (0, 1): 54*y1 - 64*t1 + 70, (0, 2): 81*y1 - 58*t1 + 70, (0, 3): 71*y1 - 95*t1 + 70, (1, 2): 92*y1 + 6*t1 + 6, (2, 3): -55*y1 - 37*t1 + 12, (0,): 70, (1,): 6, (2,): 12, (3,): -25}
iteration: 2 num_vertices: 4 max_num_facets: 3 facets: {(0, 1, 3), (0, 2, 3), (1, 2)}
{(0, 1, 3): -12*y1*y2 + 47*t2*y1 - 47*t1*y2 - 59*y1 + 22*y2 - 95*t1 - 132*t2 + 67, (0, 2, 3): -178*y1*y2 - 29*t2*y1 + 29*t1*y2 - 15*y1 + 22*y2 - 7*t1 - 132*t2 + 67, (0, 1): -59*y1 - 95*t1 + 67, (0, 2): -15*y1 - 7*t1 + 67, (0, 3): 22*y1 - 132*t1 + 67, (1, 2): -5*y1 + 88*t1 - 28, (1, 3): 34*y1 - 37*t1 - 28, (2, 3): 66*y1 - 125*t1 + 60, (0,): 67, (1,): -28, (2,): 60, (3,): -65}
iteration: 3 num_vertices: 6 max_num_facets: 2 facets: {(2, 3, 4), (0, 1, 3, 4)}
{(0, 1, 3, 4): -36*y1*y2*y3 + 444*t3*y1*y2 - 444*t2*y1*y3 + 444*t1*y2*y3 - 22*y1*y2 + 120*y1*y3 - 130*y2*y3 - 51*t2*y1 - 129*t3*y1 + 51*t1*y2 - 118*t3*y2 + 129*t1*y3 + 118*t2*y3 + 22*y1 + 67*y2 - 93*y3 - 57*t1 - 8*t2 + 112*t3 - 22, (0, 1, 3): -22*y1*y2 - 51*t2*y1 + 51*t1*y2 + 22*y1 + 67*y2 - 57*t1 - 8*t2 - 22, (0, 1, 4): 120*y1*y2 - 129*t2*y1 + 129*t1*y2 + 22*y1 - 93*y2 - 57*t1 + 112*t2 - 22, (0, 3, 4): -130*y1*y2 - 118*t2*y1 + 118*t1*y2 + 67*y1 - 93*y2 - 8*t1 + 112*t2 - 22, (1, 3, 4): 172*y1*y2 - 40*t2*y1 + 40*t1*y2 + 96*y1 + 14*y2 + 49*t1 + 169*t2 - 79, (2, 3, 4): -96*y1*y2 + 92*t2*y1 - 92*t1*y2 + 35*y1 + 85*y2 - 35*t1 + 85*t2 + 5, (0, 1): 22*y1 - 57*t1 - 22, (0, 3): 67*y1 - 8*t1 - 22, (0, 4): -93*y1 + 112*t1 - 22, (1, 3): 96*y1 + 49*t1 - 79, (1, 4): 14*y1 + 169*t1 - 79, (2, 3): 35*y1 - 35*t1 + 5, (2, 4): 85*y1 + 85*t1 + 5, (3, 4): -42*y1 + 120*t1 - 30, (0,): -22, (1,): -79, (2,): 5, (3,): -30, (4,): 90}
iteration: 4 num_vertices: 2 max_num_facets: 2 facets: {(1,), (0,)}
{(0,): -2, (1,): 97}
iteration: 5 num_vertices: 5 max_num_facets: 5 facets: {(0, 2, 3, 4), (0, 1, 2, 4), (1, 2, 3)}
{(0, 1, 2, 4): -384*y1*y2*y3 + 212*t3*y1*y2 - 212*t2*y1*y3 + 212*t1*y2*y3 - 76*y1*y2 - 44*y1*y3 - 128*y2*y3 + 8*t2*y1 + 28*t3*y1 - 8*t1*y2 - 103*t3*y2 - 28*t1*y3 + 103*t2*y3 - 6*y1 + 51*y2 - 46*y3 - 37*t1 + 119*t2 + 147*t3 - 63, (0, 2, 3, 4): -150*y1*y2*y3 - 254*t3*y1*y2 + 254*t2*y1*y3 - 254*t1*y2*y3 + 142*y1*y2 - 128*y1*y3 + 74*y2*y3 + 61*t2*y1 - 103*t3*y1 - 61*t1*y2 + t3*y2 + 103*t1*y3 - t2*y3 + 51*y1 + 53*y2 - 46*y3 + 119*t1 + 125*t2 + 147*t3 - 63, (0, 1, 2): -76*y1*y2 + 8*t2*y1 - 8*t1*y2 - 6*y1 + 51*y2 - 37*t1 + 119*t2 - 63, (0, 1, 4): -44*y1*y2 + 28*t2*y1 - 28*t1*y2 - 6*y1 - 46*y2 - 37*t1 + 147*t2 - 63, (0, 2, 3): 142*y1*y2 + 61*t2*y1 - 61*t1*y2 + 51*y1 + 53*y2 + 119*t1 + 125*t2 - 63, (0, 2, 4): -128*y1*y2 - 103*t2*y1 + 103*t1*y2 + 51*y1 - 46*y2 + 119*t1 + 147*t2 - 63, (0, 3, 4): 74*y1*y2 + t2*y1 - t1*y2 + 53*y1 - 46*y2 + 125*t1 + 147*t2 - 63, (1, 2, 3): 148*y1*y2 - 55*t2*y1 + 55*t1*y2 + 49*y1 - 65*y2 + 156*t1 + 162*t2 - 100, (1, 2, 4): 52*y1*y2 - 123*t2*y1 + 123*t1*y2 + 49*y1 - 68*y2 + 156*t1 + 184*t2 - 100, (2, 3, 4): 90*y1*y2 + 165*t2*y1 - 165*t1*y2 - 59*y1 + 6*y2 + 6*t1 + 28*t2 + 56, (0, 1): -6*y1 - 37*t1 - 63, (0, 2): 51*y1 + 119*t1 - 63, (0, 3): 53*y1 + 125*t1 - 63, (0, 4): -46*y1 + 147*t1 - 63, (1, 2): 49*y1 + 156*t1 - 100, (1, 3): -65*y1 + 162*t1 - 100, (1, 4): -68*y1 + 184*t1 - 100, (2, 3): -59*y1 + 6*t1 + 56, (2, 4): 6*y1 + 28*t1 + 56, (3, 4): -100*y1 + 22*t1 + 62, (0,): -63, (1,): -100, (2,): 56, (3,): 62, (4,): 84}
iteration: 6 num_vertices: 2 max_num_facets: 1 facets: {(1,), (0,)}
{(0,): -95, (1,): 1}
iteration: 7 num_vertices: 4 max_num_facets: 3 facets: {(1, 3), (0, 2, 3)}
{(0, 2, 3): -182*y1*y2 - 93*t2*y1 + 93*t1*y2 - 53*y1 - 66*y2 - 25*t1 - 26*t2 - 52, (0, 2): -53*y1 - 25*t1 - 52, (0, 3): -66*y1 - 26*t1 - 52, (1, 3): -35*y1 + 16*t1 - 94, (2, 3): 80*y1 - t1 - 77, (0,): -52, (1,): -94, (2,): -77, (3,): -78}
iteration: 8 num_vertices: 5 max_num_facets: 4 facets: {(2, 3, 4), (1, 2), (0, 1, 3, 4)}
{(0, 1, 3, 4): 36*y1*y2*y3 - 74*t3*y1*y2 + 74*t2*y1*y3 - 74*t1*y2*y3 + 190*y1*y2 - 138*y1*y3 - 172*y2*y3 - 6*t3*y1 - 16*t3*y2 + 6*t1*y3 + 16*t2*y3 + 44*y1 - 3*y2 - 13*y3 + 90*t1 - 8*t2 + 136*t3 - 46, (0, 1, 3): 190*y1*y2 + 44*y1 - 3*y2 + 90*t1 - 8*t2 - 46, (0, 1, 4): -138*y1*y2 - 6*t2*y1 + 6*t1*y2 + 44*y1 - 13*y2 + 90*t1 + 136*t2 - 46, (0, 3, 4): -172*y1*y2 - 16*t2*y1 + 16*t1*y2 - 3*y1 - 13*y2 - 8*t1 + 136*t2 - 46, (1, 3, 4): 82*y1*y2 - 10*t2*y1 + 10*t1*y2 - 47*y1 - 51*y2 - 98*t1 + 46*t2 + 44, (2, 3, 4): 6*y1*y2 + 85*t2*y1 - 85*t1*y2 - 72*y1 + 19*y2 + 17*t1 + 161*t2 - 71, (0, 1): 44*y1 + 90*t1 - 46, (0, 3): -3*y1 - 8*t1 - 46, (0, 4): -13*y1 + 136*t1 - 46, (1, 2): -27*y1 - 115*t1 + 44, (1, 3): -47*y1 - 98*t1 + 44, (1, 4): -51*y1 + 46*t1 + 44, (2, 3): -72*y1 + 17*t1 - 71, (2, 4): 19*y1 + 161*t1 - 71, (3, 4): 6*y1 + 144*t1 - 54, (0,): -46, (1,): 44, (2,): -71, (3,): -54, (4,): 90}
iteration: 9 num_vertices: 5 max_num_facets: 3 facets: {(1, 3), (1, 2)}
{(1, 2): 91*y1 - 78*t1 + 81, (1, 3): 100*y1 + 5*t1 + 81, (1,): 81, (2,): 3, (3,): 86}
success: True
In [33]:
S = random_simplicial_complex(5,4) A = AplK(S)
In [34]:
c1 = random_cochain(S) p1 = A.lift(c1) c2 = random_cochain(S) p2 = A.lift(c2)
In [40]:
(p2*p1).differential
Object `differential` not found.
In [ ]:
a = apl.algebras[2]
In [50]:
Out[50]:
Commutative Differential Graded Algebra with generators ('t0', 't1', 't2', 'y0', 'y1', 'y2') in degrees ((0, 2), (0, 2), (0, 2), (1, 2), (1, 2), (1, 2)) over Rational Field with differential:
t0 --> y0
t1 --> y1
t2 --> y2
y0 --> 0
y1 --> 0
y2 --> 0
In [45]:
Minimal model $S^2 \wedge S^1$¶
In [ ]:
In [ ]:
S1 = SimplicialComplex([[0,1,2],[0,1,3],[0,2,3],[1,2,3],[3,4],[3,5],[4,5]],is_mutable=False) S2 = SimplicialComplex([[0,1,2],[0,1,3],[0,2,3],[1,2,3],[3,4,5],[3,4,6],[3,5,6],[4,5,6]],is_mutable=False) S = S1 apl = Apln(S.dimension()) A = AplK(S)
In [ ]:
# busco el primer grupo de cohomología no trivial gens = cohomology_gens(S,1) gens
In [ ]:
c10 = lift_cohomology_generator(S,gens[(1,0)]) a10 = A.lift(c10) a10
In [ ]:
# compruebo que la diferencial es cero a10.is_closed()
In [ ]:
# pasamos al sigiente grado gens = cohomology_gens(S,2) gens
In [ ]:
c20 = lift_cohomology_generator(S,gens[(2,0)]) a20 = A.lift(c20) a20
In [ ]:
c20.keys()
In [ ]:
a20.is_closed()
In [ ]:
a10*a20
In [ ]:
Minimal model $S^2 \wedge S^2$¶
In [ ]:
S2 = SimplicialComplex([[0,1,2],[0,1,3],[0,2,3],[1,2,3],[3,4,5],[3,4,6],[3,5,6],[4,5,6]],is_mutable=False) S = S2 apl = Apln(S.dimension()) A = AplK(S)
In [ ]:
# busco el primer grupo de cohomología no trivial gens = cohomology_gens(S,2) gens
In [ ]:
c20 = lift_cohomology_generator(S,gens[(2,0)]) a20 = A.lift(c20) c21 = lift_cohomology_generator(S,gens[(2,1)]) a21 = A.lift(c21) a20*a21 == a20.nullElement()
In [ ]:
a31 = a20.nullElement()
In [ ]:
for k in gens.keys(): print(k[0])
Minimal model¶
In [ ]:
class MinimalModel(): def __init__(self, S): self.K = S self.Phi = {} self.AplK = AplK(S) self.Apln = Apln(S.dimension()) gens = self.first_non_trivial_cohomology_group() [self.cdga, self.cohomology_dict] = self.createModel(gens) def first_non_trivial_cohomology_group(self, max_iter=20): # busco el primer grupo de cohomología no trivial i=1 gens = self.cohomology_gens(i) while(len(gens)==0 and i<max_iter): i+=1 gens = self.cohomology_gens(i) return gens def lift_cohomology_generator(self, g): cycle = g.to_cycle() cochain = {} for n in range(self.K.dimension()+1): for simplex in self.K._n_cells_sorted(n): cochain[simplex.tuple()] = 0 for i in cycle: #print(type(i[0].tuple())) cochain[i[0].tuple()] = i[1] return cochain def cohomology_gens(self, n): gens = {} basis = self.K.cohomology_ring().basis() for k in basis.keys(): if k[0] == n: gens[k] = basis[k] return gens def createModel(self, gens): n = len(gens) generators = [] degrees = [] cohomology_dict = {} for k in gens.keys(): degree = k[0] index = k[1] genName = 'x'+str(index)+'d'+str(degree) generators.append(genName) degrees.append(degree) cohomology_dict[genName] = gens[k] gca = GradedCommutativeAlgebra(QQ, names=generators, degrees=degrees) dfs = {gca.gens_dict()[generators[i]]:0 for i in range(n)} return [gca.cdg_algebra(dfs), cohomology_dict]
In [ ]:
S3 = simplicial_complexes.Sphere(3)
In [ ]:
M = MinimalModel(S3)
In [ ]:
h = M.cohomology_dict['x0d3'] cochain = M.lift_cohomology_generator(h) M.AplK.lift(cochain)
In [ ]:
In [ ]:
In [ ]:
In [ ]:
In [ ]:
S = simplicial_complexes.Sphere(8) M = MinimalModel(S)
In [ ]:
M.cdga
In [ ]:
In [ ]:
In [ ]:
In [ ]:
In [ ]:
In [ ]:
In [ ]:
In [ ]:
list(M.cohomology_dict.values())[0]
In [ ]:
M.cdga.gens_dict()[list(M.cohomology_dict.values())[0]]
In [ ]:
# busco el primer grupo de cohomología no trivial i=1 gens = cohomology_gens(S,i) while(len(gens)==0): i+=1 gens = cohomology_gens(S,i) print(gens)
In [ ]:
In [ ]:
c80 = lift_cohomology_generator(S,gens[(4,0)]) a80 = A.lift(c80)
In [ ]:
a80
In [ ]: