diff --git a/src/tests_swap.py b/src/tests_swap.py new file mode 100644 index 0000000000000000000000000000000000000000..da520d63df31d52412ba93f8c8bf27680afdb95d --- /dev/null +++ b/src/tests_swap.py @@ -0,0 +1,258 @@ +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)