Example #1
0
 def _simplifyWithAlgo1(self, element):
     """
         Find the simplest form of an element. For example, for the group of 1 generator x1 and 1 relation x1^5=0, [1,1,1,1] will return [3]
         This works with element in list form.
     """
     #If element is [1,2,3], element_sublists will be [[1,2,3], [1,2], [2,3], [1], [2], [3]]
     if element == []:
         return []
     
     element_sublists = sublists(element)
     transformed_element = element
     
     for sequence in element_sublists:
         #Sequence is an element of sublists, is sth like [1,2,3] or [1,2]
         transformed_sequence = self._shortenSequence(sequence)
         #After this step, if there are some relation like [1,2,1] = [] then [1,2] will be replaced by [4]
         if transformed_sequence != sequence:
             position = position_of_list_in_list(sequence, element)
             transformed_element = element[:position] + transformed_sequence + element[position + len(sequence):]
             #It will be then substituted in [1,2,3], this latter become [4,3]
             break
         
     if transformed_element != element:
         #Recurse this step to have a shorter form
         element = transformed_element
         return self._simplify(transformed_element)
         
     if len(element) <= self.nb_terms_in_simplest_form:
         #Stop if the simplified form is already short enough
         return element
     
     # When nothing changes, return the last form
     return element
Example #2
0
    def _simplifyWithAlgo2(self, element):
        """
            Find the simplest form of an element. For example, for the group of 1 generator x1 and 1 relation x1^5=0, [1,1,1,1] will return [3]
            This works with element in list form.
        """
        #If element is [1,2,3], element_sublists will be [[1,2,3], [1,2], [2,3], [1], [2], [3]]
        if element == []:
            return []
        
        element_sublists = sublists(element)
        transformed_element = element

        for sequence in element_sublists:
            #If it is not the case, realize the step above with stronger transformation, i.e, substitute with longer sequence
            transformed_sequence = self._shortenSequence(sequence)
            
            if transformed_sequence != sequence:
                transformed_sequence = self._shortenSequenceWithAlgo1(sequence)
            
            if transformed_sequence != sequence:
                position = position_of_list_in_list(sequence, element)
                transformed_element = element[:position] + transformed_sequence + element[position + len(sequence):]
                break
        
        if transformed_element != element:
            element = transformed_element
            return self._simplify(transformed_element)
        
        if len(element) <= self.nb_terms_in_simplest_form:
            #Stop if the simplified form is already short enough
            return element
        
        # When nothing changes, return the last form
        return element
Example #3
0
    def _generalizeRelations(self):
        for i in range(1, self.nb_generators + 1):
            # Firstly, find all relations of the form x * inverse(x) = e
            self.generalized_relations.append([i, self._index_of_inverse(i)])
            self.generalized_relations.append([self._index_of_inverse(i), i]) 
        
        #Now, generate all relations that is a permutation of relations in self.relations, for example [1,2,3] will be [1,2,3], [2,3,1] and [3,1,2]
        #We call them relation of type 1
        
        relations_type_1 = []
        for relation in self.relations:
            # Here relation is sth like ([(1,1), (2,-1), (3,1)])                       
            reformulated_relation = []
            for term in relation:
                #term is sth like (1,1)
                base, exponent = term[0], term[1]
                if exponent > 0:
                    reformulated_relation += [base] * exponent
                else:
                    reformulated_relation += [self._index_of_inverse(base)] * (-exponent)
                #After this step, our example become [1,5,3]
            
            n = len(reformulated_relation)
            for permutator in range(n):
                permutated_relation = [reformulated_relation[(permutator + i) % n] for i in range(n)]
                if permutated_relation not in relations_type_1:
                    relations_type_1.append(permutated_relation)
            #After this step, relations_type_1 contains [1,5,3], [5,3,1], [3,1,5]
            
            #We also express the inverse form of the relation. E.g, [1,5,3] becomes [6,2,4]
            #Do the same, we get more elements of relations_type_1: [6,2,4], [2,4,6], [4,6,2]
            reformulated_relation = []
            for term in reversed(relation):
                #term is sth like (0,1)
                base, exponent = term[0], term[1]
                if exponent > 0:
                    reformulated_relation += [self._index_of_inverse(base)] * exponent
                else:
                    reformulated_relation += [base] * (-exponent)
            
            n = len(reformulated_relation)
            for permutator in range(n):
                permutated_relation = [reformulated_relation[(permutator + i) % n] for i in range(n)]
                if permutated_relation not in relations_type_1:
                    relations_type_1.append(permutated_relation)          
        
        #We want to define relations of type 2, which is formed by mean of: find another form of some sequence form a relation, then replace it in another relation
        #For example, if x1*x1=e, we have [1,1]=[] or equivalently, [1]=[4], hence in [1,5,3], we can substitute [1] in this relation and it becomes [4,5,3]
        
        relations_type_2 = relations_type_1
        
        relations_type_1 = sorted(relations_type_1, key = lambda x: len(x))
        
        for relation in relations_type_1:
            #print "-----Current relation-------", relation
            relation_sublists = sublists(relation)
            for sequence in relation_sublists:
                #print "---Current sequence---", sequence
                for other_relation in relations_type_1:
                    #print "Working with", other_relation
                    positions = all_discrete_positions_of_list_in_list(sequence, other_relation)
                    #print "Positions", positions
                    if len(positions) > 1:
                        for subset in all_subsets(positions):
                            if len(subset) > 0:
                                #print "Subset", subset
                                for position in subset:
                                    new_relation = other_relation[:position] + self._shortenSequenceInSpecifiedRelation(sequence, relation) + other_relation[position + len(sequence):]
                                    #print "Use %s in position %d in %s, %s becomes %s"% (sequence, position, relation, other_relation, new_relation)
                                    #print "New relation", new_relation                        
                                    if new_relation not in relations_type_2 and new_relation not in self.generalized_relations:
                                        relations_type_2.append(new_relation)
       
        self.generalized_relations += relations_type_2   

        relations_type_3 = []
        for relation in self.relations:
            if len(relation) == 1 and relation[0][1] == 2:
                x = relation[0][0]
                y = self._index_of_inverse(x)
                for another_relation in self.generalized_relations:
                    new_another_relation = copy.copy(another_relation)
                    for idx in range(len(another_relation)):
                        if another_relation[idx] == x:
                            new_another_relation[idx] = y
                        if another_relation[idx] == y:
                            new_another_relation[idx] = x
                    if new_another_relation not in self.generalized_relations and new_another_relation not in relations_type_3:
                        relations_type_3.append(new_another_relation)
        self.generalized_relations += relations_type_3        
        
        self.to_class[to_string([])] = 0
        self.equality_classes.append([])
        self.equality_classes[0].append([])
    
        for reformulated_relation in self.generalized_relations:      
            for i in range(len(reformulated_relation), -1, -1):
                for j in range (0, len(reformulated_relation) - i):                
                    sequence = reformulated_relation[j : j + i + 1]
                    
                    remaining = remaining_of_list_after_removing(sequence, reformulated_relation, j)
                    transformed_sequence = self._inverse(remaining[0]) + self._inverse(remaining[1])
                    if to_string(sequence) not in self.to_class.keys():
                        if to_string(transformed_sequence) not in self.to_class.keys():
                            self.create_new_class(transformed_sequence)
                        if sequence != transformed_sequence:
                            self.join_class(sequence, transformed_sequence)
                    else:
                        if to_string(transformed_sequence) not in self.to_class.keys():
                            self.join_class(transformed_sequence, sequence)
                        else:
                            self.update_equalitiy_classes(transformed_sequence, sequence)
        
        print self.equality_classes
Example #4
0
 def _generalizeRelationsWithAlgo1(self):
     for i in range(1, self.nb_generators + 1):
         # Firstly, find all relations of the form x * inverse(x) = e
         self.generalized_relations.append([i, self._index_of_inverse(i)])
         self.generalized_relations.append([self._index_of_inverse(i), i]) 
     
     #Now, generate all relations that is a permutation of relations in self.relations, for example [1,2,3] will be [1,2,3], [2,3,1] and [3,1,2]
     #We call them relation of type 1
     
     relations_type_1 = []
     for relation in self.relations:
         # Here relation is sth like ([(1,1), (2,-1), (3,1)])                       
         reformulated_relation = []
         for term in relation:
             #term is sth like (1,1)
             base, exponent = term[0], term[1]
             if exponent > 0:
                 reformulated_relation += [base] * exponent
             else:
                 reformulated_relation += [self._index_of_inverse(base)] * (-exponent)
             #After this step, our example become [1,5,3]
         
         n = len(reformulated_relation)
         for permutator in range(n):
             permutated_relation = [reformulated_relation[(permutator + i) % n] for i in range(n)]
             if permutated_relation not in relations_type_1:
                 relations_type_1.append(permutated_relation)
         #After this step, relations_type_1 contains [1,5,3], [5,3,1], [3,1,5]
         
         #We also express the inverse form of the relation. E.g, [1,5,3] becomes [6,2,4]
         #Do the same, we get more elements of relations_type_1: [6,2,4], [2,4,6], [4,6,2]
         reformulated_relation = []
         for term in reversed(relation):
             #term is sth like (0,1)
             base, exponent = term[0], term[1]
             if exponent > 0:
                 reformulated_relation += [self._index_of_inverse(base)] * exponent
             else:
                 reformulated_relation += [base] * (-exponent)
         
         n = len(reformulated_relation)
         for permutator in range(n):
             permutated_relation = [reformulated_relation[(permutator + i) % n] for i in range(n)]
             if permutated_relation not in relations_type_1:
                 relations_type_1.append(permutated_relation)          
     
     #We want to define relations of type 2, which is formed by mean of: find another form of some sequence form a relation, then replace it in another relation
     #For example, if x1*x1=e, we have [1,1]=[] or equivalently, [1]=[4], hence in [1,5,3], we can substitute [1] in this relation and it becomes [4,5,3]
     
     relations_type_2 = relations_type_1
     
     relations_type_1 = sorted(relations_type_1, key = lambda x: len(x))
     
     for relation in relations_type_1:
         #print "-----Current relation-------", relation
         relation_sublists = sublists(relation)
         for sequence in relation_sublists:
             #print "---Current sequence---", sequence
             for other_relation in relations_type_1:
                 #print "Working with", other_relation
                 positions = all_discrete_positions_of_list_in_list(sequence, other_relation)
                 #print "Positions", positions
                 if len(positions) > 1:
                     for subset in all_subsets(positions):
                         if len(subset) > 0:
                             #print "Subset", subset
                             for position in subset:
                                 new_relation = other_relation[:position] + self._shortenSequenceInSpecifiedRelation(sequence, relation) + other_relation[position + len(sequence):]
                                 #print "Use %s in position %d in %s, %s becomes %s"% (sequence, position, relation, other_relation, new_relation)
                                 #print "New relation", new_relation                        
                                 if new_relation not in relations_type_2 and new_relation not in self.generalized_relations:
                                     relations_type_2.append(new_relation)
    
     self.generalized_relations += relations_type_2