diff --git a/.gitignore b/.gitignore
index 8838127e130472948c20b06902bc8567040ba1de..ac1bff0ba514cfa3bae2d6d3b7a565f7394d082c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -26,6 +26,8 @@ persisted_content
 #Dump
 DoNotPush
 */DoNotPush/*
+guichaoua_pc_costs
+*/guichaoua_pc_costs/*
 
 #Baseline folders, do not need to be pushed (code duplication)
 Baselines
diff --git a/LICENSE b/LICENSE
index c4e596467bbdb7c0552dd68acc68e3b8cedd5b02..b45875f0343f3bad8ce48399f4d8b0d206df7bd6 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,5 +1,7 @@
 Copyright (c) 2021 Marmoret Axel
 
+BSD 3-Clause "New" or "Revised" License
+
 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 
 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
diff --git a/polytopes/__init__.py b/MusicOnPolytopes/__init__.py
similarity index 83%
rename from polytopes/__init__.py
rename to MusicOnPolytopes/__init__.py
index 8e74a9e4a3fe4205dccf7f43f2418450f8482f0e..f4774ddc490714dd1b01f1caa34f6335ada9e373 100644
--- a/polytopes/__init__.py
+++ b/MusicOnPolytopes/__init__.py
@@ -1,3 +1,4 @@
+from . import triad_transformations
 from . import chord_movement
 from . import data_manipulation
 #from . import pattern_manipulation
@@ -11,3 +12,4 @@ from .model import chord
 from .model import note
 from .model import constants
 from .model import errors
+from .model import triad_manipulation
diff --git a/MusicOnPolytopes/accelerated_polytopical_costs.py b/MusicOnPolytopes/accelerated_polytopical_costs.py
new file mode 100644
index 0000000000000000000000000000000000000000..c51ea102786fa7964aabd7dd8d1ff41b37737f92
--- /dev/null
+++ b/MusicOnPolytopes/accelerated_polytopical_costs.py
@@ -0,0 +1,485 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Wed Apr  7 10:38:31 2021
+
+@author: amarmore
+"""
+#@jit(nopython=True)
+def accelerated_triadic_tonnetz_distance_symbol(chord_1, chord_2):
+    circle_sharp =  ['C','Am','F','Dm','A#','Gm','D#','Cm','G#','Fm','C#','A#m','F#','D#m','B','G#m','E','C#m','A','F#m','D','Bm','G','Em']
+    circle_flat = ['C','Am','F','Dm','Bb','Gm','Eb','Cm','Ab','Fm','Db','Bbm','Gb','Ebm','B','Abm','E','Dbm','A','Gbm','D','Bm','G','Em']
+    tonnetz_distance_matrix = [[0, 1, 2, 3, 4, 3, 2, 1, 2, 3, 4, 5, 4, 3, 4, 3, 2, 3, 2, 3, 4, 3,
+        2, 1],
+       [1, 0, 1, 2, 3, 4, 3, 2, 3, 2, 3, 4, 3, 4, 5, 4, 3, 2, 1, 2, 3, 4,
+        3, 2],
+       [2, 1, 0, 1, 2, 3, 4, 3, 2, 1, 2, 3, 4, 5, 4, 3, 4, 3, 2, 3, 2, 3,
+        4, 3],
+       [3, 2, 1, 0, 1, 2, 3, 4, 3, 2, 3, 2, 3, 4, 3, 4, 5, 4, 3, 2, 1, 2,
+        3, 4],
+       [4, 3, 2, 1, 0, 1, 2, 3, 4, 3, 2, 1, 2, 3, 4, 5, 4, 3, 4, 3, 2, 3,
+        2, 3],
+       [3, 4, 3, 2, 1, 0, 1, 2, 3, 4, 3, 2, 3, 2, 3, 4, 3, 4, 5, 4, 3, 2,
+        1, 2],
+       [2, 3, 4, 3, 2, 1, 0, 1, 2, 3, 4, 3, 2, 1, 2, 3, 4, 5, 4, 3, 4, 3,
+        2, 3],
+       [1, 2, 3, 4, 3, 2, 1, 0, 1, 2, 3, 4, 3, 2, 3, 2, 3, 4, 3, 4, 5, 4,
+        3, 2],
+       [2, 3, 2, 3, 4, 3, 2, 1, 0, 1, 2, 3, 4, 3, 4, 1, 4, 3, 4, 5, 4, 3,
+        4, 3],
+       [3, 2, 1, 2, 3, 4, 3, 2, 1, 0, 1, 2, 3, 4, 3, 2, 3, 2, 3, 4, 3, 4,
+        5, 4],
+       [4, 3, 2, 3, 2, 3, 4, 3, 2, 1, 0, 1, 2, 3, 4, 3, 4, 1, 4, 3, 4, 5,
+        4, 3],
+       [5, 4, 3, 2, 1, 2, 3, 4, 3, 2, 1, 0, 1, 2, 3, 4, 3, 2, 3, 2, 3, 4,
+        3, 4],
+       [4, 3, 4, 3, 2, 3, 2, 3, 4, 3, 2, 1, 0, 1, 2, 3, 4, 3, 2, 1, 2, 3,
+        4, 5],
+       [3, 4, 5, 4, 3, 2, 1, 2, 3, 4, 3, 2, 1, 0, 1, 2, 3, 4, 3, 2, 3, 2,
+        3, 4],
+       [4, 5, 4, 3, 4, 3, 2, 3, 2, 3, 4, 3, 2, 1, 0, 1, 2, 3, 4, 3, 2, 1,
+        2, 3],
+       [3, 4, 3, 4, 5, 4, 3, 2, 1, 2, 3, 4, 3, 2, 1, 0, 1, 2, 3, 4, 3, 2,
+        3, 2],
+       [2, 3, 4, 5, 4, 3, 4, 3, 2, 3, 2, 3, 4, 3, 2, 1, 0, 1, 2, 3, 4, 3,
+        2, 1],
+       [3, 2, 3, 4, 3, 4, 5, 4, 3, 2, 1, 2, 3, 4, 3, 2, 1, 0, 1, 2, 3, 4,
+        3, 2],
+       [2, 1, 2, 3, 4, 5, 4, 3, 4, 3, 2, 3, 2, 3, 4, 3, 2, 1, 0, 1, 2, 3,
+        4, 3],
+       [3, 2, 3, 2, 3, 4, 3, 4, 5, 4, 3, 2, 1, 2, 3, 4, 3, 2, 1, 0, 1, 2,
+        3, 4],
+       [4, 3, 2, 1, 2, 3, 4, 5, 4, 3, 4, 3, 2, 3, 2, 3, 4, 3, 2, 1, 0, 1,
+        2, 3],
+       [3, 4, 3, 2, 3, 2, 3, 4, 3, 4, 5, 4, 3, 2, 1, 2, 3, 4, 3, 2, 1, 0,
+        1, 2],
+       [2, 3, 4, 3, 2, 1, 2, 3, 4, 5, 4, 3, 4, 3, 2, 3, 2, 3, 4, 3, 2, 1,
+        0, 1],
+       [1, 2, 3, 4, 3, 2, 3, 2, 3, 4, 3, 4, 5, 4, 3, 2, 1, 2, 3, 4, 3, 2,
+        1, 0]]
+    if chord_1 in circle_sharp:
+        idx_c_1 = circle_sharp.index(chord_1)
+    else:
+        idx_c_1 = circle_flat.index(chord_1)
+        
+    if chord_2 in circle_sharp:
+        idx_c_2 = circle_sharp.index(chord_2)
+    else:
+        idx_c_2 = circle_flat.index(chord_2)
+    
+    return tonnetz_distance_matrix[idx_c_1][idx_c_2]
+
+#@jit(nopython=True)
+def accelerated_triadic_tonnetz_relation_symbol(chord_1, chord_2):
+    circle_sharp =  ['C','Am','F','Dm','A#','Gm','D#','Cm','G#','Fm','C#','A#m','F#','D#m','B','G#m','E','C#m','A','F#m','D','Bm','G','Em']
+    circle_flat = ['C','Am','F','Dm','Bb','Gm','Eb','Cm','Ab','Fm','Db','Bbm','Gb','Ebm','B','Abm','E','Dbm','A','Gbm','D','Bm','G','Em']
+    relation_list = [0,'R','RL','RLR','LRPR','LRP','PR','P','PL','PLR','LPRP','LPRPR','PRPR','PRP','LPLR','LPL','LP','LPR','RP','RPR','LRLR','LRL','LR','L','LRPL','LPLP']
+    tonnetz_relation_matrix = [[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
+        16, 17, 18, 19, 20, 21, 22, 23],
+       [ 1,  0, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10,
+         9,  8,  7,  6,  5,  4,  3,  2],
+       [22, 23,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13,
+        14, 15, 16, 17, 18, 19, 20, 21],
+       [ 3,  2,  1,  0, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12,
+        11, 10,  9,  8,  7,  6,  5,  4],
+       [20, 21, 22, 23,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11,
+        12, 13, 14, 15, 16, 17, 18, 19],
+       [ 5,  4,  3,  2,  1,  0, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14,
+        13, 12, 11, 10,  9,  8,  7,  6],
+       [18, 19, 20, 21, 22, 23,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
+        10, 11, 12, 13, 14, 15, 16, 17],
+       [ 7,  6,  5,  4,  3,  2,  1,  0, 23, 22, 21, 20, 19, 18, 17, 16,
+        15, 14, 13, 12, 11, 10,  9,  8],
+       [16, 17,  6, 19, 20, 21, 22, 23,  0,  1,  2,  3,  4,  5, 24,  7,
+        25,  9, 10, 11, 12, 13, 14, 15],
+       [ 9,  8,  7,  6,  5,  4,  3,  2,  1,  0, 23, 22, 21, 20, 19, 18,
+        17, 16, 15, 14, 13, 12, 11, 10],
+       [14, 15, 16, 17,  6, 19, 20, 21, 22, 23,  0,  1,  2,  3,  4,  5,
+        24,  7, 25,  9, 10, 11, 12, 13],
+       [11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0, 23, 22, 21, 20,
+        19, 18, 17, 16, 15, 14, 13, 12],
+       [12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,  0,  1,  2,  3,
+         4,  5,  6,  7,  8,  9, 10, 11],
+       [13, 12, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0, 23, 22,
+        21, 20, 19, 18, 17, 16, 15, 14],
+       [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,  0,  1,
+         2,  3,  4,  5,  6,  7,  8,  9],
+       [15, 14, 13, 12, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0,
+        23, 22, 21, 20, 19, 18, 17, 16],
+       [ 8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+         0,  1,  2,  3,  4,  5,  6,  7],
+       [17, 16, 15, 14, 13, 12, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,
+         1,  0, 23, 22, 21, 20, 19, 18],
+       [ 6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+        22, 23,  0,  1,  2,  3,  4,  5],
+       [19, 18, 17, 16, 15, 14, 13, 12, 11, 10,  9,  8,  7,  6,  5,  4,
+         3,  2,  1,  0, 23, 22, 21, 20],
+       [ 4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+        20, 21, 22, 23,  0,  1,  2,  3],
+       [21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10,  9,  8,  7,  6,
+         5,  4,  3,  2,  1,  0, 23, 22],
+       [ 2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17,
+        18, 19, 20, 21, 22, 23,  0,  1],
+       [23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10,  9,  8,
+         7,  6,  5,  4,  3,  2,  1,  0]]
+    
+    if chord_1 in circle_sharp:
+        idx_c_1 = circle_sharp.index(chord_1)
+    else:
+        idx_c_1 = circle_flat.index(chord_1)
+        
+    if chord_2 in circle_sharp:
+        idx_c_2 = circle_sharp.index(chord_2)
+    else:
+        idx_c_2 = circle_flat.index(chord_2)
+    
+    idx_relation = tonnetz_relation_matrix[idx_c_1][idx_c_2]
+    return relation_list[idx_relation]
+
+#@jit(nopython=True)
+def accelerated_apply_triadic_tonnetz_relation_symbol(chord_1, rel):
+    circle_sharp =  ['C','Am','F','Dm','A#','Gm','D#','Cm','G#','Fm','C#','A#m','F#','D#m','B','G#m','E','C#m','A','F#m','D','Bm','G','Em']
+    circle_flat = ['C','Am','F','Dm','Bb','Gm','Eb','Cm','Ab','Fm','Db','Bbm','Gb','Ebm','B','Abm','E','Dbm','A','Gbm','D','Bm','G','Em']
+    relation_list = [0,'R','RL','RLR','LRPR','LRP','PR','P','PL','PLR','LPRP','LPRPR','PRPR','PRP','LPLR','LPL','LP','LPR','RP','RPR','LRLR','LRL','LR','L','LRPL','LPLP']
+    tonnetz_relation_applied_matrix = [[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
+        16, 17, 18, 19, 20, 21, 22, 23,  6,  8],
+       [ 1,  0, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10,
+         9,  8,  7,  6,  5,  4,  3,  2, 19, 17],
+       [ 2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17,
+        18, 19, 20, 21, 22, 23,  0,  1,  8, 10],
+       [ 3,  2,  1,  0, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12,
+        11, 10,  9,  8,  7,  6,  5,  4, 21, 19],
+       [ 4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+        20, 21, 22, 23,  0,  1,  2,  3, 10, 12],
+       [ 5,  4,  3,  2,  1,  0, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14,
+        13, 12, 11, 10,  9,  8,  7,  6, 23, 21],
+       [ 6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+        22, 23,  0,  1,  2,  3,  4,  5, 12, 14],
+       [ 7,  6,  5,  4,  3,  2,  1,  0, 23, 22, 21, 20, 19, 18, 17, 16,
+        15, 14, 13, 12, 11, 10,  9,  8,  1, 23],
+       [ 8,  9, 10, 11, 12, 13,  2, 15,  0, 17, 18, 19, 20, 21, 22, 23,
+         0,  1,  2,  3,  4,  5,  6,  7, 14, 16],
+       [ 9,  8,  7,  6,  5,  4,  3,  2,  1,  0, 23, 22, 21, 20, 19, 18,
+        17, 16, 15, 14, 13, 12, 11, 10,  3,  1],
+       [10, 11, 12, 13, 14, 15,  4, 17,  2, 19, 20, 21, 22, 23,  0,  1,
+         2,  3,  4,  5,  6,  7,  8,  9, 16, 18],
+       [11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0, 23, 22, 21, 20,
+        19, 18, 17, 16, 15, 14, 13, 12,  5,  3],
+       [12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,  0,  1,  2,  3,
+         4,  5,  6,  7,  8,  9, 10, 11, 18, 20],
+       [13, 12, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0, 23, 22,
+        21, 20, 19, 18, 17, 16, 15, 14,  7,  5],
+       [14, 15, 16, 17, 18, 19, 20, 21, 22, 23,  0,  1,  2,  3,  4,  5,
+         6,  7,  8,  9, 10, 11, 12, 13, 20, 22],
+       [15, 14, 13, 12, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0,
+        23, 22, 21, 20, 19, 18, 17, 16,  9,  7],
+       [16, 17, 18, 19, 20, 21, 22, 23,  0,  1,  2,  3,  4,  5,  6,  7,
+         8,  9, 10, 11, 12, 13, 14, 15, 22,  0],
+       [17, 16, 15, 14, 13, 12, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,
+         1,  0, 23, 22, 21, 20, 19, 18, 11,  9],
+       [18, 19, 20, 21, 22, 23,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
+        10, 11, 12, 13, 14, 15, 16, 17,  0,  2],
+       [19, 18, 17, 16, 15, 14, 13, 12, 11, 10,  9,  8,  7,  6,  5,  4,
+         3,  2,  1,  0, 23, 22, 21, 20, 13, 11],
+       [20, 21, 22, 23,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11,
+        12, 13, 14, 15, 16, 17, 18, 19,  2,  4],
+       [21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10,  9,  8,  7,  6,
+         5,  4,  3,  2,  1,  0, 23, 22, 15, 13],
+       [22, 23,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13,
+        14, 15, 16, 17, 18, 19, 20, 21,  4,  6],
+       [23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10,  9,  8,
+         7,  6,  5,  4,  3,  2,  1,  0, 17, 15]]
+    
+    if chord_1 in circle_sharp:
+        idx_c_1 = circle_sharp.index(chord_1)
+    else:
+        idx_c_1 = circle_flat.index(chord_1)
+        
+    rel_idx = relation_list.index(rel)
+    
+    return circle_sharp[tonnetz_relation_applied_matrix[idx_c_1][rel_idx]]
+
+
+def accelerated_chromatic_mvt_triads(chord_1, chord_2):
+    circle_sharp =  ['C','Am','F','Dm','A#','Gm','D#','Cm','G#','Fm','C#','A#m','F#','D#m','B','G#m','E','C#m','A','F#m','D','Bm','G','Em']
+    circle_flat = ['C','Am','F','Dm','Bb','Gm','Eb','Cm','Ab','Fm','Db','Bbm','Gb','Ebm','B','Abm','E','Dbm','A','Gbm','D','Bm','G','Em']
+    chromatic_relations_tab = [[  0,  -7,  10,   3,  -4, -11,   6,  -1,  -8,   9,   2,  -5,  12,
+          5,  -2,  -9,   8,   1,  -6,  11,   4,  -3, -10,   7],
+       [  7,   0,  -7,  10,   3,  -4, -11,   6,  -1,  -8,   9,   2,  -5,
+         12,   5,  -2,  -9,   8,   1,  -6,  11,   4,  -3, -10],
+       [-10,   7,   0,  -7,  10,   3,  -4, -11,   6,  -1,  -8,   9,   2,
+         -5,  12,   5,  -2,  -9,   8,   1,  -6,  11,   4,  -3],
+       [ -3, -10,   7,   0,  -7,  10,   3,  -4, -11,   6,  -1,  -8,   9,
+          2,  -5,  12,   5,  -2,  -9,   8,   1,  -6,  11,   4],
+       [  4,  -3, -10,   7,   0,  -7,  10,   3,  -4, -11,   6,  -1,  -8,
+          9,   2,  -5,  12,   5,  -2,  -9,   8,   1,  -6,  11],
+       [ 11,   4,  -3, -10,   7,   0,  -7,  10,   3,  -4, -11,   6,  -1,
+         -8,   9,   2,  -5,  12,   5,  -2,  -9,   8,   1,  -6],
+       [ -6,  11,   4,  -3, -10,   7,   0,  -7,  10,   3,  -4, -11,   6,
+         -1,  -8,   9,   2,  -5,  12,   5,  -2,  -9,   8,   1],
+       [  1,  -6,  11,   4,  -3, -10,   7,   0,  -7,  10,   3,  -4, -11,
+          6,  -1,  -8,   9,   2,  -5,  12,   5,  -2,  -9,   8],
+       [  8,   1,  -6,  11,   4,  -3, -10,   7,   0,  -7,  10,   3,  -4,
+        -11,   6,  -1,  -8,   9,   2,  -5,  12,   5,  -2,  -9],
+       [ -9,   8,   1,  -6,  11,   4,  -3, -10,   7,   0,  -7,  10,   3,
+         -4, -11,   6,  -1,  -8,   9,   2,  -5,  12,   5,  -2],
+       [ -2,  -9,   8,   1,  -6,  11,   4,  -3, -10,   7,   0,  -7,  10,
+          3,  -4, -11,   6,  -1,  -8,   9,   2,  -5,  12,   5],
+       [  5,  -2,  -9,   8,   1,  -6,  11,   4,  -3, -10,   7,   0,  -7,
+         10,   3,  -4, -11,   6,  -1,  -8,   9,   2,  -5,  12],
+       [ 12,   5,  -2,  -9,   8,   1,  -6,  11,   4,  -3, -10,   7,   0,
+         -7,  10,   3,  -4, -11,   6,  -1,  -8,   9,   2,  -5],
+       [ -5,  12,   5,  -2,  -9,   8,   1,  -6,  11,   4,  -3, -10,   7,
+          0,  -7,  10,   3,  -4, -11,   6,  -1,  -8,   9,   2],
+       [  2,  -5,  12,   5,  -2,  -9,   8,   1,  -6,  11,   4,  -3, -10,
+          7,   0,  -7,  10,   3,  -4, -11,   6,  -1,  -8,   9],
+       [  9,   2,  -5,  12,   5,  -2,  -9,   8,   1,  -6,  11,   4,  -3,
+        -10,   7,   0,  -7,  10,   3,  -4, -11,   6,  -1,  -8],
+       [ -8,   9,   2,  -5,  12,   5,  -2,  -9,   8,   1,  -6,  11,   4,
+         -3, -10,   7,   0,  -7,  10,   3,  -4, -11,   6,  -1],
+       [ -1,  -8,   9,   2,  -5,  12,   5,  -2,  -9,   8,   1,  -6,  11,
+          4,  -3, -10,   7,   0,  -7,  10,   3,  -4, -11,   6],
+       [  6,  -1,  -8,   9,   2,  -5,  12,   5,  -2,  -9,   8,   1,  -6,
+         11,   4,  -3, -10,   7,   0,  -7,  10,   3,  -4, -11],
+       [-11,   6,  -1,  -8,   9,   2,  -5,  12,   5,  -2,  -9,   8,   1,
+         -6,  11,   4,  -3, -10,   7,   0,  -7,  10,   3,  -4],
+       [ -4, -11,   6,  -1,  -8,   9,   2,  -5,  12,   5,  -2,  -9,   8,
+          1,  -6,  11,   4,  -3, -10,   7,   0,  -7,  10,   3],
+       [  3,  -4, -11,   6,  -1,  -8,   9,   2,  -5,  12,   5,  -2,  -9,
+          8,   1,  -6,  11,   4,  -3, -10,   7,   0,  -7,  10],
+       [ 10,   3,  -4, -11,   6,  -1,  -8,   9,   2,  -5,  12,   5,  -2,
+         -9,   8,   1,  -6,  11,   4,  -3, -10,   7,   0,  -7],
+       [ -7,  10,   3,  -4, -11,   6,  -1,  -8,   9,   2,  -5,  12,   5,
+         -2,  -9,   8,   1,  -6,  11,   4,  -3, -10,   7,   0]]
+    
+    if chord_1 in circle_sharp:
+        idx_c_1 = circle_sharp.index(chord_1)
+    else:
+        idx_c_1 = circle_flat.index(chord_1)
+        
+    if chord_2 in circle_sharp:
+        idx_c_2 = circle_sharp.index(chord_2)
+    else:
+        idx_c_2 = circle_flat.index(chord_2)
+    
+    return chromatic_relations_tab[idx_c_1][idx_c_2]
+
+def accelerated_get_voice_leading_transformation_symbol(chord_1, chord_2):
+    circle_sharp =  ['C','Am','F','Dm','A#','Gm','D#','Cm','G#','Fm','C#','A#m','F#','D#m','B','G#m','E','C#m','A','F#m','D','Bm','G','Em']
+    circle_flat = ['C','Am','F','Dm','Bb','Gm','Eb','Cm','Ab','Fm','Db','Bbm','Gb','Ebm','B','Abm','E','Dbm','A','Gbm','D','Bm','G','Em']
+    relations_list = [[0, 0, 0],
+                     [9, -4, -3],
+                     [5, 5, -7],
+                     [2, 1, 2],
+                     [10, -2, -2],
+                     [7, 6, -5],
+                     [3, 3, 3],
+                     [0, -1, 0],
+                     [8, -4, -4],
+                     [5, 4, -7],
+                     [1, 1, 1],
+                     [10, -3, -2],
+                     [6, 6, -6],
+                     [3, 2, 3],
+                     [11, -1, -1],
+                     [8, 7, -4],
+                     [4, 4, 4],
+                     [1, 0, 1],
+                     [9, -3, -3],
+                     [6, 5, -6],
+                     [2, 2, 2],
+                     [11, -2, -1],
+                     [7, 7, -5],
+                     [4, 3, 4],
+                     [-9, 4, 3],
+                     [-4, 9, -4],
+                     [-7, 5, 5],
+                     [1, 2, 1],
+                     [-2, 10, -2],
+                     [-6, 7, 6],
+                     [-9, 3, 3],
+                     [-1, 0, -1],
+                     [-4, 8, -4],
+                     [-8, 5, 4],
+                     [-3, 10, -3],
+                     [-6, 6, 6],
+                     [2, 3, 2],
+                     [-1, 11, -1],
+                     [-5, 8, 7],
+                     [-8, 4, 4],
+                     [0, 1, 0],
+                     [-3, 9, -3],
+                     [-7, 6, 5],
+                     [-2, 11, -2],
+                     [-5, 7, 7],
+                     [-5, -5, 7],
+                     [4, -9, 4],
+                     [-3, -4, 9],
+                     [5, -7, 5],
+                     [-2, -2, 10],
+                     [-5, -6, 7],
+                     [3, -9, 3],
+                     [-4, -4, 8],
+                     [5, -8, 5],
+                     [-2, -3, 10],
+                     [6, -6, 6],
+                     [-1, -1, 11],
+                     [-4, -5, 8],
+                     [4, -8, 4],
+                     [-3, -3, 9],
+                     [6, -7, 6],
+                     [-1, -2, 11],
+                     [-2, -1, -2],
+                     [7, -5, -5],
+                     [3, 4, -9],
+                     [8, -3, -4],
+                     [-2, -2, -2],
+                     [6, -5, -6],
+                     [3, 3, -9],
+                     [4, 5, -8],
+                     [9, -2, -3],
+                     [-1, -1, -1],
+                     [7, -4, -5],
+                     [4, 4, -8],
+                     [5, 6, -7],
+                     [-10, 2, 2],
+                     [-1, -2, -1],
+                     [-5, 7, -5],
+                     [-8, 3, 4],
+                     [-3, 8, -3],
+                     [-10, 1, 2],
+                     [-5, 6, -5],
+                     [-7, 4, 5],
+                     [-2, 9, -2],
+                     [-9, 2, 3],
+                     [-4, 7, -4],
+                     [-6, 5, 6],
+                     [-7, -6, 5],
+                     [2, -10, 2],
+                     [3, -8, 3],
+                     [-4, -3, 8],
+                     [-7, -7, 5],
+                     [1, -10, 1],
+                     [-6, -5, 6],
+                     [4, -7, 4],
+                     [-3, -2, 9],
+                     [-6, -6, 6],
+                     [2, -9, 2],
+                     [-5, -4, 7],
+                     [-3, -3, -3],
+                     [6, -7, -6],
+                     [2, 2, -10],
+                     [4, 3, -8],
+                     [-3, -4, -3],
+                     [5, -7, -7],
+                     [2, 1, -10],
+                     [7, -6, -5],
+                     [-2, -3, -2],
+                     [6, -6, -6],
+                     [3, 2, -9],
+                     [8, -5, -4],
+                     [10, -1, -2],
+                     [3, 4, 3],
+                     [6, 7, -6],
+                     [11, 0, -1],
+                     [8, 8, -4],
+                     [4, 5, 4],
+                     [7, 8, -5],
+                     [-1, 10, -1],
+                     [-5, 6, 7],
+                     [0, 11, 0],
+                     [-4, 8, 8],
+                     [-4, 7, 8],
+                     [5, -6, 5],
+                     [-2, -1, 10],
+                     [6, -5, 6],
+                     [-1, 0, 11],
+                     [-10, 3, 2],
+                     [-5, 8, -5],
+                     [3, -10, 3],
+                     [-6, -7, 6],
+                     [-3, -2, -3],
+                     [2, 3, -10],
+                     [5, -6, -7],
+                     [-11, 1, 1],
+                     [-6, 6, -6],
+                     [-11, 0, 1],
+                     [-6, 5, -6],
+                     [-8, -7, 4],
+                     [1, -11, 1],
+                     [-8, -8, 4],
+                     [0, -11, 0],
+                     [-4, -4, -4],
+                     [5, -8, -7],
+                     [1, 1, -11],
+                     [-4, -5, -4],
+                     [4, -8, -8],
+                     [1, 0, -11],
+                     [-11, 2, 1],
+                     [-6, 7, -6],
+                     [2, -11, 2],
+                     [-7, -8, 5],
+                     [-4, -3, -4],
+                     [1, 2, -11],
+                     [4, -7, -8]]
+    
+    triad_transformations_tab_idx = [[  0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,
+         13,  14,  15,  16,  17,  18,  19,  20,  21,  22,  23],
+       [ 24,   0,  25,  26,  27,  28,  29,  30,  31,  32,  33,  10,  34,
+         35,  36,  37,  38,  39,  40,  41,  42,  20,  43,  44],
+       [ 45,  46,   0,  47,  48,   3,  49,  50,  51,   7,  52,  53,  10,
+         54,  55,  13,  56,  57,  58,  17,  59,  60,  20,  61],
+       [ 62,  63,  64,   0,  65,   2,  27,  66,  67,  68,  31,   8,  69,
+         10,  70,  12,  36,  71,  72,  73,  40,  18,  74,  20],
+       [ 75,  76,  77,  78,   0,  79,  26,  80,  66,  81,  30,   7,  32,
+         82,  10,  83,  35,  84,  71,  85,  39,  17,  41,  86],
+       [ 87,  88,  62,  45,  89,   0,  90,  91,  92,  66,  93,  51,  31,
+         52,  94,  10,  95,  96,  97,  71,  98,  58,  40,  59],
+       [ 99, 100, 101,  76,  63, 102,   0, 103, 104, 105,  66, 106,  68,
+          7,   8,   9,  10, 107, 108, 109,  71, 110,  73,  17],
+       [ 40,  18,  74,  20, 111,  22, 112,   0,  65,   2,  27,   4, 113,
+          6, 114, 115, 116,  10,  70,  12,  36,  14, 117,  16],
+       [ 39,  17,  41,  86,  20, 118,  44,  78,   0,  79,  26,   3,  28,
+        119,   6, 120, 121,  82,  10,  83,  35,  13,  37, 122],
+       [ 98,  58,  40,  59, 123,  20, 124,  45,  89,   0,  90,  48,  27,
+         49, 125,   6, 126,  52,  94,  10,  95,  55,  36,  56],
+       [ 71, 110,  73,  17,  18,  19,  20,  76,  63, 102,   0,   1,   2,
+          3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13],
+       [127,  71, 128,  39,  40,  41,  42,  75,  62,  77,  24,   0,  25,
+         26,  27,  28,  29,  30,  31,  32,  33,  10,  34,  35],
+       [ 96, 129,  71,  57,  58,  17,  59, 130,  88,  76,  45,  46,   0,
+         47,  48,   3,  49,  50,  51,   7,  52,  53,  10,  54],
+       [131, 108, 132,  71,  72,  73,  40,  99, 133, 101,  62,  63,  64,
+          0,  65,   2,  27,  66,  67,  68,  31,   8,  69,  10],
+       [134, 107, 135,  84,  71,  85,  39, 136,  99, 137,  75,  76,  77,
+         78,   0,  79,  26,  80,  66,  81,  30,   7,  32,  82],
+       [138, 139, 131,  96,  97,  71,  98, 140, 141,  99,  87,  88,  62,
+         45,  89,   0,  90,  91,  92,  66,  93,  51,  31,  52],
+       [142, 143, 144, 107, 108, 109,  71, 145, 146, 147,  99, 100, 101,
+         76,  63, 102,   0, 103, 104, 105,  66, 106,  68,   7],
+       [ 31,   8,  69,  10,  70,  12,  36,  71,  72,  73,  40,  18,  74,
+         20, 111,  22, 112,   0,  65,   2,  27,   4, 113,   6],
+       [ 30,   7,  32,  82,  10,  83,  35,  84,  71,  85,  39,  17,  41,
+         86,  20, 118,  44,  78,   0,  79,  26,   3,  28, 119],
+       [ 93,  51,  31,  52,  94,  10,  95,  96,  97,  71,  98,  58,  40,
+         59, 123,  20, 124,  45,  89,   0,  90,  48,  27,  49],
+       [ 66, 106,  68,   7,   8,   9,  10, 107, 108, 109,  71, 110,  73,
+         17,  18,  19,  20,  76,  63, 102,   0,   1,   2,   3],
+       [148,  66, 149,  30,  31,  32,  33, 134, 131, 135, 127,  71, 128,
+         39,  40,  41,  42,  75,  62,  77,  24,   0,  25,  26],
+       [ 91, 150,  66,  50,  51,   7,  52, 151, 139, 107,  96, 129,  71,
+         57,  58,  17,  59, 130,  88,  76,  45,  46,   0,  47],
+       [152, 104, 153,  66,  67,  68,  31, 142, 154, 144, 131, 108, 132,
+         71,  72,  73,  40,  99, 133, 101,  62,  63,  64,   0]]
+    
+    if chord_1 in circle_sharp:
+        idx_c_1 = circle_sharp.index(chord_1)
+    else:
+        idx_c_1 = circle_flat.index(chord_1)
+        
+    if chord_2 in circle_sharp:
+        idx_c_2 = circle_sharp.index(chord_2)
+    else:
+        idx_c_2 = circle_flat.index(chord_2)
+    
+    transformation_idx = triad_transformations_tab_idx[idx_c_1][idx_c_2]
+    return relations_list[transformation_idx]
diff --git a/polytopes/chord_movement.py b/MusicOnPolytopes/chord_movement.py
similarity index 99%
rename from polytopes/chord_movement.py
rename to MusicOnPolytopes/chord_movement.py
index f6e17f3e5adf07ce39bf830117f7b145390df282..3c873b4be4f308ab23fb22d653895cb97abc521b 100644
--- a/polytopes/chord_movement.py
+++ b/MusicOnPolytopes/chord_movement.py
@@ -183,7 +183,7 @@ def apply_triadic_mvt(chord, mvt, chromatic = True):
         The new chord, after applying the relation.
 
     """
-    circle = dm.get_circle_of_triads(flat = True, chromatic = chromatic)
+    circle = dm.get_circle_of_triads(flat = False, chromatic = chromatic)
     idx = get_triadic_position(chord, chromatic = chromatic)
     return circle[(idx + mvt)%24]
 
diff --git a/polytopes/compute_frontiers.py b/MusicOnPolytopes/compute_frontiers.py
similarity index 100%
rename from polytopes/compute_frontiers.py
rename to MusicOnPolytopes/compute_frontiers.py
diff --git a/MusicOnPolytopes/compute_scores.py b/MusicOnPolytopes/compute_scores.py
new file mode 100644
index 0000000000000000000000000000000000000000..14c5fbfddc6c48f510acb7ad13953bc6d3550436
--- /dev/null
+++ b/MusicOnPolytopes/compute_scores.py
@@ -0,0 +1,115 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Thu Aug  5 12:21:07 2021
+
+@author: amarmore
+"""
+
+from IPython.display import display, Markdown
+
+# Self-code imports
+import polytopes.segmentation_algorithms as algos
+import polytopes.data_manipulation as dm
+
+
+#Generic imports
+import numpy as np
+import matplotlib.pyplot as plt
+import pandas as pd
+import math
+
+database_path = "C:/Users/amarmore/Desktop/Projects/RWC_annotations/final_bimbot_al/"
+annotations_folder_path = "C:/Users/amarmore/Desktop/Audio samples/RWC Pop/annotations/final_bimbot/"
+
+def compute_scores_for_different_penalties(database, database_name, segments_size_range, polytope_irr_range, relation_type, max_size = 42):
+    """
+    Compute the scores for different penalty values and print the in readable format.
+
+    Parameters
+    ----------
+    database : TYPE
+        DESCRIPTION.
+    segments_size_range : TYPE
+        DESCRIPTION.
+    polytope_irr_range : TYPE
+        DESCRIPTION.
+    relation_type : TYPE
+        DESCRIPTION.
+    max_size : TYPE, optional
+        DESCRIPTION. The default is 42.
+
+    Returns
+    -------
+    None.
+
+    """
+
+    all_scores = math.inf * np.ones((len(database), len(segments_size_range), len(polytope_irr_range), 2, 3))
+    
+    for idx_song, song in enumerate(database):
+        #time_start = time.time()
+        song_number = song.split(".")[0]
+        #print(song_number)
+        bag_of_chords = dm.flowify_song(database_path + song)
+    
+        annot_name = "{:03d}.manual.seg".format(int(song_number))
+        annotation_file = open(annotations_folder_path + annot_name,'r')
+        annotation = annotation_file.read().replace("\n", "").split(" ")
+        annotation = np.array([int(x) - 1 for x in annotation])
+        beat_indexed_annotation = np.array(dm.frontiers_to_segments(annotation))
+        
+        for idx_seg, segment_size_penalty in enumerate(segments_size_range):
+            for idx_irr, polytope_irregularity_penalty in enumerate(polytope_irr_range):
+    
+                frontiers, cost = algos.dynamic_minimization_guichaoua_persist_segments(bag_of_chords, database_name,
+                                                                                segment_size_penalty = segment_size_penalty,
+                                                                                min_size = 8, max_size = max_size, target_size = 32, 
+                                                                                polytope_irregularity_penalty = polytope_irregularity_penalty,
+                                                                                relation_type = relation_type, song_number = song_number)
+    
+                #for fst, snd in zip(frontiers[:-1], frontiers[1:]):
+                #    g_distrib_segments.append(snd - fst)
+    
+                #Scores, computed on the beat annotation
+                beat_indexed_segments = dm.frontiers_to_segments(frontiers)
+    
+                all_scores[idx_song, idx_seg, idx_irr, 0] = dm.compute_score_of_segmentation(beat_indexed_annotation, beat_indexed_segments, 
+                                                                           window_length = 0.2)
+                all_scores[idx_song, idx_seg, idx_irr, 1] = dm.compute_score_of_segmentation(beat_indexed_annotation, beat_indexed_segments, 
+                                                                           window_length = 3)
+        
+    """print_res_for_songs_range(g_all_res_zero_tol, context = "Zero Tolerance")
+    print_res_for_songs_range(g_all_res_three_tol, context = "Three Tolerance")
+    plt.figure(figsize=(15,5))
+    plt.hist(g_distrib_segments, bins = range(max_size))
+    plt.xlabel("Segment's size (in nb of beats)")
+    #plt.title("Prec: {}, rap: {}, F measure: {}".format(prec, rap, fmes))
+    plt.plot()"""
+    
+    lines = np.array(['Precision', 'Recall', 'F measure'])  
+    
+    all_scores_np = np.array(all_scores)
+    arr_zero_five = []
+    arr_three = []
+    
+    col_seg = []
+    col_irr = []
+    for i_seg in range(len(segments_size_range)):
+        for i_irr in range(len(polytope_irr_range)):
+            line_zero_five = []
+            line_three = []
+            for j in range(3):
+                line_zero_five.append(round(np.mean(all_scores_np[:,i_seg, i_irr, 0, j]),4))
+                line_three.append(round(np.mean(all_scores_np[:,i_seg, i_irr, 1, j]),4))
+            arr_zero_five.append(line_zero_five)
+            arr_three.append(line_three)
+            col_seg.append(f"Size penalty: {segments_size_range[i_seg]}")
+            col_irr.append(f"Polytope penalty: {polytope_irr_range[i_irr]}")
+    
+    col = [np.array(col_seg),np.array(col_irr)]
+    
+    dataframe = pd.DataFrame(arr_zero_five, index=col, columns=lines)
+    display(dataframe.style.bar(subset=["F measure"], color='#5fba7d'))
+    
+    dataframe = pd.DataFrame(arr_three, index=col, columns=lines)
+    display(dataframe.style.bar(subset=["F measure"], color='#5fba7d'))
\ No newline at end of file
diff --git a/polytopes/data_manipulation.py b/MusicOnPolytopes/data_manipulation.py
similarity index 97%
rename from polytopes/data_manipulation.py
rename to MusicOnPolytopes/data_manipulation.py
index 9a6ed9061b54d725f60b5bb6506cda3233c4daad..5a4133829b3397bc00cc531b5b8b2f54322523c1 100644
--- a/polytopes/data_manipulation.py
+++ b/MusicOnPolytopes/data_manipulation.py
@@ -54,7 +54,7 @@ def get_circle_of_triads(flat = True, chromatic = True):
     #     if flat:
     #         return ['C','Fm','Db','Gbm','D','Gm','Eb','Abm','E','Am','F','Bbm','Gb','Bm','G','Cm','Ab','Dbm','A','Dm','Bb','Ebm','B','Em']
     #     else:
-    #         return ['C','Fm','C#','F#m','D','Gm','D#','G#m','E','Am','F','A#m','F#','Bm','G','Cm','G#','C#m','A','Cm','A#','D#m','B','Em'] 
+    #         return ['C','Fm','C#','F#m','D','Gm','D#','G#m','E','Am','F','A#m','F#','Bm','G','Cm','G#','C#m','A','Dm','A#','D#m','B','Em'] 
 
 # %% Read and treat inputs
 def get_piano_roll(path, hop_length_seconds, threshold_offset = None):
@@ -477,13 +477,18 @@ def flowify_song(path):
                     try:
                         bag_of_chords.append(bag_of_chords[-1])
                     except IndexError:
-                        if len(np.unique(chords)) == 1:
-                            raise NotImplementedError("Song is only composed of silence, to check the origianl file at {}".format(path))
+                        if len(np.unique(chords)) == 1 or (len(np.unique(chords)) == 2 and '' in np.unique(chords)):
+                            raise NotImplementedError("Song is only composed of silence, to check the original file at {}".format(path))
                         else:
                             for i in chords:
                                 if i != "N":
-                                    bag_of_chords.append(Chord(i))
-                                    break
+                                    try:
+                                        Chord(i)
+                                        bag_of_chords.append(Chord(i))
+                                        break
+                                    except err.InvalidChordNotesException:
+                                        raise NotImplementedError(f"Chord '{i}' have cause failure, on line: {line}")
+                                        
     return bag_of_chords
 
 def frontiers_to_chord_sequence(flow, frontiers):
diff --git a/polytopes/model/__init__.py b/MusicOnPolytopes/model/__init__.py
similarity index 100%
rename from polytopes/model/__init__.py
rename to MusicOnPolytopes/model/__init__.py
diff --git a/polytopes/model/chord.py b/MusicOnPolytopes/model/chord.py
similarity index 100%
rename from polytopes/model/chord.py
rename to MusicOnPolytopes/model/chord.py
diff --git a/polytopes/model/constants.py b/MusicOnPolytopes/model/constants.py
similarity index 100%
rename from polytopes/model/constants.py
rename to MusicOnPolytopes/model/constants.py
diff --git a/polytopes/model/errors.py b/MusicOnPolytopes/model/errors.py
similarity index 94%
rename from polytopes/model/errors.py
rename to MusicOnPolytopes/model/errors.py
index 976d246112562bc560572414bc2ee4d45bfbd41f..154f217672b2b1a2a64f042eb6db2f300d4fe711 100644
--- a/polytopes/model/errors.py
+++ b/MusicOnPolytopes/model/errors.py
@@ -7,6 +7,9 @@ Created on Mon Dec  9 11:06:19 2019
 class InvalidArgumentValueException(BaseException): pass
 class OutdatedBehaviorException(BaseException): pass
 
+class TriadException(BaseException): pass
+class NotAMajMinTriadException(TriadException): pass
+
 class NoteException(BaseException): pass
 class InvalidNoteException(NoteException): pass
 class InvalidNoteNumberException(InvalidNoteException): pass
diff --git a/polytopes/model/note.py b/MusicOnPolytopes/model/note.py
similarity index 100%
rename from polytopes/model/note.py
rename to MusicOnPolytopes/model/note.py
diff --git a/MusicOnPolytopes/model/triad_manipulation.py b/MusicOnPolytopes/model/triad_manipulation.py
new file mode 100644
index 0000000000000000000000000000000000000000..c37b8b47f128199b8a1ae1a05ca1ba0f3a13b077
--- /dev/null
+++ b/MusicOnPolytopes/model/triad_manipulation.py
@@ -0,0 +1,121 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Tue Nov 26 10:08:18 2019
+
+@author: amarmore
+"""
+import math
+import music21
+
+import polytopes.data_manipulation as dm
+import polytopes.model.errors as err
+
+notes_sharp = ['C','C#','D','D#','E','F','F#','G','G#','A','A#','B']
+notes_flat = ['C','Db','D','Eb','E','F','Gb','G','Ab','A','Bb','B']
+
+### Basic chord manipulation
+# We only consider minor and major triads
+def triad_symbol_from_notes(triad_notes):
+    notes = reindex_inversed_triad(triad_notes)
+    triad = notes_sharp[notes[0]]
+    if (notes[1] - notes[0])%12 == 3:
+        triad += "m"
+    return triad
+
+def root_from_notes(notes):
+    notes = reindex_inversed_triad(notes)
+    return notes_sharp[notes[0]]
+
+def triad_notes_from_symbol(symbol, triadic_reduction = True):
+    symbol = little_format_symbol(symbol)
+    if not is_maj_min_triad_from_symbol(symbol):
+        if not triadic_reduction:
+            raise err.NotAMajMinTriadException(f"This symbol ({symbol}) does not correspond to a major or minor triad, which is our only case study.")
+        else:
+            symbol = maj_min_triad_reduction_of_symbol(symbol)
+    notes = []
+    root_name = root_from_symbol(symbol)
+    for i in range(12):
+        if notes_sharp[i] == root_name or notes_flat[i] == root_name:
+            root = i
+            notes.append(root)
+            break
+    if "m" in symbol:
+        notes.append((root+3)%12)
+    else:
+        notes.append((root+4)%12)
+    notes.append((root+7)%12)
+    return notes
+
+def root_from_symbol(symbol):
+    root_name = symbol[0]
+    if len(symbol) > 1:
+        if symbol[1] == '-' or symbol[1] == 'b':
+            root_name += 'b'
+        elif symbol[1] == '+' or symbol[1] == '#':
+            root_name += '#'
+    return root_name
+
+def reindex_inversed_triad(list_of_notes_numbers):
+    if len(list_of_notes_numbers) != 3:
+        raise err.NotAMajMinTriadException(f"Too many notes for this chord to be a triad ({list_of_notes_numbers}).")
+    for i in range(3):
+        root = list_of_notes_numbers[i]
+        first_gap = (list_of_notes_numbers[(i+1)%3] - root)%12
+        second_gap = (list_of_notes_numbers[(i+2)%3] - root)%12
+        if first_gap == 7:
+            if second_gap == 3 or second_gap == 4:
+                return [root, list_of_notes_numbers[(i+2)%3], list_of_notes_numbers[(i+1)%3]]
+        elif second_gap == 7:
+            if first_gap == 3 or first_gap == 4:
+                return [root, list_of_notes_numbers[(i+1)%3], list_of_notes_numbers[(i+2)%3]]
+    raise err.NotAMajMinTriadException(f"These notes ({list_of_notes_numbers}) does not correspond to a major or minor triad, which is our only case study.")
+
+def is_maj_min_triad_from_notes(list_of_notes_numbers):
+    if len(list_of_notes_numbers) != 3:
+        return False
+    for i in range(3):
+        root = list_of_notes_numbers[i]
+        first_gap = (list_of_notes_numbers[(i+1)%3] - root)%12
+        second_gap = (list_of_notes_numbers[(i+2)%3] - root)%12
+        if first_gap == 7:
+            if second_gap == 3 or second_gap == 4:
+                return True
+        elif second_gap == 7:
+            if first_gap == 3 or first_gap == 4:
+                return True
+    return False
+
+def is_maj_min_triad_from_symbol(symbol):
+    symbol = little_format_symbol(symbol)
+    root = root_from_symbol(symbol)
+    idx_post_root = len(root)
+    return len(symbol) == idx_post_root or (len(symbol) == idx_post_root + 1 and symbol[idx_post_root] == "m")
+
+def maj_min_triad_reduction_of_symbol(symbol, to_sharp = True):
+    """
+    Reducing a chord to its maj or min triad
+    
+    Returns
+    -------
+    string: the triad symbol of the chord.
+    """
+    symbol = little_format_symbol(symbol)
+    root = root_from_symbol(symbol)
+    if to_sharp:
+        if root not in notes_sharp:
+            root_idx = notes_flat.index(root)
+            root = notes_sharp[root_idx]
+    idx_post_root = len(root)
+    if len(symbol) > idx_post_root and symbol[idx_post_root] in ["m","d"]: # minor or diminished triad
+        root += "m"
+    return root
+
+def little_format_symbol(symbol):
+    if "maj" in symbol:
+        symbol = symbol.replace("maj","")
+    if "min" in symbol:
+        symbol = symbol.replace("min","m")
+    if "dim" in symbol:
+        symbol = symbol.replace("dim","d")
+    return symbol
diff --git a/polytopes/pattern_factory.py b/MusicOnPolytopes/pattern_factory.py
similarity index 100%
rename from polytopes/pattern_factory.py
rename to MusicOnPolytopes/pattern_factory.py
diff --git a/polytopes/pattern_manip.py b/MusicOnPolytopes/pattern_manip.py
similarity index 100%
rename from polytopes/pattern_manip.py
rename to MusicOnPolytopes/pattern_manip.py
diff --git a/polytopes/polytopical_costs.py b/MusicOnPolytopes/polytopical_costs.py
similarity index 66%
rename from polytopes/polytopical_costs.py
rename to MusicOnPolytopes/polytopical_costs.py
index dc3e97bb3a3caab28ca1ab37501db4fe9032b7e6..f6ffa04fa20fbf0dc92036d73acd8f74cf5025f7 100644
--- a/polytopes/polytopical_costs.py
+++ b/MusicOnPolytopes/polytopical_costs.py
@@ -13,15 +13,18 @@ TODO: maybe define such functions.
 
 import math
 import numpy as np
+from numba import jit
 
 import polytopes.segmentation_helper as sh
 import polytopes.chord_movement as mvt
 import polytopes.pattern_manip as pm
 import polytopes.pattern_factory as pf
+import polytopes.triad_transformations as tt
 import polytopes.model.errors as err
+import polytopes.accelerated_polytopical_costs as acc_pc
 
 # %% Louboutin (and more generally, high-level S&C) pardigm
-def louboutin_cost_for_a_ppp(segment, a_ppp, pattern_of_ones, reindex, current_min = math.inf):
+def louboutin_cost_for_a_ppp(segment, a_ppp, pattern_of_ones, reindex, current_min = math.inf, relation_type = "triad_circle"):
     """
     Compute the cost in the Louboutin's paradigm, for this segment and this PPP 'a_ppp'.
 
@@ -53,9 +56,9 @@ def louboutin_cost_for_a_ppp(segment, a_ppp, pattern_of_ones, reindex, current_m
     # pattern_made_of_ones = pf.extract_pattern_from_indexed_pattern(a_ppp)
     
     new_segment = pm.swap_chord_sequence(segment, reindex)
-    return polytopic_scale_s_and_c_cost_computation(new_segment, pattern_of_ones, current_min = current_min)
+    return polytopic_scale_s_and_c_cost_computation(new_segment, pattern_of_ones, current_min = current_min, relation_type = relation_type)
 
-def polytopic_scale_s_and_c_cost_computation(symbol_flow, polytope_pattern, extended_s_and_c = False, current_min = math.inf):
+def polytopic_scale_s_and_c_cost_computation(symbol_flow, polytope_pattern, extended_s_and_c = False, current_min = math.inf, relation_type = "triad_circle"):
     """
     Compute the cost of a chord sequence on a polytope, in the Louboutin paradigm (extended by A. Marmoret to irregular polytopes).
 
@@ -84,18 +87,18 @@ def polytopic_scale_s_and_c_cost_computation(symbol_flow, polytope_pattern, exte
     """
     # Global cost means: low systems cost, and computing the cost of the primers.
     if pf.get_pattern_dimension(polytope_pattern) <= 2:
-        return recursive_low_level_splitter_for_s_and_c_cost(symbol_flow, polytope_pattern, extended_s_and_c = extended_s_and_c)
+        return recursive_low_level_splitter_for_s_and_c_cost(symbol_flow, polytope_pattern, extended_s_and_c = extended_s_and_c, relation_type = relation_type)
     else:
-        inner_systems_cost = recursive_low_level_splitter_for_s_and_c_cost(symbol_flow, polytope_pattern, extended_s_and_c = extended_s_and_c)
+        inner_systems_cost = recursive_low_level_splitter_for_s_and_c_cost(symbol_flow, polytope_pattern, extended_s_and_c = extended_s_and_c, relation_type = relation_type)
         if inner_systems_cost > current_min:
             # Cost is already higher than current min, so avoid further computation.
             return math.inf
         primers_chords = recursively_find_primers_chords(symbol_flow, polytope_pattern)
         primer_pattern = extract_pattern_from_primers_chords(primers_chords)
         primer_symbol_flow = pf.flatten_pattern(primers_chords)
-        return inner_systems_cost + polytopic_scale_s_and_c_cost_computation(primer_symbol_flow, primer_pattern, extended_s_and_c = extended_s_and_c)
+        return inner_systems_cost + polytopic_scale_s_and_c_cost_computation(primer_symbol_flow, primer_pattern, extended_s_and_c = extended_s_and_c, relation_type = relation_type)
 
-def recursive_low_level_splitter_for_s_and_c_cost(symbol_flow, polytope_pattern, extended_s_and_c = False):
+def recursive_low_level_splitter_for_s_and_c_cost(symbol_flow, polytope_pattern, extended_s_and_c = False, relation_type = "triad_circle"):
     """
     Split the polytope in a list of dimension 2 polytopes, and compute score on these polytopes, as defined in the Louboutin paradigm, extended by A. Marmoret.
     
@@ -133,19 +136,19 @@ def recursive_low_level_splitter_for_s_and_c_cost(symbol_flow, polytope_pattern,
         if extended_s_and_c:
             return dim_two_extended_s_and_c_cost(symbol_flow, polytope_pattern)
         else:
-            return low_level_system_s_and_c_cost(symbol_flow, polytope_pattern)
+            return low_level_system_s_and_c_cost(symbol_flow, polytope_pattern, relation_type = relation_type)
     else:
         if len(polytope_pattern) == 1:
             first_nested_pattern = polytope_pattern[0]
-            return recursive_low_level_splitter_for_s_and_c_cost(symbol_flow, first_nested_pattern, extended_s_and_c = extended_s_and_c)
+            return recursive_low_level_splitter_for_s_and_c_cost(symbol_flow, first_nested_pattern, extended_s_and_c = extended_s_and_c, relation_type = relation_type)
         else:
             first_nested_pattern = polytope_pattern[0]
-            cost_first_nested_pattern = recursive_low_level_splitter_for_s_and_c_cost(symbol_flow[:pf.get_pattern_size(first_nested_pattern)], first_nested_pattern, extended_s_and_c = extended_s_and_c)
+            cost_first_nested_pattern = recursive_low_level_splitter_for_s_and_c_cost(symbol_flow[:pf.get_pattern_size(first_nested_pattern)], first_nested_pattern, extended_s_and_c = extended_s_and_c, relation_type = relation_type)
             second_nested_pattern = polytope_pattern[1]
-            cost_second_nested_pattern = recursive_low_level_splitter_for_s_and_c_cost(symbol_flow[pf.get_pattern_size(first_nested_pattern):], second_nested_pattern, extended_s_and_c = extended_s_and_c)
+            cost_second_nested_pattern = recursive_low_level_splitter_for_s_and_c_cost(symbol_flow[pf.get_pattern_size(first_nested_pattern):], second_nested_pattern, extended_s_and_c = extended_s_and_c, relation_type = relation_type)
             return cost_first_nested_pattern + cost_second_nested_pattern
 
-def low_level_system_s_and_c_cost(symbol_flow, polytope_pattern):
+def low_level_system_s_and_c_cost(symbol_flow, polytope_pattern, relation_type = "triad_circle"):
     """
     Compute the cost of a low-level system (dimension 2 polytope).
 
@@ -177,7 +180,7 @@ def low_level_system_s_and_c_cost(symbol_flow, polytope_pattern):
         raise err.UnexpectedDimensionForPattern("This pattern is of high dimension (higher than 2), can't compute a cost on it.")
 
     if pattern_size == 2:
-        return voice_leading_cost(symbol_flow[0], symbol_flow[1])
+        return score_relation_switcher(relation_type, symbol_flow[0], symbol_flow[1])
     s_and_c = []
     primer = symbol_flow[0]
     score = 0
@@ -189,27 +192,27 @@ def low_level_system_s_and_c_cost(symbol_flow, polytope_pattern):
             sequence_idx += 2
             
         elif one_dimension_pattern == [1,(1,1)]:
-            score += voice_leading_cost(symbol_flow[sequence_idx + 1], symbol_flow[sequence_idx + 2])
+            score += score_relation_switcher(relation_type, symbol_flow[sequence_idx + 1], symbol_flow[sequence_idx + 2])
             s_and_c.append(symbol_flow[sequence_idx])
             s_and_c.append(symbol_flow[sequence_idx + 1])
             sequence_idx += 3
             
         elif one_dimension_pattern == [(1,1),(1,1)]:
-            score += voice_leading_cost(symbol_flow[sequence_idx],symbol_flow[sequence_idx + 1])
-            score += voice_leading_cost(symbol_flow[sequence_idx + 2],symbol_flow[sequence_idx + 3])
+            score += score_relation_switcher(relation_type, symbol_flow[sequence_idx],symbol_flow[sequence_idx + 1])
+            score += score_relation_switcher(relation_type, symbol_flow[sequence_idx + 2],symbol_flow[sequence_idx + 3])
             s_and_c.append(symbol_flow[sequence_idx])
             s_and_c.append(symbol_flow[sequence_idx + 2])
             sequence_idx += 4
         
         elif one_dimension_pattern == [1]:
             if sequence_idx != 0:
-                score += voice_leading_cost(primer, symbol_flow[sequence_idx])
+                score += score_relation_switcher(relation_type, primer, symbol_flow[sequence_idx])
             sequence_idx += 1
 
         elif one_dimension_pattern == [(1,1)]:
             if sequence_idx != 0:
-                score += voice_leading_cost(primer, symbol_flow[sequence_idx])
-            score += voice_leading_cost(symbol_flow[sequence_idx], symbol_flow[sequence_idx + 1])
+                score += score_relation_switcher(relation_type, primer, symbol_flow[sequence_idx])
+            score += score_relation_switcher(relation_type, symbol_flow[sequence_idx], symbol_flow[sequence_idx + 1])
             sequence_idx += 2
 
         else:
@@ -219,7 +222,7 @@ def low_level_system_s_and_c_cost(symbol_flow, polytope_pattern):
         score += s_and_c_cost(s_and_c)
 
     elif len(s_and_c) == 2:
-        score += voice_leading_cost(s_and_c[0], s_and_c[1])
+        score += score_relation_switcher(relation_type, s_and_c[0], s_and_c[1])
     
     elif len(s_and_c) != 0:
         raise err.PatternToDebugError("Pattern resulting in {}-element S&C, to debug ({})".format(len(s_and_c), str(polytope_pattern)))
@@ -227,133 +230,134 @@ def low_level_system_s_and_c_cost(symbol_flow, polytope_pattern):
     return score
     
 def dim_two_extended_s_and_c_cost(symbol_flow, polytope_pattern):
-    """
-    Compute the cost of a low-level system (dimension 2 polytope), but in a new paradigm.
+    raise err.OutdatedBehaviorException("Extended S&C cost isn't supported anymore.")
+#     """
+#     Compute the cost of a low-level system (dimension 2 polytope), but in a new paradigm.
     
-    This cost function is not promising enough, so it's kind of left here for posterity.
-    TODO: maybe delete it (at least think about it)
-
-    Parameters
-    ----------
-    symbol_flow : list of Chord, in any form
-        The segment, on which to compute the score.
-    polytope_pattern : nested list of 1
-        The pattern of oness corresponding to the polytope on which to compute the score.
-
-    Raises
-    ------
-    PatternAndSequenceIncompatible
-        Error raised when the pattern and the sequence are of different sizes.
-
-    Returns
-    -------
-    integer (but could be float with other cost functions)
-        Cost of this low-level system (dimension 2 polytope).
-
-    """
-    # Computing the cost of a dim 2 polytopes in the extended s&c scheme.
-    pattern_size = pf.get_pattern_size(polytope_pattern)
-    if len(symbol_flow) != pattern_size:
-        raise err.PatternAndSequenceIncompatible("The pattern's length is different than the the chord sequence's length, which make them incompatible.") from None
-    if pattern_size < 2:
-        raise err.UnexpectedDim1Pattern("Side effect (pattern of size 1), should it happen ?")
-    if pf.get_pattern_dimension(polytope_pattern) > 2:
-        raise err.UnexpectedDimensionForPattern("This pattern is of high dimension (higher than 2), can't compute a cost on it.")
-
-    if pattern_size == 2:
-        return voice_leading_cost(symbol_flow[0], symbol_flow[1])
+#     This cost function is not promising enough, so it's kind of left here for posterity.
+#     TODO: maybe delete it (at least think about it)
+
+#     Parameters
+#     ----------
+#     symbol_flow : list of Chord, in any form
+#         The segment, on which to compute the score.
+#     polytope_pattern : nested list of 1
+#         The pattern of oness corresponding to the polytope on which to compute the score.
+
+#     Raises
+#     ------
+#     PatternAndSequenceIncompatible
+#         Error raised when the pattern and the sequence are of different sizes.
+
+#     Returns
+#     -------
+#     integer (but could be float with other cost functions)
+#         Cost of this low-level system (dimension 2 polytope).
+
+#     """
+#     # Computing the cost of a dim 2 polytopes in the extended s&c scheme.
+#     pattern_size = pf.get_pattern_size(polytope_pattern)
+#     if len(symbol_flow) != pattern_size:
+#         raise err.PatternAndSequenceIncompatible("The pattern's length is different than the the chord sequence's length, which make them incompatible.") from None
+#     if pattern_size < 2:
+#         raise err.UnexpectedDim1Pattern("Side effect (pattern of size 1), should it happen ?")
+#     if pf.get_pattern_dimension(polytope_pattern) > 2:
+#         raise err.UnexpectedDimensionForPattern("This pattern is of high dimension (higher than 2), can't compute a cost on it.")
+
+#     if pattern_size == 2:
+#         return voice_leading_cost(symbol_flow[0], symbol_flow[1])
     
-    if pf.get_pattern_dimension(polytope_pattern) != 2:
-        raise err.PatternToDebugError("Should be of dimension 2, but is {}" + str(polytope_pattern))
-
-    if pattern_size == 3:
-        if polytope_pattern == [[1,1],[1]]:
-            return voice_leading_cost(symbol_flow[0], symbol_flow[1]) + voice_leading_cost(symbol_flow[0], symbol_flow[2])
-        elif polytope_pattern == [[1,(1,1)]]:
-            f = mvt.triadic_mvt_chords(symbol_flow[0], symbol_flow[1])            
-            cost = voice_leading_cost(symbol_flow[0], symbol_flow[1])
-            fictive_element = mvt.apply_triadic_mvt(symbol_flow[1], f)
-            cost += voice_leading_cost(fictive_element, symbol_flow[2])
-            return cost
-        else:
-            raise err.PatternToDebugError("Uknonwn pattern: " + str(polytope_pattern))
-
-    if pattern_size == 4:
-        if polytope_pattern == [[1,1],[1,1]]:
-            return s_and_c_cost(symbol_flow)
-        elif polytope_pattern == [[1,(1,1)],[1]]:
-            f = mvt.triadic_mvt_chords(symbol_flow[0], symbol_flow[1])            
-            cost = voice_leading_cost(symbol_flow[0], symbol_flow[1])
-            fictive_element = mvt.apply_triadic_mvt(symbol_flow[1], f)
-            cost += voice_leading_cost(fictive_element, symbol_flow[2])
-            cost += voice_leading_cost(symbol_flow[0], symbol_flow[3])
-            return cost
-        elif polytope_pattern == [[1,1],[(1,1)]]:
-            g = mvt.triadic_mvt_chords(symbol_flow[0], symbol_flow[2])
-            cost = voice_leading_cost(symbol_flow[0], symbol_flow[1])
-            cost = voice_leading_cost(symbol_flow[0], symbol_flow[2])
-            fictive_element = mvt.apply_triadic_mvt(symbol_flow[2], g)
-            cost += voice_leading_cost(fictive_element, symbol_flow[3])
-            return cost
-        else:
-            raise err.PatternToDebugError("Uknonwn pattern: " + str(polytope_pattern))
-    if pattern_size == 5:
-        if polytope_pattern == [[1,1],[1,(1,1)]]:
-            cost = s_and_c_cost(symbol_flow[:4])
-            cost += voice_leading_cost(symbol_flow[3], symbol_flow[4])
-            return cost
-        else:
-            raise err.PatternToDebugError("Uknonwn pattern: " + str(polytope_pattern))
-    if pattern_size == 6:
-        if polytope_pattern == [[1,1],[(1,1),(1,1)]]:
-            cost = voice_leading_cost(symbol_flow[0], symbol_flow[1])
-            cost = voice_leading_cost(symbol_flow[0], symbol_flow[2])
-            f = mvt.triadic_mvt_chords(symbol_flow[0], symbol_flow[2])
-            first_fictive_element = mvt.apply_triadic_mvt(symbol_flow[2], f)
-            cost += voice_leading_cost(first_fictive_element, symbol_flow[3])
+#     if pf.get_pattern_dimension(polytope_pattern) != 2:
+#         raise err.PatternToDebugError("Should be of dimension 2, but is {}" + str(polytope_pattern))
+
+#     if pattern_size == 3:
+#         if polytope_pattern == [[1,1],[1]]:
+#             return voice_leading_cost(symbol_flow[0], symbol_flow[1]) + voice_leading_cost(symbol_flow[0], symbol_flow[2])
+#         elif polytope_pattern == [[1,(1,1)]]:
+#             f = mvt.triadic_mvt_chords(symbol_flow[0], symbol_flow[1])            
+#             cost = voice_leading_cost(symbol_flow[0], symbol_flow[1])
+#             fictive_element = mvt.apply_triadic_mvt(symbol_flow[1], f)
+#             cost += voice_leading_cost(fictive_element, symbol_flow[2])
+#             return cost
+#         else:
+#             raise err.PatternToDebugError("Uknonwn pattern: " + str(polytope_pattern))
+
+#     if pattern_size == 4:
+#         if polytope_pattern == [[1,1],[1,1]]:
+#             return s_and_c_cost(symbol_flow)
+#         elif polytope_pattern == [[1,(1,1)],[1]]:
+#             f = mvt.triadic_mvt_chords(symbol_flow[0], symbol_flow[1])            
+#             cost = voice_leading_cost(symbol_flow[0], symbol_flow[1])
+#             fictive_element = mvt.apply_triadic_mvt(symbol_flow[1], f)
+#             cost += voice_leading_cost(fictive_element, symbol_flow[2])
+#             cost += voice_leading_cost(symbol_flow[0], symbol_flow[3])
+#             return cost
+#         elif polytope_pattern == [[1,1],[(1,1)]]:
+#             g = mvt.triadic_mvt_chords(symbol_flow[0], symbol_flow[2])
+#             cost = voice_leading_cost(symbol_flow[0], symbol_flow[1])
+#             cost = voice_leading_cost(symbol_flow[0], symbol_flow[2])
+#             fictive_element = mvt.apply_triadic_mvt(symbol_flow[2], g)
+#             cost += voice_leading_cost(fictive_element, symbol_flow[3])
+#             return cost
+#         else:
+#             raise err.PatternToDebugError("Uknonwn pattern: " + str(polytope_pattern))
+#     if pattern_size == 5:
+#         if polytope_pattern == [[1,1],[1,(1,1)]]:
+#             cost = s_and_c_cost(symbol_flow[:4])
+#             cost += voice_leading_cost(symbol_flow[3], symbol_flow[4])
+#             return cost
+#         else:
+#             raise err.PatternToDebugError("Uknonwn pattern: " + str(polytope_pattern))
+#     if pattern_size == 6:
+#         if polytope_pattern == [[1,1],[(1,1),(1,1)]]:
+#             cost = voice_leading_cost(symbol_flow[0], symbol_flow[1])
+#             cost = voice_leading_cost(symbol_flow[0], symbol_flow[2])
+#             f = mvt.triadic_mvt_chords(symbol_flow[0], symbol_flow[2])
+#             first_fictive_element = mvt.apply_triadic_mvt(symbol_flow[2], f)
+#             cost += voice_leading_cost(first_fictive_element, symbol_flow[3])
             
-            snd_fictive_element = mvt.apply_triadic_mvt(symbol_flow[1], f)
-            cost += voice_leading_cost(snd_fictive_element, symbol_flow[4])
+#             snd_fictive_element = mvt.apply_triadic_mvt(symbol_flow[1], f)
+#             cost += voice_leading_cost(snd_fictive_element, symbol_flow[4])
             
-            trd_fictive_element = mvt.apply_triadic_mvt(symbol_flow[4], f)
-            cost += voice_leading_cost(trd_fictive_element, symbol_flow[5])
-            return cost
-
-        elif polytope_pattern == [[1,(1,1)],[1,(1,1)]]:
-            f = mvt.triadic_mvt_chords(symbol_flow[0], symbol_flow[1])
-            cost = voice_leading_cost(symbol_flow[0], symbol_flow[1])
-            first_fictive_element = mvt.apply_triadic_mvt(symbol_flow[1], f)
-            cost += voice_leading_cost(first_fictive_element, symbol_flow[2])
+#             trd_fictive_element = mvt.apply_triadic_mvt(symbol_flow[4], f)
+#             cost += voice_leading_cost(trd_fictive_element, symbol_flow[5])
+#             return cost
+
+#         elif polytope_pattern == [[1,(1,1)],[1,(1,1)]]:
+#             f = mvt.triadic_mvt_chords(symbol_flow[0], symbol_flow[1])
+#             cost = voice_leading_cost(symbol_flow[0], symbol_flow[1])
+#             first_fictive_element = mvt.apply_triadic_mvt(symbol_flow[1], f)
+#             cost += voice_leading_cost(first_fictive_element, symbol_flow[2])
             
-            cost = voice_leading_cost(symbol_flow[0], symbol_flow[3])
-            snd_fictive_element = mvt.apply_triadic_mvt(symbol_flow[3], f)
-            cost += voice_leading_cost(snd_fictive_element, symbol_flow[4])
+#             cost = voice_leading_cost(symbol_flow[0], symbol_flow[3])
+#             snd_fictive_element = mvt.apply_triadic_mvt(symbol_flow[3], f)
+#             cost += voice_leading_cost(snd_fictive_element, symbol_flow[4])
             
-            trd_fictive_element = mvt.apply_triadic_mvt(symbol_flow[4], f)
-            cost += voice_leading_cost(trd_fictive_element, symbol_flow[5])
-            return cost
+#             trd_fictive_element = mvt.apply_triadic_mvt(symbol_flow[4], f)
+#             cost += voice_leading_cost(trd_fictive_element, symbol_flow[5])
+#             return cost
         
-        elif polytope_pattern == [[(1,1),(1,1)],[(1,1)]]:
-            f = mvt.triadic_mvt_chords(symbol_flow[0], symbol_flow[1])
-            cost = voice_leading_cost(symbol_flow[0], symbol_flow[1])
-            cost = voice_leading_cost(symbol_flow[0], symbol_flow[2])
-            first_fictive_element = mvt.apply_triadic_mvt(symbol_flow[2], f)
-            cost += voice_leading_cost(first_fictive_element, symbol_flow[3])
+#         elif polytope_pattern == [[(1,1),(1,1)],[(1,1)]]:
+#             f = mvt.triadic_mvt_chords(symbol_flow[0], symbol_flow[1])
+#             cost = voice_leading_cost(symbol_flow[0], symbol_flow[1])
+#             cost = voice_leading_cost(symbol_flow[0], symbol_flow[2])
+#             first_fictive_element = mvt.apply_triadic_mvt(symbol_flow[2], f)
+#             cost += voice_leading_cost(first_fictive_element, symbol_flow[3])
             
-            cost = voice_leading_cost(symbol_flow[0], symbol_flow[4])
-            snd_fictive_element = mvt.apply_triadic_mvt(symbol_flow[4], f)
-            cost += voice_leading_cost(snd_fictive_element, symbol_flow[5])
-            return cost
-        else:
-            raise err.PatternToDebugError("Uknonwn pattern: " + str(polytope_pattern))
-    if pattern_size == 8:
-        return polytopic_scale_s_and_c_cost_computation(symbol_flow, pf.make_regular_polytope_pattern(3))
-    else:
-        raise err.PatternToDebugError("Uknonwn pattern size: " + str(polytope_pattern))
+#             cost = voice_leading_cost(symbol_flow[0], symbol_flow[4])
+#             snd_fictive_element = mvt.apply_triadic_mvt(symbol_flow[4], f)
+#             cost += voice_leading_cost(snd_fictive_element, symbol_flow[5])
+#             return cost
+#         else:
+#             raise err.PatternToDebugError("Uknonwn pattern: " + str(polytope_pattern))
+#     if pattern_size == 8:
+#         return polytopic_scale_s_and_c_cost_computation(symbol_flow, pf.make_regular_polytope_pattern(3))
+#     else:
+#         raise err.PatternToDebugError("Uknonwn pattern size: " + str(polytope_pattern))
 
 # %% System and contrast definition
 # Triadic optimization of a System and Contrast
-def s_and_c_cost(four_chords, measure = mvt.l1_norm, chromatic = True):
+def s_and_c_cost(four_chords, relation_type = "triad_circle"):
     """
     Compute the cost of these four chords in the System and Cotnrast paradigm, with the cost function for relation defined in 'measure'.
     
@@ -375,52 +379,52 @@ def s_and_c_cost(four_chords, measure = mvt.l1_norm, chromatic = True):
     cost : integer 
         the cost of this S&C.
     """
-    cost = voice_leading_cost(four_chords[0], four_chords[1], triadic = True, measure = measure, chromatic = chromatic)
-    cost += voice_leading_cost(four_chords[0], four_chords[2], triadic = True, measure = measure, chromatic = chromatic)
-    rel = mvt.triadic_mvt_chords(four_chords[0], four_chords[1])
-    fictive_element = mvt.apply_triadic_mvt(four_chords[2], rel)
-    cost += voice_leading_cost(fictive_element, four_chords[3], triadic = True, measure = measure, chromatic = chromatic)
+    cost = score_relation_switcher(relation_type, four_chords[0], four_chords[1])
+    cost += score_relation_switcher(relation_type,four_chords[0], four_chords[2])
+    rel = find_relation_switcher(relation_type,four_chords[0], four_chords[1])
+    fictive_element = apply_relation_switcher(relation_type,four_chords[2], rel)
+    cost += score_relation_switcher(relation_type,fictive_element, four_chords[3])
     return cost
 
 # Cost function between two chords
-def voice_leading_cost(first_chord, second_chord, measure = mvt.l1_norm, triadic = False, fifth = False, chromatic = True):
-    """
-    Compute the score/cost associated with a voice leading movement between two chords.
+# def voice_leading_cost(first_chord, second_chord, measure = mvt.l1_norm, triadic = False, fifth = False, chromatic = True):
+#     """
+#     Compute the score/cost associated with a voice leading movement between two chords.
     
-    Parameters
-    ----------
-    first_chord, second_chord: Chord objects
-        The chords between which the voice leading is to compute.
-    measure: function of mvt
-        The norm of the relation vector, defining the distance
-        (implemented: l1, l2 and infinite norm).
-        Default: l1_norm
-    triadic: boolean
-        If True, the movement between the chords is computed as a rotation in the circle of triads.
-        If False, the movement is computed in the optimal transport paradigm.
-        Default: False
-    fifth: boolean
-        Only useful if triadic is set to False.
-        If True, the transport between 2 notes is computed as a movement in the circle of fifth,
-        If False, the transport is the difference of the numbers of the notes (second - first).
-        # NB: Optimal transport is not used anymore
-        Default: False.
-    chromatic: boolean
-        Only useful if triadic is set to True.
-        If True, the chords in the circle of triads are ordered in the chromatic order,
-        If False, the chords in the circle of triads are ordered in the 3-5 Torus order.
-        Default: True
+#     Parameters
+#     ----------
+#     first_chord, second_chord: Chord objects
+#         The chords between which the voice leading is to compute.
+#     measure: function of mvt
+#         The norm of the relation vector, defining the distance
+#         (implemented: l1, l2 and infinite norm).
+#         Default: l1_norm
+#     triadic: boolean
+#         If True, the movement between the chords is computed as a rotation in the circle of triads.
+#         If False, the movement is computed in the optimal transport paradigm.
+#         Default: False
+#     fifth: boolean
+#         Only useful if triadic is set to False.
+#         If True, the transport between 2 notes is computed as a movement in the circle of fifth,
+#         If False, the transport is the difference of the numbers of the notes (second - first).
+#         # NB: Optimal transport is not used anymore
+#         Default: False.
+#     chromatic: boolean
+#         Only useful if triadic is set to True.
+#         If True, the chords in the circle of triads are ordered in the chromatic order,
+#         If False, the chords in the circle of triads are ordered in the 3-5 Torus order.
+#         Default: True
         
-    Returns
-    -------
-    integer: 
-        the cost of the voice leading.
+#     Returns
+#     -------
+#     integer: 
+#         the cost of the voice leading.
             
-    """
-    return measure(mvt.triadic_mvt_chords(first_chord, second_chord, chromatic = chromatic))
+#     """
+#     return measure(mvt.triadic_mvt_chords(first_chord, second_chord, chromatic = chromatic))
 
 
-def best_louboutin_cost_segment(segment, irregularity_penalty = 0, target_size = 32, segment_size_penalty = 0):
+def best_louboutin_cost_segment(segment, irregularity_penalty = 0, target_size = 32, segment_size_penalty = 0, relation_type = "triad_circle"):
     """
     Compute the optimal cost in the C. Guichaoua's paradigm, for this chord_sequence, among all possible patterns.
     
@@ -459,7 +463,7 @@ def best_louboutin_cost_segment(segment, irregularity_penalty = 0, target_size =
     for a_pattern in this_bag:
         this_polytope_cost = math.inf
         for i in range(len(a_pattern[0])):
-            this_ppp_cost = louboutin_cost_for_a_ppp(segment, a_pattern[0][i], a_pattern[3][i], a_pattern[4][i], current_min = this_segment_cost)
+            this_ppp_cost = louboutin_cost_for_a_ppp(segment, a_pattern[0][i], a_pattern[3][i], a_pattern[4][i], current_min = this_segment_cost, relation_type = relation_type)
             if this_ppp_cost < this_polytope_cost:
                 this_polytope_cost = this_ppp_cost
                 best_ppp = a_pattern[0][i]
@@ -474,7 +478,7 @@ def best_louboutin_cost_segment(segment, irregularity_penalty = 0, target_size =
     return this_segment_cost, best_pattern
 
 # %% Guichaoua paradigm
-def guichaoua_cost(chord_sequence, indexed_pattern, antecedents_with_pivots, successors, correct_antecedents, current_min = math.inf):
+def guichaoua_cost(chord_sequence, indexed_pattern, antecedents_with_pivots, successors, correct_antecedents, current_min = math.inf, relation_type = "triad_circle"):
     """
     Compute the cost in the C. Guichaoua's paradigm, for this chord_sequence and this 'indexed_pattern'.
     
@@ -532,8 +536,8 @@ def guichaoua_cost(chord_sequence, indexed_pattern, antecedents_with_pivots, suc
                 found = False
                 for ant, piv in this_elt_ant:
                     if ant in correct_antecedents[elt]:
-                        rel = mvt.triadic_mvt_chords(chord_sequence[0], chord_sequence[ant])
-                        if rel == mvt.triadic_mvt_chords(chord_sequence[piv], chord_sequence[elt]):
+                        rel = find_relation_switcher(relation_type, chord_sequence[0], chord_sequence[ant])
+                        if rel == find_relation_switcher(relation_type, chord_sequence[piv], chord_sequence[elt]):
                             found = True
                 if not found:
                     score += 1
@@ -544,7 +548,7 @@ def guichaoua_cost(chord_sequence, indexed_pattern, antecedents_with_pivots, suc
 
     return score
 
-def guichaoua_cost_global_antecedents_successors(chord_sequence, indexed_pattern, antecedents_with_pivots, successors, correct_antecedents, current_min = math.inf):
+def guichaoua_cost_global_antecedents_successors(chord_sequence, indexed_pattern, antecedents_with_pivots, successors, correct_antecedents, current_min = math.inf, relation_type = "triad_circle"):
     """
     Compute the cost in the C. Guichaoua's paradigm, but with antecedents as "global" and not just the ones linked to the element by a direct arrow (original behavior from my point of view).
     
@@ -626,8 +630,8 @@ def guichaoua_cost_global_antecedents_successors(chord_sequence, indexed_pattern
                 found = False
                 for ant, piv in this_elt_ant:
                     if ant in correct_antecedents[elt]:
-                        rel = mvt.triadic_mvt_chords(chord_sequence[0], chord_sequence[ant])
-                        if rel == mvt.triadic_mvt_chords(chord_sequence[piv], chord_sequence[elt]):
+                        rel = find_relation_switcher(relation_type,chord_sequence[0], chord_sequence[ant])
+                        if rel == find_relation_switcher(relation_type,chord_sequence[piv], chord_sequence[elt]):
                             found = True
                 if not found:
                     score += 1
@@ -710,7 +714,7 @@ def best_guichaoua_cost_segment(segment, positive_penalty = 0, negative_penalty
     return this_segment_cost, best_pattern
 
 # %% New paradigms, developed by A. Marmoret
-def louboutaoua_cost(chord_sequence, indexed_pattern, antecedents_with_pivots, successors, correct_antecedents, direct_antecedents, current_min = math.inf):
+def louboutaoua_cost(chord_sequence, indexed_pattern, antecedents_with_pivots, successors, correct_antecedents, direct_antecedents, current_min = math.inf, relation_type = "triad_circle"):
     """
     Louboutaoua cost (name still pending). Need a reference to be explained.
 
@@ -758,17 +762,17 @@ def louboutaoua_cost(chord_sequence, indexed_pattern, antecedents_with_pivots, s
             raise err.PatternToDebugError("Element with no antecedent: {} in {}. This shouldn't happen a priori.".format(elt, indexed_pattern))
         elif (0,0) in this_elt_ant:
             if chord_sequence[0] != chord_sequence[elt]:
-                score += voice_leading_cost(chord_sequence[0], chord_sequence[elt])
+                score += score_relation_switcher(relation_type, chord_sequence[0], chord_sequence[elt])
         else:
             # If this element doesn't hold valid predecessors.
             if correct_antecedents[elt] == []:
                 direct_ant = direct_antecedents[elt]
                 if type(direct_ant) is tuple: # Antecedent is a fictive element, to construct
-                    f = mvt.triadic_mvt_chords(chord_sequence[direct_ant[0]], chord_sequence[direct_ant[1]])            
-                    fictive_element = mvt.apply_triadic_mvt(chord_sequence[direct_ant[2]], f)
-                    score += voice_leading_cost(fictive_element, chord_sequence[elt])
+                    f = find_relation_switcher(relation_type,chord_sequence[direct_ant[0]], chord_sequence[direct_ant[1]])            
+                    fictive_element = apply_relation_switcher(relation_type,chord_sequence[direct_ant[2]], f)
+                    score += score_relation_switcher(relation_type, fictive_element, chord_sequence[elt])
                 else:
-                    score += voice_leading_cost(chord_sequence[direct_ant], chord_sequence[elt])
+                    score += score_relation_switcher(relation_type,chord_sequence[direct_ant], chord_sequence[elt])
 
                 # Update the correct antecedents of this element' successors
                 for this_elt_successor in successors[elt]:
@@ -780,31 +784,129 @@ def louboutaoua_cost(chord_sequence, indexed_pattern, antecedents_with_pivots, s
                 contrasts = []
                 for ant, piv in this_elt_ant:
                     if ant in correct_antecedents[elt]:
-                        rel = mvt.triadic_mvt_chords(chord_sequence[0], chord_sequence[ant])
-                        fictive = mvt.apply_triadic_mvt(chord_sequence[piv], rel)
-                        gamma = mvt.triadic_mvt_chords(fictive, chord_sequence[elt])
+                        rel = find_relation_switcher(relation_type,chord_sequence[0], chord_sequence[ant])
+                        fictive = apply_relation_switcher(relation_type,chord_sequence[piv], rel)
+                        gamma = find_relation_switcher(relation_type,fictive, chord_sequence[elt])
                         if gamma == 0:
                             found = True
                         else:
                             contrasts.append(gamma)
                 if not found:
                     if len(np.unique(contrasts)) == 1:
-                        score += mvt.l1_norm(contrasts[0])
+                        score += abs(contrasts[0])
                     else:
                         direct_ant = direct_antecedents[elt]
                         if type(direct_ant) is tuple: # Antecedent is a fictive element, to construct
-                            f = mvt.triadic_mvt_chords(chord_sequence[direct_ant[0]], chord_sequence[direct_ant[1]])            
-                            fictive_element = mvt.apply_triadic_mvt(chord_sequence[direct_ant[2]], f)
-                            score += voice_leading_cost(fictive_element, chord_sequence[elt])
+                            f = find_relation_switcher(relation_type,chord_sequence[direct_ant[0]], chord_sequence[direct_ant[1]])            
+                            fictive_element = apply_relation_switcher(relation_type,chord_sequence[direct_ant[2]], f)
+                            score += score_relation_switcher(relation_type,fictive_element, chord_sequence[elt])
                         else:
-                            score += voice_leading_cost(chord_sequence[direct_ant], chord_sequence[elt])
+                            score += score_relation_switcher(relation_type,chord_sequence[direct_ant], chord_sequence[elt])
                     # Update the correct antecedents of this element' successors
                     for this_elt_successor in successors[elt]:
                         correct_antecedents[this_elt_successor] = sh.update_correct_antecedents(elt, antecedents_with_pivots[this_elt_successor], correct_antecedents[this_elt_successor])
 
     return score
 
-def cohen_marmoret_cost(chord_sequence, indexed_pattern, antecedents_with_pivots, current_min = math.inf):
+# def cohen_marmoret_cost(chord_sequence, indexed_pattern, antecedents_with_pivots, current_min = math.inf, relation_type = "triad_circle"):
+#     """
+#     Cohen-Marmoret cost (name still pending). Need a reference to be explained.
+
+#     Parameters
+#     ----------
+#     chord_sequence : list of Chords, in any form
+#         The chord sequence.
+#     indexed_pattern : nested list of integers
+#         The indexed pattern, to compute score on.
+#     antecedents_with_pivots : list of list of tuples (integer, integer)
+#         Antedents with their pivots, for each element.
+#         Given as arguments so as they can be computed once and then feeded when needed in the function (when segmenting a song).
+#         It's an acceleration technique.
+#     current_min : integer, optional
+#         The current minimal cost.
+#         It's an acceleration parameter, to check that the current cost we're computing' isn't already higher than the current minimal value.
+#         If it's the case, this ppp won't be chosen, so we don't need an exact score, and it returns math.inf.
+#         The default is math.inf.
+
+#     Raises
+#     ------
+#     PatternToDebugError
+#         Error raised when an element has no antecedent (which is not normal behavior).
+
+#     Returns
+#     -------
+#     score : integer
+#         Cost of this sequence on this pattern in the Cohen-Marmoret's paradigm.
+
+#     """
+#     print("Should pass through this cost function again, because contrast are all scores now (and not functions). See if it breaks sthg")
+#     score = 1
+#     contrasts = [None for i in range(pf.get_pattern_size(indexed_pattern))]
+#     for elt in range(1, pf.get_pattern_size(indexed_pattern)):
+#         if score > current_min:
+#             return math.inf
+#         this_elt_ant = antecedents_with_pivots[elt]
+#         if len(this_elt_ant) == 2 and (this_elt_ant[0][0], this_elt_ant[0][1]) == (this_elt_ant[1][1], this_elt_ant[1][0]):
+#             this_elt_ant = [this_elt_ant[0]]
+#         if this_elt_ant == []:
+#             raise err.PatternToDebugError("Element with no antecedent: {} in {}. This shouldn't happen a priori.".format(elt, indexed_pattern))
+#         elif (0,0) in this_elt_ant:
+#             if chord_sequence[0] != chord_sequence[elt]:
+#                 score += score_relation_switcher(relation_type, chord_sequence[0], chord_sequence[elt])
+#         else:
+#             # Searching for a valid implication of the current element.
+#             if len(this_elt_ant) == 1:
+#                 ant, piv = this_elt_ant[0]
+#                 rel = find_relation_switcher(relation_type,chord_sequence[0], chord_sequence[ant])
+#                 fictive = apply_relation_switcher(relation_type,chord_sequence[piv], rel)
+#                 #contrast = find_relation_switcher(relation_type, fictive, chord_sequence[elt])
+#                 contrast_score = score_relation_switcher(relation_type,fictive, chord_sequence[elt])
+
+#             elif len(this_elt_ant) == 0:
+#                 raise err.PatternToDebugError("Element with no antecedent: {}, antecedents and pivots for it: {} in {}. This shouldn't happen a priori.".format(elt, this_elt_ant, indexed_pattern))
+#             else:
+#                 contrasts_of_ants = []
+#                 possible_fictive = []
+#                 for ant, piv in this_elt_ant:
+#                     if contrasts[ant] == None:
+#                         raise err.PatternToDebugError("Contrast for the element: {}, hasn't been computed when looping for element: {} in {}. This shouldn't happen a priori.".format(ant, elt, indexed_pattern))
+#                     else:
+#                         contrasts_of_ants.append(contrasts[ant])
+#                         rel = find_relation_switcher(relation_type, chord_sequence[0], chord_sequence[ant])
+#                         fictive = apply_relation_switcher(relation_type, chord_sequence[piv], rel)
+#                         possible_fictive.append(fictive)
+
+#                 if len(np.unique(possible_fictive)) == 1: # No ambiguity
+#                     #contrast = find_relation_switcher(relation_type,possible_fictive[0], chord_sequence[elt])
+#                     contrast_score = score_relation_switcher(relation_type,possible_fictive[0], chord_sequence[elt])
+#                 else:
+#                     the_max = -1
+#                     maximal_contrastic_ants = None
+#                     for idx in range(len(contrasts_of_ants)): # Looping among the antecedents of our current element, and searching for the maximally contrastic one. If they are several, we will evaluate them all.
+#                         absolute_val_contrast = contrasts_of_ants[idx] # Adding a score now, so it will always be positive
+#                         if absolute_val_contrast > the_max: # Higher contrast than the previous ones.
+#                             the_max = absolute_val_contrast
+#                             maximal_contrastic_ants = [idx]
+#                         elif absolute_val_contrast == the_max: # Contrast equal to the max, to evaluate.
+#                             maximal_contrastic_ants.append(idx)
+                            
+#                     min_contrast_score_among_valids = math.inf
+#                     for ant in maximal_contrastic_ants: # Happens that all contrasts are equal, but that they result in different fictive. In that case, we keep the minimal contrast.
+#                         #current_contrast = find_relation_switcher(relation_type, possible_fictive[ant], chord_sequence[elt])
+#                         current_contrast_score = score_relation_switcher(relation_type, possible_fictive[ant], chord_sequence[elt])
+#                         if current_contrast_score < min_contrast_score_among_valids:
+#                             min_contrast_score_among_valids = current_contrast_score
+#                             #min_contrast_among_valids = current_contrast
+#                     if min_contrast_score_among_valids == math.inf:
+#                         raise err.ToDebugException("Infinite contrast.")
+#                     contrast_score = min_contrast_score_among_valids
+                    
+#             contrasts[elt] = contrast_score
+#             score += contrast_score
+
+#     return score
+    
+def cohen_marmoret_cost(chord_sequence, indexed_pattern, antecedents_with_pivots, current_min = math.inf, relation_type = "triad_circle"):
     """
     Cohen-Marmoret cost (name still pending). Need a reference to be explained.
 
@@ -846,19 +948,24 @@ def cohen_marmoret_cost(chord_sequence, indexed_pattern, antecedents_with_pivots
         if this_elt_ant == []:
             raise err.PatternToDebugError("Element with no antecedent: {} in {}. This shouldn't happen a priori.".format(elt, indexed_pattern))
         elif (0,0) in this_elt_ant:
+            #print("la")
             if chord_sequence[0] != chord_sequence[elt]:
-                score += voice_leading_cost(chord_sequence[0], chord_sequence[elt])
+                score += score_relation_switcher(relation_type, chord_sequence[0], chord_sequence[elt])
         else:
+            #print("lab")
             # Searching for a valid implication of the current element.
             if len(this_elt_ant) == 1:
+                #print("1ant")
                 ant, piv = this_elt_ant[0]
-                rel = mvt.triadic_mvt_chords(chord_sequence[0], chord_sequence[ant])
-                fictive = mvt.apply_triadic_mvt(chord_sequence[piv], rel)
-                contrast = mvt.triadic_mvt_chords(fictive, chord_sequence[elt])
+                rel = find_relation_switcher(relation_type, chord_sequence[0], chord_sequence[ant])
+                fictive = apply_relation_switcher(relation_type, chord_sequence[piv], rel)
+                contrast = find_relation_switcher(relation_type, fictive, chord_sequence[elt])
 
             elif len(this_elt_ant) == 0:
                 raise err.PatternToDebugError("Element with no antecedent: {}, antecedents and pivots for it: {} in {}. This shouldn't happen a priori.".format(elt, this_elt_ant, indexed_pattern))
             else:
+                #print("Several ant")
+
                 contrasts_of_ants = []
                 possible_fictive = []
                 for ant, piv in this_elt_ant:
@@ -866,38 +973,100 @@ def cohen_marmoret_cost(chord_sequence, indexed_pattern, antecedents_with_pivots
                         raise err.PatternToDebugError("Contrast for the element: {}, hasn't been computed when looping for element: {} in {}. This shouldn't happen a priori.".format(ant, elt, indexed_pattern))
                     else:
                         contrasts_of_ants.append(contrasts[ant])
-                        rel = mvt.triadic_mvt_chords(chord_sequence[0], chord_sequence[ant])
-                        fictive = mvt.apply_triadic_mvt(chord_sequence[piv], rel)
+                        rel = find_relation_switcher(relation_type, chord_sequence[0], chord_sequence[ant])
+                        fictive = apply_relation_switcher(relation_type, chord_sequence[piv], rel)
                         possible_fictive.append(fictive)
 
                 if len(np.unique(possible_fictive)) == 1: # No ambiguity
-                    contrast = mvt.triadic_mvt_chords(possible_fictive[0], chord_sequence[elt])
+                    #print("No amb")
+
+                    contrast = find_relation_switcher(relation_type, possible_fictive[0], chord_sequence[elt])
                 else:
                     the_max = -1
                     maximal_contrastic_ants = None
                     for idx in range(len(contrasts_of_ants)): # Looping among the antecedents of our current element, and searching for the maximally contrastic one. If they are several, we will evaluate them all.
-                        absolute_val_contrast = mvt.l1_norm(contrasts_of_ants[idx])
-                        if absolute_val_contrast > the_max: # Higher contrast than the previous ones.
-                            the_max = absolute_val_contrast
+                        #print("La la ouais")
+
+                        score_contrast = score_one_relation_switcher(relation_type, contrasts_of_ants[idx])
+                        if score_contrast > the_max: # Higher contrast than the previous ones.
+                            the_max = score_contrast
                             maximal_contrastic_ants = [idx]
-                        elif absolute_val_contrast == the_max: # Contrast equal to the max, to evaluate.
+                        elif score_contrast == the_max: # Contrast equal to the max, to evaluate.
                             maximal_contrastic_ants.append(idx)
                             
-                    min_contrast_among_valids = 13 # Careful: if the norm changes, this bounds has too!!!
+                    min_contrast_among_valids = math.inf # Careful: if the norm changes, this bounds has too!!!
                     for ant in maximal_contrastic_ants: # Happens that all contrasts are equal, but that they result in different fictive. In that case, we keep the minimal contrast.
-                        current_contrast = mvt.triadic_mvt_chords(possible_fictive[ant], chord_sequence[elt])
-                        if mvt.l1_norm(current_contrast) < mvt.l1_norm(min_contrast_among_valids):
+                        #print("Raise marche pas")
+
+                        current_contrast = find_relation_switcher(relation_type, possible_fictive[ant], chord_sequence[elt])
+                        if score_one_relation_switcher(relation_type, current_contrast) < score_one_relation_switcher(relation_type, min_contrast_among_valids):
                             min_contrast_among_valids = current_contrast
+                    if min_contrast_among_valids == math.inf:
+                        raise NotImplementedError("Infinite contrast")
                     contrast = min_contrast_among_valids
                     
             contrasts[elt] = contrast
-            score += mvt.l1_norm(contrast)
+            score += score_one_relation_switcher(relation_type, contrast)
 
     return score
 
 
+# %% Relation system
+def find_relation_switcher(relation_type, chord_1, chord_2):
+    if relation_type == "triad_circle":
+        return tt.triadic_mvt_triads(chord_1, chord_2)
+    elif relation_type == "chromatic_circle":
+        return acc_pc.accelerated_chromatic_mvt_triads(chord_1, chord_2)
+    elif relation_type == "3_5_torus":
+        return tt.three_five_torus_mvt_triads(chord_1, chord_2)
+    elif relation_type == "tonnetz":
+        return acc_pc.accelerated_triadic_tonnetz_relation_symbol(chord_1, chord_2)
+    elif relation_type == "voice_leading":
+        return acc_pc.accelerated_get_voice_leading_transformation_symbol(chord_1, chord_2)
+    else:
+        raise err.InvalidArgumentValueException(f"Invalid relation_type: {relation_type}")
+    
+def apply_relation_switcher(relation_type, chord_1, relation):
+    if relation_type == "triad_circle":
+        return tt.apply_triadic_mvt(chord_1, relation)
+    elif relation_type == "tonnetz":
+        return acc_pc.accelerated_apply_triadic_tonnetz_relation_symbol(chord_1, relation)
+    elif relation_type == "voice_leading":
+        raise NotImplementedError("TODO")
+    else:
+        raise err.InvalidArgumentValueException(f"Invalid relation_type: {relation_type}")
+        
+def score_relation_switcher(relation_type, chord_1, chord_2):
+    if relation_type == "triad_circle":
+        return abs(tt.triadic_mvt_triads(chord_1, chord_2))
+    elif relation_type == "chromatic_circle":
+        return abs(tt.chromatic_mvt_triads(chord_1, chord_2))
+    elif relation_type == "3_5_torus":
+        return abs(tt.three_five_torus_mvt_triads(chord_1, chord_2))
+    elif relation_type == "tonnetz":
+        return acc_pc.accelerated_triadic_tonnetz_distance_symbol(chord_1, chord_2)
+    elif relation_type == "voice_leading":
+        return tt.get_voice_leading_distance_symbol(chord_1, chord_2)
+        raise NotImplementedError("TODO")
+    else:
+        raise err.InvalidArgumentValueException(f"Invalid relation_type: {relation_type}")
+        
+def score_one_relation_switcher(relation_type, rel):
+    if rel == math.inf:
+        return math.inf
+    if relation_type == "triad_circle":
+        return abs(rel)
+    elif relation_type == "tonnetz":
+        if rel == 0:
+            return 0
+        return len(rel)
+    elif relation_type == "voice_leading":
+        raise NotImplementedError("TODO")
+    else:
+        raise err.InvalidArgumentValueException(f"Invalid relation_type: {relation_type}")
+
 # %% Sequential score
-def sequential_score(chord_flow, penalty):
+def sequential_score(chord_flow, penalty, relation_type = "triad_circle"):
     """
     Sequential score for this sequence (score where relations are taken in the chronological order, useful as a baseline).
 
@@ -916,7 +1085,7 @@ def sequential_score(chord_flow, penalty):
     """
     score = 0
     for two_chords in zip(chord_flow[:-1], chord_flow[1:]):
-        score += voice_leading_cost(two_chords[0], two_chords[1])
+        score += score_relation_switcher(relation_type, two_chords[0], two_chords[1])
     return score + penalty
 
 # %% Penalties form irregularities in polytopes
diff --git a/polytopes/segmentation_algorithms.py b/MusicOnPolytopes/segmentation_algorithms.py
similarity index 77%
rename from polytopes/segmentation_algorithms.py
rename to MusicOnPolytopes/segmentation_algorithms.py
index 3261efcaf3b82ab0c94953b8acc99cf2713f0ecd..6d728a4abd56bde32d5b853f5d18578d389234cd 100644
--- a/polytopes/segmentation_algorithms.py
+++ b/MusicOnPolytopes/segmentation_algorithms.py
@@ -5,13 +5,13 @@ Created on Thu Jan 21 15:14:22 2021
 @author: amarmore
 """
 import math
+import time
 import warnings
 
 from polytopes.model.chord import Chord
 import polytopes.data_manipulation as dm
 import polytopes.polytopical_costs as pc
 import polytopes.pattern_factory as pf
-
 import polytopes.model.errors as err
 import polytopes.segmentation_helper as sh
 import numpy as np
@@ -24,11 +24,11 @@ TODO: when the code is stable, I should keep only one dynamic programming algori
 
 CURR_DIR = os.path.dirname(os.path.realpath(__file__))
 
-# %% Costs developed by A. Marmoret
-### 1st cost: Louboutaoua
-def dynamic_minimization_louboutaoua(chord_sequence, min_size = 8, max_size = 40, segment_size_penalty = 1, irregularity_penalty = 1, target_size = 32, persist_patterns = True):
+# %% Costs with implication system
+## Guichaoua original cost
+def dynamic_minimization_guichaoua(chord_sequence, positive_penalty = 2.25, negative_penalty = 3, min_size = 8, max_size = 40, positive_segment_size_penalty = 0, negative_segment_size_penalty = 0.125, target_size = 32, global_antecedents = False, persist_patterns = True, relation_type = "triad_circle", song_for_persist = None):
     """
-    Dynamic programming algorithm applied to the search of the optimal segmentation of a piece of music, with Louboutaoua's cost.
+    Dynamic programming algorithm applied to the search of the optimal segmentation of a piece of music, with Guichaoua's cost.
     
     Given the costs of all possible segments in the piece (flow), it finds the segmentation which minimizes the gloabl sum of all segment costs.
     TODO: add a reference to explain this cost.
@@ -37,17 +37,24 @@ def dynamic_minimization_louboutaoua(chord_sequence, min_size = 8, max_size = 40
     ----------
     chord_sequence : list of chords, of any type
         The chord sequence (the song) to segment.
+    positive_penalty, negative_penalty : float/integer, optional
+        Penalty parameter related to irregularities of the polytope.
+        Positive corresponds to the penalty when the polytope contains addition, negative is for deletion.
+        They are constants and not function of the size of irregularities.
     min_size : integer, optional
         Minimal size for a segment (except the first one and the last one). The default is 8.
     max_size : integer, optional
         Maximal size for a segment. The default is 40.
-    segment_size_penalty : float/integer, optional
-        Penalty parameter to multiply to the raw penalty score for the size of the segment. The default is 1.
-    irregularity_penalty : float/integer, optional
-        Penalty parameter to multiply to the raw penalty score for the irregularities of the polytope. The default is 1.
+    positive_segment_size_penalty, negative_segment_size_penalty : float/integer, optional
+        Penalty parameter to multiply to the raw penalty score for the size of the segment.
+        positive_segment_size_penalty is the parameter when size exceeds 'target_size', negative is for size shorter than 'target_size'.
     target_size : integer, optional
         The optimal size, used for the penalty related to the segment size. 
         The default is 32.
+    global_antecedents : boolean, optional
+        A boolean to indicate whether antecedents should be the directs ones (i.e. the ones which are linked with an arrow to the actual element),
+        or global ones (i.e. antecedents where a path exists with the current element, like in Guichaoua's exact paradigm).
+        In my understanding of the model, direct antecedents should be considered as the default behavior.
     persist_patterns : boolean, optional
         A boolean, used to decide whether patterns should be computed once, and then reused (True) or not (False).
         If True, the patterns (and other informations such as antecedents of every element for instance) are persisted on a file on the machine running the code at first computation.
@@ -79,11 +86,12 @@ def dynamic_minimization_louboutaoua(chord_sequence, min_size = 8, max_size = 40
         if dm.is_a_chord_object(chord):
             symbolic_flow.append(chord.triad)
         else:
-            symbolic_flow.append(Chord(chord).triad)
+            symbolic_flow.append(chord)
+            #symbolic_flow.append(Chord(chord).triad)
 
     segments_best_starts = [None for i in range(len(chord_sequence))]
     segments_best_starts[0] = 0   
-                
+    
     for current_idx in range(2, len(symbolic_flow)):
         if current_idx < min_size:
             possible_starts = [0]
@@ -98,35 +106,199 @@ def dynamic_minimization_louboutaoua(chord_sequence, min_size = 8, max_size = 40
             segment_size = len(segment)
             
             if persist_patterns:
-                try:
-                    this_bag = np.load("{}\\persisted_content\\patterns_and_ppps_with_antecedents_for_size_{}.npy".format(CURR_DIR, segment_size), allow_pickle = True)
-                except FileNotFoundError:
-                    this_bag = sh.compute_patterns_with_ppp_and_antecedents_for_size(segment_size)
-                    arr = np.array(this_bag, dtype=object)
-                    np.save("{}\\persisted_content\\patterns_and_ppps_with_antecedents_for_size_{}".format(CURR_DIR, segment_size), arr)
+                if global_antecedents:
+                    try:
+                        this_bag = np.load("{}/persisted_content/compute_patterns_with_global_antecedents_for_size_{}.npy".format(CURR_DIR, segment_size), allow_pickle = True)
+                    except FileNotFoundError:
+                        this_bag = sh.compute_patterns_with_global_antecedents_for_size(segment_size)
+                        arr = np.array(this_bag, dtype=object)
+                        np.save("{}/persisted_content/compute_patterns_with_global_antecedents_for_size_{}".format(CURR_DIR, segment_size), arr)            
+                else:
+                    try:
+                        this_bag = np.load("{}/persisted_content/compute_patterns_with_antecedents_for_size_{}.npy".format(CURR_DIR, segment_size), allow_pickle = True)
+                    except FileNotFoundError:
+                        this_bag = sh.compute_patterns_with_antecedents_for_size(segment_size)
+                        arr = np.array(this_bag, dtype=object)
+                        np.save("{}/persisted_content/compute_patterns_with_antecedents_for_size_{}".format(CURR_DIR, segment_size), arr)
             else:
-                this_bag = sh.compute_patterns_with_ppp_and_antecedents_for_size(segment_size)
+                if global_antecedents:
+                    this_bag = sh.compute_patterns_with_global_antecedents_for_size(segment_size)
+                else:
+                    this_bag = sh.compute_patterns_with_antecedents_for_size(segment_size)
 
-            if this_bag != []:
+            if this_bag != []:                
                 this_segment_cost = math.inf
-                
                 for a_pattern in this_bag:
-                    this_polytope_cost = math.inf
-                    for i in range(len(a_pattern[0])):
-                        this_ppp_cost = pc.louboutaoua_cost(segment, a_pattern[0][i], a_pattern[3], a_pattern[4], a_pattern[5], a_pattern[6][i], current_min = this_polytope_cost)
-                        if this_ppp_cost < this_polytope_cost:
-                            this_polytope_cost = this_ppp_cost
-                    
-                    this_polytope_cost += pc.irregularities_penalty_guichaoua(adding_code = a_pattern[1], deleting_code = a_pattern[2], positive_penalty = irregularity_penalty, negative_penalty = irregularity_penalty)
+                    if global_antecedents:
+                        this_polytope_cost = pc.guichaoua_cost_global_antecedents_successors(segment, a_pattern[0], a_pattern[3], a_pattern[4], a_pattern[5], current_min = this_segment_cost, relation_type = relation_type)
+                    else:
+                        this_polytope_cost = pc.guichaoua_cost(segment, a_pattern[0], a_pattern[3], a_pattern[4], a_pattern[5], current_min = this_segment_cost, relation_type = relation_type)
 
+                    this_polytope_cost += pc.irregularities_penalty_guichaoua(adding_code = a_pattern[1], deleting_code = a_pattern[2], positive_penalty = positive_penalty, negative_penalty = negative_penalty)
                     if this_polytope_cost < this_segment_cost:
                         this_segment_cost = this_polytope_cost
 
             else:
                 warnings.warn("No Polytope is available for this size of segment. Trying sequential cost instead.")
-                this_segment_cost = pc.sequential_score(segment, 0)
+                this_segment_cost = pc.sequential_score(segment, 0, relation_type = relation_type)
                 #this_segment_cost = math.inf
+
+            this_segment_cost += sh.penalty_cost_guichaoua(segment_size, target_size = target_size, positive_segment_size_penalty = positive_segment_size_penalty, negative_segment_size_penalty = negative_segment_size_penalty)
+                
+            # Avoiding errors, as segment_cost are initially set to -inf.
+            if possible_start_idx == 0:
+                if this_segment_cost < costs[current_idx]:
+                    costs[current_idx] = this_segment_cost
+                    segments_best_starts[current_idx] = 0
+
+            else:
+                if costs[possible_start_idx - 1] + this_segment_cost < costs[current_idx]:
+                    # Optimal cost until previous segment + cost of this segment.
+                    costs[current_idx] = costs[possible_start_idx - 1] + this_segment_cost
+                    segments_best_starts[current_idx] = possible_start_idx
+
+    frontiers = [len(chord_sequence)] #  Because frontiers are start of next segment, so it should be the chord after the next one.
+    best_start_for_this_segment = segments_best_starts[len(chord_sequence) - 1]
+    while best_start_for_this_segment > 0: # If best_start_for_this_segment == None, an error is raised.
+        frontiers.append(best_start_for_this_segment)
+        precedent_end = best_start_for_this_segment - 1 # Because previous segment ends at the chord before this one.
+        best_start_for_this_segment = segments_best_starts[precedent_end]
+        if precedent_end == None:
+            raise err.ToDebugException("Well... Viterbi took an impossible path, so it failed. Understand why.") from None
+    frontiers.append(0) # Frontiers are here the start of a new segment, the first chord of a segment.
+    return frontiers[::-1], costs[-1]
+
+# Persisting computations, to gain time
+def dynamic_minimization_guichaoua_persist_segments(chord_sequence, database, polytope_irregularity_penalty = 2, polytope_irregularity_function = "guichaoua", min_size = 8, max_size = 40, segment_size_penalty = 1, target_size = 32, relation_type = "triad_circle", song_number = None):
+    """
+    Dynamic programming algorithm applied to the search of the optimal segmentation of a piece of music, with Guichaoua's cost.
+    
+    Given the costs of all possible segments in the piece (flow), it finds the segmentation which minimizes the gloabl sum of all segment costs.
+    TODO: add a reference to explain this cost.
+
+    Parameters
+    ----------
+    chord_sequence : list of chords, of any type
+        The chord sequence (the song) to segment.
+    positive_penalty, negative_penalty : float/integer, optional
+        Penalty parameter related to irregularities of the polytope.
+        Positive corresponds to the penalty when the polytope contains addition, negative is for deletion.
+        They are constants and not function of the size of irregularities.
+    min_size : integer, optional
+        Minimal size for a segment (except the first one and the last one). The default is 8.
+    max_size : integer, optional
+        Maximal size for a segment. The default is 40.
+    positive_segment_size_penalty, negative_segment_size_penalty : float/integer, optional
+        Penalty parameter to multiply to the raw penalty score for the size of the segment.
+        positive_segment_size_penalty is the parameter when size exceeds 'target_size', negative is for size shorter than 'target_size'.
+    target_size : integer, optional
+        The optimal size, used for the penalty related to the segment size. 
+        The default is 32.
+    global_antecedents : boolean, optional
+        A boolean to indicate whether antecedents should be the directs ones (i.e. the ones which are linked with an arrow to the actual element),
+        or global ones (i.e. antecedents where a path exists with the current element, like in Guichaoua's exact paradigm).
+        In my understanding of the model, direct antecedents should be considered as the default behavior.
+    persist_patterns : boolean, optional
+        A boolean, used to decide whether patterns should be computed once, and then reused (True) or not (False).
+        If True, the patterns (and other informations such as antecedents of every element for instance) are persisted on a file on the machine running the code at first computation.
+        (NB: I tried to store them as a variable in a huge list at first, but it resulted in errors, probably due to the size of all patterns...)
+        If False, they are computed at each iteration (so for each element in each possible size).
+        I strongly encourage to set it to True, as it reduces the computation time by a factor of 10.
+        The default is True.
+
+    Raises
+    ------
+    err
+        Errors to avoid bugs at runtime (ToDebugException) or invalid arguments (InvalidArgumentValueException).
+
+    Returns
+    -------
+    frontiers : list of integers
+        The estimated frontiers for this segmentation.
+    cost : integer
+        The total cost of this segmentation.
+
+    """
+    if min_size < 2:
+        raise err.InvalidArgumentValueException("Minimum size should be at least 2.")
+    costs = [math.inf for i in range(len(chord_sequence))]
+    costs[0] = 0
+    
+    symbolic_flow = []
+    for chord in chord_sequence:
+        if dm.is_a_chord_object(chord):
+            symbolic_flow.append(chord.triad)
+        else:
+            symbolic_flow.append(chord)
+            #symbolic_flow.append(Chord(chord).triad)
+
+    segments_best_starts = [None for i in range(len(chord_sequence))]
+    segments_best_starts[0] = 0
+    
+    if song_number == None:
+        raise NotImplementedError("Can't precompute or load anything")
+    
+    try:
+        this_song_optimal_costs = np.load("{}/persisted_content/guichaoua_song_costs_{}/guichaoua_song{}_relation{}_irreg_function{}_irreg_val{}.npy".format(CURR_DIR, database, song_number, relation_type, polytope_irregularity_function, polytope_irregularity_penalty), allow_pickle = True)
+        costs_loaded = True
+    except FileNotFoundError:
+        costs_loaded = False
+        to_save_optimal_costs = -1 * np.ones((len(chord_sequence),len(chord_sequence)))
+    
+    for current_idx in range(2, len(symbolic_flow)):
+        if current_idx < min_size:
+            possible_starts = [0]
+        elif current_idx == len(symbolic_flow) - 1:
+            possible_starts = sh.possible_segment_start(current_idx, min_size = 2, max_size = max_size)
+        else:
+            possible_starts = sh.possible_segment_start(current_idx, min_size = min_size, max_size = max_size)
+        for possible_start_idx in possible_starts:
+            if possible_start_idx < 0:
+                raise err.ToDebugException("Invalid value of start index.")
+            segment = [symbolic_flow[k] for k in range(possible_start_idx, current_idx + 1)]
+            segment_size = len(segment)
             
+            if costs_loaded:
+                this_segment_cost = this_song_optimal_costs[possible_start_idx,current_idx]
+                if this_segment_cost == -1 or this_segment_cost == math.inf:
+                    raise err.ToDebugException("Error here, invalid value persisted")
+            else:
+                try:
+                    this_bag = np.load("{}/persisted_content/compute_patterns_with_antecedents_for_size_{}.npy".format(CURR_DIR, segment_size), allow_pickle = True)
+                except FileNotFoundError:
+                    this_bag = sh.compute_patterns_with_antecedents_for_size(segment_size)
+                    arr = np.array(this_bag, dtype=object)
+                    np.save("{}/persisted_content/compute_patterns_with_antecedents_for_size_{}".format(CURR_DIR, segment_size), arr)
+    
+                if this_bag != []:
+                    it_sgt = ''
+                    for chord in segment:
+                        it_sgt += chord.replace('b','-')
+                    try:
+                        all_costs = np.load("{}/persisted_content/guichaoua_pc_costs_{}/guichaoua_costs_seg{}_relation{}.npy".format(CURR_DIR, database, it_sgt, relation_type), allow_pickle = True)
+                    except FileNotFoundError:
+                        all_costs = [pc.guichaoua_cost(segment, a_pattern[0], a_pattern[3], a_pattern[4], a_pattern[5], current_min = math.inf, relation_type = relation_type) for a_pattern in this_bag]
+                        #arr_costs = np.array(all_costs, dtype=object)
+                        #np.save("{}\\persisted_content\\guichaoua_pc_costs\\guichaoua_costs_seg{}_relation{}".format(CURR_DIR, it_sgt, relation_type), arr_costs)
+                    this_segment_cost = math.inf
+                    for idx, a_pattern in enumerate(this_bag):
+                        this_polytope_cost = all_costs[idx]
+                        if polytope_irregularity_function == "guichaoua":
+                            this_polytope_cost += pc.irregularities_penalty_guichaoua(adding_code = a_pattern[1], deleting_code = a_pattern[2], positive_penalty = polytope_irregularity_penalty, negative_penalty = polytope_irregularity_penalty)
+                        else:
+                            raise NotImplementedError("No other irregularity function is implemented")
+                        if this_polytope_cost < this_segment_cost:
+                            this_segment_cost = this_polytope_cost
+    
+                else:
+                    warnings.warn("No Polytope is available for this size of segment. Trying sequential cost instead.")
+                    this_segment_cost = pc.sequential_score(segment, 0, relation_type = relation_type)
+                    #this_segment_cost = math.inf
+                
+                to_save_optimal_costs[possible_start_idx, current_idx] = this_segment_cost
+                if this_segment_cost == math.inf or this_segment_cost == -1:
+                    raise err.ToDebugException("Invalid segment cost to persist")
+
             this_segment_cost += sh.penalty_cost_guichaoua(segment_size, target_size = target_size, positive_segment_size_penalty = segment_size_penalty, negative_segment_size_penalty = segment_size_penalty)
                 
             # Avoiding errors, as segment_cost are initially set to -inf.
@@ -141,6 +313,9 @@ def dynamic_minimization_louboutaoua(chord_sequence, min_size = 8, max_size = 40
                     costs[current_idx] = costs[possible_start_idx - 1] + this_segment_cost
                     segments_best_starts[current_idx] = possible_start_idx
                     
+    if not costs_loaded:
+        np.save("{}/persisted_content/guichaoua_song_costs_{}/guichaoua_song{}_relation{}_irreg_function{}_irreg_val{}".format(CURR_DIR, database, song_number, relation_type, polytope_irregularity_function, polytope_irregularity_penalty), to_save_optimal_costs)
+
     frontiers = [len(chord_sequence)] #  Because frontiers are start of next segment, so it should be the chord after the next one.
     best_start_for_this_segment = segments_best_starts[len(chord_sequence) - 1]
     while best_start_for_this_segment > 0: # If best_start_for_this_segment == None, an error is raised.
@@ -150,10 +325,12 @@ def dynamic_minimization_louboutaoua(chord_sequence, min_size = 8, max_size = 40
         if precedent_end == None:
             raise err.ToDebugException("Well... Viterbi took an impossible path, so it failed. Understand why.") from None
     frontiers.append(0) # Frontiers are here the start of a new segment, the first chord of a segment.
-    return frontiers[::-1], costs[-1]      
+    return frontiers[::-1], costs[-1]
+
 
-### 2nd cost: Cohen-Marmoret
-def dynamic_minimization_cohen_marmoret(chord_sequence, min_size = 8, max_size = 40, segment_size_penalty = 1, irregularity_penalty = 1, target_size = 32, persist_patterns = True):
+
+### Cohen-Marmoret cost: Guichaoua's implication with harmonic distance
+def dynamic_minimization_cohen_marmoret(chord_sequence, min_size = 8, max_size = 40, segment_size_penalty = 1, irregularity_penalty = 1, target_size = 32, persist_patterns = True, relation_type = "triad_circle"):
     """
     Dynamic programming algorithm applied to the search of the optimal segmentation of a piece of music, with Cohen-Marmoret's cost.
     
@@ -240,7 +417,7 @@ def dynamic_minimization_cohen_marmoret(chord_sequence, min_size = 8, max_size =
                 this_segment_cost = math.inf
                 
                 for a_pattern in this_bag:
-                    this_polytope_cost = pc.cohen_marmoret_cost(segment, a_pattern[0], a_pattern[3], current_min = this_segment_cost)
+                    this_polytope_cost = pc.cohen_marmoret_cost(segment, a_pattern[0], a_pattern[3], current_min = this_segment_cost, relation_type = relation_type)
 
                     this_polytope_cost += pc.irregularities_penalty_guichaoua(adding_code = a_pattern[1], deleting_code = a_pattern[2], positive_penalty = irregularity_penalty, negative_penalty = irregularity_penalty)
 
@@ -249,7 +426,7 @@ def dynamic_minimization_cohen_marmoret(chord_sequence, min_size = 8, max_size =
 
             else:
                 warnings.warn("No Polytope is available for this size of segment. Trying sequential cost instead.")
-                this_segment_cost = pc.sequential_score(segment, 0)
+                this_segment_cost = pc.sequential_score(segment, 0, relation_type = relation_type)
                 #this_segment_cost = math.inf
             
             this_segment_cost += sh.penalty_cost_guichaoua(segment_size, target_size = target_size, positive_segment_size_penalty = segment_size_penalty, negative_segment_size_penalty = segment_size_penalty)
@@ -314,6 +491,7 @@ def dynamic_minimization_reg_or_seq(chord_sequence, segment_size_penalty = 1, mi
         The total cost of this segmentation.
 
     """
+    raise err.OutdatedBehaviorException("Tis function doesn't work anymore actually")
     if min_size < 2:
         raise NotImplementedError("TODO better error, but minimum size should be at least 2.")
     costs = [math.inf for i in range(len(chord_sequence))]
@@ -369,10 +547,10 @@ def dynamic_minimization_reg_or_seq(chord_sequence, segment_size_penalty = 1, mi
     frontiers.append(0) # Frontiers are here the start of a new segment, the first chord of a segment.
     return frontiers[::-1], costs[-1]
 
-# %% C. Guichaoua paradigm
-def dynamic_minimization_guichaoua(chord_sequence, positive_penalty = 2.25, negative_penalty = 3, min_size = 8, max_size = 40, positive_segment_size_penalty = 0, negative_segment_size_penalty = 0.125, target_size = 32, global_antecedents = False, persist_patterns = True):
+# %% C. Louboutin paradigm
+def dynamic_minimization_louboutin(chord_sequence, min_size = 8, max_size = 40, segment_size_penalty = 1, irregularity_penalty = 1, target_size = 32, persist_patterns = True, relation_type = "triad_circle"):
     """
-    Dynamic programming algorithm applied to the search of the optimal segmentation of a piece of music, with Guichaoua's cost.
+    Dynamic programming algorithm applied to the search of the optimal segmentation of a piece of music, with C. Louboutin's cost.
     
     Given the costs of all possible segments in the piece (flow), it finds the segmentation which minimizes the gloabl sum of all segment costs.
     TODO: add a reference to explain this cost.
@@ -381,24 +559,17 @@ def dynamic_minimization_guichaoua(chord_sequence, positive_penalty = 2.25, nega
     ----------
     chord_sequence : list of chords, of any type
         The chord sequence (the song) to segment.
-    positive_penalty, negative_penalty : float/integer, optional
-        Penalty parameter related to irregularities of the polytope.
-        Positive corresponds to the penalty when the polytope contains addition, negative is for deletion.
-        They are constants and not function of the size of irregularities.
     min_size : integer, optional
         Minimal size for a segment (except the first one and the last one). The default is 8.
     max_size : integer, optional
         Maximal size for a segment. The default is 40.
-    positive_segment_size_penalty, negative_segment_size_penalty : float/integer, optional
-        Penalty parameter to multiply to the raw penalty score for the size of the segment.
-        positive_segment_size_penalty is the parameter when size exceeds 'target_size', negative is for size shorter than 'target_size'.
+    segment_size_penalty : float/integer, optional
+        Penalty parameter to multiply to the raw penalty score for the size of the segment. The default is 1.
+    irregularity_penalty : float/integer, optional
+        Penalty parameter to multiply to the raw penalty score for the irregularities of the polytope. The default is 1.
     target_size : integer, optional
         The optimal size, used for the penalty related to the segment size. 
         The default is 32.
-    global_antecedents : boolean, optional
-        A boolean to indicate whether antecedents should be the directs ones (i.e. the ones which are linked with an arrow to the actual element),
-        or global ones (i.e. antecedents where a path exists with the current element, like in Guichaoua's exact paradigm).
-        In my understanding of the model, direct antecedents should be considered as the default behavior.
     persist_patterns : boolean, optional
         A boolean, used to decide whether patterns should be computed once, and then reused (True) or not (False).
         If True, the patterns (and other informations such as antecedents of every element for instance) are persisted on a file on the machine running the code at first computation.
@@ -430,12 +601,13 @@ def dynamic_minimization_guichaoua(chord_sequence, positive_penalty = 2.25, nega
         if dm.is_a_chord_object(chord):
             symbolic_flow.append(chord.triad)
         else:
-            symbolic_flow.append(chord)
-            #symbolic_flow.append(Chord(chord).triad)
+            symbolic_flow.append(Chord(chord).triad)
 
     segments_best_starts = [None for i in range(len(chord_sequence))]
     segments_best_starts[0] = 0   
     
+    CURR_DIR = os.path.dirname(os.path.realpath(__file__))
+            
     for current_idx in range(2, len(symbolic_flow)):
         if current_idx < min_size:
             possible_starts = [0]
@@ -450,45 +622,36 @@ def dynamic_minimization_guichaoua(chord_sequence, positive_penalty = 2.25, nega
             segment_size = len(segment)
             
             if persist_patterns:
-                if global_antecedents:
-                    try:
-                        this_bag = np.load("{}\\persisted_content\\compute_patterns_with_global_antecedents_for_size_{}.npy".format(CURR_DIR, segment_size), allow_pickle = True)
-                    except FileNotFoundError:
-                        this_bag = sh.compute_patterns_with_global_antecedents_for_size(segment_size)
-                        arr = np.array(this_bag, dtype=object)
-                        np.save("{}\\persisted_content\\compute_patterns_with_global_antecedents_for_size_{}".format(CURR_DIR, segment_size), arr)            
-                else:
-                    try:
-                        this_bag = np.load("{}\\persisted_content\\compute_patterns_with_antecedents_for_size_{}.npy".format(CURR_DIR, segment_size), allow_pickle = True)
-                    except FileNotFoundError:
-                        this_bag = sh.compute_patterns_with_antecedents_for_size(segment_size)
-                        arr = np.array(this_bag, dtype=object)
-                        np.save("{}\\persisted_content\\compute_patterns_with_antecedents_for_size_{}".format(CURR_DIR, segment_size), arr)
+                try:
+                    this_bag = np.load("{}\\persisted_content\\compute_patterns_and_ppp_for_size_{}.npy".format(CURR_DIR, segment_size), allow_pickle = True)
+                except FileNotFoundError:
+                    this_bag = sh.compute_patterns_and_ppp_for_size(segment_size)
+                    arr = np.array(this_bag, dtype=object)
+                    np.save("{}\\persisted_content\\compute_patterns_and_ppp_for_size_{}".format(CURR_DIR, segment_size), arr)
             else:
-                if global_antecedents:
-                    this_bag = sh.compute_patterns_with_global_antecedents_for_size(segment_size)
-                else:
-                    this_bag = sh.compute_patterns_with_antecedents_for_size(segment_size)
+                this_bag = sh.compute_patterns_and_ppp_for_size(segment_size)
 
             if this_bag != []:
                 this_segment_cost = math.inf
                 
                 for a_pattern in this_bag:
-                    if global_antecedents:
-                        this_polytope_cost = pc.guichaoua_cost_global_antecedents_successors(segment, a_pattern[0], a_pattern[3], a_pattern[4], a_pattern[5], current_min = this_segment_cost)
-                    else:
-                        this_polytope_cost = pc.guichaoua_cost(segment, a_pattern[0], a_pattern[3], a_pattern[4], a_pattern[5], current_min = this_segment_cost)
-                        
-                    this_polytope_cost += pc.irregularities_penalty_guichaoua(adding_code = a_pattern[1], deleting_code = a_pattern[2], positive_penalty = positive_penalty, negative_penalty = negative_penalty)
+                    this_polytope_cost = math.inf
+                    for i in range(len(a_pattern[0])):
+                        this_ppp_cost = pc.louboutin_cost_for_a_ppp(segment, a_pattern[0][i], a_pattern[3][i], a_pattern[4][i], current_min = this_segment_cost, relation_type = relation_type)
+                        if this_ppp_cost < this_polytope_cost:
+                            this_polytope_cost = this_ppp_cost
+                    
+                    this_polytope_cost += pc.irregularities_penalty_guichaoua(adding_code = a_pattern[1], deleting_code = a_pattern[2], positive_penalty = irregularity_penalty, negative_penalty = irregularity_penalty)
+
                     if this_polytope_cost < this_segment_cost:
                         this_segment_cost = this_polytope_cost
 
             else:
                 warnings.warn("No Polytope is available for this size of segment. Trying sequential cost instead.")
-                this_segment_cost = pc.sequential_score(segment, 0)
+                this_segment_cost = pc.sequential_score(segment, 0, relation_type = relation_type)
                 #this_segment_cost = math.inf
-
-            this_segment_cost += sh.penalty_cost_guichaoua(segment_size, target_size = target_size, positive_segment_size_penalty = positive_segment_size_penalty, negative_segment_size_penalty = negative_segment_size_penalty)
+            
+            this_segment_cost += sh.penalty_cost_guichaoua(segment_size, target_size = target_size, positive_segment_size_penalty = segment_size_penalty, negative_segment_size_penalty = segment_size_penalty)
                 
             # Avoiding errors, as segment_cost are initially set to -inf.
             if possible_start_idx == 0:
@@ -501,7 +664,7 @@ def dynamic_minimization_guichaoua(chord_sequence, positive_penalty = 2.25, nega
                     # Optimal cost until previous segment + cost of this segment.
                     costs[current_idx] = costs[possible_start_idx - 1] + this_segment_cost
                     segments_best_starts[current_idx] = possible_start_idx
-
+                    
     frontiers = [len(chord_sequence)] #  Because frontiers are start of next segment, so it should be the chord after the next one.
     best_start_for_this_segment = segments_best_starts[len(chord_sequence) - 1]
     while best_start_for_this_segment > 0: # If best_start_for_this_segment == None, an error is raised.
@@ -513,10 +676,10 @@ def dynamic_minimization_guichaoua(chord_sequence, positive_penalty = 2.25, nega
     frontiers.append(0) # Frontiers are here the start of a new segment, the first chord of a segment.
     return frontiers[::-1], costs[-1]
 
-# %% C. Louboutin paradigm
-def dynamic_minimization_louboutin(chord_sequence, min_size = 8, max_size = 40, segment_size_penalty = 1, irregularity_penalty = 1, target_size = 32, persist_patterns = True):
+### Mix of PPP and implication: Louboutaoua
+def dynamic_minimization_louboutaoua(chord_sequence, min_size = 8, max_size = 40, segment_size_penalty = 1, irregularity_penalty = 1, target_size = 32, persist_patterns = True, relation_type = "triad_circle"):
     """
-    Dynamic programming algorithm applied to the search of the optimal segmentation of a piece of music, with C. Louboutin's cost.
+    Dynamic programming algorithm applied to the search of the optimal segmentation of a piece of music, with Louboutaoua's cost.
     
     Given the costs of all possible segments in the piece (flow), it finds the segmentation which minimizes the gloabl sum of all segment costs.
     TODO: add a reference to explain this cost.
@@ -571,9 +734,7 @@ def dynamic_minimization_louboutin(chord_sequence, min_size = 8, max_size = 40,
 
     segments_best_starts = [None for i in range(len(chord_sequence))]
     segments_best_starts[0] = 0   
-    
-    CURR_DIR = os.path.dirname(os.path.realpath(__file__))
-            
+                
     for current_idx in range(2, len(symbolic_flow)):
         if current_idx < min_size:
             possible_starts = [0]
@@ -589,13 +750,13 @@ def dynamic_minimization_louboutin(chord_sequence, min_size = 8, max_size = 40,
             
             if persist_patterns:
                 try:
-                    this_bag = np.load("{}\\persisted_content\\compute_patterns_and_ppp_for_size_{}.npy".format(CURR_DIR, segment_size), allow_pickle = True)
+                    this_bag = np.load("{}\\persisted_content\\patterns_and_ppps_with_antecedents_for_size_{}.npy".format(CURR_DIR, segment_size), allow_pickle = True)
                 except FileNotFoundError:
-                    this_bag = sh.compute_patterns_and_ppp_for_size(segment_size)
+                    this_bag = sh.compute_patterns_with_ppp_and_antecedents_for_size(segment_size)
                     arr = np.array(this_bag, dtype=object)
-                    np.save("{}\\persisted_content\\compute_patterns_and_ppp_for_size_{}".format(CURR_DIR, segment_size), arr)
+                    np.save("{}\\persisted_content\\patterns_and_ppps_with_antecedents_for_size_{}".format(CURR_DIR, segment_size), arr)
             else:
-                this_bag = sh.compute_patterns_and_ppp_for_size(segment_size)
+                this_bag = sh.compute_patterns_with_ppp_and_antecedents_for_size(segment_size)
 
             if this_bag != []:
                 this_segment_cost = math.inf
@@ -603,7 +764,7 @@ def dynamic_minimization_louboutin(chord_sequence, min_size = 8, max_size = 40,
                 for a_pattern in this_bag:
                     this_polytope_cost = math.inf
                     for i in range(len(a_pattern[0])):
-                        this_ppp_cost = pc.louboutin_cost_for_a_ppp(segment, a_pattern[0][i], a_pattern[3][i], a_pattern[4][i], current_min = this_segment_cost)
+                        this_ppp_cost = pc.louboutaoua_cost(segment, a_pattern[0][i], a_pattern[3], a_pattern[4], a_pattern[5], a_pattern[6][i], current_min = this_polytope_cost, relation_type = relation_type)
                         if this_ppp_cost < this_polytope_cost:
                             this_polytope_cost = this_ppp_cost
                     
@@ -614,7 +775,7 @@ def dynamic_minimization_louboutin(chord_sequence, min_size = 8, max_size = 40,
 
             else:
                 warnings.warn("No Polytope is available for this size of segment. Trying sequential cost instead.")
-                this_segment_cost = pc.sequential_score(segment, 0)
+                this_segment_cost = pc.sequential_score(segment, 0, relation_type = relation_type)
                 #this_segment_cost = math.inf
             
             this_segment_cost += sh.penalty_cost_guichaoua(segment_size, target_size = target_size, positive_segment_size_penalty = segment_size_penalty, negative_segment_size_penalty = segment_size_penalty)
@@ -640,9 +801,7 @@ def dynamic_minimization_louboutin(chord_sequence, min_size = 8, max_size = 40,
         if precedent_end == None:
             raise err.ToDebugException("Well... Viterbi took an impossible path, so it failed. Understand why.") from None
     frontiers.append(0) # Frontiers are here the start of a new segment, the first chord of a segment.
-    return frontiers[::-1], costs[-1]
-
-
+    return frontiers[::-1], costs[-1]      
 
 # def new_viterbi_loop_size(chord_sequence, positive_penalty = 2.25, negative_penalty = 3, min_size = 8, max_size = 40, positive_segment_size_penalty = 0, negative_segment_size_penalty = 0.125, target_size = 32):
 #     # Work in progress, not functionning right now, but idea is to computes score by the size of the segments first, and then find the optimal segmentation.
@@ -741,4 +900,3 @@ def dynamic_minimization_louboutin(chord_sequence, min_size = 8, max_size = 40,
 #     frontiers.append(0) # Frontiers are here the start of a new segment, the first chord of a segment.
 #     return frontiers[::-1], costs[-1]        
 
-                
\ No newline at end of file
diff --git a/polytopes/segmentation_helper.py b/MusicOnPolytopes/segmentation_helper.py
similarity index 100%
rename from polytopes/segmentation_helper.py
rename to MusicOnPolytopes/segmentation_helper.py
diff --git a/MusicOnPolytopes/triad_transformations.py b/MusicOnPolytopes/triad_transformations.py
new file mode 100644
index 0000000000000000000000000000000000000000..4411e1bc5671bbdffdb1fd6a3194a03e6ce20cbd
--- /dev/null
+++ b/MusicOnPolytopes/triad_transformations.py
@@ -0,0 +1,243 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Tue Mar 23 15:45:22 2021
+
+@author: amarmore
+"""
+
+import math
+import music21
+import itertools
+
+import polytopes.data_manipulation as dm
+import polytopes.model.errors as err
+import polytopes.model.triad_manipulation as tm
+import polytopes.voiceleading_utilities as vl
+
+circle_flat = ['C','Am','F','Dm','Bb','Gm','Eb','Cm','Ab','Fm','Db','Bbm','Gb','Ebm','B','Abm','E','Dbm','A','Gbm','D','Bm','G','Em']
+circle_sharp =  ['C','Am','F','Dm','A#','Gm','D#','Cm','G#','Fm','C#','A#m','F#','D#m','B','G#m','E','C#m','A','F#m','D','Bm','G','Em']
+chromatic_circle_sharp = ['Cm', 'C', 'C#m', 'C#', 'Dm', 'D', 'D#m', 'D#', 'Em', 'E', 'Fm', 'F', 'F#m', 'F#', 'Gm', 'G', 'G#m', 'G#', 'Am', 'A', 'A#m', 'A#', 'Bm', 'B']
+three_five_torus_sharp = ['C','Fm','C#','F#m','D','Gm','D#','G#m','E','Am','F','A#m','F#','Bm','G','Cm','G#','C#m','A','Dm','A#','D#m','B','Em'] 
+
+# %% Voice leading, in optimal transport
+# Use Dmitri Tymoczko module instead
+def get_voice_leading_distance_symbol(triad_symbol_a, triad_symbol_b, triadic_reduction = True):
+    return get_voice_leading_distance_notes(tm.triad_notes_from_symbol(triad_symbol_a, triadic_reduction = triadic_reduction), tm.triad_notes_from_symbol(triad_symbol_b, triadic_reduction = triadic_reduction))
+
+def get_voice_leading_distance_notes(triad_a, triad_b):
+    if not tm.is_maj_min_triad_from_notes(triad_a):
+        raise err.NotAMajMinTriadException(f"This chord ({triad_a}) does not correspond to a major or minor triad, which is our only case study.")
+    if not tm.is_maj_min_triad_from_notes(triad_b):
+        raise err.NotAMajMinTriadException(f"This chord ({triad_b}) does not correspond to a major or minor triad, which is our only case study.")
+    return vl.nonbijective_vl(triad_a, triad_b)[0]
+
+## Simplistic voice leading
+def get_voice_leading_transformation_symbol(triad_symbol_a, triad_symbol_b, triadic_reduction = True):
+    return get_voice_leading_transformation_notes(tm.triad_notes_from_symbol(triad_symbol_a, triadic_reduction = triadic_reduction), tm.triad_notes_from_symbol(triad_symbol_b, triadic_reduction = triadic_reduction))
+
+def get_voice_leading_transformation_notes(triad_a, triad_b):
+    if not tm.is_maj_min_triad_from_notes(triad_a):
+        raise err.NotAMajMinTriadException(f"This chord ({triad_a}) does not correspond to a major or minor triad, which is our only case study.")
+    if not tm.is_maj_min_triad_from_notes(triad_b):
+        raise err.NotAMajMinTriadException(f"This chord ({triad_b}) does not correspond to a major or minor triad, which is our only case study.")
+    return [triad_b[i] - triad_a[i] for i in range(3)]
+
+## Work In Progress
+def apply_voice_leading_transformation(triad, transformation):
+    #TODO: reflechir à cette fonction
+    if not tm.is_maj_min_triad_from_notes(triad):
+        raise err.NotAMajMinTriadException(f"This chord ({triad}) does not correspond to a major or minor triad, which is our only case study.")
+    if len(transformation) != 3:
+        raise NotImplementedError("Not a valid transformation, better error TODO")
+    print("Check that it always returns a triad, or act consequently")
+    return [(triad[i] + transformation[i])%12 for i in range(3)]
+
+# %% Triadic relation
+def get_triadic_position_symbol(triad_symbol, triadic_reduction = True): 
+    if not tm.is_maj_min_triad_from_symbol(triad_symbol) and not triadic_reduction:
+        raise err.NotAMajMinTriadException(f"This chord ({triad_symbol}) does not correspond to a major or minor triad, which is our only case study.")
+    triad = tm.maj_min_triad_reduction_of_symbol(triad_symbol, to_sharp = True)
+    return circle_sharp.index(triad)
+
+def get_triadic_position_notes(triad_notes): 
+    if not tm.is_maj_min_triad_from_notes(triad_notes):
+        raise err.NotAMajMinTriadException(f"This chord ({triad_notes}) does not correspond to a major or minor triad, which is our only case study.")
+    symb = tm.triad_symbol_from_notes(triad_notes)
+    return get_triadic_position_symbol(symb)
+
+    
+def triadic_mvt_triads(first_triad_symbol, second_triad_symbol, triadic_reduction = True):
+    """
+    Compute the movement/relation between both chords in the circle of triads.
+    
+    It depends on the circle, and can be either on circle of fifth (chromatic) or on the 3-5 Torus (!chromatic)
+    NB: Now, only the circle of fifth is tolerated. Could be temporary or permanent.
+
+    Parameters
+    ----------
+    first_chord_symbol, second_chord_symbol : strings
+        The symbols of both chords which relation is to compute.
+    
+    Returns
+    -------
+    mvt : integer
+        The relation between both chords.
+
+    """
+    mvt = (get_triadic_position_symbol(second_triad_symbol, triadic_reduction = triadic_reduction) - get_triadic_position_symbol(first_triad_symbol, triadic_reduction = triadic_reduction))%24
+    if mvt > 12:
+        mvt -= 24
+    return mvt
+
+def apply_triadic_mvt(triad_symbol, mvt, triadic_reduction = True):
+    """
+    Apply a movement/relation to a chord in the circle of triads.
+
+    Parameters
+    ----------
+    triad_symbol : string
+        The symbol of the triad, on which to aply the movement.
+    mvt : integer
+        The relation to apply.
+        
+    Returns
+    -------
+    string
+        The new triad symbol, after applying the relation.
+
+    """
+    if not tm.is_maj_min_triad_from_symbol(triad_symbol) and not triadic_reduction:
+        raise err.NotAMajMinTriadException(f"This chord ({triad_symbol}) does not correspond to a major or minor triad, which is our only case study.")
+    triad = tm.maj_min_triad_reduction_of_symbol(triad_symbol, to_sharp = True)
+    idx = get_triadic_position_symbol(triad)
+    return circle_sharp[(idx + mvt)%24]
+
+
+# %% Triadic chromatic relation
+def get_chromatic_position_symbol(triad_symbol, triadic_reduction = True): 
+    if not tm.is_maj_min_triad_from_symbol(triad_symbol) and not triadic_reduction:
+        raise err.NotAMajMinTriadException(f"This chord ({triad_symbol}) does not correspond to a major or minor triad, which is our only case study.")
+    triad = tm.maj_min_triad_reduction_of_symbol(triad_symbol, to_sharp = True)
+    return chromatic_circle_sharp.index(triad)
+
+def get_chromatic_position_notes(triad_notes): 
+    if not tm.is_maj_min_triad_from_notes(triad_notes):
+        raise err.NotAMajMinTriadException(f"This chord ({triad_notes}) does not correspond to a major or minor triad, which is our only case study.")
+    symb = tm.triad_symbol_from_notes(triad_notes)
+    return get_chromatic_position_symbol(symb)
+    
+def chromatic_mvt_triads(first_triad_symbol, second_triad_symbol, triadic_reduction = True):
+    mvt = (get_chromatic_position_symbol(second_triad_symbol, triadic_reduction = triadic_reduction) - get_chromatic_position_symbol(first_triad_symbol, triadic_reduction = triadic_reduction))%24
+    if mvt > 12:
+        mvt -= 24
+    return mvt
+
+def apply_chromatic_mvt(triad_symbol, mvt, triadic_reduction = True):
+    if not tm.is_maj_min_triad_from_symbol(triad_symbol) and not triadic_reduction:
+        raise err.NotAMajMinTriadException(f"This chord ({triad_symbol}) does not correspond to a major or minor triad, which is our only case study.")
+    triad = tm.maj_min_triad_reduction_of_symbol(triad_symbol, to_sharp = True)
+    idx = get_chromatic_position_symbol(triad)
+    return chromatic_circle_sharp[(idx + mvt)%24]
+
+# %% Triadic 3-5 torus relation
+def get_three_five_torus_position_symbol(triad_symbol, triadic_reduction = True): 
+    if not tm.is_maj_min_triad_from_symbol(triad_symbol) and not triadic_reduction:
+        raise err.NotAMajMinTriadException(f"This chord ({triad_symbol}) does not correspond to a major or minor triad, which is our only case study.")
+    triad = tm.maj_min_triad_reduction_of_symbol(triad_symbol, to_sharp = True)
+    return three_five_torus_sharp.index(triad)
+
+def get_three_five_torus_position_notes(triad_notes): 
+    if not tm.is_maj_min_triad_from_notes(triad_notes):
+        raise err.NotAMajMinTriadException(f"This chord ({triad_notes}) does not correspond to a major or minor triad, which is our only case study.")
+    symb = tm.triad_symbol_from_notes(triad_notes)
+    return get_three_five_torus_position_symbol(symb)
+    
+def three_five_torus_mvt_triads(first_triad_symbol, second_triad_symbol, triadic_reduction = True):
+    mvt = (get_three_five_torus_position_symbol(second_triad_symbol, triadic_reduction = triadic_reduction) - get_three_five_torus_position_symbol(first_triad_symbol, triadic_reduction = triadic_reduction))%24
+    if mvt > 12:
+        mvt -= 24
+    return mvt
+
+def apply_three_five_torus_mvt(triad_symbol, mvt, triadic_reduction = True):
+    if not tm.is_maj_min_triad_from_symbol(triad_symbol) and not triadic_reduction:
+        raise err.NotAMajMinTriadException(f"This chord ({triad_symbol}) does not correspond to a major or minor triad, which is our only case study.")
+    triad = tm.maj_min_triad_reduction_of_symbol(triad_symbol, to_sharp = True)
+    idx = get_three_five_torus_position_symbol(triad)
+    return three_five_torus_sharp[(idx + mvt)%24]
+   
+# %% Tonnetz distances, for triads
+def triadic_tonnetz_relation_notes(triad_notes_a, triad_notes_b):
+    a = music21.chord.Chord(triad_notes_a)
+    c_1 = music21.analysis.neoRiemannian._simplerEnharmonics(a)
+    
+    b = music21.chord.Chord(triad_notes_b)
+    c_2 = music21.analysis.neoRiemannian._simplerEnharmonics(b)
+    
+    if c_2.orderedPitchClasses == c_1.orderedPitchClasses:
+        return 0
+    
+    for i in range(1,9):
+        for permut in itertools.product('LPR', repeat=i):
+            try:
+                c_1_permuted = music21.analysis.neoRiemannian.LRP_combinations(c_1, permut, raiseException=True, simplifyEnharmonics=True)
+            except music21.analysis.neoRiemannian.LRPException:
+                # Happens sometimes for now, but should be solved in near future
+                c_1_permuted = manually_loop_lrp_comb(c_1, permut)
+
+            if c_2.orderedPitchClasses == c_1_permuted.orderedPitchClasses:
+                return permut
+    raise NotImplementedError("Not found, try increasing the accepted amout of relations.")
+    
+def triadic_tonnetz_distance_notes(triad_notes_a, triad_notes_b):
+    relation = triadic_tonnetz_relation_notes(triad_notes_a, triad_notes_b)
+    if relation == 0 or relation == None:
+        return 0
+    return len(relation)
+    
+def triadic_tonnetz_relation_symbol(triad_symbol_a, triad_symbol_b):
+    return triadic_tonnetz_relation_notes(tm.triad_notes_from_symbol(triad_symbol_a), tm.triad_notes_from_symbol(triad_symbol_b))
+
+def triadic_tonnetz_distance_symbol(triad_symbol_a, triad_symbol_b):
+    relation = triadic_tonnetz_relation_symbol(triad_symbol_a, triad_symbol_b)
+    if relation == 0 or relation == None:
+        return 0
+    return len(relation)
+
+def manually_loop_lrp_comb(chord, relations):
+    while len(relations) > 0:
+        if relations[-1] == "P":
+            chord = music21.analysis.neoRiemannian.P(chord)
+        elif relations[-1] == "L":
+            chord = music21.analysis.neoRiemannian.L(chord)
+        elif relations[-1] == "R":
+            chord = music21.analysis.neoRiemannian.R(chord)
+        else:
+            raise err.InvalidArgumentValueException(f"Invalid relation type: {relations[-1]}, only L, P and R are accepted.")
+        chord = music21.analysis.neoRiemannian._simplerEnharmonics(chord)
+        relations = relations[:-1]
+    return chord
+
+def apply_triadic_tonnetz_relation_notes(triad_notes_a, LRP_relation):
+    a = music21.chord.Chord(triad_notes_a)
+    c_1 = music21.analysis.neoRiemannian._simplerEnharmonics(a)
+    
+    if LRP_relation == 0 or LRP_relation == None:
+        return triad_notes_a
+    
+    try:
+        c_transformed = music21.analysis.neoRiemannian.LRP_combinations(c_1, LRP_relation, raiseException=True, simplifyEnharmonics=True)
+    except music21.analysis.neoRiemannian.LRPException:
+        # Happens sometimes for now, but should be solved in near future
+        c_transformed = manually_loop_lrp_comb(c_1, LRP_relation)
+    notes = []
+    for a_pitch in c_transformed.pitches:
+        notes.append(int(a_pitch.ps)%12)
+    return tm.reindex_inversed_triad(notes)
+
+def apply_triadic_tonnetz_relation_symbol(triad_symbol_a, LRP_relation):
+    if LRP_relation == 0:
+        return triad_symbol_a
+    notes = tm.triad_notes_from_symbol(triad_symbol_a)
+    notes_transformed = apply_triadic_tonnetz_relation_notes(notes, LRP_relation)
+    return tm.triad_symbol_from_notes(notes_transformed)
+    
diff --git a/MusicOnPolytopes/voiceleading_utilities.py b/MusicOnPolytopes/voiceleading_utilities.py
new file mode 100644
index 0000000000000000000000000000000000000000..5b6b997603175ce46b047f4f6f87139aa999cf8a
--- /dev/null
+++ b/MusicOnPolytopes/voiceleading_utilities.py
@@ -0,0 +1,212 @@
+import random
+
+_VERYLARGENUMBER = 1000000				# effectively infinity
+_MODULUS = 12							# size of the octave
+
+_HALFMODULUS = int(0.5 + _MODULUS/2.0)
+
+"""
+
+voiceleading_utilities version 1.0, (c) 2015 by Dmitri Tymoczko
+
+Voiceleading_utilities is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License 
+as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Voiceleading_utilities 
+is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
+FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.   You should have received a copy of the GNU Lesser 
+General Public License along with Voiceleading_utilities.  If not, see <http://www.gnu.org/licenses/>. 
+
+A set of routines that identify the minimal voice leadings between sets of pitches and pitch classes.
+
+1. bijective_vl finds the best bijective voice leading between pitch-class sets assuming a fixed number of voices
+	- use this if you want to control the number of voices exactly, 
+		e.g., a 3-voice voice leading from [C, E, G] to [F, A, C], or
+		a 4-voice voice leading from [G, B, D, F] to [C, C, E, G]
+	- this routine will also rank all the voice-leadings by size, so that, e.g. you can use the second-most efficient voice leading if you want
+	NB: this routine passes back pairs of the form [startPC, path]
+		
+2. voicelead takes an input set of pitches and a target set of PCs, and outputs a set of pitches;
+	- this is useful if you are generating music, and have a specific C-major chord in register; it will tell you where each voice should go
+	there is an option here to randomly choose one of the N most efficient voice leadings, so you are not always restricted to the most efficient ones
+	
+3. nonbijective_vl allows notes to be doubled; sometimes this produces a more efficient voice leading than a bijective voice leading
+	- for this reason, you cannot always control the number of voices
+	NB: this routine passes back pairs of PCs, from which you may need to calculate paths
+
+(For details on the nonbijective_vl algorithm, see Tymozko, D., "The Geometry of Musical Chords", Science, 2006.)
+
+Sometimes, you want something in between, e.g. the best 4-voice voice leading between triads or from a 4-voice seventh to a triad; in this case, 
+you need to iterate bijective_vl over all possible doublings of the chords.  This can be time consuming.
+
+TODO: allow different choices of metric
+
+"""
+
+"""==============================================================================================================================
+
+bijective_vl expects two SORTED equal-length sets of integers representing PCs (in any modulus).
+the sort parameter sorts the possible bijective VLs by size; by default it is set to False.  Set it to true only if you want to choose from
+	among the n most efficient VLs"""
+
+def bijective_vl(firstPCs, secondPCs, sort = False):
+	if len(firstPCs) != len(secondPCs):
+		return False
+	bijective_vl.fullList = []										# collects all the bijective VLs along with their size
+	currentBest = []												# currentBest records the best VL we have found so far
+	currentBestSize = _VERYLARGENUMBER								# currentBestSize is the size of the current best VL (starts at infinity)
+	for i in range(0, len(firstPCs)):								# iterate through every inversion of the  second PC
+		secondPCs = secondPCs[-1:] + secondPCs[:-1]
+		newSize = 0	
+		newPaths = []
+		for i in range(0, len(firstPCs)):
+			path = (secondPCs[i] - firstPCs[i]) % _MODULUS			# calculate most efficient path based on the pairs
+			if path > _HALFMODULUS: 								# negative numbers for descending paths
+				path -= _MODULUS
+			newPaths.append([firstPCs[i], path])
+			newSize += abs(path)
+		bijective_vl.fullList.append([newPaths, newSize])		
+		if newSize < currentBestSize:								# record the current best size
+			currentBestSize = newSize
+			currentBest = newPaths
+	bijective_vl.size = currentBestSize
+	if sort:
+		bijective_vl.fullList = sorted(bijective_vl.fullList, key = lambda x: x[1])
+	return currentBest
+
+"""==============================================================================================================================
+
+voicelead expects a source list of PITCHES and a target list of PCs, both should be the same length; it outputs one of the topN most efficient voice leadings
+from the source pitches to the target PCs.  
+
+if topN is 1, it gives you the most efficient voice leading"""
+
+def voicelead(inPitches, targetPCs, topN = 1):
+	inPCs = sorted([p % _MODULUS for p in inPitches])							# convert input pitches to PCs and sort them
+	targetPCs = sorted(targetPCs)
+	paths = bijective_vl(inPCs, targetPCs, topN != 1)							# find the possible bijective VLs
+	if topN != 1:																# randomly select on of the N most efficient possibilities
+		myRange = min(len(bijective_vl.fullList), topN)
+		paths = bijective_vl.fullList[random.randrange(0, myRange)][0]
+	output = []
+	tempPaths = paths[:]														# copy the list of paths
+	for inPitch in inPitches:
+		for path in tempPaths:													# when we find a path remove it from our list (so we don't duplicate paths)
+			if (inPitch % _MODULUS) == path[0]:
+				output.append(inPitch + path[1])
+				tempPaths.remove(path)
+				break
+	return output
+
+"""==============================================================================================================================
+
+nonbijective_vl expects a source list of PCs or pitches and a target list of PCs or pitches, of any lengths; it outputs the most efficient voice leading from 
+source to target.  Voices can be arbitrarily doubled.  
+
+To see why this is interesting, compare bijective_vl([0, 4, 7, 11], [4, 8, 11, 3]) to nonbijective_vl([0, 4, 7, 11], [4, 8, 11, 3])
+
+for PCs, nonbijective_vl iterates over every inversion of the target chord; for each inversion it builds a matrix showing the most efficient voice leading
+such that the first note of source goes to the first note of target (see Tymoczko "The Geometry of Musical Chords" for details)
+
+TODO: choose the smaller of source and target to iterate over??
+
+"""
+
+def nonbijective_vl(source, target, pcs = True):
+	curVL = []
+	curSize = _VERYLARGENUMBER
+	if pcs: 
+		source = [x % _MODULUS for x in source]
+		target = [x % _MODULUS for x in target]
+	source = sorted(list(set(source)))
+	target = sorted(list(set(target)))
+	if pcs:
+		for i in range(len(target)):								# for PCs, iterate over every inversion of the target
+			tempTarget = target[i:] + target[:i]					
+			newSize = build_matrix(source, tempTarget)				# generate the matrix for this pairing
+			if newSize < curSize:									# save it if it is the most efficient we've found
+				curSize = newSize
+				curVL = find_matrix_vl()
+		curVL = curVL[:-1]
+	else:
+		curSize = build_matrix(source, tempTarget)					# no need to iterate for pitches
+		curVL = find_matrix_vl()
+	return curSize, curVL
+
+def build_matrix(source, target, pcs = True):						# requires sorted source and target chords
+	global theMatrix
+	global outputMatrix
+	global globalSource
+	global globalTarget
+	if pcs: 
+		source = source + [source[0]]
+		target = target + [target[0]]
+		distanceFunction = lambda x, y: min((x - y) % _MODULUS, (y - x) % _MODULUS)		# add **2 for Euclidean distance
+	else:
+		distanceFunction = lambda x, y: abs(x - y)
+	globalSource = source
+	globalTarget = target
+	theMatrix = []
+	for targetItem in target:
+		theMatrix.append([])
+		for sourceItem in source:
+			theMatrix[-1].append(distanceFunction(targetItem, sourceItem))
+	outputMatrix = [x[:] for x in theMatrix]
+	for i in range(1, len(outputMatrix[0])):
+		outputMatrix[0][i] += outputMatrix[0][i-1]
+	for i in range(1, len(outputMatrix)):
+		outputMatrix[i][0] += outputMatrix[i-1][0]
+	for i in range(1, len(outputMatrix)):
+		for j in range(1, len(outputMatrix[i])):
+			outputMatrix[i][j] += min([outputMatrix[i][j-1], outputMatrix[i-1][j], outputMatrix[i-1][j-1]])
+	return outputMatrix[i][j] - theMatrix[i][j]
+			
+def find_matrix_vl():							# identifies the voice leading for each matrix
+	theVL = []
+	i = len(outputMatrix) - 1
+	j = len(outputMatrix[i-1]) - 1
+	theVL.append([globalSource[j], globalTarget[i]])
+	while (i > 0 or j > 0): 
+		newi = i
+		newj = j
+		myMin = _VERYLARGENUMBER
+		if i > 0 and j > 0:
+			newi = i - 1
+			newj = j - 1
+			myMin = outputMatrix[i-1][j-1]
+			if outputMatrix[i-1][j] < myMin:
+				myMin = outputMatrix[i-1][j]
+				newj = j
+			if outputMatrix[i][j - 1] < myMin:
+				myMin = outputMatrix[i][j-1]
+				newi = i
+			i = newi
+			j = newj
+		elif i > 0:
+			i = i - 1
+		elif j > 0:
+			j = j - 1
+		theVL.append([globalSource[j], globalTarget[i]])
+	return theVL[::-1]
+
+"""==============================================================================================================================
+
+A simple routine to put voice leadings in 'normal form.'  Essentially, we just apply the standard "left-packing" algorithm to the first element
+in a list of [startPC, path] pairs.
+
+"""
+
+def vl_normal_form(inList):														# list of [PC, path] pairs
+	myList = sorted([[k[0] % _MODULUS] + k[1:] for k in inList])
+	currentBest = [[(k[0] - myList[0][0]) % _MODULUS] + k[1:] for k in myList]
+	vl_normal_form.transposition = myList[0][0] * -1
+	for i in range(1, len(myList)):
+		newChallenger = myList[-i:] + myList[:-i]
+		transp = newChallenger[0][0] * -1
+		newChallenger = sorted([[(k[0] - newChallenger[0][0]) % _MODULUS] + k[1:] for k in newChallenger])
+		for j in reversed(range(len(myList))):
+			if newChallenger[j][0] < currentBest[j][0]:
+				currentBest = newChallenger
+				vl_normal_form.transposition = transp
+			else:
+				if newChallenger[j][0] > currentBest[j][0]:
+					break
+	return currentBest
\ No newline at end of file
diff --git a/Notebooks/Baseline - Regular or Sequential.ipynb b/Notebooks/Baseline - Regular or Sequential.ipynb
deleted file mode 100644
index a96592c5e63a60e076181773b7eadaba13fefcf4..0000000000000000000000000000000000000000
--- a/Notebooks/Baseline - Regular or Sequential.ipynb	
+++ /dev/null
@@ -1,263 +0,0 @@
-{
- "cells": [
-  {
-   "cell_type": "code",
-   "execution_count": 1,
-   "metadata": {
-    "ExecuteTime": {
-     "end_time": "2020-11-27T10:37:17.222319Z",
-     "start_time": "2020-11-27T10:37:15.745961Z"
-    }
-   },
-   "outputs": [],
-   "source": [
-    "import os\n",
-    "import time\n",
-    "\n",
-    "# Self-code imports\n",
-    "import polytopes.baselines as baselines\n",
-    "from polytopes.model.note import Note\n",
-    "from polytopes.model.chord import Chord\n",
-    "import polytopes.polytopical_costs as pc\n",
-    "import polytopes.data_manipulation as dm\n",
-    "import polytopes.pattern_manipulation as pm\n",
-    "\n",
-    "#Generic imports\n",
-    "import numpy as np\n",
-    "import matplotlib.pyplot as plt\n",
-    "import pandas as pd\n",
-    "import math"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 2,
-   "metadata": {
-    "ExecuteTime": {
-     "end_time": "2020-11-27T10:37:17.228983Z",
-     "start_time": "2020-11-27T10:37:17.222319Z"
-    }
-   },
-   "outputs": [],
-   "source": [
-    "# Database\n",
-    "database_path = \"C:\\\\Users\\\\amarmore\\\\Desktop\\\\Projects\\\\RWC_annotations\\\\final_bimbot_al\\\\\""
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 3,
-   "metadata": {
-    "ExecuteTime": {
-     "end_time": "2020-11-27T10:37:17.243565Z",
-     "start_time": "2020-11-27T10:37:17.230978Z"
-    }
-   },
-   "outputs": [],
-   "source": [
-    "# Files to load: .seq\n",
-    "auto = []\n",
-    "manual = []\n",
-    "auto_simple = []\n",
-    "manual_simple = []\n",
-    "for file in os.listdir(database_path):\n",
-    "    bag_of_words = file.split(\".\")\n",
-    "    if bag_of_words[-1] == \"seq\":\n",
-    "        if bag_of_words[-2] == \"auto\":\n",
-    "            auto.append(file)\n",
-    "        elif bag_of_words[-2] == \"manual\":\n",
-    "            manual.append(file)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 4,
-   "metadata": {
-    "ExecuteTime": {
-     "end_time": "2020-11-27T11:04:13.665385Z",
-     "start_time": "2020-11-27T10:37:17.245560Z"
-    },
-    "scrolled": false
-   },
-   "outputs": [
-    {
-     "data": {
-      "image/png": "iVBORw0KGgoAAAANSUhEUgAAA3MAAAFNCAYAAACqpjaOAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjEsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy8QZhcZAAAgAElEQVR4nO3debhdVX3/8feHSayoTAExILEaWwE10ghYtA5YQNGCLVTUSlD80TpiW7XRtqJUWrBVrGNLBQUnwBEEHFIUFUUEZAaRiGgiFELDqIgFv78/9rpycrkjubk3O/f9ep773L3XXnuftYebnM9Ze6+TqkKSJEmS1C/rzXQDJEmSJEmTZ5iTJEmSpB4yzEmSJElSDxnmJEmSJKmHDHOSJEmS1EOGOUmSJEnqIcOcpFktyTOTLJ/pdkiSJE2WYU7SWiPJdUnuSnJnkhuTfDTJJjPQhudM4fYWJLkwyS/b7wVTte3pks7RSf63/bwrSUapu02S05Jcn6SSzBu2/M+TfLcdj7NHWP8FSS5v18B3k+ywRnZqCiTZPMkXkvwiyU+TvGSc+jsn+dbA9X3YwLIFSb6d5LYky5O8bWDZDkkuSHJL+/nv4cdlrG2P06aDk9zb1hv6+cBkj8W6ajLnOMmb2rV7R5KfJHnTsOXzknyjXfs/HPx3JslOSb6a5OYk9/sC4CRnJ/nVwDm6emr3VFJfGeYkrW1eUFWbADsDTwH+YYbb84Al2Qg4FfgEsBlwAnBqK5/q19pgqrc54FBgP+BJwBOB5wN/OUrd3wBfAf5slOUrgfcCRw1fkGQ+8Engr4BNgS8Bpz2QfVvDx2PIB4FfA1sDLwU+nGTHUdqzJd1x+U9gC+CxwNcGqnwK+BawOfAM4FVJ/qQtux7Yvy3bEjgNOGkS2x7PuVW1ycDPayex7lpriq6BCZ9jIMBBdH/rewOvTXLgwPJPAxfRnaO/Bz6bZE5b9n/AKcAhY7TltQPn6Pce6A5JWrcY5iStlarq58CXgZ0Akjw8yXFJbkjy8yTvTLJ+W3ZwknOS/FvrufhJkucObSvJy5Nc1T4xvzbJiEEkyceBRwFfap9+vznJGUleN6zepUn2m8BuPBPYAHhvVd1dVe+je8P37Ikcg9az9frW5puT/GuS9Qb2+TtJjkmyEnh7K39F29db2if92w9sb8ckS5KsbL03b51IO4BFwLurank7L+8GDh6pYlXdWFUfAs4fZfl/V9UpdAFluL2Ab1fVOVV1D3A0MJcu3IwrXa/q3yW5FPhFkg2SLE7y43bur0zywoH6Q8fw/a1H7IdJ9pjgaz2ELrD+Y1XdWVXn0IWsl42yyt8AX62qT7Zr4Y6qumpg+Tzgk1V1b1X9GDgH2BGgqm6tquuqquiun3vpAttEtz0lWu/QO9P1mN6Z5EtJtkjyySS3Jzk/Az2xSX5/4Hq7OsmfDyzbJ8lFbb1lSd4+sGzjJJ9I1wt8a9vu1m3ZKj3nSd6e5BNtel77mzkkyc+Ar7fy3Vqbb01ySZJnTnB/J3WOq+pdVfWDqrqnqq6m+yBn97atx9F9QHV4Vd1VVZ8DLmvbp6qurqrjgCsm0jZJGmKYk7RWSrId8Dy6T7Kh69W6h+5N7JOBPYFXDqyyK3A1Xc/Fu4Djkt/eCngTXW/Sw4CXA8ck2Xn4a1bVy4Cf0XoHq+pd7XX/YqBdT6ILGGe2+dOTLB5lN3YELm1vwodc2son6oXAQro3gvsCrxi2z9cCWwFHtoD5VuBPgTnAt+l6A0jyUOC/6XpwHkl3HM9qy56W5NYx2rAjcMnA/CWT3IeJSvsZPr/TJLbxYmAfYNMWCH8MPB14OPAO4BNJthmoP3QMtwQOBz6fZHOAFgRPH+V1HgfcW1U/Gigb67jsBqxsoeKmFoQeNbD8vcBBSTZM8nvAU+nO12+1c/Qr4P3AP09i21PpQLowMxd4DHAu8FG6XsOr6I7hUBBaQtfjuBXdeflQ7uvV+gVdL9amdOfrVQMfkCyiO1/b0fVi/RVw1yTa+Azg8cBeSeYCZwDvbG18I/C5tB6xKT7Hv9X+7Xk694WzHYFrq+qOyW5rwL+0D3W+M9FAKmndZ5iTtLb5YnvTeg7wTeCf26fyzwXeUFW/qKqbgGPo3lgO+WlV/VdV3UsXwLahuzWKqjqjqn5cnW/S3YL29Am251RgfrpbAKF7I3tyVf26bfv5VXW/WwabTYDbhpXdBjx0gq8NcHRVrayqn9G94X/xwLLrq+r9rSfgLrpbH/+lqq5qQeafgQWtd+75wP9U1bur6let9+a8tg/nVNWmY7Rh+H7cBmwyEJanyhLgGekGpdmILphuBPzOJLbxvqpa1o4HVfWZqrq+qn5TVScD1wC7DNS/ia7n9P/a8qvpwgVVdVRVPX+U15nsud2WLqQcRtf7+xNa0G5Op7uV8i7gh8BxVbVK72Y7Rw8HXst9H3JMZNvj2a31Wg397DZG3Y+2v6Xb6HrOf9x6W+8BPkP3QQt019t1VfXRdn3+APhc20eq6uyquqydl0tbe4d6YP+Pdrto66m8sKpun8T+vL39O3EX3QcxZ1bVme21lgAX0H1QNNXneJU20L3H+ugUbAvg74DfpQvRx9LdPfCYCa4raR1mmJO0ttmvqjatqu2r6tXtDdn2wIbADUNvOOmeD9pqYL3/GZqoql+2yU0Akjw3yffa7V630r2R23Iijamqu+meZfmLdLc4vhj4+AT35U663sBBDwPuGKHuaJYNTP+UrldtpGXQHad/HzhGK+l6tubS9XL8eBKvO2j4fjwMuHNYj+Nqq6of0oWSDwA30J2jK4HJjDa6yjFJclCSiweOyU6seu5/Pmw/hh/j0Uz23N4FfKGqzq+qX9H1Ev5hutuHN6frMT0C2JjuXO2V5NXDN1JVvwD+AzgxyVbjbXsC+wHwvfY3N/TzvTHq3jhsn4bPDw1YtD2w62BIpHvm7BEASXZNNxjIiiS30fW+DZ2XjwNfBU5KN5DOu5JsOMF9gVWvge2BA4a142l0H/aM5wH9/SZ5LV2v4z7t348HvK0hVXVe+wDm7qo6AfgOLZBKmt0Mc5L6YBlwN7DlwBvOh1XVRG53ehBdj8C/AVu33o0zWfV2vkEjBZQT6N6I7gH8sqrOnWC7rwCeOKwH64lM7rmY7QamH8Wqz5oNb+sy4C+HvTF/cFV9ty17oJ/kX0E3+MmQJ7GGnu2pqs9W1U5VtQXdLXvbM8rzd6NtYmii9Uj+F11P1hbt3F/Oqud+7rDzM/wYj+ZHwAYDPbYw9nG5lFXP19B06Hpc7q2qE1sv1nK6AU5Ge7O+Hl1v5dwJbHumLAO+Oexa3KSqXtWWf4ru+bPtqurhdAE1AK2X9B1VtQPwh3S9fAe19X7Bqj21jxjhtQePxTLg48Pa8ZAxetMHTfYck+QVwGJgj3Yeh1wB/G673XlC2xrH0POTkmY5w5yktV5V3UB3a+S7kzwsyXpJHpNkIgNjbAQ8CFgB3JNuYJQ9x6h/I92b68HXP5dulMZ3M/FeOYCz6QareH2SB7VP7OG+gRkOTnLdONt4U5LN2jOEhwEnj1H3P4C3DD2X1Hp9DmjLTgcekeQNrS0PTbLrBPfjROBvksxN8kjgb4GPjVY5ycZ0xxzgQW1+aNn6bX4DYL10g11sOLD8D1qdOXS9r19qPXZD3wk4md7Ah9C96V3R1n8593/+biu687NhO1aPpz0POZbWQ/Z54IgkD0myO90zjaNdHx8FXpjuKwg2BP4ROKeqbqULDUnyknZtPwJ4Ee05xSR/nOTJ7bg8DHgPcAvdM2rjbXto4JK3j7dPU+x04HFJXtaO7YZJnpLk8W35Q4GVVfWrJLsAvx3yP8mzkjwh3QBHt9PddnlvW3wxcGDb3kLabZtj+ATwgiR7DV177TradrwdmOw5TvJSulub/7iqrh22rR+1th/e2vBCug92PtfWTfu72KjNb9w+iCLJpq39G6cb1OelwB/R9V5KmuUMc5L64iC6NzpX0r2R/SwTuFWqugEHXk93q+QtdG8aTxtjlX8B/qHdkvXGgfITgSfQvTn8rSRfziijQrbn6vZrbb+VbvCS/Yaet6PrdfvOOLtwKnAh3RvBM4DjRqtYVV+gGwHypCS30/VCPbctuwP4Y+AFdLekXgM8q+3D05PcOUYb/pPuawIua9s8o5XR1r8zyeAziHfR3VYG3fNfg4NXvKzNf5juucW76HrPhvw73bG6uv3+fwPLtqMbcGNCqupKugB+Ll1IfwL3P97nAfOBm4Ejgf2r6n/bfr01yZfHeIlXAw+me+7u08CrquqKtu4qx7Sqvk73DOAZrf5jaQGmPQ/2p8Bf012jF9Md5yPb6pu27d9Gd6vsY4G92y2VY267mch1NqXa9bYn3XOt19Ndc0dzX8h/NV1IugN4G93f55BH0P19304XWL/JfX93/0jXw3wL3e2knxqnHcvoAthb6UL9MuBNtPc/U3mO6QZZ2QI4P/d9H9x/DCw/kG4wo1vovppj/6pa0ZZtT/e3MNRTdxfd3wB0t5i/s7X/ZuB1dP+O+F1zksgUP/IgSeukJAcBh1bV06Zwm18DDqtRhpFvvVDzq2rpVL1mnyX5CPCZqpqSHokkBwOvnMpzurZpPVCfqaqnznRbJElTbzq+VFWSei3J79B9Qv+hqdxuVY11u6eGqapXjl9Lg9pzWwY5SVpHeZulJI0hyV50tzfdyDi3dEmSJE0nb7OUJEmSpB6yZ06SJEmSesgwJ0mSJEk9tFYPgLLlllvWvHnzZroZkiRJkjQjLrzwwpuras5Iy9bqMDdv3jwuuOCCmW6GJEmSJM2IJD8dbZm3WUqSJElSDxnmJEmSJKmHDHOSJEmS1EOGOUmSJEnqIcOcJEmSJPWQYU6SJEmSesgwJ0mSJEk9ZJiTJEmSpB4yzEmSJElSDxnmJEmSJKmHDHOSJEmS1EMbzHQD1E/zFp+xWutfd9Q+U9QSSZIkaXayZ06SJEmSesgwJ0mSJEk9ZJiTJEmSpB6aUJhLcl2Sy5JcnOSCVrZ5kiVJrmm/N2vlSfK+JEuTXJpk54HtLGr1r0myaM3skiRJkiSt+ybTM/esqlpQVQvb/GLgrKqaD5zV5gGeC8xvP4cCH4Yu/AGHA7sCuwCHDwVASZIkSdLkrM5tlvsCJ7TpE4D9BspPrM73gE2TbAPsBSypqpVVdQuwBNh7NV5fkiRJkmatiYa5Ar6W5MIkh7ayravqBoD2e6tWPhdYNrDu8lY2WrkkSZIkaZIm+j1zu1fV9Um2ApYk+eEYdTNCWY1RvurKXVg8FOBRj3rUBJsnSZIkSbPLhHrmqur69vsm4At0z7zd2G6fpP2+qVVfDmw3sPq2wPVjlA9/rWOramFVLZwzZ87k9kaSJEmSZolxw1yShyR56NA0sCdwOXAaMDQi5SLg1DZ9GnBQG9VyN+C2dhvmV4E9k2zWBj7Zs5VJkiRJkiZpIrdZbg18IclQ/U9V1VeSnA+ckuQQ4GfAAa3+mcDzgKXAL4GXA1TVyiT/BJzf6h1RVSunbE8kSZIkaRYZN8xV1bXAk0Yo/19gjxHKC3jNKNs6Hjh+8s2UJEmSJA1ana8mkCRJkiTNEMOcJEmSJPWQYU6SJEmSesgwJ0mSJEk9ZJiTJEmSpB4yzEmSJElSDxnmJEmSJKmHDHOSJEmS1EOGOUmSJEnqIcOcJEmSJPWQYU6SJEmSesgwJ0mSJEk9ZJiTJEmSpB4yzEmSJElSDxnmJEmSJKmHDHOSJEmS1EOGOUmSJEnqIcOcJEmSJPWQYU6SJEmSesgwJ0mSJEk9ZJiTJEmSpB4yzEmSJElSDxnmJEmSJKmHDHOSJEmS1EOGOUmSJEnqIcOcJEmSJPWQYU6SJEmSesgwJ0mSJEk9ZJiTJEmSpB4yzEmSJElSDxnmJEmSJKmHDHOSJEmS1EOGOUmSJEnqIcOcJEmSJPWQYU6SJEmSesgwJ0mSJEk9ZJiTJEmSpB4yzEmSJElSDxnmJEmSJKmHDHOSJEmS1EOGOUmSJEnqoQmHuSTrJ7koyelt/tFJzktyTZKTk2zUyh/U5pe25fMGtvGWVn51kr2memckSZIkabaYTM/cYcBVA/NHA8dU1XzgFuCQVn4IcEtVPRY4ptUjyQ7AgcCOwN7Ah5Ksv3rNlyRJkqTZaUJhLsm2wD7AR9p8gGcDn21VTgD2a9P7tnna8j1a/X2Bk6rq7qr6CbAU2GUqdkKSJEmSZpuJ9sy9F3gz8Js2vwVwa1Xd0+aXA3Pb9FxgGUBbflur/9vyEdaRJEmSJE3CuGEuyfOBm6rqwsHiEarWOMvGWmfw9Q5NckGSC1asWDFe8yRJkiRpVppIz9zuwJ8kuQ44ie72yvcCmybZoNXZFri+TS8HtgNoyx8OrBwsH2Gd36qqY6tqYVUtnDNnzqR3SJIkSZJmg3HDXFW9paq2rap5dAOYfL2qXgp8A9i/VVsEnNqmT2vztOVfr6pq5Qe20S4fDcwHvj9leyJJkiRJs8gG41cZ1d8BJyV5J3ARcFwrPw74eJKldD1yBwJU1RVJTgGuBO4BXlNV967G60uSJEnSrDWpMFdVZwNnt+lrGWE0yqr6FXDAKOsfCRw52UZKkiRJklY1me+ZkyRJkiStJQxzkiRJktRDhjlJkiRJ6iHDnCRJkiT1kGFOkiRJknrIMCdJkiRJPWSYkyRJkqQeMsxJkiRJUg8Z5iRJkiSphwxzkiRJktRDhjlJkiRJ6iHDnCRJkiT1kGFOkiRJknrIMCdJkiRJPWSYkyRJkqQeMsxJkiRJUg8Z5iRJkiSphwxzkiRJktRDhjlJkiRJ6iHDnCRJkiT1kGFOkiRJknrIMCdJkiRJPWSYkyRJkqQeMsxJkiRJUg8Z5iRJkiSphwxzkiRJktRDhjlJkiRJ6iHDnCRJkiT1kGFOkiRJknrIMCdJkiRJPWSYkyRJkqQeMsxJkiRJUg8Z5iRJkiSphwxzkiRJktRDhjlJkiRJ6iHDnCRJkiT1kGFOkiRJknrIMCdJkiRJPWSYkyRJkqQeMsxJkiRJUg8Z5iRJkiSph8YNc0k2TvL9JJckuSLJO1r5o5Ocl+SaJCcn2aiVP6jNL23L5w1s6y2t/Ooke62pnZIkSZKkdd1EeubuBp5dVU8CFgB7J9kNOBo4pqrmA7cAh7T6hwC3VNVjgWNaPZLsABwI7AjsDXwoyfpTuTOSJEmSNFuMG+aqc2eb3bD9FPBs4LOt/ARgvza9b5unLd8jSVr5SVV1d1X9BFgK7DIleyFJkiRJs8yEnplLsn6Si4GbgCXAj4Fbq+qeVmU5MLdNzwWWAbTltwFbDJaPsI4kSZIkaRImFOaq6t6qWgBsS9eb9viRqrXfGWXZaOWrSHJokguSXLBixYqJNE+SJEmSZp1JjWZZVbcCZwO7AZsm2aAt2ha4vk0vB7YDaMsfDqwcLB9hncHXOLaqFlbVwjlz5kymeZIkSZI0a0xkNMs5STZt0w8GngNcBXwD2L9VWwSc2qZPa/O05V+vqmrlB7bRLh8NzAe+P1U7IkmSJEmzyQbjV2Eb4IQ28uR6wClVdXqSK4GTkrwTuAg4rtU/Dvh4kqV0PXIHAlTVFUlOAa4E7gFeU1X3Tu3uSJIkSdLsMG6Yq6pLgSePUH4tI4xGWVW/Ag4YZVtHAkdOvpmSJEmSpEGTemZOkiRJkrR2MMxJkiRJUg8Z5iRJkiSphwxzkiRJktRDhjlJkiRJ6iHDnCRJkiT1kGFOkiRJknrIMCdJkiRJPWSYkyRJkqQeMsxJkiRJUg8Z5iRJkiSphwxzkiRJktRDhjlJkiRJ6iHDnCRJkiT1kGFOkiRJknrIMCdJkiRJPWSYkyRJkqQeMsxJkiRJUg8Z5iRJkiSphwxzkiRJktRDhjlJkiRJ6iHDnCRJkiT1kGFOkiRJknrIMCdJkiRJPWSYkyRJkqQeMsxJkiRJUg8Z5iRJkiSphwxzkiRJktRDhjlJkiRJ6iHDnCRJkiT1kGFOkiRJknrIMCdJkiRJPWSYkyRJkqQeMsxJkiRJUg8Z5iRJkiSphwxzkiRJktRDhjlJkiRJ6iHDnCRJkiT1kGFOkiRJknrIMCdJkiRJPWSYkyRJkqQeMsxJkiRJUg+NG+aSbJfkG0muSnJFksNa+eZJliS5pv3erJUnyfuSLE1yaZKdB7a1qNW/JsmiNbdbkiRJkrRum0jP3D3A31bV44HdgNck2QFYDJxVVfOBs9o8wHOB+e3nUODD0IU/4HBgV2AX4PChAChJkiRJmpxxw1xV3VBVP2jTdwBXAXOBfYETWrUTgP3a9L7AidX5HrBpkm2AvYAlVbWyqm4BlgB7T+neSJIkSdIsMaln5pLMA54MnAdsXVU3QBf4gK1atbnAsoHVlrey0cqHv8ahSS5IcsGKFSsm0zxJkiRJmjUmHOaSbAJ8DnhDVd0+VtURymqM8lULqo6tqoVVtXDOnDkTbZ4kSZIkzSoTCnNJNqQLcp+sqs+34hvb7ZO03ze18uXAdgOrbwtcP0a5JEmSJGmSJjKaZYDjgKuq6j0Di04DhkakXAScOlB+UBvVcjfgtnYb5leBPZNs1gY+2bOVSZIkSZImaYMJ1NkdeBlwWZKLW9lbgaOAU5IcAvwMOKAtOxN4HrAU+CXwcoCqWpnkn4DzW70jqmrllOyFJEmSJM0y44a5qjqHkZ93A9hjhPoFvGaUbR0PHD+ZBkqSJEmS7m9So1lKkiRJktYOhjlJkiRJ6iHDnCRJkiT1kGFOkiRJknrIMCdJkiRJPWSYkyRJkqQeMsxJkiRJUg8Z5iRJkiSphwxzkiRJktRDhjlJkiRJ6iHDnCRJkiT1kGFOkiRJknrIMCdJkiRJPWSYkyRJkqQeMsxJkiRJUg8Z5iRJkiSphwxzkiRJktRDhjlJkiRJ6iHDnCRJkiT1kGFOkiRJknrIMCdJkiRJPWSYkyRJkqQeMsxJkiRJUg8Z5iRJkiSphwxzkiRJktRDhjlJkiRJ6iHDnCRJkiT1kGFOkiRJknrIMCdJkiRJPWSYkyRJkqQeMsxJkiRJUg8Z5iRJkiSphwxzkiRJktRDhjlJkiRJ6iHDnCRJkiT1kGFOkiRJknrIMCdJkiRJPWSYkyRJkqQeMsxJkiRJUg8Z5iRJkiSphwxzkiRJktRD44a5JMcnuSnJ5QNlmydZkuSa9nuzVp4k70uyNMmlSXYeWGdRq39NkkVrZnckSZIkaXbYYAJ1PgZ8ADhxoGwxcFZVHZVkcZv/O+C5wPz2syvwYWDXJJsDhwMLgQIuTHJaVd0yVTui2Wfe4jNWa/3rjtpniloiSZIkTb9xe+aq6lvAymHF+wIntOkTgP0Gyk+szveATZNsA+wFLKmqlS3ALQH2noodkCRJkqTZ6IE+M7d1Vd0A0H5v1crnAssG6i1vZaOVS5IkSZIegKkeACUjlNUY5fffQHJokguSXLBixYopbZwkSZIkrSseaJi7sd0+Sft9UytfDmw3UG9b4Poxyu+nqo6tqoVVtXDOnDkPsHmSJEmStG57oGHuNGBoRMpFwKkD5Qe1US13A25rt2F+FdgzyWZt5Ms9W5kkSZIk6QEYdzTLJJ8GnglsmWQ53aiURwGnJDkE+BlwQKt+JvA8YCnwS+DlAFW1Msk/Aee3ekdU1fBBVSRJkiRJEzRumKuqF4+yaI8R6hbwmlG2czxw/KRaJ0mSJEka0VQPgCJJkiRJmgaGOUmSJEnqoXFvs9S6ad7iM2a6CZIkSZJWgz1zkiRJktRDhjlJkiRJ6iHDnCRJkiT1kGFOkiRJknrIMCdJkiRJPeRoltIDtLojgl531D5T1BJJkiTNRvbMSZIkSVIPGeYkSZIkqYcMc5IkSZLUQ4Y5SZIkSeohw5wkSZIk9ZBhTpIkSZJ6yDAnSZIkST1kmJMkSZKkHvJLwzUjVvcLtyVJkqTZzp45SZIkSeohw5wkSZIk9ZBhTpIkSZJ6yDAnSZIkST1kmJMkSZKkHjLMSZIkSVIPGeYkSZIkqYcMc5IkSZLUQ4Y5SZIkSeohw5wkSZIk9ZBhTpIkSZJ6yDAnSZIkST1kmJMkSZKkHjLMSZIkSVIPGeYkSZIkqYcMc5IkSZLUQ4Y5SZIkSeqhDWa6AZIemHmLz1it9a87ap8paokkSZJmgj1zkiRJktRDhjlJkiRJ6iHDnCRJkiT1kGFOkiRJknrIAVA0a63uACKSJEnSTJr2nrkkeye5OsnSJIun+/UlSZIkaV0wrT1zSdYHPgj8MbAcOD/JaVV15XS2Q1obrAs9g7P96xGm4hz2/RhIkqSZM909c7sAS6vq2qr6NXASsO80t0GSJEmSem+6n5mbCywbmF8O7DrNbVgrzPYeDQlmvndyXfg78t8SaebZSy9ppqSqpu/FkgOAvarqlW3+ZcAuVfW6gTqHAoe22d8Drp62Bk7clsDNM90IzXpeh1obeB1qbeB1qLWB16HWlO2ras5IC6a7Z245sN3A/LbA9YMVqupY4NjpbNRkJbmgqhbOdDs0u3kdam3gdai1gdeh1gZeh5oJ0/3M3PnA/CSPTrIRcCBw2jS3QZIkSZJ6b1p75qrqniSvBb4KrA8cX1VXTGcbJEmSJGldMO1fGl5VZwJnTvfrTrG1+jZQzRpeh1obeB1qbeB1qLWB16Gm3bQOgCJJkiRJmhrT/cycJEmSJGkKGOYmKcneSa5OsjTJ4pluj2aHJMcnuSnJ5QNlmydZkuSa9nuzmWyj1n1JtkvyjSRXJbkiyWGt3GtR0ybJxkm+n+SSdh2+o5U/Osl57To8uQ20Jq0xSdZPclGS09u816CmnWFuEpKsD3wQeC6wA/DiJDvMbKs0S3wM2HtY2WLgrKqaD5zV5qU16R7gb6vq8cBuwGvav4Fei5pOdwPPrqonAQuAvZPsBhwNHNOuw1uAQ2awjZodDgOuGpj3GtS0M8xNzi7A0qq6tqp+DZwE7DvDbdIsUFXfAlYOK94XOKFNnwDsN62N0qxTVTdU1Q/a9B10b2Lm4rWoaVSdO9vshu2ngGcDn23lXodao5JsC+wDfKTNB69BzQDD3OTMBZYNzC9vZdJM2LqqboDuTTaw1Qy3R7NIknnAk4Hz8FrUNGu3t10M3AQsAX4M3FpV97Qq/v+sNe29wJuB37T5LRPixcgAAAekSURBVPAa1AwwzE1ORihzOFBJs0qSTYDPAW+oqttnuj2afarq3qpaAGxLd9fM40eqNr2t0myR5PnATVV14WDxCFW9BrXGTfv3zPXccmC7gfltgetnqC3SjUm2qaobkmxD9wm1tEYl2ZAuyH2yqj7fir0WNSOq6tYkZ9M9w7lpkg1az4j/P2tN2h34kyTPAzYGHkbXU+c1qGlnz9zknA/Mb6MVbQQcCJw2w23S7HUasKhNLwJOncG2aBZoz4QcB1xVVe8ZWOS1qGmTZE6STdv0g4Hn0D2/+Q1g/1bN61BrTFW9paq2rap5dO8Fv15VL8VrUDPALw2fpPYpzHuB9YHjq+rIGW6SZoEknwaeCWwJ3AgcDnwROAV4FPAz4ICqGj5IijRlkjwN+DZwGfc9J/JWuufmvBY1LZI8kW5wifXpPpQ+paqOSPK7dAOTbQ5cBPxFVd09cy3VbJDkmcAbq+r5XoOaCYY5SZIkSeohb7OUJEmSpB4yzEmSJElSDxnmJEmSJKmHDHOSJEmS1EOGOUmSJEnqIcOcJM0iSf4+yRVJLk1ycZJdZ7pNg5LMS/KSgflnJvnYam7zI0l2mIK2vSHJQW36iCTPWd1ttm3duRrrzklyXpKLkjx92LLrkmw5Be1b0L6WZ7x2fGV1X0uSNDkbzHQDJEnTI8lTgecDO1fV3e2N/kYz3Kzh5gEvAT41VRusqleu7jaSbAC8Ati5bfNtq7vNKbIH8MOqWjRuzQduAbAQOHO0ClW1IskNSXavqu+swbZIkgbYMydJs8c2wM1DX2JbVTdX1fUASf4gyTeTXJjkq0m2aeVPab145yb51ySXt/KDk3wxyZeS/CTJa5P8Tesh+l6SzVu9xyT5Stvut5P8fiv/WJL3JflukmuT7N/aeBTw9NZr+NfAr4Hb2jrPaOUXt9d56ODOJXlIkjOSXJLk8iQvauVnJ1mY5E8G1r86yU/G2vdhng38oKruGWj//m36uiTvSPKDJJcN7eOwth2c5PPtWFyT5F3Dlr+7rX9WkjkjrL99W3Zp+/2oJAuAdwHPa/v04BHa/aYk328/j23bmpPkc0nObz+7t/Jd2vm4qP3+vSQbAUcAL2qv8aIxzsMXgZeO0AZJ0hpimJOk2eNrwHZJfpTkQ0meAZBkQ+D9wP5V9QfA8cCRbZ2PAn9VVU8F7h22vZ3oetF2afV/WVVPBs4FDmp1jgVe17b7RuBDA+tvAzyNrrfwqFa2GPh2VS2oqmOq6rtVdVhb9kbgNVW1AHg6cNew9uwNXF9VT6qqnYBVbvurqtPadhcAlwD/Ns6+D9oduHCE8iE3V9XOwIdbO0eyAHgR8AS6cLRdK38IXVDcGfgmcPgI634AOLGqngh8EnhfVV0MvA04ue3X8OMBcHtV7dLWf28r+3fgmKp6CvBnwEda+Q+BP2rn8G3AP1fVr4e9xsmMfh4uaPOSpGnibZaSNEtU1Z1J/oDuDfezgJOTLKZ7E74TsCQJwPrADUk2BR5aVd9tm/gUXfAa8o2qugO4I8ltwJda+WXAE5NsAvwh8Jm2XYAHDaz/xar6DXBlkq0nsAvfAd6T5JPA56tq+bDll9EFtKOB06vq2yNtJMmbgbuq6oNJdhpp30dYbRvgqjHa9vn2+0LgT0epc1ZVDfUyXglsDywDfgOc3Op8YmBbg546sN2P0/XITcSnB34f06afA+wwcE4e1nrXHg6ckGQ+UMCGo2xztPNwE/DICbZLkjQFDHOSNItU1b3A2cDZSS4DFtEFkCta79tvJdlsnM3dPTD9m4H539D9/7IecGvrwRlv/YxSZ7DtRyU5A3ge8L0kz6mqHw4s/1ELq88D/iXJ16rqiGH7tAdwAPBHA697v30fwV3AxmMsH9qXexn9/9bB/R2rXo3TlonWGV5vaHo94KnDe/KSvJ8uoL8wyTy66+T+Gxz9PGzM/XtLJUlrkLdZStIs0Z6Bmj9QtAD4KXA1MCfdACkk2TDJjlV1C12v226t/oGTeb2quh34SZID2naT5EnjrHYH8NCRFiR5TFVdVlVH0/Um/v6w5Y+ku9XzE8C/0QYrGVi+Pd1tnn8+EGRG3PcRXv4q4LHjtP2BWg8YembwJcA5I9T5Lvcd/5eOUmckLxr4fW6b/hrw2qEK7dk76Hrmft6mDx7YxirnZIzz8Djg8gm2S5I0BQxzkjR7bEJ3G92VSS4FdgDe3p6L2h84OsklwMV0t0cCHAIcm+Rcul6s2yb5mi8FDmnbvQLYd5z6lwL3tEFM/nrYsje0gU0uoesB+vKw5U8Avp/kYuDvgXcOW34wsAXwhTZ4x5nj7PugL3Nfb95U+wWwY5IL6QZaOWKEOq8HXt7O28uAw0aoM5IHJTmv1R86nq8HFrbBVK4E/qqVv4uuR/M7dLebDvkG3W2ZF6cbVGa08/As4IwJtkuSNAVSNdE7NSRJs02STarqzja9GNhmYECSWSXJF4A3V9U1M92WtVGSbwH7th5dSdI0sGdOkjSWfVqPzOV0A6cM7+2aTRbTDYSiYdrXKbzHICdJ08ueOUmSJEnqIXvmJEmSJKmHDHOSJEmS1EOGOUmSJEnqIcOcJEmSJPWQYU6SJEmSesgwJ0mSJEk99P8B8rvJxr58qG4AAAAASUVORK5CYII=\n",
-      "text/plain": [
-       "<Figure size 1080x360 with 1 Axes>"
-      ]
-     },
-     "metadata": {
-      "needs_background": "light"
-     },
-     "output_type": "display_data"
-    },
-    {
-     "data": {
-      "image/png": "iVBORw0KGgoAAAANSUhEUgAAA20AAAFNCAYAAACTwYfVAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjEsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy8QZhcZAAAgAElEQVR4nO3deZwlVX338c/XATWKiMBIcAYZFVzQCCIibnHBRBQUjBB30WB4fKIRo0ZHTdweTZCoGI0ajRhxB1cQcAuCuyjIJqCCCM4Iwii74gL8nj/qdLw0t6d7ZrqnD9Of9+vVr67lVN1TdevO1PeeU6dTVUiSJEmS+nSL+a6AJEmSJGlqhjZJkiRJ6pihTZIkSZI6ZmiTJEmSpI4Z2iRJkiSpY4Y2SZIkSeqYoU3SBiHJI5KsnO96SJIkzTZDm6RZl+SCJNcmuSbJJUn+O8km81CHR8/Svu6e5Kgkq5JcluSLSe4xqcw/JPlFkiuTvD/JrWbjtdenJMuSnJDkN0l+uLrzl+SQJCuSXJXkwiSvmrR+UZI3JLkoydVJTk2yWVt3qySHtnWXJ3lXko1H1h3W9jmx3WPn9sjXXgZvSvKr9nNIkkxR9pFJzkxyRSv7mSRLxpTbvF1r35hiP69JUqPvT5K/TvKt9t6duIbH8Nokf2if14mfl63JPjZks/y5qCS/HjnP7xtZ96Ik57dtL2qfkY1G1j84yXfb5+KMJA+dmyOW1CNDm6S58viq2gTYGXgA8E/zXJ91sRlwNHAPYCvgu8BREyuTPAZYDuwOLAPuCrxutivRAsJc/rv9MeBUYAvgVcAnkyyeouxhwD2ralPgwcDTkvzVyPrXteUPAjYFngn8tq1bDuwC3Ae4O8M1MnF9bASsAB4O3B74Z+DIJMvW5oCSLFqb7dbAgcA+wI7AfYG9gP8zRdmzgcdU1WbAnYBzgXePKfcm4JxxO0hyN2Bf4OJJqy4D3gYcvIb1n3BEVW0y8nPIWu6nK6OhZx3M5ucCYMeR8/zckeWfA3Zu296H4Zp6YTuOzRn+Dfo3hn+PDgE+l+QOs3B8km4GDG2S5lRV/Rz4PMNNCElu31pSLk7y89Yas6ite3aSbyR5c2uB+eloK0uS5yQ5p33TfH6SsTfHST4E3JnhpuaaJC9LcmySv59U7owk+8zgGL5bVYdV1WVV9QfgUOAeSbZoRfYHDquqs6rqcuD/Ac+eyflpx/zNJO/I0Er3wyS7j6w/Mckbk3wT+A1w19Wdw7bN346cp7OT7DyDekyEp9dU1bVV9SngTOBJU5yTH1XVr0cW3QBs1/Z1B+BFwN9W1YU1+EFVTYS2xwNvb+dzFfB24G/afn9dVa+tqguq6oaqOgb4KXD/GZ7PDyR5d5LjkvwaeGSSPTO02F3VWkFeO1J+WWv9OLC1blyc5CUzea1mf+AtVbWyXetvYYr3vqouqaqLRhZdTztnI/V5EMNn5b+neL3/AF4O/H7Svv+nqo4ELhq71SzJ0IL9j+2z8+t2HW6V5PPtevuf0SCRZLfWAnhFktOTPGJk3ZSf5yRbJjmmbXdZkq9PfGHR3q/tRsp+IMkb2vQjkqxM8vIkv6CdxyR7JTmt7e9bSe47w+Odtc/FdKrqJ1V1xcRLT9r2wcAlVfWJqrq+qj4MrAImB0JJGyhDm6Q5lWQb4HEM31QDHA5cx3Azcj/gL4HRb5sfCPwI2JLh2+TDkv/tbnYpQ0vGpsBzgEPHBZKqeibwM1prX2s1OBx4xki9dgSWAMe1+WOSLJ/hYf058Iuq+lWbvzdw+sj604GtRkLddB4InM9wzK8BPt2+WZ/wTIYWndsBF7Kac5hkP+C1wLMYztMTgF+1de9K8q4p6nBv4PyqunrScdx7qkonWZ7kGmAlcFvgo23Vn7X67Zuhy+iPkzx/dNP2Mzq/NMntx7zGVgytcWdNVY8xnga8keF8fQP4NcP52AzYE/i/Y8L6I4HtGc7l8rQucEkemuQKpjbuvV/dObtz29+1wEsZrvGJdYuAdwIvAGrMtvsBv6+q41ZTn/XhScBfMLwvj2f4UuaVDNfvLfhj69AS4FjgDcDmDMf7qfyxlWp1n+eXMFxXixlat1/JmHMyhT9tr7ctcGDb5/sZWkC3AN4DHJ3WhXk9fi4mfK19Lj6dSS3ISZ6W5Crglwwtbe+ZWMWNPzMTy+4zVT0kbVgMbZLmymfbzek3gK8C/9JuwB8LvKi1qFzK0Gr1lJHtLqyq/6qq6xnCydYMN21U1bHt2+iqqq8CXwIeNsP6HAVsn2T7Nv9Mhi5hv2/73quqpu1almQpw431i0cWbwJcOTI/MX27GdbtUuBtVfWHqjqCIbTuObL+A60V7zqGm9HVncPnAodU1ffaeTqvqi5sx/h3VfV3U9Rh8jFMHMeUx9DO1+0YWiI+NLL9UoaujXcH7sLQne+1Sf6irf88cFCSxUn+lHaTD9xmdP8ZnnP7CHB4Vf1wqnqMcVRVfbO11P22qk6sqjPb/BkM3d0ePmmb17XzeSZD68xT2zF+o3VnnMq4936TkS8abqSqftb2tyVDl9DR43ohcFJVnTJ5uwzPhP4LQwvmXPjr1go18XOn1ZR9R2s1/Dnw9VbnU6vqd8BnGL5IgOFLkuOq6rh27r8MnMzwJc50n+c/MHz2t22fi69X1UxD2w0MLWO/q6prgb8F3lNVJ7VWqsOB3wG7tXqsr88FDNfdMuCeDK2ix2SkC2dVfbR1j7w78J/AJW3Vt4A7JXlqko2T7A/cjUmfGUkbLkObpLmyT1VtVlXbtpuiaxm++d4YuHji5pDhm+Q7jmz3i4mJqvpNm9wEIMljk3yndZe6guHmb8uZVKbdUB4JPKN1s3oqww3VjLUWgi8B76qqj42suoahtWDCxPTot/Or8/NJN6QXMjzzNGHFyPR053Ab4CczfN1Rk4+BNr/aY2g33KcytBxNPMd3bfv9+tal7Azg47SbdYZWsFOB0xhuRj/LcJN+6cR+23v0IYZugC9Yw2MZPV8keWCGgSRWJbkSeB43vW5Gt5l8/ldn3Ht/zXQBo6ouY/hS4qgkG7WQ9EKGZ6bGeR3woar66QzrtaaObJ/XiZ/VdbO8ZGT62jHzE4MObQvsNxoGgYcyhLHpPs//BpwHfKl1nZxpKzjAqvpjV9yJerxkUj22YWbv8Wx+Lqiqr1XV71s3yIMYvtS415jtz2VoXX5Xm/8VsDfDl0WXAHsA/8PQmidpATC0SVqfVjB8w73lyM3hplU1ZVejCa0r06eANwNbtdaK47hpl6EJ426aDweezjBgyG+q6tszrXh7TudLwNFV9cZJq89i6Mo0YUeG509+xcwsmdQyc2du/GzS6LFMdw5XMHwDv6bOYnhebrQFYUdm3i1xo5HXPWNMvf9XC3IvqKolVXVXhu6bp7TWVdq5OIyhhfVJNTxHuCYmv+5HGQZx2Kaqbs/QgjH5utlmZHry+V+dce/9mpyzOzKEgF0ZwszZ7Vmsfwd2bd3oFjFcsy9s879o9T0yyctn+FrzYQVD0BwNg7etqoOn+zxX1dVV9ZJ2fTweeHH++Kznb7hxC9OfTnrdye//CuCNk+pxm0lfvExlNj8X4xRT/xt2o22r6qtV9YCq2pyhp8A9GAZFkrQAGNokrTdVdTFD8HlLkk2T3CLJ3ZJM7qo2zi2BWzE8fH9dhgFK/nI15S9hGMVx9PW/zdB16i2sQStbkk2BLwLfrKpx3/h/EDggyQ4t3P0T8IGR7U/MyOAXY9yR4YZ84/bc0r1oz9pNNoNz+D7gpUnun8F2Sbad7hir6scMLV+vSXLrJE9kGA3xU5PLttf8P0nu0F5jV+D5wPFtXz9h6Db3qgxD+N8LeDJwTNt+SZI7tW13Yxgh8jUjL/Hudg4e31poJ79+ZWRAixm4HXBZVf221fVpY8r8c5LbJLk3w/NVR8xw3x9kCBRLWmvZSxh57yfV+6+S3KOdv8XAW4FTW6vb5xm6ze3Ufl7N0Bq5UwuzuzM8vzSx/iKGZ7Te2fa9KMmtGW70b9Hew41HXvuCJM+e4THNlg8Dj0/ymIn6ZRgoZCnTfJ4zDByyXQvwVzEM2nJ9W30aw6iMi5LswU27uk72X8DzWotrktw2w+A003Zfns3PRZJ7J9mp1XsThn+Hfk4bKTTJc5PcsU3vALxiYtu27H7t34hNGcLuyqr64nTHIGnDYGiTtL49i+GG7WzgcuCTtO5Sq1PDQAAvZOjieDnDjffRq9nkX4F/at2hXjqy/IMMA2V8eLRwhtHvXjnFvp7I8GcLnpMb/y2rO7e6fYFhQIkTGLrWXciNQ8g2wDdXU9eTGAbB+CVD18F9p2mlm/IcVtUn2j4+ytCF67MMz8GR5D+T/Odq9vsUhqH4L2cYOn7fGkZ3JMnTk4y2LjyRoRvm1Qzn8h3tZ8JTGbql/YphMIp/rqqJG9C7MXSL/DVD6+fyqvpSe51tGcLITsAvRs7109v6pQxd1s5czXFM9nfA65NczRCGjhxT5qsM3fGOB948Up+HZRhUYirvYRiq/UzgB+1YJwaPoNV94jmtJcAXGM7ZmQxfIDwRhu67VfWLiR+G56D+0Kapql9NWn89cHlVTdTtmQxd8d7N8FzYtQxhhSS3ZBiA4zszOluzpKpWMHTpeyVDOFsB/CNwixl8nrdn6P53DfBthi7JJ7Z1BzG0vl3B0HL+2WnqcTLDc23/0V7rPEZG+FyPn4utGL4MuIph4KFlwF4jLckPAc7MMOrpce1n9N+klzH8G7GC4fP+xNUdt6QNS2b+XK8k3fwleRZwYFWtlz9M20LGJ6rqQVOsfzbw3PVVn5u7JM8A7l1Vr5il/S1j+JMCG9cw0MsGJ8MfYX5+VT11vusiSVo7s/FHJyXpZiHJbRhaXaYa3nvWVdVKhj8wrVlQw9+n0hqoqm8wjOIqSbqZsnukpAUhyWMYumhdwk3/bpIkSVK37B4pSZIkSR2zpU2SJEmSOmZokyRJkqSOdTEQyZZbblnLli2b72pIkiRJ0rw45ZRTfllVi8et6yK0LVu2jJNPPnm+qyFJkiRJ8yLJhVOts3ukJEmSJHXM0CZJkiRJHTO0SZIkSVLHDG2SJEmS1DFDmyRJkiR1zNAmSZIkSR0ztEmSJElSxwxtkiRJktQxQ5skSZIkdczQJkmSJEkdM7RJkiRJUsc2mu8KSJIk3RwsW37sOm1/wcF7zlJNJC00trRJkiRJUscMbZIkSZLUMUObJEmSJHXM0CZJkiRJHTO0SZIkSVLHDG2SJEmS1DFDmyRJkiR1zNAmSZIkSR0ztEmSJElSxwxtkiRJktQxQ5skSZIkdczQJkmSJEkdM7RJkiRJUscMbZIkSZLUMUObJEmSJHXM0CZJkiRJHTO0SZIkSVLHDG2SJEmS1DFDmyRJkiR1zNAmSZIkSR0ztEmSJElSxwxtkiRJktQxQ5skSZIkdczQJkmSJEkdM7RJkiRJUscMbZIkSZLUMUObJEmSJHXM0CZJkiRJHTO0SZIkSVLHDG2SJEmS1LEZh7Yki5KcmuSYNn+XJCclOTfJEUlu2Zbfqs2f19Yvm5uqS5IkSdKGb01a2g4CzhmZfxNwaFVtD1wOHNCWHwBcXlXbAYe2cpIkSZKktTCj0JZkKbAn8L42H+BRwCdbkcOBfdr03m2etn73Vl6SJEmStIZm2tL2NuBlwA1tfgvgiqq6rs2vBJa06SXACoC2/spWXpIkSZK0hqYNbUn2Ai6tqlNGF48pWjNYN7rfA5OcnOTkVatWzaiykiRJkrTQzKSl7SHAE5JcAHycoVvk24DNkmzUyiwFLmrTK4FtANr62wOXTd5pVb23qnapql0WL168TgchSZIkSRuqaUNbVb2iqpZW1TLgKcBXqurpwAnAvq3Y/sBRbfroNk9b/5WquklLmyRJkiRpeuvyd9peDrw4yXkMz6wd1pYfBmzRlr8YWL5uVZQkSZKkhWuj6Yv8UVWdCJzYps8Hdh1T5rfAfrNQN0mSJEla8NalpU2SJEmSNMcMbZIkSZLUMUObJEmSJHXM0CZJkiRJHTO0SZIkSVLHDG2SJEmS1DFDmyRJkiR1zNAmSZIkSR0ztEmSJElSxwxtkiRJktQxQ5skSZIkdczQJkmSJEkdM7RJkiRJUscMbZIkSZLUMUObJEmSJHXM0CZJkiRJHTO0SZIkSVLHDG2SJEmS1DFDmyRJkiR1zNAmSZIkSR0ztEmSJElSxwxtkiRJktQxQ5skSZIkdczQJkmSJEkdM7RJkiRJUscMbZIkSZLUMUObJEmSJHXM0CZJkiRJHTO0SZIkSVLHDG2SJEmS1DFDmyRJkiR1zNAmSZIkSR0ztEmSJElSxwxtkiRJktQxQ5skSZIkdczQJkmSJEkdM7RJkiRJUscMbZIkSZLUMUObJEmSJHXM0CZJkiRJHTO0SZIkSVLHDG2SJEmS1DFDmyRJkiR1zNAmSZIkSR0ztEmSJElSxwxtkiRJktQxQ5skSZIkdWza0Jbk1km+m+T0JGcleV1bfpckJyU5N8kRSW7Zlt+qzZ/X1i+b20OQJEmSpA3XTFrafgc8qqp2BHYC9kiyG/Am4NCq2h64HDiglT8AuLyqtgMObeUkSZIkSWth2tBWg2va7Mbtp4BHAZ9syw8H9mnTe7d52vrdk2TWaixJkiRJC8iMnmlLsijJacClwJeBnwBXVNV1rchKYEmbXgKsAGjrrwS2mM1KS5IkSdJCMaPQVlXXV9VOwFJgV+Be44q13+Na1WrygiQHJjk5ycmrVq2aaX0lSZIkaUFZo9Ejq+oK4ERgN2CzJBu1VUuBi9r0SmAbgLb+9sBlY/b13qrapap2Wbx48drVXpIkSZI2cDMZPXJxks3a9J8AjwbOAU4A9m3F9geOatNHt3na+q9U1U1a2iRJkiRJ09to+iJsDRyeZBFDyDuyqo5Jcjbw8SRvAE4FDmvlDwM+lOQ8hha2p8xBvSVJkiRpQZg2tFXVGcD9xiw/n+H5tsnLfwvsNyu1kyRJkqQFbo2eaZMkSZIkrV+GNkmSJEnqmKFNkiRJkjpmaJMkSZKkjhnaJEmSJKljhjZJkiRJ6pihTZIkSZI6ZmiTJEmSpI4Z2iRJkiSpY4Y2SZIkSeqYoU2SJEmSOmZokyRJkqSOGdokSZIkqWOGNkmSJEnqmKFNkiRJkjpmaJMkSZKkjhnaJEmSJKljhjZJkiRJ6pihTZIkSZI6ZmiTJEmSpI4Z2iRJkiSpY4Y2SZIkSeqYoU2SJEmSOmZokyRJkqSOGdokSZIkqWOGNkmSJEnqmKFNkiRJkjpmaJMkSZKkjhnaJEmSJKljhjZJkiRJ6pihTZIkSZI6ZmiTJEmSpI4Z2iRJkiSpY4Y2SZIkSeqYoU2SJEmSOmZokyRJkqSOGdokSZIkqWOGNkmSJEnqmKFNkiRJkjpmaJMkSZKkjhnaJEmSJKljhjZJkiRJ6pihTZIkSZI6ZmiTJEmSpI4Z2iRJkiSpY4Y2SZIkSeqYoU2SJEmSOjZtaEuyTZITkpyT5KwkB7Xlmyf5cpJz2+87tOVJ8vYk5yU5I8nOc30QkiRJkrShmklL23XAS6rqXsBuwPOT7AAsB46vqu2B49s8wGOB7dvPgcC7Z73WkiRJkrRATBvaquriqvp+m74aOAdYAuwNHN6KHQ7s06b3Bj5Yg+8AmyXZetZrLkmSJEkLwBo905ZkGXA/4CRgq6q6GIZgB9yxFVsCrBjZbGVbJkmSJElaQzMObUk2AT4FvKiqrlpd0THLasz+DkxycpKTV61aNdNqSJIkSdKCMqPQlmRjhsD2kar6dFt8yUS3x/b70rZ8JbDNyOZLgYsm77Oq3ltVu1TVLosXL17b+kuSJEnSBm0mo0cGOAw4p6reOrLqaGD/Nr0/cNTI8me1USR3A66c6EYpSZIkSVozG82gzEOAZwJnJjmtLXslcDBwZJIDgJ8B+7V1xwGPA84DfgM8Z1ZrLEmSJEkLyLShraq+wfjn1AB2H1O+gOevY70kSZIkSazh6JGSJEmSpPXL0CZJkiRJHTO0SZIkSVLHDG2SJEmS1DFDmyRJkiR1zNAmSZIkSR0ztEmSJElSxwxtkiRJktQxQ5skSZIkdczQJkmSJEkdM7RJkiRJUscMbZIkSZLUMUObJEmSJHXM0CZJkiRJHTO0SZIkSVLHDG2SJEmS1DFDmyRJkiR1zNAmSZIkSR0ztEmSJElSxwxtkiRJktQxQ5skSZIkdczQJkmSJEkdM7RJkiRJUscMbZIkSZLUMUObJEmSJHXM0CZJkiRJHTO0SZIkSVLHDG2SJEmS1DFDmyRJkiR1zNAmSZIkSR0ztEmSJElSxwxtkiRJktQxQ5skSZIkdczQJkmSJEkdM7RJkiRJUscMbZIkSZLUMUObJEmSJHXM0CZJkiRJHTO0SZIkSVLHDG2SJEmS1DFDmyRJkiR1zNAmSZIkSR0ztEmSJElSxwxtkiRJktQxQ5skSZIkdczQJkmSJEkdM7RJkiRJUsemDW1J3p/k0iQ/GFm2eZIvJzm3/b5DW54kb09yXpIzkuw8l5WXJEmSpA3dTFraPgDsMWnZcuD4qtoeOL7NAzwW2L79HAi8e3aqKUmSJEkL07Shraq+Blw2afHewOFt+nBgn5HlH6zBd4DNkmw9W5WVJEmSpIVmbZ9p26qqLgZov+/Yli8BVoyUW9mWSZIkSZLWwmwPRJIxy2psweTAJCcnOXnVqlWzXA1JkiRJ2jCsbWi7ZKLbY/t9aVu+EthmpNxS4KJxO6iq91bVLlW1y+LFi9eyGpIkSZK0YVvb0HY0sH+b3h84amT5s9ookrsBV050o5QkSZIkrbmNpiuQ5GPAI4Atk6wEXgMcDByZ5ADgZ8B+rfhxwOOA84DfAM+ZgzpLkiRJ0oIxbWirqqdOsWr3MWULeP66VkqSJEmSNJjtgUgkSZIkSbPI0CZJkiRJHTO0SZIkSVLHpn2mTZIWumXLj12n7S84eM9ZqokkSVqIDG3SNLxhlyRJ0nyye6QkSZIkdczQJkmSJEkdM7RJkiRJUscMbZIkSZLUMUObJEmSJHXM0CZJkiRJHTO0SZIkSVLHDG2SJEmS1DFDmyRJkiR1zNAmSZIkSR0ztEmSJElSxwxtkiRJktQxQ5skSZIkdczQJkmSJEkd22i+KyBJ0s3BsuXHrtP2Fxy85yzVRJK00NjSJkmSJEkds6VNkiRJmiFb3TUfbGmTJEmSpI4Z2iRJkiSpY4Y2SZIkSeqYoU2SJEmSOmZokyRJkqSOGdokSZIkqWOGNkmSJEnqmKFNkiRJkjpmaJMkSZKkjhnaJEmSJKljhjZJkiRJ6pihTZIkSZI6ZmiTJEmSpI4Z2iRJkiSpY4Y2SZIkSeqYoU2SJEmSOmZokyRJkqSOGdokSZIkqWOGNkmSJEnqmKFNkiRJkjpmaJMkSZKkjhnaJEmSJKljG813BST1bdnyY9d5HxccvOcs1ESSJGlhMrRJkqa1ruHd4C5J0toztGm1vFGTJEmS5techLYkewD/DiwC3ldVB8/F60iSpPXDrtICv8yV5susD0SSZBHwTuCxwA7AU5PsMNuvI0mSJEkLwVy0tO0KnFdV5wMk+TiwN3D2HLyWJEmSpPXEVvf5MRehbQmwYmR+JfDAOXgdLQB2w/AcgOcAPAcL/fjBc6DBbNww35wZGNbdhnANLcR/D1NVs7vDZD/gMVX13Db/TGDXqvr7SeUOBA5ss/cAfjSrFZkdWwK/nO9KaMHzOlQPvA7VA69D9cDrUHNl26paPG7FXLS0rQS2GZlfClw0uVBVvRd47xy8/qxJcnJV7TLf9dDC5nWoHngdqgdeh+qB16Hmw6wPRAJ8D9g+yV2S3BJ4CnD0HLyOJEmSJG3wZr2lraquS/IC4IsMQ/6/v6rOmu3XkSRJkqSFYE7+TltVHQccNxf7Xs+67r6pBcPrUD3wOlQPvA7VA69DrXezPhCJJEmSJGn2zMUzbZIkSZKkWWJom0KSPZL8KMl5SZbPd320MCR5f5JLk/xgZNnmSb6c5Nz2+w7zWUdt2JJsk+SEJOckOSvJQW2516HWmyS3TvLdJKe36/B1bfldkpzUrsMj2oBn0pxKsijJqUmOafNeh1rvDG1jJFkEvBN4LLAD8NQkO8xvrbRAfADYY9Ky5cDxVbU9cHybl+bKdcBLqupewG7A89u/f16HWp9+BzyqqnYEdgL2SLIb8Cbg0HYdXg4cMI911MJxEHDOyLzXodY7Q9t4uwLnVdX5VfV74OPA3vNcJy0AVfU14LJJi/cGDm/ThwP7rNdKaUGpqour6vtt+mqGG5UleB1qParBNW124/ZTwKOAT7blXoeac0mWAnsC72vzwetQ88DQNt4SYMXI/Mq2TJoPW1XVxTDcUAN3nOf6aIFIsgy4H3ASXodaz1qXtNOAS4EvAz8Brqiq61oR/2/W+vA24GXADW1+C7wONQ8MbeNlzDKH2ZS0YCTZBPgU8KKqumq+66OFp6qur6qdgKUMPWDuNa7Y+q2VFpIkewGXVtUpo4vHFPU61Jybk7/TtgFYCWwzMr8UuGie6iJdkmTrqro4ydYM3zpLcybJxgyB7SNV9em22OtQ86KqrkhyIsMzlpsl2ai1cvh/s+baQ4AnJHkccGtgU4aWN69DrXe2tI33PWD7NjrQLYGnAEfPc520cB0N7N+m9weOmse6aAPXntc4DDinqt46ssrrUOtNksVJNmvTfwI8muH5yhOAfVsxr0PNqap6RVUtraplDPeCX6mqp+N1qHngH9eeQvtW5W3AIuD9VfXGea6SFoAkHwMeAWwJXAK8BvgscCRwZ+BnwH5VNXmwEmlWJHko8HXgTP74DMcrGZ5r8zrUepHkvgwDPCxi+IL5yKp6fZK7MgwOtjlwKvCMqvrd/NVUC0WSRwAvraq9vA41HwxtkiRJktQxu0dKkiRJUscMbZIkSZLUMUObJEmSJHXM0CZJkiRJHTO0SZIkSVLHDG2StAFK8qokZyU5I8lpSR4433UalWRZkqeNzD8iyQfWcZ/vS7LDLNTtRUme1aZfn+TR67rPtq9r1mHbxUlOSnJqkodNWndBki1noX47tT93M109vrCuryVJWjMbzXcFJEmzK8mDgL2Anavqd+2G/pbzXK3JlmuXbpoAAAWlSURBVAFPAz46Wzusqueu6z6SbAT8DbBz2+er13Wfs2R34IdVtf+0JdfeTsAuwHFTFaiqVUkuTvKQqvrmHNZFkjTCljZJ2vBsDfxy4o+9VtUvq+oigCT3T/LVJKck+WKSrdvyB7RWuW8n+bckP2jLn53ks0k+l+SnSV6Q5MWtxec7STZv5e6W5Attv19Pcs+2/ANJ3p7kW0nOT7Jvq+PBwMNaK+A/AL8HrmzbPLwtP629zu1GDy7JbZMcm+T0JD9I8uS2/MQkuyR5wsj2P0ry09Ud+ySPAr5fVdeN1H/fNn1Bktcl+X6SMyeOcVLdnp3k0+1cnJvkkEnr39K2Pz7J4jHbb9vWndF+3znJTsAhwOPaMf3JmHr/Y5Lvtp/t2r4WJ/lUku+1n4e05bu29+PU9vseSW4JvB54cnuNJ6/mffgs8PQxdZAkzRFDmyRteL4EbJPkx0neleThAEk2Bt4B7FtV9wfeD7yxbfPfwPOq6kHA9ZP2dx+GVrFdW/nfVNX9gG8Dz2pl3gv8fdvvS4F3jWy/NfBQhta/g9uy5cDXq2qnqjq0qr5VVQe1dS8Fnl9VOwEPA66dVJ89gIuqasequg9wo+56VXV02+9OwOnAm6c59lEPAU4Zs3zCL6tqZ+DdrZ7j7AQ8GfgzhhC0TVt+W4ZAuDPwVeA1Y7b9D+CDVXVf4CPA26vqNODVwBHtuCafD4CrqmrXtv3b2rJ/Bw6tqgcATwLe15b/EPjz9h6+GviXqvr9pNc4gqnfh5PbvCRpPbF7pCRtYKrqmiT3Z7ixfiRwRJLlDDfb9wG+nARgEXBxks2A21XVt9ouPsoQsCacUFVXA1cnuRL4XFt+JnDfJJsADwY+0fYLcKuR7T9bVTcAZyfZagaH8E3grUk+Any6qlZOWn8mQxB7E3BMVX193E6SvAy4tqremeQ+4459zGZbA+espm6fbr9PAf5qijLHV9VEq+HZwLbACuAG4IhW5sMj+xr1oJH9foihhW0mPjby+9A2/Whgh5H3ZNPWWnZ74PAk2wMFbDzFPqd6Hy4F7jTDekmSZoGhTZI2QFV1PXAicGKSM4H9GYLGWa017X8lucM0u/vdyPQNI/M3MPw/cgvgitYiM932maLMaN0PTnIs8DjgO0keXVU/HFn/4xZKHwf8a5IvVdXrJx3T7sB+wJ+PvO5Njn2Ma4Fbr2b9xLFcz9T/h44e7+rK1TR1mWmZyeUmpm8BPGhyy1ySdzAE8ScmWcZwndx0h1O/D7fmpq2fkqQ5ZPdISdrAtGeUth9ZtBNwIfAjYHGGgUpIsnGSe1fV5QytaLu18k9Zk9erqquAnybZr+03SXacZrOrgduNW5HkblV1ZlW9iaF18J6T1t+JoYvmh4E30wYNGVm/LUP3zL8eCSxjj33My58DbDdN3dfWLYCJZ/qeBnxjTJlv8cfz//Qpyozz5JHf327TXwJeMFGgPRsHQ0vbz9v0s0f2caP3ZDXvw92BH8ywXpKkWWBok6QNzyYM3d/OTnIGsAPw2vbc0r7Am5KcDpzG0K0R4ADgvUm+zdAqdeUavubTgQPafs8C9p6m/BnAdW0wkX+YtO5FbYCR0xladD4/af2fAd9NchrwKuANk9Y/G9gC+EwbROO4aY591Of5Y+vcbPs1cO8kpzAMePL6MWVeCDynvW/PBA4aU2acWyU5qZWfOJ8vBHZpg5qcDTyvLT+EoYXymwzdRCecwNCd8rQMg7tM9T48Ejh2hvWSJM2CVM2054UkaUOVZJOquqZNLwe2HhkYZEFJ8hngZVV17nzXpUdJvgbs3VpoJUnrgS1tkiSAPVsLyw8YBjCZ3Hq1kCxnGJBEk7Q/U/BWA5skrV+2tEmSJElSx2xpkyRJkqSOGdokSZIkqWOGNkmSJEnqmKFNkiRJkjpmaJMkSZKkjhnaJEmSJKlj/x+bVj1K+tEW3gAAAABJRU5ErkJggg==\n",
-      "text/plain": [
-       "<Figure size 1080x360 with 1 Axes>"
-      ]
-     },
-     "metadata": {
-      "needs_background": "light"
-     },
-     "output_type": "display_data"
-    },
-    {
-     "data": {
-      "image/png": "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\n",
-      "text/plain": [
-       "<Figure size 1080x360 with 1 Axes>"
-      ]
-     },
-     "metadata": {
-      "needs_background": "light"
-     },
-     "output_type": "display_data"
-    },
-    {
-     "data": {
-      "image/png": "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\n",
-      "text/plain": [
-       "<Figure size 1080x360 with 1 Axes>"
-      ]
-     },
-     "metadata": {
-      "needs_background": "light"
-     },
-     "output_type": "display_data"
-    },
-    {
-     "data": {
-      "image/png": "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\n",
-      "text/plain": [
-       "<Figure size 1080x360 with 1 Axes>"
-      ]
-     },
-     "metadata": {
-      "needs_background": "light"
-     },
-     "output_type": "display_data"
-    }
-   ],
-   "source": [
-    "annotations_folder_path = \"C:\\\\Users\\\\amarmore\\\\Desktop\\\\Audio samples\\\\RWC Pop\\\\annotations\\\\MIREX10\"\n",
-    "persisted_path = \"C:\\\\Users\\\\amarmore\\\\Desktop\\\\data_persisted\"\n",
-    "\n",
-    "for i in range(0,100,20):\n",
-    "    all_res = []\n",
-    "    distrib_segments = []\n",
-    "    for song in manual:\n",
-    "        bag_of_chords = dm.flowify_song(database_path + song)\n",
-    "        \n",
-    "        frontiers, _ = baselines.dynamic_minimization_reg_or_seq(bag_of_chords, segment_size_penalty = i, max_size = 48)\n",
-    "\n",
-    "        for fst, snd in zip(frontiers[:-1], frontiers[1:]):\n",
-    "            distrib_segments.append(snd - fst)\n",
-    "\n",
-    "        \"\"\"\n",
-    "        # Scores, computed on time\n",
-    "        song_number = song.split(\".\")[0]\n",
-    "        this_song_ann = dm.get_annotation_name_from_song(song_number, \"MIREX10\")\n",
-    "        annotation_path = \"{}\\\\{}\".format(annotations_folder_path, this_song_ann)\n",
-    "        annotations = dm.get_segmentation_from_txt(annotation_path, \"MIREX10\")\n",
-    "        references_segments = np.array(annotations)[:, 0:2]\n",
-    "        beats = np.load(\"{}\\\\beats\\\\{}.npy\".format(persisted_path, int(song_number)), allow_pickle=True)                \n",
-    "\n",
-    "        estimation = []\n",
-    "        for f in frontiers:\n",
-    "            if f < len(beats):\n",
-    "                estimation.append(beats[f])\n",
-    "            else:\n",
-    "                estimation.append(beats[-1])\n",
-    "        estimated_seg = dm.frontiers_to_segments(estimation)\n",
-    "\n",
-    "        prec, rec, fmes = dm.compute_score_of_segmentation(references_segments, estimated_seg, window_length = 0.5)\"\"\"\n",
-    "\n",
-    "        #Scores, computed on the beat annotation\n",
-    "        beat_indexed_segments = dm.frontiers_to_segments(frontiers)\n",
-    "        \n",
-    "        song_number = song.split(\".\")[0]\n",
-    "        annot_name = \"{:03d}.manual.seg\".format(int(song_number))\n",
-    "        annotation_file = open(database_path + annot_name,'r')\n",
-    "        annotation = annotation_file.read().replace(\"\\n\", \"\").split(\" \")\n",
-    "        annotation = np.array([int(x) - 1 for x in annotation])\n",
-    "        beat_indexed_annotation = np.array(dm.frontiers_to_segments(annotation))\n",
-    "        p, r, f = dm.compute_score_of_segmentation(beat_indexed_annotation, beat_indexed_segments, window_length = 0.5)\n",
-    "        all_res.append([p, r, f])\n",
-    "    \n",
-    "    results = np.array(all_res)\n",
-    "    prec, rap, fmes = round(np.mean(results[:,0]),4), round(np.mean(results[:,1]),4), round(np.mean(results[:,2]),4)\n",
-    "    plt.figure(figsize=(15,5))\n",
-    "    plt.hist(distrib_segments, bins = range(48))\n",
-    "    plt.xlabel(\"Segment's size (in nb of beats)\")\n",
-    "    plt.title(\"Penalty: {}, prec: {}, rap: {}, F measure: {}\".format(i, prec, rap, fmes))\n",
-    "    plt.plot()"
-   ]
-  }
- ],
- "metadata": {
-  "kernelspec": {
-   "display_name": "Python 3",
-   "language": "python",
-   "name": "python3"
-  },
-  "language_info": {
-   "codemirror_mode": {
-    "name": "ipython",
-    "version": 3
-   },
-   "file_extension": ".py",
-   "mimetype": "text/x-python",
-   "name": "python",
-   "nbconvert_exporter": "python",
-   "pygments_lexer": "ipython3",
-   "version": "3.7.5"
-  },
-  "toc": {
-   "base_numbering": 1,
-   "nav_menu": {},
-   "number_sections": true,
-   "sideBar": true,
-   "skip_h1_title": false,
-   "title_cell": "Table of Contents",
-   "title_sidebar": "Contents",
-   "toc_cell": false,
-   "toc_position": {},
-   "toc_section_display": true,
-   "toc_window_display": false
-  },
-  "varInspector": {
-   "cols": {
-    "lenName": 16,
-    "lenType": 16,
-    "lenVar": 40
-   },
-   "kernels_config": {
-    "python": {
-     "delete_cmd_postfix": "",
-     "delete_cmd_prefix": "del ",
-     "library": "var_list.py",
-     "varRefreshCmd": "print(var_dic_list())"
-    },
-    "r": {
-     "delete_cmd_postfix": ") ",
-     "delete_cmd_prefix": "rm(",
-     "library": "var_list.r",
-     "varRefreshCmd": "cat(var_dic_list()) "
-    }
-   },
-   "types_to_exclude": [
-    "module",
-    "function",
-    "builtin_function_or_method",
-    "instance",
-    "_Feature"
-   ],
-   "window_display": false
-  }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/Notebooks/Baseline - distribution of sizes in annotation and segmentation every 32.ipynb b/Notebooks/Baseline - distribution of sizes in annotation and segmentation every 32.ipynb
deleted file mode 100644
index eff76ca781c05d7ba1a31f889329c2e7a65cfa6e..0000000000000000000000000000000000000000
--- a/Notebooks/Baseline - distribution of sizes in annotation and segmentation every 32.ipynb	
+++ /dev/null
@@ -1,227 +0,0 @@
-{
- "cells": [
-  {
-   "cell_type": "code",
-   "execution_count": 1,
-   "metadata": {
-    "ExecuteTime": {
-     "end_time": "2020-11-26T12:48:49.072741Z",
-     "start_time": "2020-11-26T12:48:47.532779Z"
-    }
-   },
-   "outputs": [],
-   "source": [
-    "import os\n",
-    "import time\n",
-    "\n",
-    "# Self-code imports\n",
-    "from polytopes.model.chord import Chord\n",
-    "import polytopes.data_manipulation as dm\n",
-    "\n",
-    "#Generic imports\n",
-    "import numpy as np\n",
-    "import matplotlib.pyplot as plt\n",
-    "import pandas as pd\n",
-    "import math"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "# Segment size distribution"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 2,
-   "metadata": {
-    "ExecuteTime": {
-     "end_time": "2020-11-26T12:48:49.542431Z",
-     "start_time": "2020-11-26T12:48:49.072741Z"
-    }
-   },
-   "outputs": [
-    {
-     "data": {
-      "text/plain": [
-       "[]"
-      ]
-     },
-     "execution_count": 2,
-     "metadata": {},
-     "output_type": "execute_result"
-    },
-    {
-     "data": {
-      "image/png": "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\n",
-      "text/plain": [
-       "<Figure size 1080x360 with 1 Axes>"
-      ]
-     },
-     "metadata": {
-      "needs_background": "light"
-     },
-     "output_type": "display_data"
-    }
-   ],
-   "source": [
-    "annotations_folder_path = \"C:\\\\Users\\\\amarmore\\\\Desktop\\\\Audio samples\\\\RWC Pop\\\\annotations\\\\MIREX10\"\n",
-    "persisted_path = \"C:\\\\Users\\\\amarmore\\\\Desktop\\\\data_persisted\"\n",
-    "\n",
-    "# Files to load: .seq\n",
-    "all_mirex_ten = \"C:\\\\Users\\\\amarmore\\\\Desktop\\\\Projects\\\\RWC_annotations\\\\final_bimbot_al\\\\\"\n",
-    "all_manual = []\n",
-    "for file in os.listdir(all_mirex_ten):\n",
-    "    bag_of_words = file.split(\".\")\n",
-    "    if bag_of_words[-1] == \"seq\":\n",
-    "        if bag_of_words[-2] == \"manual\":\n",
-    "            all_manual.append(file)\n",
-    "\n",
-    "all_res = []\n",
-    "distrib_segments = []\n",
-    "for song in all_manual:\n",
-    "    song_number = song.split(\".\")[0]\n",
-    "    annot_name = \"{:03d}.manual.seg\".format(int(song_number))\n",
-    "    annotation_file = open(all_mirex_ten + annot_name,'r')\n",
-    "    annotation = annotation_file.read().replace(\"\\n\", \"\").split()\n",
-    "    annotation = np.array([int(x) - 1 for x in annotation])\n",
-    "    beat_indexed_annotation = np.array(dm.frontiers_to_segments(annotation))\n",
-    "    \n",
-    "    for fst, snd in zip(annotation[:-1], annotation[1:]):\n",
-    "        distrib_segments.append(snd - fst)\n",
-    "    \n",
-    "plt.figure(figsize=(15,5))\n",
-    "plt.hist(distrib_segments, bins = range(48))\n",
-    "plt.xlabel(\"Segment's size in annotation (in nb of beats)\")\n",
-    "plt.title(\"Distribution of segment sizes in Manual annotation\")\n",
-    "plt.plot()"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "# Segmentation with segment every 32 beats"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 3,
-   "metadata": {
-    "ExecuteTime": {
-     "end_time": "2020-11-26T12:48:51.182876Z",
-     "start_time": "2020-11-26T12:48:49.542431Z"
-    }
-   },
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "Prec: 0.3597, Rec: 0.3615 Fmes: 0.3601\n"
-     ]
-    }
-   ],
-   "source": [
-    "annotations_folder_path = \"C:\\\\Users\\\\amarmore\\\\Desktop\\\\Audio samples\\\\RWC Pop\\\\annotations\\\\MIREX10\"\n",
-    "persisted_path = \"C:\\\\Users\\\\amarmore\\\\Desktop\\\\data_persisted\"\n",
-    "\n",
-    "# Files to load: .seq\n",
-    "all_mirex_ten = \"C:\\\\Users\\\\amarmore\\\\Desktop\\\\Projects\\\\RWC_annotations\\\\final_bimbot_al\\\\\"\n",
-    "all_manual = []\n",
-    "for file in os.listdir(all_mirex_ten):\n",
-    "    bag_of_words = file.split(\".\")\n",
-    "    if bag_of_words[-1] == \"seq\":\n",
-    "        if bag_of_words[-2] == \"manual\":\n",
-    "            all_manual.append(file)\n",
-    "\n",
-    "all_res = []\n",
-    "distrib_segments = []\n",
-    "for song in all_manual:\n",
-    "    bag_of_chords = dm.flowify_song(all_mirex_ten + song)\n",
-    "\n",
-    "    frontiers = [i for i in range(0,len(bag_of_chords), 32)]\n",
-    "    \n",
-    "    #Scores, computed on the beat annotation\n",
-    "    beat_indexed_segments = dm.frontiers_to_segments(frontiers)\n",
-    "\n",
-    "    song_number = song.split(\".\")[0]\n",
-    "    annot_name = \"{:03d}.manual.seg\".format(int(song_number))\n",
-    "    annotation_file = open(all_mirex_ten + annot_name,'r')\n",
-    "    annotation = annotation_file.read().replace(\"\\n\", \"\").split()\n",
-    "    annotation = np.array([int(x) - 1 for x in annotation])\n",
-    "    beat_indexed_annotation = np.array(dm.frontiers_to_segments(annotation))\n",
-    "    prec, rec, fmes = dm.compute_score_of_segmentation(beat_indexed_annotation, beat_indexed_segments, window_length = 0.5)\n",
-    "    all_res.append([prec, rec, fmes])\n",
-    "\n",
-    "results = np.array(all_res)\n",
-    "prec, rap, fmes = round(np.mean(results[:,0]),4), round(np.mean(results[:,1]),4), round(np.mean(results[:,2]),4)\n",
-    "print(\"Prec: {}, Rec: {} Fmes: {}\".format(prec, rap, fmes))"
-   ]
-  }
- ],
- "metadata": {
-  "kernelspec": {
-   "display_name": "Python 3",
-   "language": "python",
-   "name": "python3"
-  },
-  "language_info": {
-   "codemirror_mode": {
-    "name": "ipython",
-    "version": 3
-   },
-   "file_extension": ".py",
-   "mimetype": "text/x-python",
-   "name": "python",
-   "nbconvert_exporter": "python",
-   "pygments_lexer": "ipython3",
-   "version": "3.7.5"
-  },
-  "toc": {
-   "base_numbering": 1,
-   "nav_menu": {},
-   "number_sections": true,
-   "sideBar": true,
-   "skip_h1_title": false,
-   "title_cell": "Table of Contents",
-   "title_sidebar": "Contents",
-   "toc_cell": false,
-   "toc_position": {},
-   "toc_section_display": true,
-   "toc_window_display": false
-  },
-  "varInspector": {
-   "cols": {
-    "lenName": 16,
-    "lenType": 16,
-    "lenVar": 40
-   },
-   "kernels_config": {
-    "python": {
-     "delete_cmd_postfix": "",
-     "delete_cmd_prefix": "del ",
-     "library": "var_list.py",
-     "varRefreshCmd": "print(var_dic_list())"
-    },
-    "r": {
-     "delete_cmd_postfix": ") ",
-     "delete_cmd_prefix": "rm(",
-     "library": "var_list.r",
-     "varRefreshCmd": "cat(var_dic_list()) "
-    }
-   },
-   "types_to_exclude": [
-    "module",
-    "function",
-    "builtin_function_or_method",
-    "instance",
-    "_Feature"
-   ],
-   "window_display": false
-  }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/Notebooks/Repartition du nombre de polytopes par taille.ipynb b/Notebooks/Repartition du nombre de polytopes par taille.ipynb
deleted file mode 100644
index 989b3753591356d6d4d93479bf563f74de8315cd..0000000000000000000000000000000000000000
--- a/Notebooks/Repartition du nombre de polytopes par taille.ipynb	
+++ /dev/null
@@ -1,114 +0,0 @@
-{
- "cells": [
-  {
-   "cell_type": "code",
-   "execution_count": 8,
-   "metadata": {
-    "ExecuteTime": {
-     "end_time": "2021-01-21T19:16:17.418182Z",
-     "start_time": "2021-01-21T19:14:04.165913Z"
-    }
-   },
-   "outputs": [
-    {
-     "data": {
-      "text/plain": [
-       "69823"
-      ]
-     },
-     "execution_count": 8,
-     "metadata": {},
-     "output_type": "execute_result"
-    },
-    {
-     "data": {
-      "image/png": "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\n",
-      "text/plain": [
-       "<Figure size 432x288 with 1 Axes>"
-      ]
-     },
-     "metadata": {
-      "needs_background": "light"
-     },
-     "output_type": "display_data"
-    }
-   ],
-   "source": [
-    "import matplotlib.pyplot as plt\n",
-    "import polytopes.pattern_factory as pf\n",
-    "tab = []\n",
-    "count = 0\n",
-    "the_range = range(2, 300)\n",
-    "for i in the_range:\n",
-    "    codes = pf.get_unique_codes(i)\n",
-    "    tab.append(len(codes))\n",
-    "    count+=len(codes)\n",
-    "plt.plot(tab)\n",
-    "count"
-   ]
-  }
- ],
- "metadata": {
-  "kernelspec": {
-   "display_name": "Python 3",
-   "language": "python",
-   "name": "python3"
-  },
-  "language_info": {
-   "codemirror_mode": {
-    "name": "ipython",
-    "version": 3
-   },
-   "file_extension": ".py",
-   "mimetype": "text/x-python",
-   "name": "python",
-   "nbconvert_exporter": "python",
-   "pygments_lexer": "ipython3",
-   "version": "3.7.5"
-  },
-  "toc": {
-   "base_numbering": 1,
-   "nav_menu": {},
-   "number_sections": true,
-   "sideBar": true,
-   "skip_h1_title": false,
-   "title_cell": "Table of Contents",
-   "title_sidebar": "Contents",
-   "toc_cell": false,
-   "toc_position": {},
-   "toc_section_display": true,
-   "toc_window_display": false
-  },
-  "varInspector": {
-   "cols": {
-    "lenName": 16,
-    "lenType": 16,
-    "lenVar": 40
-   },
-   "kernels_config": {
-    "python": {
-     "delete_cmd_postfix": "",
-     "delete_cmd_prefix": "del ",
-     "library": "var_list.py",
-     "varRefreshCmd": "print(var_dic_list())"
-    },
-    "r": {
-     "delete_cmd_postfix": ") ",
-     "delete_cmd_prefix": "rm(",
-     "library": "var_list.r",
-     "varRefreshCmd": "cat(var_dic_list()) "
-    }
-   },
-   "types_to_exclude": [
-    "module",
-    "function",
-    "builtin_function_or_method",
-    "instance",
-    "_Feature"
-   ],
-   "window_display": false
-  }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/Notebooks/Deprecated - Tutorial - model classes.ipynb b/Notebooks/Tutorial - model classes.ipynb
similarity index 100%
rename from Notebooks/Deprecated - Tutorial - model classes.ipynb
rename to Notebooks/Tutorial - model classes.ipynb
diff --git a/README.md b/README.md
index 79502174b089e94d3a24e62c6edd8ac87886804b..c010b82c2292bf8aef87bf98eaa41ea90c572f83 100644
--- a/README.md
+++ b/README.md
@@ -1,15 +1,10 @@
 # Polytopes for music segmentation #
 
-Polytopic paradigms to study music, based on [1] and [2].
+Polytopic paradigms to study music, defined in [1], based on [2] and [3].
 
-In near future, I should upload my own reference, detailing the specificity of both approaches of [1] and [2], which have been gathered on a same framework and on a same code project (this one).
+The goal of the polytopic approach is to define a new compression criteria, then used as cost for music segmentation, based on dynamic programming. See [4] for more details on this approach.
 
-The goal of the polytopic approach is to define a new compression criteria, then used as cost for music segmentation, based on dynamic programming. See [3] or [4] for more details on this approach.
-
-[1] C. Guichaoua, Modèles de compression et critères de complexité pour la description et l’inférence de structure musicale.  PhD thesis, 2017.
-
-[2]  C. Louboutin, Modélisation multi-échelle et multi-dimensionnelle de la structure musicale par graphes polytopiques. PhD thesis, Rennes 1, 2019.
-
-[3] Sargent, G., Bimbot, F., & Vincent, E. (2016). Estimating the structural segmentation of popular music pieces under regularity constraints. IEEE/ACM Transactions on Audio, Speech, and Language Processing, 25(2), 344-358.
-
-[4] Marmoret, A., Cohen, J., Bertin, N., & Bimbot, F. (2020, October). Uncovering Audio Patterns in Music with Nonnegative Tucker Decomposition for Structural Segmentation. In ISMIR 2020-21st International Society for Music Information Retrieval.
+[1] Marmoret, A., Cohen, J. E., & Bibmot, F. (2022). Polytopic Analysis of Music. arXiv preprint arXiv:2212.11054.
+[2] Guichaoua, C., Modèles de compression et critères de complexité pour la description et l’inférence de structure musicale.  PhD thesis, 2017.
+[3] Louboutin, C., Modélisation multi-échelle et multi-dimensionnelle de la structure musicale par graphes polytopiques. PhD thesis, Rennes 1, 2019.
+[4] Sargent, G., Bimbot, F., & Vincent, E. (2016). Estimating the structural segmentation of popular music pieces under regularity constraints. IEEE/ACM Transactions on Audio, Speech, and Language Processing, 25(2), 344-358.
diff --git a/polytopes.egg-info/PKG-INFO b/polytopes.egg-info/PKG-INFO
deleted file mode 100644
index 94e8a05017b4757b57e2031d8bc6ef3aae030fe9..0000000000000000000000000000000000000000
--- a/polytopes.egg-info/PKG-INFO
+++ /dev/null
@@ -1,22 +0,0 @@
-Metadata-Version: 2.1
-Name: polytopes
-Version: 0.1.0
-Summary: Package for polytopes applied on musical segmentation
-Home-page: TODO
-Author: Marmoret Axel
-Author-email: axel.marmoret@irisa.fr
-License: BSD
-Description: # Polytope for music segmentation #
-        
-        TODO.
-        
-Platform: UNKNOWN
-Classifier: License :: OSI Approved :: BSD License
-Classifier: Programming Language :: Python
-Classifier: Development Status :: 3 - Alpha
-Classifier: Intended Audience :: Developers
-Classifier: Intended Audience :: Science/Research
-Classifier: Topic :: Multimedia :: Sound/Audio :: Analysis
-Classifier: Programming Language :: Python :: 3.7
-Requires-Python: >=3.7
-Description-Content-Type: text/markdown
diff --git a/polytopes.egg-info/SOURCES.txt b/polytopes.egg-info/SOURCES.txt
deleted file mode 100644
index 372a3902648eaa7628d175bd7332449fa1c00aee..0000000000000000000000000000000000000000
--- a/polytopes.egg-info/SOURCES.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-README.md
-setup.py
-polytopes/__init__.py
-polytopes/chord_movement.py
-polytopes/data_manipulation.py
-polytopes/pattern_manipulation.py
-polytopes/polytopical_costs.py
-polytopes/sequence_segmentation.py
-polytopes.egg-info/PKG-INFO
-polytopes.egg-info/SOURCES.txt
-polytopes.egg-info/dependency_links.txt
-polytopes.egg-info/requires.txt
-polytopes.egg-info/top_level.txt
-polytopes/model/__init__.py
-polytopes/model/chord.py
-polytopes/model/constants.py
-polytopes/model/errors.py
-polytopes/model/note.py
\ No newline at end of file
diff --git a/polytopes.egg-info/dependency_links.txt b/polytopes.egg-info/dependency_links.txt
deleted file mode 100644
index 8b137891791fe96927ad78e64b0aad7bded08bdc..0000000000000000000000000000000000000000
--- a/polytopes.egg-info/dependency_links.txt
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/polytopes.egg-info/requires.txt b/polytopes.egg-info/requires.txt
deleted file mode 100644
index fa67168283ee2a6c2276a860a9be19fbaacec28d..0000000000000000000000000000000000000000
--- a/polytopes.egg-info/requires.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-madmom
-matplotlib
-mir_eval
-numpy>=1.18.0
-pandas
-scipy>=0.13.0
-soundfile
diff --git a/polytopes.egg-info/top_level.txt b/polytopes.egg-info/top_level.txt
deleted file mode 100644
index c3f4231270e222b65101aab456c237a6c498781b..0000000000000000000000000000000000000000
--- a/polytopes.egg-info/top_level.txt
+++ /dev/null
@@ -1 +0,0 @@
-polytopes
diff --git a/tests/accelerated_function_tests.py b/tests/accelerated_function_tests.py
new file mode 100644
index 0000000000000000000000000000000000000000..36456f5ca853d24db36c85647c4df5e8f05ecf0b
--- /dev/null
+++ b/tests/accelerated_function_tests.py
@@ -0,0 +1,80 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Fri Nov 22 13:38:53 2019
+
+@author: amarmore
+"""
+
+import unittest
+import polytopes.model.triad_manipulation as tm
+import polytopes.triad_transformations as tt
+import polytopes.model.errors as err
+import polytopes.accelerated_polytopical_costs as acc_pc
+
+import numpy as np
+
+class AccelerationFunctionTests(unittest.TestCase):
+            
+    # def test_check_distance_function(self):
+    #     circle_sharp =  ['C','Am','F','Dm','A#','Gm','D#','Cm','G#','Fm','C#','A#m','F#','D#m','B','G#m','E','C#m','A','F#m','D','Bm','G','Em']
+    #     for i in range(24):
+    #         chord_1 = circle_sharp[i]
+    #         for j in range(24):
+    #             chord_2 = circle_sharp[j]
+    #             raw = tt.triadic_tonnetz_distance_symbol(chord_1, chord_2)
+    #             accelerated = acc_pc.accelerated_triadic_tonnetz_distance_symbol(chord_1, chord_2)
+    #             self.assertEqual(raw, accelerated)
+    
+    # def test_check_relation_function(self):
+    #     circle_sharp =  ['C','Am','F','Dm','A#','Gm','D#','Cm','G#','Fm','C#','A#m','F#','D#m','B','G#m','E','C#m','A','F#m','D','Bm','G','Em']        
+    #     relation_list = [0,'R','RL','RLR','LRPR','LRP','PR','P','PL','PLR','LPRP','LPRPR','PRPR','PRP','LPLR','LPL','LP','LPR','RP','RPR','LRLR','LRL','LR','L','LRPL','LPLP']
+    #     for i in range(len(circle_sharp)):
+    #         chord_1 = circle_sharp[i]
+    #         for j in range(len(circle_sharp)):
+    #             chord_2 = circle_sharp[j]
+    #             accelerated = acc_pc.accelerated_triadic_tonnetz_relation_symbol(chord_1, chord_2)
+    #             raw = tt.triadic_tonnetz_relation_symbol(chord_1, chord_2)
+    #             if raw == 0:
+    #                 self.assertEqual(raw, accelerated)
+    #                 self.assertTrue(accelerated in relation_list)
+    #             else:
+    #                 iterator_str = ''
+    #                 for rel in raw:
+    #                     iterator_str += str(rel)
+    #                 self.assertEqual(iterator_str, accelerated)
+    #                 self.assertTrue(accelerated in relation_list)
+
+                
+    # def test_check_apply_relation_function(self):
+    #     circle_sharp =  ['C','Am','F','Dm','A#','Gm','D#','Cm','G#','Fm','C#','A#m','F#','D#m','B','G#m','E','C#m','A','F#m','D','Bm','G','Em']
+    #     relation_list = [0,'R','RL','RLR','LRPR','LRP','PR','P','PL','PLR','LPRP','LPRPR','PRPR','PRP','LPLR','LPL','LP','LPR','RP','RPR','LRLR','LRL','LR','L','LRPL','LPLP']
+    #     for i in range(len(circle_sharp)):
+    #         chord_1 = circle_sharp[i]
+    #         for j in range(len(relation_list)):
+    #             rel = relation_list[j]
+    #             accelerated = acc_pc.accelerated_apply_triadic_tonnetz_relation_symbol(chord_1, rel)
+    #             raw = tt.apply_triadic_tonnetz_relation_symbol(chord_1, rel)
+    #             self.assertEqual(raw, accelerated)
+                
+    def test_check_get_chromatic_mvt_triads(self):
+        circle_sharp =  ['C','Am','F','Dm','A#','Gm','D#','Cm','G#','Fm','C#','A#m','F#','D#m','B','G#m','E','C#m','A','F#m','D','Bm','G','Em']
+        for i in range(len(circle_sharp)):
+            chord_1 = circle_sharp[i]
+            for j in range(len(circle_sharp)):
+                chord_2 = circle_sharp[j]
+                accelerated = acc_pc.accelerated_chromatic_mvt_triads(chord_1, chord_2)
+                raw = tt.chromatic_mvt_triads(chord_1, chord_2)
+                self.assertEqual(raw, accelerated)
+                
+    def test_check_get_voice_leading_transformation_symbol(self):
+        circle_sharp =  ['C','Am','F','Dm','A#','Gm','D#','Cm','G#','Fm','C#','A#m','F#','D#m','B','G#m','E','C#m','A','F#m','D','Bm','G','Em']
+        for i in range(len(circle_sharp)):
+            chord_1 = circle_sharp[i]
+            for j in range(len(circle_sharp)):
+                chord_2 = circle_sharp[j]
+                accelerated = acc_pc.accelerated_get_voice_leading_transformation_symbol(chord_1, chord_2)
+                raw = tt.get_voice_leading_transformation_symbol(chord_1, chord_2)
+                self.assertEqual(raw, accelerated)
+        
+if __name__ == '__main__':
+    unittest.main()
\ No newline at end of file
diff --git a/tests/pattern_manip_tests.py b/tests/pattern_manip_tests.py
index f745b27eb4c5b94f70498320f3267ec7ee351ac5..b312c722089d29d803bc80641ce84da8a1926575 100644
--- a/tests/pattern_manip_tests.py
+++ b/tests/pattern_manip_tests.py
@@ -19,18 +19,18 @@ class PatternManipulationTests(unittest.TestCase):
     def test_indexing_on_examples(self):
         pattern = pf.make_indexed_pattern(4, adding_code = [0,1,0,1], deleting_code = [0,0,1,0])
         # pattern = [[[[0, 1], [2, 3]], [[4, 5], [6, 7]]], [[[8, 9], [(10, 11), (12, 13)]], [[14], [(15, 16)]]]] 
-        self.assertEqual(pm.get_index_of_element(2, pattern), [0, 0, 1, 0])
-        self.assertEqual(pm.get_index_of_element(6, pattern), [0, 1, 1, 0])
-        self.assertEqual(pm.get_index_of_element(13, pattern), [1,0,1,(1,1)])
-        self.assertEqual(pm.get_index_of_element(13, pattern), [1, 1, 0, 0])
+        self.assertEqual(pm.get_index_from_element(2, pattern), [0, 0, 1, 0])
+        self.assertEqual(pm.get_index_from_element(6, pattern), [0, 1, 1, 0])
+        self.assertEqual(pm.get_index_from_element(13, pattern), [1,0,1,(1,1)])
+        self.assertEqual(pm.get_index_from_element(13, pattern), [1, 1, 0, 0])
         
     def test_indexing_on_examples(self):
         pattern = pf.make_indexed_pattern(4, adding_code = [0,1,0,1], deleting_code = [0,0,1,0])
         # pattern = [[[[0, 1], [2, 3]], [[4, 5], [6, 7]]], [[[8, 9], [(10, 11), (12, 13)]], [[14], [(15, 16)]]]] 
-        self.assertEqual(pm.get_element_with_index([0, 0, 1, 1], pattern), 3)
-        self.assertEqual(pm.get_element_with_index([0, 1, 0, 0], pattern), 4)
-        self.assertIsNone(pm.get_element_with_index([0,0,1,(1,1)], pattern))
-        self.assertEqual(pm.get_element_with_index([1, 1, 1, (0, 0)], pattern), 15)
+        self.assertEqual(pm.get_element_from_index([0, 0, 1, 1], pattern), 3)
+        self.assertEqual(pm.get_element_from_index([0, 1, 0, 0], pattern), 4)
+        self.assertIsNone(pm.get_element_from_index([0,0,1,(1,1)], pattern))
+        self.assertEqual(pm.get_element_from_index([1, 1, 1, (0, 0)], pattern), 15)
 
     def test_indexing_and_retrieving_from_index(self):
         for size in range(2, 70):
@@ -38,8 +38,8 @@ class PatternManipulationTests(unittest.TestCase):
             for add, dele in pf.get_codes(size):
                 pattern = pf.make_indexed_pattern(dim, adding_code = add, deleting_code = dele, starting_index = 0)
                 for i in range(0,pf.get_pattern_size(pattern)):
-                    idx_elt = pm.get_index_of_element(i, pattern)
-                    self.assertEqual(i, pm.get_element_with_index(idx_elt, pattern))
+                    idx_elt = pm.get_index_from_element(i, pattern)
+                    self.assertEqual(i, pm.get_element_from_index(idx_elt, pattern))
                     
     def test_delete_tuples(self):
         self.assertEqual(pm.delete_tuples([0, 1, 0, 0]), [0, 1, 0, 0])
@@ -61,16 +61,16 @@ class PatternManipulationTests(unittest.TestCase):
     def test_some_antecedents_ground_truth(self):
         pattern = pf.make_indexed_pattern(4, adding_code = [0,1,0,1], deleting_code = [0,0,1,0])
         # pattern = [[[[0, 1], [2, 3]], [[4, 5], [6, 7]]], [[[8, 9], [(10, 11), (12, 13)]], [[14], [(15, 16)]]]]
-        elt_idx = pm.get_index_of_element(5, pattern)
-        for ant in pm.get_antecedents_from_idx(elt_idx, pattern):
+        elt_idx = pm.get_index_from_element(5, pattern)
+        for ant in pm.get_antecedents_from_index(elt_idx, pattern):
             self.assertTrue(ant in [1,4])
             
-        elt_idx = pm.get_index_of_element(10, pattern)
-        for ant in pm.get_antecedents_from_idx(elt_idx, pattern):
+        elt_idx = pm.get_index_from_element(10, pattern)
+        for ant in pm.get_antecedents_from_index(elt_idx, pattern):
             self.assertTrue(ant in [2,8])
             
-        elt_idx = pm.get_index_of_element(13, pattern)
-        for ant in pm.get_antecedents_from_idx(elt_idx, pattern):
+        elt_idx = pm.get_index_from_element(13, pattern)
+        for ant in pm.get_antecedents_from_index(elt_idx, pattern):
             self.assertTrue(ant in [11,12])
                     
     def test_no_antecedent_is_none(self):
@@ -79,24 +79,24 @@ class PatternManipulationTests(unittest.TestCase):
             for add, dele in pf.get_codes(size):
                 pattern = pf.make_indexed_pattern(dim, adding_code = add, deleting_code = dele, starting_index = 0)
                 for i in range(1,pf.get_pattern_size(pattern)):
-                    idx_elt = pm.get_index_of_element(i, pattern)
-                    ant = pm.get_antecedents_from_idx(idx_elt, pattern)
+                    idx_elt = pm.get_index_from_element(i, pattern)
+                    ant = pm.get_antecedents_from_index(idx_elt, pattern)
                     self.assertNotEqual(ant, None)
                     
     def test_some_pivot_ground_truth(self):
         pattern = pf.make_indexed_pattern(4, adding_code = [0,1,0,1], deleting_code = [0,0,1,0])
         # pattern = [[[[0, 1], [2, 3]], [[4, 5], [6, 7]]], [[[8, 9], [(10, 11), (12, 13)]], [[14], [(15, 16)]]]]
-        elt_idx = pm.get_index_of_element(5, pattern)
-        ant_idx = pm.get_index_of_element(1, pattern)
-        self.assertEqual(pm.get_pivot_idx_from_idx(elt_idx, ant_idx), [0, 1, 0, 0])
+        elt_idx = pm.get_index_from_element(5, pattern)
+        ant_idx = pm.get_index_from_element(1, pattern)
+        self.assertEqual(pm.get_pivot_index_from_index(elt_idx, ant_idx), [0, 1, 0, 0])
             
-        elt_idx = pm.get_index_of_element(10, pattern)
-        ant_idx = pm.get_index_of_element(2, pattern)
-        self.assertEqual(pm.get_pivot_idx_from_idx(elt_idx, ant_idx), [1, 0, 0, 0])
+        elt_idx = pm.get_index_from_element(10, pattern)
+        ant_idx = pm.get_index_from_element(2, pattern)
+        self.assertEqual(pm.get_pivot_index_from_index(elt_idx, ant_idx), [1, 0, 0, 0])
             
-        elt_idx = pm.get_index_of_element(13, pattern)
-        ant_idx = pm.get_index_of_element(12, pattern)
-        self.assertEqual(pm.get_pivot_idx_from_idx(elt_idx, ant_idx), [0, 0, 0, 0])
+        elt_idx = pm.get_index_from_element(13, pattern)
+        ant_idx = pm.get_index_from_element(12, pattern)
+        self.assertEqual(pm.get_pivot_index_from_index(elt_idx, ant_idx), [0, 0, 0, 0])
                     
     def test_no_pivot_is_none(self):
         for size in range(2, 70):
@@ -104,24 +104,24 @@ class PatternManipulationTests(unittest.TestCase):
             for add, dele in pf.get_codes(size):
                 pattern = pf.make_indexed_pattern(dim, adding_code = add, deleting_code = dele, starting_index = 0)
                 for i in range(1,pf.get_pattern_size(pattern)):
-                    idx_elt = pm.get_index_of_element(i, pattern)
-                    ants_idx = pm.get_antecedents_idx_from_idx(idx_elt)
+                    idx_elt = pm.get_index_from_element(i, pattern)
+                    ants_idx = pm.get_antecedents_index_from_index(idx_elt)
                     for ant_idx in ants_idx:
-                        self.assertNotEqual(pm.get_pivot_idx_from_idx(idx_elt, ant_idx), None)
+                        self.assertNotEqual(pm.get_pivot_index_from_index(idx_elt, ant_idx), None)
             
     def test_some_successors_ground_truth(self):
         pattern = pf.make_indexed_pattern(4, adding_code = [0,1,0,1], deleting_code = [0,0,1,0])
         # pattern = [[[[0, 1], [2, 3]], [[4, 5], [6, 7]]], [[[8, 9], [(10, 11), (12, 13)]], [[14], [(15, 16)]]]]
-        elt_idx = pm.get_index_of_element(5, pattern)
-        self.assertEqual(pm.get_successors_from_idx(elt_idx, pattern), [7])
+        elt_idx = pm.get_index_from_element(5, pattern)
+        self.assertEqual(pm.get_successors_from_index(elt_idx, pattern), [7])
 
             
-        elt_idx = pm.get_index_of_element(10, pattern)
-        for suc in pm.get_successors_from_idx(elt_idx, pattern):
+        elt_idx = pm.get_index_from_element(10, pattern)
+        for suc in pm.get_successors_from_index(elt_idx, pattern):
             self.assertTrue(suc in [11,12,15])
             
-        elt_idx = pm.get_index_of_element(13, pattern)
-        self.assertEqual(pm.get_successors_from_idx(elt_idx, pattern), [])
+        elt_idx = pm.get_index_from_element(13, pattern)
+        self.assertEqual(pm.get_successors_from_index(elt_idx, pattern), [])
          
     def test_no_error_when_computing_successors(self):
         for size in range(2, 70):
@@ -129,8 +129,8 @@ class PatternManipulationTests(unittest.TestCase):
             for add, dele in pf.get_codes(size):
                 pattern = pf.make_indexed_pattern(dim, adding_code = add, deleting_code = dele, starting_index = 0)
                 for i in range(0,pf.get_pattern_size(pattern)):
-                    idx_elt = pm.get_index_of_element(i, pattern)
-                    suc = pm.get_successors_from_idx(idx_elt, pattern)
+                    idx_elt = pm.get_index_from_element(i, pattern)
+                    suc = pm.get_successors_from_index(idx_elt, pattern)
                     
                     
     def test_successors_and_antecedents_are_equivalent(self):
diff --git a/tests/triad_manipulation_tests.py b/tests/triad_manipulation_tests.py
new file mode 100644
index 0000000000000000000000000000000000000000..f8843366c80566fe033321d6f4d6e60b9c34d7ad
--- /dev/null
+++ b/tests/triad_manipulation_tests.py
@@ -0,0 +1,142 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Fri Nov 22 13:38:53 2019
+
+@author: amarmore
+"""
+
+import unittest
+import polytopes.data_manipulation as dm
+import polytopes.model.errors as err
+import polytopes.model.triad_manipulation as tm
+
+import numpy as np
+
+class TriadManipulationTests(unittest.TestCase):
+
+##################################### Starting from the notes ################################
+        
+    def test_symbol_from_notes(self):
+        """
+        Tests if the symbol is correctly retrieved from the notes.
+        """
+        chord_maj = [8, 0, 3]
+        chord_min = [8, 11, 3]
+        chord_sus4 = [8, 1, 3]
+        chord_sus2 = [8, 10, 3]
+        chord_aug = [8, 0, 4]
+        chord_dim = [8, 0, 2]
+        
+        self.assertEqual(tm.triad_symbol_from_notes(chord_maj), "G#")
+        self.assertEqual(tm.triad_symbol_from_notes(chord_min), "G#m")
+        with self.assertRaises(err.NotAMajMinTriadException):
+            tm.triad_symbol_from_notes(chord_sus4)
+        with self.assertRaises(err.NotAMajMinTriadException):
+            tm.triad_symbol_from_notes(chord_sus2)
+        with self.assertRaises(err.NotAMajMinTriadException):
+            tm.triad_symbol_from_notes(chord_aug)
+        with self.assertRaises(err.NotAMajMinTriadException):
+            tm.triad_symbol_from_notes(chord_dim)
+
+        
+    def test_root_from_notes(self):
+        """
+        Tests if the root is correctly retrieved from the notes.
+        """
+        chord = [8, 11, 3]
+        self.assertTrue(tm.root_from_notes(chord), "G#")
+
+        chord = [3, 11, 8]
+        self.assertTrue(tm.root_from_notes(chord), "G#")
+        
+        chord = [8, 1, 3]
+        with self.assertRaises(err.NotAMajMinTriadException):
+            tm.root_from_notes(chord)
+
+
+##################################### Starting from the symbol ################################
+
+    def test_notes_from_symbol(self):
+        """
+        Tests if the notes are correctly retrieved from the symbol.
+        """
+        notes = [8, 11, 3]
+        self.assertEqual(tm.triad_notes_from_symbol("Abm"), notes)
+        self.assertEqual(tm.triad_notes_from_symbol("Abmin"), notes)
+        self.assertEqual(tm.triad_notes_from_symbol("G#m"), notes)
+        self.assertEqual(tm.triad_notes_from_symbol("G#min"), notes)
+        self.assertEqual(tm.triad_notes_from_symbol("Abd", triadic_reduction = True), notes)
+        self.assertEqual(tm.triad_notes_from_symbol("Abdim", triadic_reduction = True), notes)
+        with self.assertRaises(err.NotAMajMinTriadException):
+            self.assertEqual(tm.triad_notes_from_symbol("Abdim", triadic_reduction = False), notes) 
+
+        notes = [8, 0, 3]
+        self.assertEqual(tm.triad_notes_from_symbol("Ab"), notes)
+        self.assertEqual(tm.triad_notes_from_symbol("Abmaj"), notes)
+        self.assertEqual(tm.triad_notes_from_symbol("G#"), notes)
+        self.assertEqual(tm.triad_notes_from_symbol("G#maj"), notes)
+        
+        self.assertEqual(tm.triad_notes_from_symbol("G#5", triadic_reduction = True), notes)  
+        with self.assertRaises(err.NotAMajMinTriadException):
+            self.assertEqual(tm.triad_notes_from_symbol("G#5", triadic_reduction = False), notes)  
+            
+        self.assertEqual(tm.triad_notes_from_symbol("Absus4", triadic_reduction = True), notes)  
+        with self.assertRaises(err.NotAMajMinTriadException):
+            self.assertEqual(tm.triad_notes_from_symbol("Absus4", triadic_reduction = False), notes)  
+            
+        self.assertEqual(tm.triad_notes_from_symbol("G#7s4", triadic_reduction = True), notes)  
+        with self.assertRaises(err.NotAMajMinTriadException):
+            self.assertEqual(tm.triad_notes_from_symbol("G#7s4", triadic_reduction = False), notes)  
+
+    def test_root_from_symbol(self):
+        """
+        Tests if the root is correctly retrieved from the symbol.
+        """
+        self.assertTrue(tm.root_from_symbol('Asus2') == 'A')
+        self.assertTrue(tm.root_from_symbol('D') == 'D')
+        self.assertTrue(tm.root_from_symbol('Db') == 'Db')
+        self.assertTrue(tm.root_from_symbol('Dbm') == 'Db')
+        self.assertTrue(tm.root_from_symbol('Cm') == 'C')
+        self.assertTrue(tm.root_from_symbol('C#') == 'C#')
+        self.assertTrue(tm.root_from_symbol('C#m') == 'C#')
+        self.assertTrue(tm.root_from_symbol('C#dim') == 'C#')
+        self.assertTrue(tm.root_from_symbol('Abmin') == 'Ab')
+        
+    def test_little_format_symbol(self):
+        self.assertTrue(tm.little_format_symbol('C#dim') == 'C#d')
+        self.assertTrue(tm.little_format_symbol('C#min') == 'C#m')
+        self.assertTrue(tm.little_format_symbol('C#maj') == 'C#')
+
+
+    def test_reindex_inversed_triad(self):
+        chord = [8, 11, 3]
+        self.assertEqual(tm.reindex_inversed_triad([8, 11, 3]), chord)
+        self.assertEqual(tm.reindex_inversed_triad([8, 3, 11]), chord)
+        self.assertEqual(tm.reindex_inversed_triad([3, 11, 8]), chord)
+        self.assertEqual(tm.reindex_inversed_triad([3, 8, 11]), chord)
+        self.assertEqual(tm.reindex_inversed_triad([11, 8, 3]), chord)
+        self.assertEqual(tm.reindex_inversed_triad([11, 3, 8]), chord)
+        
+        chord_maj = [8, 0, 3]
+        self.assertEqual(tm.reindex_inversed_triad([0, 3, 8]), chord_maj)
+        self.assertEqual(tm.reindex_inversed_triad([0, 8, 3]), chord_maj)
+
+    def test_is_maj_min_triad_from_notes(self):
+        self.assertTrue(tm.is_maj_min_triad_from_notes([8, 11, 3]))
+        self.assertTrue(tm.is_maj_min_triad_from_notes([8, 0, 3]))
+        self.assertFalse(tm.is_maj_min_triad_from_notes([8, 1, 3]))
+
+    def test_is_maj_min_triad_from_symbol(self):
+        self.assertTrue(tm.is_maj_min_triad_from_symbol("Abm"))
+        self.assertTrue(tm.is_maj_min_triad_from_symbol("G#"))
+        self.assertFalse(tm.is_maj_min_triad_from_symbol("Abd"))
+        
+    def test_is_maj_min_triad_from_symbol(self):
+        self.assertEqual(tm.maj_min_triad_reduction_of_symbol("Abm"), "G#m")
+        self.assertEqual(tm.maj_min_triad_reduction_of_symbol("G#"), "G#")
+        self.assertEqual(tm.maj_min_triad_reduction_of_symbol("Abd"), "G#m")
+        self.assertEqual(tm.maj_min_triad_reduction_of_symbol("G#sus2"), "G#")
+
+
+if __name__ == '__main__':
+    unittest.main()
\ No newline at end of file
diff --git a/tests/triad_transformations_tests.py b/tests/triad_transformations_tests.py
new file mode 100644
index 0000000000000000000000000000000000000000..52481cc5d1016a3a47d974fb660d2979b3887c2b
--- /dev/null
+++ b/tests/triad_transformations_tests.py
@@ -0,0 +1,127 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Fri Nov 22 13:38:53 2019
+
+@author: amarmore
+"""
+
+import unittest
+import polytopes.model.triad_manipulation as tm
+import polytopes.triad_transformations as tt
+import polytopes.model.errors as err
+import polytopes.chord_movement as mvt
+
+import numpy as np
+
+class TriadTransformationsTests(unittest.TestCase):
+            
+    def test_get_voice_leading_distance_symbol(self):
+        self.assertEqual(tt.get_voice_leading_distance_symbol("F","Am"), 1)
+        self.assertEqual(tt.get_voice_leading_distance_symbol("Fmaj","Amin"), 1)
+        self.assertEqual(tt.get_voice_leading_distance_symbol("F","Amin"), 1)
+        self.assertEqual(tt.get_voice_leading_distance_symbol("Fmaj","Am"), 1)
+        
+        self.assertEqual(tt.get_voice_leading_distance_symbol("Dm","Am"), 3)
+        self.assertEqual(tt.get_voice_leading_distance_symbol("Bb","F#m"), 3)
+        self.assertEqual(tt.get_voice_leading_distance_symbol("C#","F#m"), 2)
+        self.assertEqual(tt.get_voice_leading_distance_symbol("C#","F#dim", triadic_reduction = True), 2)
+        with self.assertRaises(err.NotAMajMinTriadException):
+            tt.get_voice_leading_distance_symbol("Cdim","Asus2", triadic_reduction = False)
+        
+    def test_get_voice_leading_distance_notes(self):
+        self.assertEqual(tt.get_voice_leading_distance_notes([8,0,3],[8,11,3]), 1)
+        self.assertEqual(tt.get_voice_leading_distance_notes([11,3,6],[8,11,3]), 2)
+        with self.assertRaises(err.NotAMajMinTriadException):
+            tt.get_voice_leading_distance_notes([11,3,6],[8,1,3])
+                                                    
+    def test_get_voice_leading_tranformation_notes(self):
+        self.assertEqual(tt.get_voice_leading_transformation_notes([8,0,3],[8,11,3]), [0,11,0])
+        self.assertEqual(tt.get_voice_leading_transformation_notes([11,3,6],[8,11,3]), [-3, 8, -3])
+        with self.assertRaises(err.NotAMajMinTriadException):
+            tt.get_voice_leading_transformation_notes([11,3,6],[8,1,3])
+            
+    def test_get_voice_leading_tranformation_symbol(self):
+        self.assertEqual(tt.get_voice_leading_transformation_symbol("Ab","Abm"), [0,11,0])
+        self.assertEqual(tt.get_voice_leading_transformation_symbol("B","Abm"), [-3, 8, -3])
+        self.assertEqual(tt.get_voice_leading_transformation_symbol("B","Absus2"), [-3, -3, -3])
+
+        with self.assertRaises(err.NotAMajMinTriadException):
+            tt.get_voice_leading_transformation_symbol("A","Asus2", triadic_reduction = False)
+            
+    def test_get_triadic_position_symbol(self):
+        self.assertEqual(tt.get_triadic_position_symbol("Am"), 1)
+        self.assertEqual(tt.get_triadic_position_symbol("Gbm"), 19)
+        self.assertEqual(tt.get_triadic_position_symbol("F#m"), 19)
+        self.assertEqual(tt.get_triadic_position_symbol("F#dim", triadic_reduction=True), 19)
+        with self.assertRaises(err.NotAMajMinTriadException):
+            tt.get_triadic_position_symbol("F#dim", triadic_reduction=False)
+            
+    def test_get_triadic_position_notes(self):
+        self.assertEqual(tt.get_triadic_position_notes([9,0,4]), 1)
+        self.assertEqual(tt.get_triadic_position_notes([8,0,3]), 8)
+        with self.assertRaises(err.NotAMajMinTriadException):
+            tt.get_triadic_position_notes([8,1,3])
+
+    def test_triadic_mvt_triads(self):
+        self.assertEqual(tt.triadic_mvt_triads("C","Em"), -1)
+        self.assertEqual(tt.triadic_mvt_triads("Abm","A"), 3)
+        self.assertEqual(tt.triadic_mvt_triads("C#","Gbm"), 9)
+        self.assertEqual(tt.triadic_mvt_triads("C#","Gbdim", triadic_reduction=True), 9)
+        with self.assertRaises(err.NotAMajMinTriadException):
+            tt.triadic_mvt_triads("C#","Gbdim", triadic_reduction=False)
+            
+    def test_triad_and_mvt(self):
+        circle_sharp =  ['C','Am','F','Dm','A#','Gm','D#','Cm','G#','Fm','C#','A#m','F#','D#m','B','G#m','E','C#m','A','F#m','D','Bm','G','Em']
+        for chord_1 in circle_sharp:
+            for chord_2 in circle_sharp:
+                self.assertEqual(tt.triadic_mvt_triads(chord_1, chord_2), mvt.triadic_mvt_chords(chord_1, chord_2))
+            for rel in range(0,24):
+                self.assertEqual(tt.apply_triadic_mvt(chord_1, rel), mvt.apply_triadic_mvt(chord_1, rel))
+    
+    def test_apply_triadic_mvt(self):
+        self.assertEqual(tt.apply_triadic_mvt("C", -1), "Em")
+        self.assertEqual(tt.apply_triadic_mvt("Abm", 3), "A")
+        self.assertEqual(tt.apply_triadic_mvt("D#", 5), "A#m")
+        self.assertEqual(tt.apply_triadic_mvt("D#sus2", 5, triadic_reduction = True), "A#m")
+        with self.assertRaises(err.NotAMajMinTriadException):
+            tt.apply_triadic_mvt("D#sus2", 5, triadic_reduction = False)
+
+    def test_triadic_tonnetz_relation_symbol(self):
+        self.assertEqual(tt.triadic_tonnetz_relation_symbol("D","Gm"), ('P', 'L', 'R'))
+        self.assertEqual(tt.triadic_tonnetz_relation_symbol("Dm","Db"), ('L', 'P', 'R'))
+        self.assertEqual(tt.triadic_tonnetz_relation_symbol("C","A"), ('R', 'P'))
+        self.assertEqual(tt.triadic_tonnetz_relation_symbol("C","Db"), ('L','P','R', 'P'))
+        
+    def test_triadic_tonnetz_distance_symbol(self):
+        self.assertEqual(tt.triadic_tonnetz_distance_symbol("D","Gm"), 3)
+        self.assertEqual(tt.triadic_tonnetz_distance_symbol("Dm","Db"), 3)
+        self.assertEqual(tt.triadic_tonnetz_distance_symbol("C","A"), 2)
+        self.assertEqual(tt.triadic_tonnetz_distance_symbol("C","Db"), 4)
+        
+    def test_triadic_tonnetz_relation_notes(self):
+        self.assertEqual(tt.triadic_tonnetz_relation_notes([2,6,9],[7,10,2]), ('P', 'L', 'R'))
+        
+    def test_triadic_tonnetz_distance_notes(self):
+        self.assertEqual(tt.triadic_tonnetz_distance_notes([2,6,9],[7,10,2]), 3)
+        
+    def test_apply_triadic_tonnetz_relation_symbol(self):
+        self.assertEqual(tt.apply_triadic_tonnetz_relation_symbol("D",('P', 'L', 'R')), "Gm")
+        self.assertEqual(tt.apply_triadic_tonnetz_relation_symbol("D",('L', 'P', 'R')), "D#m")
+
+    def test_apply_triadic_tonnetz_relation_notes(self):
+        self.assertEqual(tt.apply_triadic_tonnetz_relation_notes([2,6,9],('P', 'L', 'R')), [7,10,2])
+
+    def test_chromatic_equals_fifth(self):
+        circle_sharp =  ['C','Am','F','Dm','A#','Gm','D#','Cm','G#','Fm','C#','A#m','F#','D#m','B','G#m','E','C#m','A','F#m','D','Bm','G','Em']
+        for i in range(len(circle_sharp)):
+            chord_1 = circle_sharp[i]
+            for j in range(len(circle_sharp)):
+                chord_2 = circle_sharp[j]
+                rel_triadic = tt.triadic_mvt_triads(chord_1, chord_2)
+                triadic = tt.apply_triadic_mvt(chord_1, rel_triadic)
+                rel_chromatic = tt.chromatic_mvt_triads(chord_1, chord_2)
+                chromatic = tt.apply_chromatic_mvt(chord_1, rel_chromatic)
+                self.assertEqual(chromatic, triadic)        
+
+if __name__ == '__main__':
+    unittest.main()
\ No newline at end of file