Advertisement
Guest User

Untitled

a guest
Nov 22nd, 2019
134
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 8.76 KB | None | 0 0
  1. ## BIBLIS
  2.  
  3. import numpy as np
  4. import matplotlib.pyplot as plt
  5. plt.style.use('dark_background')
  6.  
  7. import cypari
  8.  
  9. ## CLASS treeNode
  10.  
  11. class treeNode(object):
  12.     def __init__(self, matrix=None, address="",
  13.                        leftChild=None, rightChild=None):
  14.         """ A node of the Farey binary tree.
  15.            Args:
  16.            
  17.            matrix: np 2x2 matrix (dtype=np.int64)
  18.            address: string of 'L' and 'T' giving the address in the tree.
  19.            leftChild, rightChild: children of that node.
  20.        """
  21.        
  22.         self.matrix = matrix
  23.         self.address = address
  24.         self.leftChild = leftChild
  25.         self.rightChild = rightChild
  26.        
  27.     def get_coord(self):
  28.         """ Transforms the matrix in coordinates.
  29.        """
  30.         return sum(self.matrix[0]), sum(self.matrix[1])
  31.    
  32.     def get_trace(self):
  33.         return self.matrix.trace()
  34.  
  35. ### J'AI ECHANGE L ORDRE DES FONCTIONS
  36.  
  37. ## FAREY TREE AND ITS DESCENDANCE
  38.  
  39. # construct_tree(node_criterion) : d'abord on construit l'arbre
  40. # tree_size(node) : on peut calculer sa taille
  41.  
  42. # list_of_descendants(node) : on peut lister la descendance
  43. # get_noes_with_property(node,prop) : on peut lister la descendance filtrée selon un critere
  44.  
  45. # get_node_with_trace(t) : liste des nodes de trace t
  46. # get_trace_property(t) : renvoie une fonction node --> bool (testant si trace == t)
  47.  
  48. # get_max_height_criterion(max_height) : renvoie fonction
  49.  
  50. def construct_tree(include_node_criterion,
  51.                    left_coord=(1,0), right_coord=(0,1),
  52.                    last_address = "", last_move = "", height=0):
  53.     """ Construct the Farey binary tree.
  54.        Args:
  55.        
  56.        include_node_criterion: function that takes a node and the height
  57.                                and decide whether or not to include this node in the tree (thus stops the construction).
  58.        left_coord: starting at (1,0)
  59.        right_coord: starting at (0,1)
  60.        last_addresss: address of the father
  61.        last_move: last move 'L' or 'T' to get to the current node
  62.        height: current height in the tree
  63.    """
  64.     node = treeNode()
  65.     node.matrix = np.array([[left_coord[0],right_coord[0]], [left_coord[1],right_coord[1]]], dtype=np.int64)
  66.     node.address = last_address + last_move
  67.    
  68.     if not include_node_criterion(node, height):
  69.         return None
  70.    
  71.     node.leftChild = construct_tree(include_node_criterion,
  72.                                     left_coord, node.get_coord(),
  73.                                     node.address, "T", height+1)
  74.    
  75.     node.rightChild = construct_tree(include_node_criterion,
  76.                                     node.get_coord(), right_coord,
  77.                                     node.address, "L", height+1)
  78.    
  79.     return node
  80.  
  81. def tree_size(node):
  82.     """ Returns the number of nodes in the tree of a given root.
  83.    """
  84.     if node is None:
  85.         return 0
  86.     return 1 + tree_size(node.leftChild) + tree_size(node.rightChild)
  87.  
  88. def list_of_descendants(node):
  89.     """ Returns the list of descendants of a node including this node.
  90.    """
  91.     return get_nodes_with_property(node, lambda x: True)
  92.  
  93. def get_nodes_with_property(root, prop):
  94.     """ Returns all nodes of the tree having the given property.
  95.        Args:
  96.        
  97.        root: root of the tree (type treeNode)
  98.        prop: predicate treeNode -> bool
  99.    """
  100.    
  101.     if root is None:
  102.         return []
  103.  
  104.     l=prop(root)*[root] ### ICI JE ME SUIS PERMIS UNE MODIF DE CODE
  105.    
  106.     return l + get_nodes_with_property(root.leftChild, prop) + \
  107.                get_nodes_with_property(root.rightChild, prop)
  108.  
  109. def get_trace_property(trace):
  110.     """ Returns a predicate treeNode -> bool,
  111.        choosing nodes which have a given trace.
  112.    """
  113.     def trace_property(node):
  114.         return node.get_trace() == trace
  115.     return trace_property
  116.  
  117. def get_nodes_with_trace(t):
  118.     """ Construct the tree from root to find those nodes.
  119.        We skim the branches that are too large in trace.
  120.    """
  121.     criterion = lambda node, height: node.get_trace() <= t and height <= t
  122.     root = construct_tree(criterion)
  123.     all_nodes = list_of_descendants(root)
  124.  
  125.     return list(filter(get_trace_property(t),all_nodes))
  126.  
  127. def get_max_height_criterion(max_height):
  128.     """ Return a stopping criterion for a given height.
  129.    """
  130.     def max_height_criterion(node, height):
  131.         return height <= max_height
  132.     return max_height_criterion
  133.  
  134. ## REPRESENTATION DES MATRICES ET DES CLASSES DE CONJUGAISON
  135.  
  136. def get_matrix_of_address(address):
  137.     """ Returns the matrix corresponding to a given 'L'/'T' address.
  138.    """
  139.     T = np.array([[1,1],[0,1]])
  140.     L = np.array([[1,0],[1,1]])
  141.     prod = np.array([[1,0],[0,1]])
  142.     for c in address:
  143.         if c == 'T':
  144.             prod = prod.dot(T)
  145.         elif c=='L':
  146.             prod = prod.dot(L)
  147.     return prod
  148.  
  149. def get_circular_shifts(word):
  150.     """ Returns all the circular shifts of the given input word.
  151.    """
  152.     n = len(word)
  153.     return ["".join([word[i - j] for i in range(n)]) for j in range(n)]
  154.  
  155. def get_circular_rep(word):
  156.     """ Returns the canonical representant of the set of circular shifts
  157.        of a word. We choose: min (lex order) of the circular permutations
  158.        of 'word'.
  159.    """
  160.     if word == '':
  161.         return ''
  162.     return min(get_circular_shifts(word)) ### J'AI LAISSE LE MIN CAR L<T ET C CE QUE JE VEUX
  163.  
  164. def compress(word):
  165.     """ Returns compact representation of word.
  166.        Example: LTTTT -> L T4
  167.    """
  168.  
  169.     letters = ['L', 'T']
  170.     first_letter = word[0]
  171.     current_letter = word[0]
  172.     counts = [0]
  173.     for c in word:
  174.         if c == current_letter:
  175.             counts[-1] += 1
  176.         else:
  177.             current_letter = c
  178.             counts.append(1)
  179.  
  180.     compress = ""
  181.     for i,c in enumerate(counts):
  182.         choose = i%2 if first_letter == 'L' else 1-i%2 ### ICI JE N'AI PAS CHANGE LE L : JE NE SAIS PAS SI JE DOIS
  183.         compress += letters[choose]+ ("" if c == 1 else str(c)) + " "
  184.  
  185.     return compress[:-1]
  186.  
  187. def get_conjugaison_classes(t):
  188.     """ Return the conjugaison classes of trace t.
  189.  
  190.        Input:
  191.            t: a trace (different than 2)
  192.  
  193.        Output:
  194.            1. The number of classes
  195.            2. np.array [coord[0], cood[1], class_number]
  196.            3. Array of representant of each classes
  197.    """
  198.     nodes = get_nodes_with_trace(t)
  199.     classes = {}
  200.     for n in nodes:
  201.         rep = get_circular_rep(n.address)
  202.         if not rep in classes:
  203.             classes[rep] = []
  204.         classes[rep].append(n)
  205.    
  206.     sorted_class = sorted(list(classes.items()), key=lambda x: len(x[0]))
  207.    
  208.     to_return = []
  209.     reps = []
  210.     for i,(rep,class_) in enumerate(sorted_class):
  211.         for n in class_:
  212.             to_return.append([n.get_coord()[0], n.get_coord()[1],i])
  213.         reps.append(compress(rep))
  214.            
  215.     return len(classes), np.array(to_return), reps
  216.  
  217. ## CALCUL DE L'ENLACEMENT
  218.  
  219. def get_word_base(max_word_length, current_pair=('LT', 'TL')):
  220.     """ Returns the word base for the computation of enl.
  221.    """
  222.     ### A rentrer dans le commentaire rouge juste au dessus :
  223.    
  224.     # The set of pairs form a binary tree which we fill in à la Pascal
  225.     # The root pair is ('LT','TL')
  226.     # The pairs to the extreme left are ('Ln T', 'T Ln')
  227.     # The pairs on the extreme right are ('L Tn', 'Tn L')
  228.     # The children of (G, D) are
  229.     # to the left (P, Q) with P=G[:-1]+'LT' (on enlève 'T' on rajoute 'LT') and Q=D+'L'
  230.     # to the right (R, S) with R=G+'T' and S=D[:-1]+'TL' (on enlève 'L' on rajoute 'TL')
  231.      
  232.     # Note the properties : 'G' ends with 'T' and 'D' ends with 'L' are preserved
  233.     # which is why G[:-1] = G - 'T' and D[:-1] = D - 'L'
  234.  
  235.     if len(current_pair[0]) > max_word_length:
  236.         return []
  237.  
  238.     pair_left = current_pair[0]+'L', 'L'+current_pair[1]
  239.     pair_right = 'R'+current_pair[0], current_pair[0]+'R'
  240.  
  241.     return [current_pair] + get_word_base(max_word_length, pair_left) +\
  242.                             get_word_base(max_word_length, pair_right)
  243.  
  244. def occ(P,A):
  245.     """ Returns the number of times P appears at the begining of circular
  246.        shifts of A.
  247.    """
  248.     shifts = get_circular_shifts(A)
  249.     counter = 0
  250.     n = len(P)
  251.  
  252.     if n > len(A):
  253.         return counter
  254.  
  255.     for shift in shifts:
  256.         if shift[:n] == P:
  257.             counter += 1
  258.  
  259.     return counter
  260.  
  261. def scal_PQ(P,Q,A,B):
  262.     return 0.5*(occ(P,A)*occ(Q,B)+ occ(P,B)*occ(Q,A))
  263.  
  264. def enl(A,B):
  265.     """ Returns the enl metric on the words A and B in the L/T alphabet.
  266.    """
  267.     word_base = get_word_base(max(len(A),len(B)))
  268.     return sum([scal_PQ(P,Q,A,B) for P,Q in word_base])
  269.  
  270. ## CALCUL DE LA TRACE
  271.  
  272. ## FORME QUADRATIQUE ASSOCIEE
  273.  
  274. ## INVERSE DE GAUSS
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement