Loading src/tests_swap.py 0 → 100644 +258 −0 Changes for src/tests_swap.py: 258 added lines, 0 removed lines. Original line number Diff line number Diff line import itertools #Fonction outil pour calculer la parent distance. #max_j(seq, i) trouve le plus grand entier j tq S[j] < S[i] #et retourne j, ou retourne 0 si un tel j n'existe pas. def max_j(seq, i): j = 0 for k in range(0, i): if seq[k] < seq[i]: j = k + 1 #+1 pour la numérotation return j #Parent-distance classique, lue de la gauche vers la droite. def pdd(seq): res = [] for i in range(len(seq)): j = max_j(seq, i) if j != 0: res.append(i + 1 - j) #+1 pour la numérotation else: res.append(0) return res #Parent-distance de la droite vers la gauche, version paresseuse #Il serait peut-être bon de la redéfinir comme pdd. def pdg(seq): s = seq.copy() list.reverse(s) res = pdd(s) list.reverse(res) return res #first_diff gauche et droite identifient la première position #où les parent-distances diffèrent afin de mettre en évidence #les deux indices sur lesquels le swap s'est possiblement produit. #Chaque fonction renvoie l'indice de la première position qui diffère #ou -1 si une telle position n'existe pas def first_diff_d(pdd1, pdd2): for index, value in enumerate(zip(pdd1, pdd2)): if value[0] != value[1]: return index return -1 def first_diff_g(pdg1, pdg2): for index, value in reversed(list(enumerate(zip(pdg1, pdg2)))): if value[0] != value[1]: return index return -1 #Vérifie les conditions nécessaires (mais pas suffisantes) #sur les éléments des parent-distances #Voir pour factoriser le code plus tard def check_abcd(pdd1, pdd2, pdg1, pdg2, i): ad = pdd1[i] bd = pdd1[i+1] cd = pdd2[i] dd = pdd2[i+1] ag = pdg1[i+1] bg = pdg1[i] cg = pdg2[i+1] dg = pdg2[i] #cas x[i] < x[i+1] if (bd == 1 and dg == 1): if ((ad == 0 and dd != 0) or (ad > 0 and (cd > ad or dd != ad + 1)) or (bg == 0 and cg != 0) or (bg > 1 and cg != bg - 1) or (bg == 1)): return False #cas x[i] > x[i+1] if (bg == 1 and dd == 1): if ((ag == 0 and dg != 0) or (ag > 0 and (cg > ag or dg != ag + 1)) or (bd == 0 and cd != 0) or (bd > 1 and cd != bd - 1) or (bd == 1)): return False #Tout est cohérent sinon return True #Vérifie si seq2 peut être CT-équivalente (à un swap près) à seq1 def check_swap(seq1, seq2): pdd1 = pdd(seq1) pdd2 = pdd(seq2) pdg1 = pdg(seq1) pdg2 = pdg(seq2) i = first_diff_d(pdd1, pdd2) j = first_diff_g(pdg1, pdg2) if i == -1 or j == -1: return False diff = j - i if diff == 1: return check_abcd(pdd1, pdd2, pdg1, pdg2, i) if diff == -1: return check_abcd(pdd1, pdd2, pdg1, pdg2, j) if diff == 0: return (check_abcd(pdd1, pdd2, pdg1, pdg2, i-1) or check_abcd(pdd1, pdd2, pdg1, pdg2, i)) return False #Fonction outil qui onstruit la séquence '1..n' qui permet #d'ensuite générer toutes les permutations à l'aide d'itertools def seq_n(n): res = '' for i in range(n): res += str(i+1) return res #Brute force pour des permutations de taille n en effectuant #toutes les poignées de mains possibles, puis retourne #le nombre de matchs d'après check_swap ainsi que le nombre de #poignées de main #Décommenter la partie sur res permet de retourner une liste de #toutes les permutations qui ont match en plus def check_all(n): perm = list(itertools.permutations(seq_n(n))) l = len(perm) check = 0 handshake = 0 #res = [] for i in range(l): for j in range(i + 1, l): if check_swap(list(perm[i]), list(perm[j])): check += 1 #res.append((i,j)) handshake += 1 return check, handshake#, res #LEGACY CODE - USELESS AS OF NOW # def check_swap_flag_or(seq1, seq2): # pdd1 = pdd(seq1) # pdd2 = pdd(seq2) # pdg1 = pdg(seq1) # pdg2 = pdg(seq2) # i = first_diff_d(pdd1, pdd2) # j = first_diff_g(pdg1, pdg2) # if i == -1 or j == -1: # return (False, False) # diff = j - i # if diff == 1: # return (check_abcd(pdd1, pdd2, pdg1, pdg2, i), False) # if diff == -1: # return (check_abcd(pdd1, pdd2, pdg1, pdg2, j), False) # if diff == 0: # return ((check_abcd(pdd1, pdd2, pdg1, pdg2, i-1) # or check_abcd(pdd1, pdd2, pdg1, pdg2, i)), True) # return (False, False) # def check_all_flag_or(n): # perm = list(itertools.permutations(seq_n(n))) # l = len(perm) # check = 0 # handshake = 0 # res = [] # for i in range(l): # for j in range(i + 1, l): # ref = check_swap_flag_or(list(perm[i]), list(perm[j])) # if (ref == (True, True)): # check += 1 # res.append((i+1,j+1)) # handshake += 1 # return check, handshake, res # def check_swap_flag_xor(seq1, seq2): # pdd1 = pdd(seq1) # pdd2 = pdd(seq2) # pdg1 = pdg(seq1) # pdg2 = pdg(seq2) # i = first_diff_d(pdd1, pdd2) # j = first_diff_g(pdg1, pdg2) # if i == -1 or j == -1: # return (False, False) # diff = j - i # if diff == 1: # return (check_abcd(pdd1, pdd2, pdg1, pdg2, i), False) # if diff == -1: # return (check_abcd(pdd1, pdd2, pdg1, pdg2, j), False) # if diff == 0: # return ((check_abcd(pdd1, pdd2, pdg1, pdg2, i-1) # ^ check_abcd(pdd1, pdd2, pdg1, pdg2, i)), True) # return (False, False) # def check_all_flag_xor(n): # perm = list(itertools.permutations(seq_n(n))) # l = len(perm) # check = 0 # handshake = 0 # res = [] # for i in range(l): # for j in range(i + 1, l): # ref = check_swap_flag_xor(list(perm[i]), list(perm[j])) # if (ref == (True, True)): # check += 1 # res.append((i+1,j+1)) # handshake += 1 # return check, handshake, res #------------------------------------------- #TESTS #list(itertools.permutations('012')) #max_j(["5","6","1","3","4","2"], 4) #max_j(('5','6','1','3','4','2'), 2) #pdd(["4","5","6","1","2","7","8","3","9"]) #pdg(["4","5","6","1","2","7","8","3","9"]) #pdd(["4","5","6","3","1","7","8","2","9"]) #pdg(["4","5","6","3","1","7","8","2","9"]) #s1 = ["4","5","6","1","2","7","8","3","9"] #s2 = ["4","5","6","3","1","7","8","2","9"] #s3 = ("4","5","6","1","2","7","8","3","9") #pd1 = pdd(s1) #pd2 = pdd(s2) #pd3 = pdg(s1) #pd4 = pdg(s2) #pd5 = pdd(s3) #first_diff_d(pd1, pd2) #first_diff_g(pd3, pd4) #check_swap(s1, s2) #check_swap(s1, s1) #seq_n(3) #list(itertools.permutations('1234')) #l1 = check_all_flag_or(4)[2] #l2 = check_all_flag_xor(4)[2] #set(l1).symmetric_difference(set(l2)) #s4 = ["1","4","2","3"] #s5 = ["3","2","1","4"] #first_diff_d(pdd(s4), pdd(s5)) #first_diff_g(pdg(s4), pdg(s5)) #pdd(s4) #pdd(s5) #pdg(s4) #pdg(s5) #check_all_flag_or(4) #check_all_flag_xor(4) check_all(3) check_all(4) check_all(5) check_all(6) check_all(7) Loading
src/tests_swap.py 0 → 100644 +258 −0 Changes for src/tests_swap.py: 258 added lines, 0 removed lines. Original line number Diff line number Diff line import itertools #Fonction outil pour calculer la parent distance. #max_j(seq, i) trouve le plus grand entier j tq S[j] < S[i] #et retourne j, ou retourne 0 si un tel j n'existe pas. def max_j(seq, i): j = 0 for k in range(0, i): if seq[k] < seq[i]: j = k + 1 #+1 pour la numérotation return j #Parent-distance classique, lue de la gauche vers la droite. def pdd(seq): res = [] for i in range(len(seq)): j = max_j(seq, i) if j != 0: res.append(i + 1 - j) #+1 pour la numérotation else: res.append(0) return res #Parent-distance de la droite vers la gauche, version paresseuse #Il serait peut-être bon de la redéfinir comme pdd. def pdg(seq): s = seq.copy() list.reverse(s) res = pdd(s) list.reverse(res) return res #first_diff gauche et droite identifient la première position #où les parent-distances diffèrent afin de mettre en évidence #les deux indices sur lesquels le swap s'est possiblement produit. #Chaque fonction renvoie l'indice de la première position qui diffère #ou -1 si une telle position n'existe pas def first_diff_d(pdd1, pdd2): for index, value in enumerate(zip(pdd1, pdd2)): if value[0] != value[1]: return index return -1 def first_diff_g(pdg1, pdg2): for index, value in reversed(list(enumerate(zip(pdg1, pdg2)))): if value[0] != value[1]: return index return -1 #Vérifie les conditions nécessaires (mais pas suffisantes) #sur les éléments des parent-distances #Voir pour factoriser le code plus tard def check_abcd(pdd1, pdd2, pdg1, pdg2, i): ad = pdd1[i] bd = pdd1[i+1] cd = pdd2[i] dd = pdd2[i+1] ag = pdg1[i+1] bg = pdg1[i] cg = pdg2[i+1] dg = pdg2[i] #cas x[i] < x[i+1] if (bd == 1 and dg == 1): if ((ad == 0 and dd != 0) or (ad > 0 and (cd > ad or dd != ad + 1)) or (bg == 0 and cg != 0) or (bg > 1 and cg != bg - 1) or (bg == 1)): return False #cas x[i] > x[i+1] if (bg == 1 and dd == 1): if ((ag == 0 and dg != 0) or (ag > 0 and (cg > ag or dg != ag + 1)) or (bd == 0 and cd != 0) or (bd > 1 and cd != bd - 1) or (bd == 1)): return False #Tout est cohérent sinon return True #Vérifie si seq2 peut être CT-équivalente (à un swap près) à seq1 def check_swap(seq1, seq2): pdd1 = pdd(seq1) pdd2 = pdd(seq2) pdg1 = pdg(seq1) pdg2 = pdg(seq2) i = first_diff_d(pdd1, pdd2) j = first_diff_g(pdg1, pdg2) if i == -1 or j == -1: return False diff = j - i if diff == 1: return check_abcd(pdd1, pdd2, pdg1, pdg2, i) if diff == -1: return check_abcd(pdd1, pdd2, pdg1, pdg2, j) if diff == 0: return (check_abcd(pdd1, pdd2, pdg1, pdg2, i-1) or check_abcd(pdd1, pdd2, pdg1, pdg2, i)) return False #Fonction outil qui onstruit la séquence '1..n' qui permet #d'ensuite générer toutes les permutations à l'aide d'itertools def seq_n(n): res = '' for i in range(n): res += str(i+1) return res #Brute force pour des permutations de taille n en effectuant #toutes les poignées de mains possibles, puis retourne #le nombre de matchs d'après check_swap ainsi que le nombre de #poignées de main #Décommenter la partie sur res permet de retourner une liste de #toutes les permutations qui ont match en plus def check_all(n): perm = list(itertools.permutations(seq_n(n))) l = len(perm) check = 0 handshake = 0 #res = [] for i in range(l): for j in range(i + 1, l): if check_swap(list(perm[i]), list(perm[j])): check += 1 #res.append((i,j)) handshake += 1 return check, handshake#, res #LEGACY CODE - USELESS AS OF NOW # def check_swap_flag_or(seq1, seq2): # pdd1 = pdd(seq1) # pdd2 = pdd(seq2) # pdg1 = pdg(seq1) # pdg2 = pdg(seq2) # i = first_diff_d(pdd1, pdd2) # j = first_diff_g(pdg1, pdg2) # if i == -1 or j == -1: # return (False, False) # diff = j - i # if diff == 1: # return (check_abcd(pdd1, pdd2, pdg1, pdg2, i), False) # if diff == -1: # return (check_abcd(pdd1, pdd2, pdg1, pdg2, j), False) # if diff == 0: # return ((check_abcd(pdd1, pdd2, pdg1, pdg2, i-1) # or check_abcd(pdd1, pdd2, pdg1, pdg2, i)), True) # return (False, False) # def check_all_flag_or(n): # perm = list(itertools.permutations(seq_n(n))) # l = len(perm) # check = 0 # handshake = 0 # res = [] # for i in range(l): # for j in range(i + 1, l): # ref = check_swap_flag_or(list(perm[i]), list(perm[j])) # if (ref == (True, True)): # check += 1 # res.append((i+1,j+1)) # handshake += 1 # return check, handshake, res # def check_swap_flag_xor(seq1, seq2): # pdd1 = pdd(seq1) # pdd2 = pdd(seq2) # pdg1 = pdg(seq1) # pdg2 = pdg(seq2) # i = first_diff_d(pdd1, pdd2) # j = first_diff_g(pdg1, pdg2) # if i == -1 or j == -1: # return (False, False) # diff = j - i # if diff == 1: # return (check_abcd(pdd1, pdd2, pdg1, pdg2, i), False) # if diff == -1: # return (check_abcd(pdd1, pdd2, pdg1, pdg2, j), False) # if diff == 0: # return ((check_abcd(pdd1, pdd2, pdg1, pdg2, i-1) # ^ check_abcd(pdd1, pdd2, pdg1, pdg2, i)), True) # return (False, False) # def check_all_flag_xor(n): # perm = list(itertools.permutations(seq_n(n))) # l = len(perm) # check = 0 # handshake = 0 # res = [] # for i in range(l): # for j in range(i + 1, l): # ref = check_swap_flag_xor(list(perm[i]), list(perm[j])) # if (ref == (True, True)): # check += 1 # res.append((i+1,j+1)) # handshake += 1 # return check, handshake, res #------------------------------------------- #TESTS #list(itertools.permutations('012')) #max_j(["5","6","1","3","4","2"], 4) #max_j(('5','6','1','3','4','2'), 2) #pdd(["4","5","6","1","2","7","8","3","9"]) #pdg(["4","5","6","1","2","7","8","3","9"]) #pdd(["4","5","6","3","1","7","8","2","9"]) #pdg(["4","5","6","3","1","7","8","2","9"]) #s1 = ["4","5","6","1","2","7","8","3","9"] #s2 = ["4","5","6","3","1","7","8","2","9"] #s3 = ("4","5","6","1","2","7","8","3","9") #pd1 = pdd(s1) #pd2 = pdd(s2) #pd3 = pdg(s1) #pd4 = pdg(s2) #pd5 = pdd(s3) #first_diff_d(pd1, pd2) #first_diff_g(pd3, pd4) #check_swap(s1, s2) #check_swap(s1, s1) #seq_n(3) #list(itertools.permutations('1234')) #l1 = check_all_flag_or(4)[2] #l2 = check_all_flag_xor(4)[2] #set(l1).symmetric_difference(set(l2)) #s4 = ["1","4","2","3"] #s5 = ["3","2","1","4"] #first_diff_d(pdd(s4), pdd(s5)) #first_diff_g(pdg(s4), pdg(s5)) #pdd(s4) #pdd(s5) #pdg(s4) #pdg(s5) #check_all_flag_or(4) #check_all_flag_xor(4) check_all(3) check_all(4) check_all(5) check_all(6) check_all(7)