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
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
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
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