feat: rajout comparaison glpk

This commit is contained in:
Laureηt 2021-12-10 11:07:22 +01:00
parent 0432661aeb
commit e1018a3c0c
3 changed files with 40 additions and 141 deletions

3
.gitignore vendored
View file

@ -1,4 +1,5 @@
solveurGLPK/
*.stdout_glpk
*.stdout_lp
*.lp
*.stdout
*.sol

View file

@ -1,29 +1,29 @@
PATH = "data"
import os
result = [os.path.join(dp, f) for dp, dn, filenames in os.walk(PATH) for f in filenames if os.path.splitext(f)[1] == '.opb']
result = [os.path.join(dp, f) for dp, dn, filenames in os.walk("data") for f in filenames if os.path.splitext(f)[1] == '.opb']
with open("machines.txt") as file:
machines = file.readlines()
machines = [machine.rstrip() for machine in machines]
i = 0
while len(result) > 0:
knap = result.pop()[:-4]
victime = machines[i % len(machines)]
i+=1
cmd = f"""ssh lfainsin@{victime} -o "ConnectTimeout 3" -o "StrictHostKeyChecking no" -o "UserKnownHostsFile /dev/null" "cd 2A/RO/tp2/ && tmux new-session -d 'julia test.jl {knap}.opb > {knap}.stdout'" """
print(cmd)
os.system(cmd)
machines = [machine.rstrip() for machine in file.readlines()]
# i = 0
# while len(result) > 0:
# knap = result.pop()[:-4]
# victime = machines[i % len(machines)]
# i+=1
# cmd = f"""ssh lfainsin@{victime} -o "ConnectTimeout 3" -o "StrictHostKeyChecking no" -o "UserKnownHostsFile /dev/null" "cd 2A/RO/tp2/ && tmux new-session -d 'glpsol --lp {knap}.lp -o {knap}.sol'" """
# cmd = f"""ssh lfainsin@{victime} -o "ConnectTimeout 3" -o "StrictHostKeyChecking no" -o "UserKnownHostsFile /dev/null" "cd 2A/RO/tp2/ && tmux new-session -d 'julia test.jl {knap}.opb > {knap}.stdout_jl'" """
# print(cmd)
# os.system(cmd)
# i = 0
# while len(result) > 0:
# knap = result.pop()[:-4]
# victime = machines[i % len(machines)]
# i+=1
# cmd = f"""ssh lfainsin@{victime} -o "ConnectTimeout 3" -o "StrictHostKeyChecking no" -o "UserKnownHostsFile /dev/null" "cd 2A/RO/tp2/ && tmux new-session -d 'glpsol --lp {knap}.lp -o {knap}.sol > {knap}.stdout_lp'" """
# print(cmd)
# os.system(cmd)
# for machine in machines:
# os.system(f"""ssh lfainsin@{machine} -o "ConnectTimeout 3" -o "StrictHostKeyChecking no" -o "UserKnownHostsFile /dev/null" "tmux kill-server" """)
# cmd = f"""ssh lfainsin@{machine} -o "ConnectTimeout 3" -o "StrictHostKeyChecking no" -o "UserKnownHostsFile /dev/null" "tmux kill-server" """
# print(cmd)
# os.system(cmd)

View file

@ -34928,140 +34928,38 @@
"## Notre implémentation\n",
"\n",
"Pour l'implémentation de notre `branch and bound`, nous avons gardé la même architecture que celle du sujet. Nous avons simplement ré-écrit les fonctions qui calculent la valeur objectif et la valeur de la capacité. \\\n",
"Notre vecteur de décision $x$ est tel que $x\\in\\{-1,0,1\\}^n$ avec $n$ le nombre d'objets disponibles. $1$ et $0$ représente, respectivement, un objet non-pris ou non-pris. La valeur $-1$ représente un objet ou la décision n'a pas encore été faite.\n",
"Dans la fonction `Objetive`, si la valeur est a $-1$, on fait comme-ci elle était à $1$ pour calculer une borne supérieur. Dans la fonction `Constraints` les $-1$ sont concidéré comme des $0$ pour avoir une borne inférieur de notre problème. \\\n",
"<br>\n",
"Notre vecteur de décision $x$ est tel que $x\\in\\{-1,0,1\\}^n$ avec $n$ le nombre d'objets disponibles. $1$ et $0$ représentent, respectivement, un objet pris ou non-pris. La valeur $-1$ représente un objet ou la décision n'a pas encore été faite. \\\n",
"Dans la fonction `Objective`, si la valeur est a $-1$, on fait comme-ci elle était à $1$ pour calculer une borne supérieur. Dans la fonction `Constraints` les $-1$ sont concidérés comme des $0$ pour avoir une borne inférieur de notre problème. \\\n",
"\n",
"Pour l'exploration et la création de noeud, nous faisons une exploration des noeuds avec le plus de $1$ en premier. \\\n",
"Lorsque nous arrivons sur un noeud, nous l'enlevons de la pile des noeuds. Nous calculons ensuite si il est \"trivial\" ou si il dépasse déjà l'une des bornes ou si il est divisible. Dans le cas ou il est \"trivial\", nous calculons sa valeur et remplaçons la meilleure valeur si nécessaire. Dans le cas ou il dépasse une borne, nous l'abandonnons. Et enfin, si il est séparable, nous le séparons en deux en ajoutant la pile des noeuds les deux sous noeuds. \\\n",
"Exemple : $[(0,-1,-1)]$ -> $[(0,0,-1) ; (0,1,-1)]$\n",
"Lorsque nous arrivons sur un noeud, nous l'enlevons de la pile des noeuds. Nous calculons ensuite s'il est \"trivial\", s'il dépasse déjà l'une des bornes ou s'il est divisible.\n",
"- Dans le cas ou il est \"trivial\", nous calculons sa valeur et remplaçons la meilleure valeur si nécessaire.\n",
"- Dans le cas ou il dépasse une borne, nous l'abandonnons.\n",
"- Et enfin, si il est séparable, nous le séparons en deux en ajoutant la pile des noeuds les deux sous noeuds. Exemple : $[(0,-1,-1)]$ -> $[(0,0,-1) ; (0,1,-1)]$\n",
"\n",
"## Justification de nos résultats\n",
"\n",
"Notre algorithme trouve bien les solutions idéales (comme indiqué dans le nom du fichier). Pour le test `uncorrelated_span/knapPI_11_20_1000_1_-1428` Nous avons trouvé la valeur optimale qui est de `1428` en `2131` exploration de noeuds là ou un algorithme classique de parcours de l'ensemble des noeuds aurait exploré `1048576` noeuds.\n",
"Notre algorithme trouve bien les solutions idéales. Pour le test `uncorrelated_span/knapPI_11_20_1000_1_-1428` Nous avons trouvé la valeur optimale qui est de `1428` en `2131` exploration de noeuds là ou un algorithme classique de parcours de l'ensemble des noeuds aurait exploré `1048576` noeuds, et ce sans dépasser la capacité maximale du sac bien evidemment.\n",
"\n",
"## Analyse\n",
"\n",
"```\n",
"lfainsin@bonite:~/2A/RO/tp2$ time julia test.jl data/weakly_correlated/knapPI_2_50_1000_1_-1396.opb\n",
"---data/weakly_correlated/knapPI_2_50_1000_1_-1396.opb---\n",
"Capacity = 995\n",
"Number of objects = 50\n",
"Expected optimal value = 1396\n",
"Maximum number of nodes = 1125899906842624\n",
"Nous avaons réalisé les calculs de deux manières différentes:\n",
"- La première fois, nous mettions a jour les coordonnées de $x$ dans l'ordre des indices.\n",
"- La deuxième fois, nous avons d'abbord trié les vecteurs `weight` et `price` par leur rapport $prix / poids$. Cela revient à mettre à jour les coordonnées de $x$ dans l'ordre du meilleur rapport $prix / poids$. (NB : le vecteur résultat n'est pas ré-ordonné comme l'était les `price` et `weight` initialement)\n",
"\n",
"Node n°96: BestProfit = 825\n",
"Node n°169: BestProfit = 844\n",
"Node n°243: BestProfit = 919\n",
"Node n°297: BestProfit = 943\n",
"Node n°1126: BestProfit = 946\n",
"Node n°1224: BestProfit = 1030\n",
"Node n°1456: BestProfit = 1045\n",
"Node n°2960: BestProfit = 1105\n",
"Node n°3342: BestProfit = 1120\n",
"Node n°4596: BestProfit = 1126\n",
"Node n°6129: BestProfit = 1207\n",
"Node n°10462: BestProfit = 1212\n",
"Node n°24382: BestProfit = 1278\n",
"Node n°418695: BestProfit = 1288\n",
"Node n°422566: BestProfit = 1308\n",
"Node n°436804: BestProfit = 1329\n",
"Node n°443759: BestProfit = 1337\n",
"Node n°446051: BestProfit = 1352\n",
"Node n°916081: BestProfit = 1360\n",
"Node n°1044425: BestProfit = 1396\n",
"\n",
"--------------------------------------------------\n",
"Expected optimal value = 1396\n",
"Optimal value = 1396\n",
"Optimal x = [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0]\n",
"Maximum number of nodes = 1125899906842624\n",
"Nodes explored = 3053865\n",
"\n",
"real 0m29,301s\n",
"user 0m29,372s\n",
"sys 0m0,809s\n",
"```\n",
"\n",
"```\n",
"lfainsin@bonite:~/2A/RO/tp2$ time julia test.jl data/weakly_correlated/knapPI_2_50_1000_1_-1396.opb\n",
"---data/weakly_correlated/knapPI_2_50_1000_1_-1396.opb---\n",
"Capacity = 995\n",
"Number of objects = 50\n",
"Expected optimal value = 1396\n",
"Maximum number of nodes = 1125899906842624\n",
"\n",
"Node n°93: BestProfit = 487\n",
"Node n°175: BestProfit = 626\n",
"Node n°293: BestProfit = 705\n",
"Node n°544: BestProfit = 810\n",
"Node n°1671: BestProfit = 815\n",
"Node n°1871: BestProfit = 836\n",
"Node n°2019: BestProfit = 872\n",
"Node n°2074: BestProfit = 886\n",
"Node n°3204: BestProfit = 918\n",
"Node n°4406: BestProfit = 950\n",
"Node n°4708: BestProfit = 952\n",
"Node n°4770: BestProfit = 978\n",
"Node n°8898: BestProfit = 990\n",
"Node n°9214: BestProfit = 1049\n",
"Node n°18160: BestProfit = 1059\n",
"Node n°18616: BestProfit = 1095\n",
"Node n°25906: BestProfit = 1099\n",
"Node n°27015: BestProfit = 1104\n",
"Node n°27130: BestProfit = 1119\n",
"Node n°27585: BestProfit = 1121\n",
"Node n°28076: BestProfit = 1125\n",
"Node n°43768: BestProfit = 1132\n",
"Node n°44203: BestProfit = 1134\n",
"Node n°59004: BestProfit = 1142\n",
"Node n°59465: BestProfit = 1144\n",
"Node n°59964: BestProfit = 1148\n",
"Node n°65923: BestProfit = 1154\n",
"Node n°66110: BestProfit = 1156\n",
"Node n°71779: BestProfit = 1186\n",
"Node n°71992: BestProfit = 1188\n",
"Node n°73054: BestProfit = 1190\n",
"Node n°73127: BestProfit = 1197\n",
"Node n°73146: BestProfit = 1241\n",
"Node n°152150: BestProfit = 1249\n",
"Node n°154060: BestProfit = 1251\n",
"Node n°179062: BestProfit = 1260\n",
"Node n°181638: BestProfit = 1261\n",
"Node n°181907: BestProfit = 1281\n",
"Node n°192060: BestProfit = 1298\n",
"Node n°202348: BestProfit = 1330\n",
"Node n°203862: BestProfit = 1341\n",
"Node n°206773: BestProfit = 1351\n",
"Node n°399253: BestProfit = 1365\n",
"Node n°619338: BestProfit = 1375\n",
"Node n°619695: BestProfit = 1377\n",
"Node n°842654: BestProfit = 1394\n",
"Node n°844341: BestProfit = 1396\n",
"\n",
"--------------------------------------------------\n",
"Expected optimal value = 1396\n",
"Optimal value = 1396\n",
"Optimal x = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1]\n",
"Maximum number of nodes = 1125899906842624\n",
"Nodes explored = 846447\n",
"\n",
"real 0m4,348s\n",
"user 0m4,480s\n",
"sys 0m0,747s\n",
"```\n",
"\n",
"Nous avaons réalisé les calcules de deux manières différentes : \\\n",
"La première fois, nous mettions a jour les coordonnées de $x$ dans l'ordre des indices. \\\n",
"La deuxième fois, nous avons d'abbord trié les vecteurs `weight` et `price` par leur rapport $prix / poids$. Cela revient a mettre a jour les coordonnées de $x$ dans l'ordre du meilleur rapport $prix / poids$. (NB : le vecteur résultat n'est pas ré-ordonné comme l'était les `price` et `weight` initialement) \\\n",
"<br>\n",
"Pour le fichier `weakly_correlated/knapPI_2_50_1000_1_-1396`, nous avons comparé les résultats :\n",
"| Valeurs | Sans tri | Avec tri |\n",
"| :- | :- | :- |\n",
"| Optimal value | 1396 | 1396 |\n",
"| user | 29.372s | 4.480s |\n",
"| Nodes explored | 3053865 | 846447 |\n",
"| Valeurs | Sans tri | Avec tri |\n",
"| :------------- | :------- | :------- |\n",
"| Optimal value | 1396 | 1396 |\n",
"| Nodes explored | 3053865 | 846447 |\n",
"| time | 29.372s | 4.480s |\n",
"\n",
"Il serait finalement possible d'optimiser encore plus notre algorithme en ne stockant que les changements de valeurs dans l'abre, au lieu de stocker le vecteurs $x$ en entier à chaque noeud de l'arbre."
"Il serait possible d'optimiser encore plus notre algorithme en ne stockant que les changements de valeurs dans l'abre, au lieu de stocker le vecteurs $x$ en entier à chaque noeud de l'arbre. Cela permetterait d'économiser pas mal de RAM.\n",
"\n",
"## Bonus: Comparaison avec GLPK\n",
"\n",
"La huitième cellule de ce notebook permet de convertir les `.opb` en `.lp`, et permet ainsi de résoudre les problèmes en utilisant GLPK.\n",
"Via les fichiers `test.jl` et `distrib.py` on lance sur toutes les machines de l'enseeiht (la nuit), la résolution de chaque problème via GLPK et via notre implémentation. On observe alors que l'on obtient la même valeur `Objective` optimale finale, de même le nombre de noeuds explorés par GLPK ainsi que son temps d'execution sont nettement inférieur à ceux de notre algorithme."
]
}
],