AplK/notebooks/todo-limpio.ipynb

31 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]:
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 [3]:
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 [4]:
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 [12]:
S = random_simplicial_complex(5,4)
S.facets()
Out[12]:
{(2, 4), (0, 1, 3, 4)}
In [ ]:
 

Apln

In [6]:
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 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 [ ]:
 

Apl(K)

In [7]:
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 [ ]:
 

Apl(K) Element

In [8]:
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 [ ]:
 

Test lift == integral

In [9]:
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 [10]:
test(max_vertices=6, verbose=True)
iteration: 0 num_vertices: 6 max_num_facets: 4 facets: {(1, 2, 5), (0, 3, 4, 5), (0, 1, 3), (1, 3, 4)}
{(0, 3, 4, 5): 288*y1*y2*y3 + 84*t3*y1*y2 - 84*t2*y1*y3 + 84*t1*y2*y3 - 174*y1*y2 - 112*y1*y3 + 124*y2*y3 + 43*t2*y1 + 225*t3*y1 - 43*t1*y2 + 3*t3*y2 - 225*t1*y3 - 3*t2*y3 - 63*y1 + 37*y2 + 81*y3 - 86*t1 - 69*t2 - 114*t3 + 97, (0, 1, 3): 200*y1*y2 + 13*t2*y1 - 13*t1*y2 + 18*y1 - 63*y2 - 178*t1 - 86*t2 + 97, (0, 3, 4): -174*y1*y2 + 43*t2*y1 - 43*t1*y2 - 63*y1 + 37*y2 - 86*t1 - 69*t2 + 97, (0, 3, 5): -112*y1*y2 + 225*t2*y1 - 225*t1*y2 - 63*y1 + 81*y2 - 86*t1 - 114*t2 + 97, (0, 4, 5): 124*y1*y2 + 3*t2*y1 - 3*t1*y2 + 37*y1 + 81*y2 - 69*t1 - 114*t2 + 97, (1, 2, 5): 160*y1*y2 + 83*t2*y1 - 83*t1*y2 + 20*y1 + 57*y2 + 64*t1 + 64*t2 - 81, (1, 3, 4): 14*y1*y2 + 9*t2*y1 - 9*t1*y2 - 94*y1 - 28*y2 + 92*t1 + 109*t2 - 81, (3, 4, 5): 146*y1*y2 - 179*t2*y1 + 179*t1*y2 + 57*y1 - 81*y2 + 17*t1 - 28*t2 + 11, (0, 1): 18*y1 - 178*t1 + 97, (0, 3): -63*y1 - 86*t1 + 97, (0, 4): 37*y1 - 69*t1 + 97, (0, 5): 81*y1 - 114*t1 + 97, (1, 2): 20*y1 + 64*t1 - 81, (1, 3): -94*y1 + 92*t1 - 81, (1, 4): -28*y1 + 109*t1 - 81, (1, 5): 57*y1 + 64*t1 - 81, (2, 5): -46*y1 - 17, (3, 4): 57*y1 + 17*t1 + 11, (3, 5): -81*y1 - 28*t1 + 11, (4, 5): 41*y1 - 45*t1 + 28, (0,): 97, (1,): -81, (2,): -17, (3,): 11, (4,): 28, (5,): -17}
iteration: 1 num_vertices: 5 max_num_facets: 2 facets: {(0, 2, 3, 4), (1, 3, 4)}
{(0, 2, 3, 4): 6*y1*y2*y3 + 506*t3*y1*y2 - 506*t2*y1*y3 + 506*t1*y2*y3 - 196*y1*y2 + 6*y1*y3 - 106*y2*y3 - 56*t2*y1 - 75*t3*y1 + 56*t1*y2 - 23*t3*y2 + 75*t1*y3 + 23*t2*y3 - 38*y1 - 86*y2 - 16*y3 - 50*t1 - 54*t2 - 3*t3 + 65, (0, 2, 3): -196*y1*y2 - 56*t2*y1 + 56*t1*y2 - 38*y1 - 86*y2 - 50*t1 - 54*t2 + 65, (0, 2, 4): 6*y1*y2 - 75*t2*y1 + 75*t1*y2 - 38*y1 - 16*y2 - 50*t1 - 3*t2 + 65, (0, 3, 4): -106*y1*y2 - 23*t2*y1 + 23*t1*y2 - 86*y1 - 16*y2 - 54*t1 - 3*t2 + 65, (1, 3, 4): -2*y1*y2 + 4*t2*y1 - 4*t1*y2 - 37*y1 + 60*y2 - 13*t1 + 38*t2 + 24, (2, 3, 4): 198*y1*y2 - 4*t2*y1 + 4*t1*y2 + 8*y1 + 97*y2 - 4*t1 + 47*t2 + 15, (0, 2): -38*y1 - 50*t1 + 65, (0, 3): -86*y1 - 54*t1 + 65, (0, 4): -16*y1 - 3*t1 + 65, (1, 3): -37*y1 - 13*t1 + 24, (1, 4): 60*y1 + 38*t1 + 24, (2, 3): 8*y1 - 4*t1 + 15, (2, 4): 97*y1 + 47*t1 + 15, (3, 4): 93*y1 + 51*t1 + 11, (0,): 65, (1,): 24, (2,): 15, (3,): 11, (4,): 62}
iteration: 2 num_vertices: 3 max_num_facets: 2 facets: {(0, 2), (1,)}
{(0, 2): 89*y1 + 2*t1 - 26, (0,): -26, (1,): -60, (2,): -24}
iteration: 3 num_vertices: 6 max_num_facets: 4 facets: {(1, 3), (2, 3), (0, 3, 5), (0, 1, 2, 4, 5)}
{(0, 1, 2, 4, 5): -1704*y1*y2*y3*y4 - 534*t4*y1*y2*y3 + 534*t3*y1*y2*y4 - 534*t2*y1*y3*y4 + 534*t1*y2*y3*y4 - 558*y1*y2*y3 - 444*y1*y2*y4 + 192*y1*y3*y4 - 132*y2*y3*y4 - 90*t3*y1*y2 + 238*t4*y1*y2 + 90*t2*y1*y3 + 236*t4*y1*y3 - 90*t1*y2*y3 + 198*t4*y2*y3 - 238*t2*y1*y4 - 236*t3*y1*y4 + 238*t1*y2*y4 - 198*t3*y2*y4 + 236*t1*y3*y4 + 198*t2*y3*y4 - 112*y1*y2 - 36*y1*y3 + 8*y2*y3 + 146*y1*y4 + 94*y2*y4 - 24*y3*y4 - 55*t2*y1 - 41*t3*y1 + 23*t4*y1 + 55*t1*y2 - 121*t3*y2 - 60*t4*y2 + 41*t1*y3 + 121*t2*y3 - 23*t4*y3 - 23*t1*y4 + 60*t2*y4 + 23*t3*y4 + 38*y1 + 73*y2 + 31*y3 + 85*y4 - 88*t1 - 115*t2 - 74*t3 - 63*t4 + 85, (0, 1, 2, 4): -558*y1*y2*y3 - 90*t3*y1*y2 + 90*t2*y1*y3 - 90*t1*y2*y3 - 112*y1*y2 - 36*y1*y3 + 8*y2*y3 - 55*t2*y1 - 41*t3*y1 + 55*t1*y2 - 121*t3*y2 + 41*t1*y3 + 121*t2*y3 + 38*y1 + 73*y2 + 31*y3 - 88*t1 - 115*t2 - 74*t3 + 85, (0, 1, 2, 5): -444*y1*y2*y3 + 238*t3*y1*y2 - 238*t2*y1*y3 + 238*t1*y2*y3 - 112*y1*y2 + 146*y1*y3 + 94*y2*y3 - 55*t2*y1 + 23*t3*y1 + 55*t1*y2 - 60*t3*y2 - 23*t1*y3 + 60*t2*y3 + 38*y1 + 73*y2 + 85*y3 - 88*t1 - 115*t2 - 63*t3 + 85, (0, 1, 4, 5): 192*y1*y2*y3 + 236*t3*y1*y2 - 236*t2*y1*y3 + 236*t1*y2*y3 - 36*y1*y2 + 146*y1*y3 - 24*y2*y3 - 41*t2*y1 + 23*t3*y1 + 41*t1*y2 - 23*t3*y2 - 23*t1*y3 + 23*t2*y3 + 38*y1 + 31*y2 + 85*y3 - 88*t1 - 74*t2 - 63*t3 + 85, (0, 2, 4, 5): -132*y1*y2*y3 + 198*t3*y1*y2 - 198*t2*y1*y3 + 198*t1*y2*y3 + 8*y1*y2 + 94*y1*y3 - 24*y2*y3 - 121*t2*y1 - 60*t3*y1 + 121*t1*y2 - 23*t3*y2 + 60*t1*y3 + 23*t2*y3 + 73*y1 + 31*y2 + 85*y3 - 115*t1 - 74*t2 - 63*t3 + 85, (1, 2, 4, 5): 324*y1*y2*y3 + 290*t3*y1*y2 - 290*t2*y1*y3 + 290*t1*y2*y3 - 158*y1*y2 + 74*y1*y3 + 30*y2*y3 - 135*t2*y1 - 138*t3*y1 + 135*t1*y2 - 87*t3*y2 + 138*t1*y3 + 87*t2*y3 + 90*y1 + 34*y2 + 24*y3 - 27*t1 + 14*t2 + 25*t3 - 3, (0, 1, 2): -112*y1*y2 - 55*t2*y1 + 55*t1*y2 + 38*y1 + 73*y2 - 88*t1 - 115*t2 + 85, (0, 1, 4): -36*y1*y2 - 41*t2*y1 + 41*t1*y2 + 38*y1 + 31*y2 - 88*t1 - 74*t2 + 85, (0, 1, 5): 146*y1*y2 + 23*t2*y1 - 23*t1*y2 + 38*y1 + 85*y2 - 88*t1 - 63*t2 + 85, (0, 2, 4): 8*y1*y2 - 121*t2*y1 + 121*t1*y2 + 73*y1 + 31*y2 - 115*t1 - 74*t2 + 85, (0, 2, 5): 94*y1*y2 - 60*t2*y1 + 60*t1*y2 + 73*y1 + 85*y2 - 115*t1 - 63*t2 + 85, (0, 3, 5): -146*y1*y2 + 167*t2*y1 - 167*t1*y2 - 46*y1 + 85*y2 - 13*t1 - 63*t2 + 85, (0, 4, 5): -24*y1*y2 - 23*t2*y1 + 23*t1*y2 + 31*y1 + 85*y2 - 74*t1 - 63*t2 + 85, (1, 2, 4): -158*y1*y2 - 135*t2*y1 + 135*t1*y2 + 90*y1 + 34*y2 - 27*t1 + 14*t2 - 3, (1, 2, 5): 74*y1*y2 - 138*t2*y1 + 138*t1*y2 + 90*y1 + 24*y2 - 27*t1 + 25*t2 - 3, (1, 4, 5): 30*y1*y2 - 87*t2*y1 + 87*t1*y2 + 34*y1 + 24*y2 + 14*t1 + 25*t2 - 3, (2, 4, 5): 88*y1*y2 - 84*t2*y1 + 84*t1*y2 + 79*y1 + 72*y2 + 41*t1 + 52*t2 - 30, (0, 1): 38*y1 - 88*t1 + 85, (0, 2): 73*y1 - 115*t1 + 85, (0, 3): -46*y1 - 13*t1 + 85, (0, 4): 31*y1 - 74*t1 + 85, (0, 5): 85*y1 - 63*t1 + 85, (1, 2): 90*y1 - 27*t1 - 3, (1, 3): -88*y1 + 75*t1 - 3, (1, 4): 34*y1 + 14*t1 - 3, (1, 5): 24*y1 + 25*t1 - 3, (2, 3): -68*y1 + 102*t1 - 30, (2, 4): 79*y1 + 41*t1 - 30, (2, 5): 72*y1 + 52*t1 - 30, (3, 5): -36*y1 - 50*t1 + 72, (4, 5): 77*y1 + 11*t1 + 11, (0,): 85, (1,): -3, (2,): -30, (3,): 72, (4,): 11, (5,): 22}
iteration: 4 num_vertices: 4 max_num_facets: 3 facets: {(0, 1, 2), (0, 3)}
{(0, 1, 2): -128*y1*y2 + 102*t2*y1 - 102*t1*y2 - 83*y1 - 17*y2 - 3*t1 + 23*t2 + 1, (0, 1): -83*y1 - 3*t1 + 1, (0, 2): -17*y1 + 23*t1 + 1, (0, 3): -98*y1 - 21*t1 + 1, (1, 2): -36*y1 + 26*t1 - 2, (0,): 1, (1,): -2, (2,): 24, (3,): -20}
iteration: 5 num_vertices: 3 max_num_facets: 2 facets: {(0, 2), (1,)}
{(0, 2): 91*y1 - 45*t1 - 46, (0,): -46, (1,): -75, (2,): -91}
iteration: 6 num_vertices: 4 max_num_facets: 1 facets: {(0, 1, 2)}
{(0, 1, 2): 106*y1*y2 + 100*t2*y1 - 100*t1*y2 - 83*y1 + 50*y2 - 60*t1 + 7*t2 - 20, (0, 1): -83*y1 - 60*t1 - 20, (0, 2): 50*y1 + 7*t1 - 20, (1, 2): 33*y1 + 67*t1 - 80, (0,): -20, (1,): -80, (2,): -13}
iteration: 7 num_vertices: 5 max_num_facets: 1 facets: {(0, 1, 4), (1, 3)}
{(0, 1, 4): -36*y1*y2 + 72*t2*y1 - 72*t1*y2 - 88*y1 + 25*y2 - 12*t1 + 77*t2 - 1, (0, 1): -88*y1 - 12*t1 - 1, (0, 4): 25*y1 + 77*t1 - 1, (1, 3): 52*y1 + 43*t1 - 13, (1, 4): 41*y1 + 89*t1 - 13, (0,): -1, (1,): -13, (3,): 30, (4,): 76}
iteration: 8 num_vertices: 5 max_num_facets: 2 facets: {(0, 3, 4), (0, 2, 4), (1, 2)}
{(0, 2, 4): 198*y1*y2 - 84*t2*y1 + 84*t1*y2 - 68*y1 - 75*y2 - 129*t1 - 5*t2 + 46, (0, 3, 4): 152*y1*y2 + 57*t2*y1 - 57*t1*y2 - 100*y1 - 75*y2 - 40*t1 - 5*t2 + 46, (0, 2): -68*y1 - 129*t1 + 46, (0, 3): -100*y1 - 40*t1 + 46, (0, 4): -75*y1 - 5*t1 + 46, (1, 2): -86*y1 - 66*t1 - 17, (2, 4): 77*y1 + 124*t1 - 83, (3, 4): -32*y1 + 35*t1 + 6, (0,): 46, (1,): -17, (2,): -83, (3,): 6, (4,): 41}
iteration: 9 num_vertices: 2 max_num_facets: 2 facets: {(1,), (0,)}
{(0,): -75, (1,): -70}
success: True
In [ ]:
 

Minimal model (sin terminar)

In [ ]:
class MinimalModel():

    def __init__(self, S):
        self.K = S
        self.Phi = {}
        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[gens[k]] = genName
        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]