Merge remote-tracking branch 'tp2/master'
This commit is contained in:
commit
e5f84c77ce
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
solveurGLPK/
|
||||||
|
*.stdout_glpk
|
||||||
|
*.stdout_lp
|
||||||
|
*.lp
|
||||||
|
*.sol
|
29
distrib.py
Normal file
29
distrib.py
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
import os
|
||||||
|
|
||||||
|
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 = [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 '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:
|
||||||
|
# cmd = f"""ssh lfainsin@{machine} -o "ConnectTimeout 3" -o "StrictHostKeyChecking no" -o "UserKnownHostsFile /dev/null" "tmux kill-server" """
|
||||||
|
# print(cmd)
|
||||||
|
# os.system(cmd)
|
22
install_glpk.sh
Executable file
22
install_glpk.sh
Executable file
|
@ -0,0 +1,22 @@
|
||||||
|
mkdir solveurGLPK
|
||||||
|
cd solveurGLPK
|
||||||
|
mkdir sources
|
||||||
|
cd sources
|
||||||
|
|
||||||
|
wget ftp://ftp.gnu.org/gnu/glpk/glpk-5.0.tar.gz
|
||||||
|
tar -xzvf glpk-5.0.tar.gz
|
||||||
|
cd glpk-5.0
|
||||||
|
|
||||||
|
./configure --disable-shared
|
||||||
|
make
|
||||||
|
#make --jobs=4
|
||||||
|
make check
|
||||||
|
|
||||||
|
cd ../..
|
||||||
|
mkdir executables
|
||||||
|
cp sources/glpk-5.0/examples/glpsol executables/.
|
||||||
|
cp sources/glpk-5.0/doc/glpk.pdf executables/.
|
||||||
|
cp sources/glpk-5.0/doc/gmpl.pdf executables/.
|
||||||
|
|
||||||
|
cd executables
|
||||||
|
./glpsol --help
|
252
machines.txt
Normal file
252
machines.txt
Normal file
|
@ -0,0 +1,252 @@
|
||||||
|
ablette.enseeiht.fr
|
||||||
|
acdc.enseeiht.fr
|
||||||
|
ackbar.enseeiht.fr
|
||||||
|
actinium.enseeiht.fr
|
||||||
|
ader.enseeiht.fr
|
||||||
|
aerosmith.enseeiht.fr
|
||||||
|
alose.enseeiht.fr
|
||||||
|
anguille.enseeiht.fr
|
||||||
|
antimoine.enseeiht.fr
|
||||||
|
apollinaire.enseeiht.fr
|
||||||
|
aragorn.enseeiht.fr
|
||||||
|
archimede.enseeiht.fr
|
||||||
|
arryn.enseeiht.fr
|
||||||
|
arwen.enseeiht.fr
|
||||||
|
aspicot.enseeiht.fr
|
||||||
|
aston.enseeiht.fr
|
||||||
|
atanasoff.enseeiht.fr
|
||||||
|
atkinson.enseeiht.fr
|
||||||
|
azote.enseeiht.fr
|
||||||
|
babagge.enseeiht.fr
|
||||||
|
backus.enseeiht.fr
|
||||||
|
banshee.enseeiht.fr
|
||||||
|
baratheon.enseeiht.fr
|
||||||
|
basilic.enseeiht.fr
|
||||||
|
bastie.enseeiht.fr
|
||||||
|
baudelaire.enseeiht.fr
|
||||||
|
behemot.enseeiht.fr
|
||||||
|
bilbo.enseeiht.fr
|
||||||
|
bishop.enseeiht.fr
|
||||||
|
bleriot.enseeiht.fr
|
||||||
|
bobafett.enseeiht.fr
|
||||||
|
boeing.enseeiht.fr
|
||||||
|
bonite.enseeiht.fr
|
||||||
|
boole.enseeiht.fr
|
||||||
|
boromir.enseeiht.fr
|
||||||
|
bouba.enseeiht.fr
|
||||||
|
boucher.enseeiht.fr
|
||||||
|
brassens.enseeiht.fr
|
||||||
|
bravoos.enseeiht.fr
|
||||||
|
brochet.enseeiht.fr
|
||||||
|
bulbizarre.enseeiht.fr
|
||||||
|
cable.enseeiht.fr
|
||||||
|
calimero.enseeiht.fr
|
||||||
|
candy.enseeiht.fr
|
||||||
|
carapuce.enseeiht.fr
|
||||||
|
carbone.enseeiht.fr
|
||||||
|
carmack.enseeiht.fr
|
||||||
|
carpe.enseeiht.fr
|
||||||
|
casimir.enseeiht.fr
|
||||||
|
chenipan.enseeiht.fr
|
||||||
|
chevesne.enseeiht.fr
|
||||||
|
chewie.enseeiht.fr
|
||||||
|
clapton.enseeiht.fr
|
||||||
|
clash.enseeiht.fr
|
||||||
|
clementine.enseeiht.fr
|
||||||
|
cobalt.enseeiht.fr
|
||||||
|
colossus.enseeiht.fr
|
||||||
|
cooper.enseeiht.fr
|
||||||
|
copernic.enseeiht.fr
|
||||||
|
corb.enseeiht.fr
|
||||||
|
cyclope.enseeiht.fr
|
||||||
|
dagobah.enseeiht.fr
|
||||||
|
darwin.enseeiht.fr
|
||||||
|
daurade.enseeiht.fr
|
||||||
|
dazzler.enseeiht.fr
|
||||||
|
deeppurple.enseeiht.fr
|
||||||
|
demusset.enseeiht.fr
|
||||||
|
descartes.enseeiht.fr
|
||||||
|
diabolo.enseeiht.fr
|
||||||
|
dijkstra.enseeiht.fr
|
||||||
|
doors.enseeiht.fr
|
||||||
|
dorne.enseeiht.fr
|
||||||
|
dragon.enseeiht.fr
|
||||||
|
dylan.enseeiht.fr
|
||||||
|
eagles.enseeiht.fr
|
||||||
|
edison.enseeiht.fr
|
||||||
|
einsten.enseeiht.fr
|
||||||
|
elrond.enseeiht.fr
|
||||||
|
eomer.enseeiht.fr
|
||||||
|
eowyn.enseeiht.fr
|
||||||
|
eperlan.enseeiht.fr
|
||||||
|
epica.enseeiht.fr
|
||||||
|
esteban.enseeiht.fr
|
||||||
|
ewok.enseeiht.fr
|
||||||
|
farman.enseeiht.fr
|
||||||
|
fermat.enseeiht.fr
|
||||||
|
ferre.enseeiht.fr
|
||||||
|
fletan.enseeiht.fr
|
||||||
|
fluor.enseeiht.fr
|
||||||
|
forge.enseeiht.fr
|
||||||
|
frodon.enseeiht.fr
|
||||||
|
galilee.enseeiht.fr
|
||||||
|
galium.enseeiht.fr
|
||||||
|
gambit.enseeiht.fr
|
||||||
|
gandalf.enseeiht.fr
|
||||||
|
gardon.enseeiht.fr
|
||||||
|
garros.enseeiht.fr
|
||||||
|
gautier.enseeiht.fr
|
||||||
|
gimli.enseeiht.fr
|
||||||
|
gobelin.enseeiht.fr
|
||||||
|
gobie.enseeiht.fr
|
||||||
|
goldorak.enseeiht.fr
|
||||||
|
gorgone.enseeiht.fr
|
||||||
|
gosling.enseeiht.fr
|
||||||
|
goujon.enseeiht.fr
|
||||||
|
greyjoy.enseeiht.fr
|
||||||
|
griffon.enseeiht.fr
|
||||||
|
grove.enseeiht.fr
|
||||||
|
guynemer.enseeiht.fr
|
||||||
|
havok.enseeiht.fr
|
||||||
|
hawking.enseeiht.fr
|
||||||
|
heidi.enseeiht.fr
|
||||||
|
hendrix.enseeiht.fr
|
||||||
|
hippogriffe.enseeiht.fr
|
||||||
|
hopper.enseeiht.fr
|
||||||
|
hugo.enseeiht.fr
|
||||||
|
hydre.enseeiht.fr
|
||||||
|
hypotrempe.enseeiht.fr
|
||||||
|
iceberg.enseeiht.fr
|
||||||
|
iode.enseeiht.fr
|
||||||
|
jabba.enseeiht.fr
|
||||||
|
jeangrey.enseeiht.fr
|
||||||
|
jobs.enseeiht.fr
|
||||||
|
jubele.enseeiht.fr
|
||||||
|
kenobi.enseeiht.fr
|
||||||
|
kepler.enseeiht.fr
|
||||||
|
kernighan.enseeiht.fr
|
||||||
|
kiss.enseeiht.fr
|
||||||
|
knuth.enseeiht.fr
|
||||||
|
ladyoscar.enseeiht.fr
|
||||||
|
lafontaine.enseeiht.fr
|
||||||
|
lamartine.enseeiht.fr
|
||||||
|
lando.enseeiht.fr
|
||||||
|
lannister.enseeiht.fr
|
||||||
|
latecoere.enseeiht.fr
|
||||||
|
legolas.enseeiht.fr
|
||||||
|
leia.enseeiht.fr
|
||||||
|
lindbergh.enseeiht.fr
|
||||||
|
liskov.enseeiht.fr
|
||||||
|
loureed.enseeiht.fr
|
||||||
|
lovelace.enseeiht.fr
|
||||||
|
luke.enseeiht.fr
|
||||||
|
magicarpe.enseeiht.fr
|
||||||
|
magma.enseeiht.fr
|
||||||
|
magneto.enseeiht.fr
|
||||||
|
malicia.enseeiht.fr
|
||||||
|
mallarme.enseeiht.fr
|
||||||
|
manticore.enseeiht.fr
|
||||||
|
marcheursblancs.enseeiht.fr
|
||||||
|
martell.enseeiht.fr
|
||||||
|
maupassant.enseeiht.fr
|
||||||
|
maya.enseeiht.fr
|
||||||
|
meeren.enseeiht.fr
|
||||||
|
melofee.enseeiht.fr
|
||||||
|
mermoz.enseeiht.fr
|
||||||
|
merry.enseeiht.fr
|
||||||
|
messerschmitt.enseeiht.fr
|
||||||
|
metallica.enseeiht.fr
|
||||||
|
minotaure.enseeiht.fr
|
||||||
|
mordocet.enseeiht.fr
|
||||||
|
motorhead.enseeiht.fr
|
||||||
|
murdock.enseeiht.fr
|
||||||
|
muse.enseeiht.fr
|
||||||
|
mystique.enseeiht.fr
|
||||||
|
neon.enseeiht.fr
|
||||||
|
nerophis.enseeiht.fr
|
||||||
|
neumann.enseeiht.fr
|
||||||
|
newton.enseeiht.fr
|
||||||
|
nickel.enseeiht.fr
|
||||||
|
nymphe.enseeiht.fr
|
||||||
|
ohm.enseeiht.fr
|
||||||
|
omble.enseeiht.fr
|
||||||
|
orphie.enseeiht.fr
|
||||||
|
oxygene.enseeiht.fr
|
||||||
|
palomete.enseeiht.fr
|
||||||
|
palpatine.enseeiht.fr
|
||||||
|
pascal.enseeiht.fr
|
||||||
|
pegase.enseeiht.fr
|
||||||
|
phenix.enseeiht.fr
|
||||||
|
phosphore.enseeiht.fr
|
||||||
|
piafabec.enseeiht.fr
|
||||||
|
pikachu.enseeiht.fr
|
||||||
|
pinkfloyd.enseeiht.fr
|
||||||
|
pippin.enseeiht.fr
|
||||||
|
poe.enseeiht.fr
|
||||||
|
polaris.enseeiht.fr
|
||||||
|
polonium.enseeiht.fr
|
||||||
|
portreal.enseeiht.fr
|
||||||
|
prevert.enseeiht.fr
|
||||||
|
psykokwak.enseeiht.fr
|
||||||
|
psylocke.enseeiht.fr
|
||||||
|
queen.enseeiht.fr
|
||||||
|
r2d2.enseeiht.fr
|
||||||
|
rattata.enseeiht.fr
|
||||||
|
rimbaud.enseeiht.fr
|
||||||
|
rocket.enseeiht.fr
|
||||||
|
rondoudou.enseeiht.fr
|
||||||
|
roucool.enseeiht.fr
|
||||||
|
rouget.enseeiht.fr
|
||||||
|
saintexupery.enseeiht.fr
|
||||||
|
salameche.enseeiht.fr
|
||||||
|
sam.enseeiht.fr
|
||||||
|
sand.enseeiht.fr
|
||||||
|
sandre.enseeiht.fr
|
||||||
|
sar.enseeiht.fr
|
||||||
|
sauvageons.enseeiht.fr
|
||||||
|
scorpion.enseeiht.fr
|
||||||
|
scoubidou.enseeiht.fr
|
||||||
|
shadowcat.enseeiht.fr
|
||||||
|
shannon.enseeiht.fr
|
||||||
|
silure.enseeiht.fr
|
||||||
|
snorki.enseeiht.fr
|
||||||
|
snow.enseeiht.fr
|
||||||
|
socrate.enseeiht.fr
|
||||||
|
sodium.enseeiht.fr
|
||||||
|
solo.enseeiht.fr
|
||||||
|
stallman.enseeiht.fr
|
||||||
|
stark.enseeiht.fr
|
||||||
|
stones.enseeiht.fr
|
||||||
|
succube.enseeiht.fr
|
||||||
|
sunfire.enseeiht.fr
|
||||||
|
superbus.enseeiht.fr
|
||||||
|
swartz.enseeiht.fr
|
||||||
|
tacaud.enseeiht.fr
|
||||||
|
tanche.enseeiht.fr
|
||||||
|
tao.enseeiht.fr
|
||||||
|
targaryen.enseeiht.fr
|
||||||
|
taupiqueur.enseeiht.fr
|
||||||
|
tesla.enseeiht.fr
|
||||||
|
titane.enseeiht.fr
|
||||||
|
tornade.enseeiht.fr
|
||||||
|
torvalds.enseeiht.fr
|
||||||
|
truite.enseeiht.fr
|
||||||
|
turing.enseeiht.fr
|
||||||
|
tyrell.enseeiht.fr
|
||||||
|
uranium.enseeiht.fr
|
||||||
|
vador.enseeiht.fr
|
||||||
|
vairon.enseeiht.fr
|
||||||
|
verlaine.enseeiht.fr
|
||||||
|
voisin.enseeiht.fr
|
||||||
|
volantis.enseeiht.fr
|
||||||
|
volta.enseeiht.fr
|
||||||
|
winterfell.enseeiht.fr
|
||||||
|
wright.enseeiht.fr
|
||||||
|
wyvern.enseeiht.fr
|
||||||
|
xorn.enseeiht.fr
|
||||||
|
yoda.enseeiht.fr
|
||||||
|
z6po.enseeiht.fr
|
||||||
|
zemanek.enseeiht.fr
|
||||||
|
zia.enseeiht.fr
|
||||||
|
zirconium.enseeiht.fr
|
||||||
|
zztop.enseeiht.fr
|
366
notebook-exemple.ipynb
Normal file
366
notebook-exemple.ipynb
Normal file
|
@ -0,0 +1,366 @@
|
||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# TP 2-3 : Branch-and-bound applied to a knapsack problem"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### Initialisation (à faire une seule fois)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"import Pkg; \n",
|
||||||
|
"Pkg.add(\"GraphRecipes\");\n",
|
||||||
|
"Pkg.add(\"Plots\"); \n",
|
||||||
|
"using GraphRecipes, Plots #only used to visualize the search tree at the end of the branch-and-bound"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### Récupération des données"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"function readKnaptxtInstance(filename)\n",
|
||||||
|
" price=[]\n",
|
||||||
|
" weight=[]\n",
|
||||||
|
" KnapCap=[]\n",
|
||||||
|
" open(filename) do f\n",
|
||||||
|
" for i in 1:3\n",
|
||||||
|
" tok = split(readline(f))\n",
|
||||||
|
" if (tok[1] == \"ListPrices=\")\n",
|
||||||
|
" for i in 2:(length(tok)-1)\n",
|
||||||
|
" push!(price,parse(Int64, tok[i]))\n",
|
||||||
|
" end\n",
|
||||||
|
" elseif(tok[1] == \"ListWeights=\")\n",
|
||||||
|
" for i in 2:(length(tok)-1)\n",
|
||||||
|
" push!(weight,parse(Int64, tok[i]))\n",
|
||||||
|
" end\n",
|
||||||
|
" elseif(tok[1] == \"Capacity=\")\n",
|
||||||
|
" push!(KnapCap, parse(Int64, tok[2]))\n",
|
||||||
|
" else\n",
|
||||||
|
" println(\"Unknown read :\", tok)\n",
|
||||||
|
" end \n",
|
||||||
|
" end\n",
|
||||||
|
" end\n",
|
||||||
|
" capacity=KnapCap[1]\n",
|
||||||
|
" return price, weight, capacity\n",
|
||||||
|
"end"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### Procédure d'application des tests de sondabilités TA, TO et TR pour le cas de la relaxation linéaire"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"function TestsSondabilite_relaxlin(model2, x, varsbin, BestProfit, Bestsol)\n",
|
||||||
|
" TA, TO, TR = false, false, false\n",
|
||||||
|
" if (termination_status(model2) == MOI.INFEASIBLE)#Test de faisabilite\n",
|
||||||
|
" TA=true\n",
|
||||||
|
" println(\"TA\")\n",
|
||||||
|
" elseif (objective_value(model2) <= BestProfit) #Test d'optimalite\n",
|
||||||
|
" TO=true\n",
|
||||||
|
" println(\"TO\")\n",
|
||||||
|
" elseif ( prod(abs.([round.(v, digits=0) for v in value.(varsbin)]-value.(varsbin)) .<= fill(10^-5, size(varsbin))) \n",
|
||||||
|
" ) #Test de resolution\n",
|
||||||
|
" TR=true\n",
|
||||||
|
" println(\"TR\")\n",
|
||||||
|
" #if (value(benef) >= BestProfit)\n",
|
||||||
|
" if (objective_value(model2) >= BestProfit)\n",
|
||||||
|
" Bestsol = value.(x)\n",
|
||||||
|
" #BestProfit=value(benef)\n",
|
||||||
|
" BestProfit=objective_value(model2)\n",
|
||||||
|
" end\n",
|
||||||
|
" else\n",
|
||||||
|
" println(\"non sondable\")\n",
|
||||||
|
" end\n",
|
||||||
|
" TA, TO, TR, Bestsol, BestProfit\n",
|
||||||
|
"end"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### Procédure de séparation et stratégie d'exploration permettant de se placer au prochain noeud à traiter"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"\n",
|
||||||
|
"function SeparerNoeud_relaxlin(varsshouldbebinary, listvars, listvals)\n",
|
||||||
|
" # le noeud est non-sondable. Appliquer le critère de séparation pour le séparer en sous-noeuds \n",
|
||||||
|
" # et choisir un noeud-fils le plus à gauche \n",
|
||||||
|
" \n",
|
||||||
|
" #find a fractionnal variable\n",
|
||||||
|
" i, var = 1, 0\n",
|
||||||
|
" while ((i <= length(varsshouldbebinary)) && (var==0))\n",
|
||||||
|
" #if (varsshouldbebinary[i] ∉ listvars)\n",
|
||||||
|
" if (abs(round(value(varsshouldbebinary[i]), digits=0) - value(varsshouldbebinary[i]) ) >= 10^-5)\n",
|
||||||
|
" var=varsshouldbebinary[i]\n",
|
||||||
|
" end\n",
|
||||||
|
" i+=1\n",
|
||||||
|
" end\n",
|
||||||
|
" \n",
|
||||||
|
" #=\n",
|
||||||
|
" #find most fractionnal variable ?\n",
|
||||||
|
" i, var, maxfrac = -1, 0, 0.0\n",
|
||||||
|
" for i in 1:length(varsshouldbebinary)\n",
|
||||||
|
" if (abs(round(value(varsshouldbebinary[i]), digits=0) - value(varsshouldbebinary[i]) ) >= maxfrac) \n",
|
||||||
|
" #if a variable is more fractinonal\n",
|
||||||
|
" var=varsshouldbebinary[i]\n",
|
||||||
|
" maxfrac=abs(round(value(varsshouldbebinary[i]), digits=0) - value(varsshouldbebinary[i]) )\n",
|
||||||
|
" #println(i, \" \", var, \" \", maxfrac)\n",
|
||||||
|
" end\n",
|
||||||
|
" end\n",
|
||||||
|
" =#\n",
|
||||||
|
" \n",
|
||||||
|
"\n",
|
||||||
|
" set_lower_bound(var,1.0)\n",
|
||||||
|
" set_upper_bound(var,1.0)\n",
|
||||||
|
"\n",
|
||||||
|
" push!(listvars,var) #stocker l'identite de la variable choisie pour la séparation\n",
|
||||||
|
" push!(listvals,1.0) #stocker la branche choisie, identifiee par la valeur de la variable choisie\n",
|
||||||
|
" listvars, listvals\n",
|
||||||
|
"end\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"function ExplorerAutreNoeud_relaxlin(listvars, listvals, listnodes)\n",
|
||||||
|
" #this node is sondable, go back to parent node then right child if possible\n",
|
||||||
|
" \n",
|
||||||
|
" stop=false\n",
|
||||||
|
" #check if we are not at the root node\n",
|
||||||
|
" if (length(listvars)>= 1)\n",
|
||||||
|
" #go back to parent node\n",
|
||||||
|
" var=pop!(listvars)\n",
|
||||||
|
" theval=pop!(listvals)\n",
|
||||||
|
" tmp=pop!(listnodes)\n",
|
||||||
|
" set_lower_bound(var,0.0)\n",
|
||||||
|
" set_upper_bound(var,1.0)\n",
|
||||||
|
"\n",
|
||||||
|
" #go to right child if possible, otherwise go back to parent\n",
|
||||||
|
" while ( (theval==0.0) && (length(listvars)>= 1))\n",
|
||||||
|
" var=pop!(listvars)\n",
|
||||||
|
" theval=pop!(listvals)\n",
|
||||||
|
" tmp=pop!(listnodes)\n",
|
||||||
|
" set_lower_bound(var,0.0) \n",
|
||||||
|
" set_upper_bound(var,1.0)\n",
|
||||||
|
" end\n",
|
||||||
|
" if theval==1.0\n",
|
||||||
|
" set_lower_bound(var,0.0)\n",
|
||||||
|
" set_upper_bound(var,0.0)\n",
|
||||||
|
" push!(listvars,var)\n",
|
||||||
|
" push!(listvals,0.0)\n",
|
||||||
|
" else\n",
|
||||||
|
" println(\"\\nFINISHED\")\n",
|
||||||
|
" stop=true\n",
|
||||||
|
" end\n",
|
||||||
|
" else\n",
|
||||||
|
" #the root node was sondable\n",
|
||||||
|
" println(\"\\nFINISHED\")\n",
|
||||||
|
" stop=true\n",
|
||||||
|
" end\n",
|
||||||
|
" listvars, listvals, listnodes, stop \n",
|
||||||
|
"end"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### Création de la relaxation linéaire (= modèle associé au noeud 0): <span style=\"color:red\"> SECTION A SUPPRIMER !!!! </span>\n",
|
||||||
|
"\n",
|
||||||
|
"<span style=\"color:red\"> Cette section est à commenter/supprimer et remplacer par vos propres calculs de bornes supérieures et autres, par exemple basées sur les bornes 1 et 2 vues en cours, ou d'autres calculs de bornes de votre choix/conception validés au préalable par votre encadrant/e de TP </span>"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"Pkg.add(\"Clp\");\n",
|
||||||
|
"using JuMP, Clp"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"function CreationModeleLP(price, weight, capacity)\n",
|
||||||
|
"# ROOT NODE\n",
|
||||||
|
" \n",
|
||||||
|
" model2 = Model(Clp.Optimizer) # set optimizer\n",
|
||||||
|
" set_optimizer_attribute(model2, \"LogLevel\", 0) #don't display anything during solve\n",
|
||||||
|
" set_optimizer_attribute(model2, \"Algorithm\", 4) #LP solver chosen is simplex\n",
|
||||||
|
"\n",
|
||||||
|
" # define x variables as CONTINUOUS (recall that it is not possible to define binary variables in Clp)\n",
|
||||||
|
" @variable(model2, 0 <= x[i in 1:4] <= 1)\n",
|
||||||
|
" varsshouldbebinary=[x[1] x[2] x[3] x[4]]\n",
|
||||||
|
"\n",
|
||||||
|
" # define objective function\n",
|
||||||
|
" @objective(model2, Max, sum(price[i]*x[i] for i in 1:4))\n",
|
||||||
|
"\n",
|
||||||
|
" # define the capacity constraint \n",
|
||||||
|
" @constraint(model2, sum(weight[i]*x[i] for i in 1:4) <= capacity)\n",
|
||||||
|
"\n",
|
||||||
|
" println(model2)\n",
|
||||||
|
"\n",
|
||||||
|
" return model2, x, varsshouldbebinary\n",
|
||||||
|
"end\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### Boucle principale : résoudre la relaxation linéaire, appliquer les tests de sondabilité, identifier le prochain noeud, répéter."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"\n",
|
||||||
|
"function SolveKnapInstance(filename)\n",
|
||||||
|
"\n",
|
||||||
|
" if (split(filename,\"/\")[end] != \"test.opb\")\n",
|
||||||
|
" println(\"This version of the code works only for the test instance !!!!\")\n",
|
||||||
|
" else\n",
|
||||||
|
" price, weight, capacity = readKnaptxtInstance(filename)\n",
|
||||||
|
" model2, x, varsshouldbebinary = CreationModeleLP(price, weight, capacity)\n",
|
||||||
|
" \n",
|
||||||
|
" #create the structure to memorize the search tree for visualization at the end\n",
|
||||||
|
" trParentnodes=Int64[] #will store orig node of arc in search tree\n",
|
||||||
|
" trChildnodes=Int64[] #will store destination node of arc in search tree\n",
|
||||||
|
" trNamenodes=[] #will store names of nodes in search tree\n",
|
||||||
|
" \n",
|
||||||
|
" #intermediate structure to navigate in the search tree\n",
|
||||||
|
" listvars=[]\n",
|
||||||
|
" listvals=[]\n",
|
||||||
|
" listnodes=[]\n",
|
||||||
|
"\n",
|
||||||
|
" BestProfit=-1\n",
|
||||||
|
" Bestsol=[]\n",
|
||||||
|
"\n",
|
||||||
|
" current_node_number=0\n",
|
||||||
|
" stop = false\n",
|
||||||
|
"\n",
|
||||||
|
" while (!stop)\n",
|
||||||
|
"\n",
|
||||||
|
" println(\"\\nNode number \", current_node_number, \": \\n-----\\n\", model2)\n",
|
||||||
|
"\n",
|
||||||
|
" #Update the search tree\n",
|
||||||
|
" push!(trNamenodes,current_node_number+1) \n",
|
||||||
|
" if (length(trNamenodes)>=2)\n",
|
||||||
|
" push!(trParentnodes,listnodes[end]+1) # +1 because the 1st node is \"node 0\"\n",
|
||||||
|
" push!(trChildnodes, current_node_number+1) # +1 because the 1st node is \"node 0\"\n",
|
||||||
|
" end\n",
|
||||||
|
" push!(listnodes, current_node_number)\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
" print(\"Solve model2 to compute the bounds of the current node: start ... \")\n",
|
||||||
|
" status = optimize!(model2)\n",
|
||||||
|
" println(\"... end\")\n",
|
||||||
|
"\n",
|
||||||
|
" print(\"\\nSolution relax lin\"); \n",
|
||||||
|
" if (termination_status(model2) == MOI.INFEASIBLE)#(has_values(model2))\n",
|
||||||
|
" print(\" : NOT AVAILABLE (probably infeasible or ressources limit reached)\")\n",
|
||||||
|
" else\n",
|
||||||
|
" [print(\"\\t\", name(v),\"=\",value(v)) for v in all_variables(model2)] \n",
|
||||||
|
" end\n",
|
||||||
|
" println(\" \"); println(\"\\nPrevious Solution memorized \", Bestsol, \" with bestprofit \", BestProfit, \"\\n\")\n",
|
||||||
|
"\n",
|
||||||
|
" TA, TO, TR, Bestsol, BestProfit = TestsSondabilite_relaxlin(model2, x, varsshouldbebinary, BestProfit, Bestsol)\n",
|
||||||
|
"\n",
|
||||||
|
" is_node_sondable = TA || TO || TR\n",
|
||||||
|
"\n",
|
||||||
|
" if (!is_node_sondable)\n",
|
||||||
|
" listvars, listvals = SeparerNoeud_relaxlin(varsshouldbebinary, listvars, listvals)\n",
|
||||||
|
" else\n",
|
||||||
|
" listvars, listvals, listnodes, stop = ExplorerAutreNoeud_relaxlin(listvars, listvals, listnodes)\n",
|
||||||
|
" end\n",
|
||||||
|
"\n",
|
||||||
|
" current_node_number = current_node_number + 1\n",
|
||||||
|
" end\n",
|
||||||
|
"\n",
|
||||||
|
" println(\"\\n******\\n\\nOptimal value = \", BestProfit, \"\\n\\nOptimal x=\", Bestsol)\n",
|
||||||
|
"\n",
|
||||||
|
" return BestProfit, Bestsol, trParentnodes, trChildnodes, trNamenodes\n",
|
||||||
|
" end\n",
|
||||||
|
"\n",
|
||||||
|
"end\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### Affichage du résultat final"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"BestProfit, Bestsol, trParentnodes, trChildnodes, trNamenodes = SolveKnapInstance(\"data/test.opb\")\n",
|
||||||
|
"println(\"\\n******\\n\\nOptimal value = \", BestProfit, \"\\n\\nOptimal x=\", Bestsol)\n",
|
||||||
|
"graphplot(trParentnodes, trChildnodes, names=trNamenodes, method=:tree)\n",
|
||||||
|
"println(trParentnodes)\n",
|
||||||
|
"println(trChildnodes)\n",
|
||||||
|
"println(trNamenodes)"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Julia 1.6.3",
|
||||||
|
"language": "julia",
|
||||||
|
"name": "julia-1.6"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"file_extension": ".jl",
|
||||||
|
"mimetype": "application/julia",
|
||||||
|
"name": "julia",
|
||||||
|
"version": "1.6.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 4
|
||||||
|
}
|
967
notebook.ipynb
Normal file
967
notebook.ipynb
Normal file
File diff suppressed because one or more lines are too long
242
test.jl
Normal file
242
test.jl
Normal file
|
@ -0,0 +1,242 @@
|
||||||
|
function readKnapInstance(filename)
|
||||||
|
price = []
|
||||||
|
weight = []
|
||||||
|
capacity = -1
|
||||||
|
open(filename) do f
|
||||||
|
for i = 1:3
|
||||||
|
tok = split(readline(f))
|
||||||
|
if (tok[1] == "ListPrices=")
|
||||||
|
for i = 2:(length(tok)-1)
|
||||||
|
push!(price, parse(Int64, tok[i]))
|
||||||
|
end
|
||||||
|
elseif (tok[1] == "ListWeights=")
|
||||||
|
for i = 2:(length(tok)-1)
|
||||||
|
push!(weight, parse(Int64, tok[i]))
|
||||||
|
end
|
||||||
|
elseif (tok[1] == "Capacity=")
|
||||||
|
capacity = parse(Int64, tok[2])
|
||||||
|
else
|
||||||
|
println("Unknown read :", tok)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return price, weight, capacity
|
||||||
|
end
|
||||||
|
|
||||||
|
function TestsSondabilite_relaxlin(x, price, weight, capacity, BestProfit, Bestsol, affich)
|
||||||
|
TA, TO, TR = false, false, false
|
||||||
|
|
||||||
|
if (!Constraints(x, weight, capacity)) # Test de faisabilite
|
||||||
|
TA = true
|
||||||
|
if affich
|
||||||
|
println("TA\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif (Objective(x, price) <= BestProfit) # Test d'optimalite
|
||||||
|
TO = true
|
||||||
|
if affich
|
||||||
|
println("TO\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif (AllDef(x)) # Test de resolution
|
||||||
|
TR = true
|
||||||
|
if affich
|
||||||
|
println("TR : solution ", " de profit ", Objective(x, price), "\n")
|
||||||
|
end
|
||||||
|
if (Objective(x, price) >= BestProfit) # Le profit de la solution trouvée est meilleur que les autres
|
||||||
|
if affich
|
||||||
|
println("\t-> Cette solution a un meilleur profit.\n")
|
||||||
|
end
|
||||||
|
# On remplace la solution et le profit par les nouvelles valeurs
|
||||||
|
Bestsol = x
|
||||||
|
BestProfit = Objective(x, price)
|
||||||
|
else
|
||||||
|
if affich
|
||||||
|
println("\t-> Cette solution est moins bonne.\n")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif affich
|
||||||
|
println("non sondable\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
return TA, TO, TR, Bestsol, BestProfit
|
||||||
|
end
|
||||||
|
|
||||||
|
function SeparerNoeud_relaxlin(price, listvars, listvals)
|
||||||
|
# Le noeud est non-sondable. Appliquer le critère de séparation pour le séparer en sous-noeuds
|
||||||
|
# Cas du noeud le plus à gauche
|
||||||
|
# On sépare le noeud actuel en 2 sous-noeuds
|
||||||
|
predX = pop!(listvars)
|
||||||
|
nextX0 = copy(predX)
|
||||||
|
nextX1 = copy(predX)
|
||||||
|
|
||||||
|
# On initialise leurs valeurs à zéro
|
||||||
|
val0 = 0
|
||||||
|
val1 = 0
|
||||||
|
|
||||||
|
# On fixe la nouvelle variable des deux sous-noeuds
|
||||||
|
n = length(predX)
|
||||||
|
for i = 1:n
|
||||||
|
if predX[i] == -1
|
||||||
|
# L'un a zéro
|
||||||
|
nextX0[i] = 0
|
||||||
|
# L'autre a un
|
||||||
|
nextX1[i] = 1
|
||||||
|
|
||||||
|
# On calcule leurs valeurs
|
||||||
|
val0 = Objective(nextX0, price)
|
||||||
|
val1 = Objective(nextX1, price)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# On ajoute les sous-noeuds a la pile des noeuds a explorer
|
||||||
|
push!(listvars, nextX0)
|
||||||
|
push!(listvars, nextX1)
|
||||||
|
|
||||||
|
# On ajoute aussi leurs valeurs
|
||||||
|
push!(listvals, val0)
|
||||||
|
push!(listvals, val1)
|
||||||
|
|
||||||
|
return listvars, listvals
|
||||||
|
end
|
||||||
|
|
||||||
|
function ExplorerAutreNoeud_relaxlin(listvars, listvals)
|
||||||
|
# Le noeud est sondable, on l'enlève de la pile des noeuds à sonder
|
||||||
|
|
||||||
|
stop = false
|
||||||
|
if (length(listvars) > 1)
|
||||||
|
# On passe au noeud suivant
|
||||||
|
var = pop!(listvars)
|
||||||
|
val = pop!(listvals)
|
||||||
|
else
|
||||||
|
# Il n'y a pas d'autre noeud
|
||||||
|
stop = true
|
||||||
|
end
|
||||||
|
|
||||||
|
return listvars, listvals, stop
|
||||||
|
end
|
||||||
|
|
||||||
|
# Fonction objectif que l'on souhaite maximiser/minimiser (évalué dans le meilleur des cas)
|
||||||
|
Objective(x, price) =
|
||||||
|
sum(
|
||||||
|
if x[i] < 0
|
||||||
|
price[i]
|
||||||
|
else
|
||||||
|
price[i] * x[i]
|
||||||
|
end
|
||||||
|
for i = 1:length(x)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Fonction permettant de vérfier toutes les contraintes du modèle (dans le meilleur des cas)
|
||||||
|
Constraints(x, weight, capacity) =
|
||||||
|
sum(
|
||||||
|
if x[i] < 0
|
||||||
|
0
|
||||||
|
else
|
||||||
|
weight[i] * x[i]
|
||||||
|
end
|
||||||
|
for i = 1:length(x)
|
||||||
|
) <= capacity
|
||||||
|
|
||||||
|
# Fonction qui nous dis si toutes les variables de x sont fixées
|
||||||
|
function AllDef(x)
|
||||||
|
for i = 1:length(x)
|
||||||
|
if x[i] < 0
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function SolveKnapInstance(filename)
|
||||||
|
|
||||||
|
stop = false
|
||||||
|
affich = true
|
||||||
|
|
||||||
|
# Extraction des données
|
||||||
|
price, weight, capacity = readKnapInstance(filename)
|
||||||
|
|
||||||
|
tri = true
|
||||||
|
if tri
|
||||||
|
couples = zip(price, weight)
|
||||||
|
couples = sort(collect(couples), by = x -> x[1] / x[2])
|
||||||
|
unzip(a) = map(x->getfield.(a, x), fieldnames(eltype(a)))
|
||||||
|
price, weight = unzip(couples)
|
||||||
|
end
|
||||||
|
|
||||||
|
expected = split(split(filename, "-")[2], ".")[1]
|
||||||
|
nodes_nb = length(price)
|
||||||
|
nodes_max = 2^nodes_nb
|
||||||
|
|
||||||
|
if affich
|
||||||
|
println("---", filename, "---")
|
||||||
|
println("Capacity = ", capacity)
|
||||||
|
println("Number of objects = ", nodes_nb)
|
||||||
|
println("Expected optimal value = ", expected)
|
||||||
|
println("Maximum number of nodes = ", nodes_max)
|
||||||
|
println()
|
||||||
|
end
|
||||||
|
|
||||||
|
# Liste des variable pour naviguer de noeuds en noeuds
|
||||||
|
listvars = []
|
||||||
|
listvals = []
|
||||||
|
listnodes = []
|
||||||
|
|
||||||
|
# La meilleur solution et sa valeur
|
||||||
|
BestProfit = -1
|
||||||
|
LastBestProfit = -1
|
||||||
|
Bestsol = []
|
||||||
|
|
||||||
|
# Compter le nombre de noeud explorés
|
||||||
|
current_node_number = 0
|
||||||
|
|
||||||
|
# On ajoute le premier noeud à explorer (la racine)
|
||||||
|
push!(listvars, [-1 for p in price])
|
||||||
|
push!(listvals, Objective(last(listvars), price))
|
||||||
|
push!(listnodes, 1)
|
||||||
|
newnodeid = 2
|
||||||
|
|
||||||
|
while (!stop)
|
||||||
|
|
||||||
|
# Le noeud actuel
|
||||||
|
x = last(listvars)
|
||||||
|
|
||||||
|
if affich && LastBestProfit != BestProfit
|
||||||
|
println("Node n°", current_node_number, ": \tBestProfit = ", BestProfit)
|
||||||
|
LastBestProfit = BestProfit
|
||||||
|
end
|
||||||
|
|
||||||
|
# Test de sondabilité du noeud actuel
|
||||||
|
# -> On mets a jour la solution et sa valeur si besoin
|
||||||
|
TA, TO, TR, Bestsol, BestProfit = TestsSondabilite_relaxlin(x, price, weight, capacity, BestProfit, Bestsol, false)
|
||||||
|
|
||||||
|
is_node_sondable = TA || TO || TR
|
||||||
|
if (!is_node_sondable)
|
||||||
|
# Le noeud n'est pas sondable, on le sépare en 2 sous-noeuds
|
||||||
|
listvars, listvals = SeparerNoeud_relaxlin(price, listvars, listvals)
|
||||||
|
newnodeid += 2
|
||||||
|
else
|
||||||
|
# Le noeud est sondable, on passe au noeud suivant
|
||||||
|
listvars, listvals, stop = ExplorerAutreNoeud_relaxlin(listvars, listvals)
|
||||||
|
end
|
||||||
|
|
||||||
|
current_node_number += 1
|
||||||
|
end
|
||||||
|
|
||||||
|
println("\n--------------------------------------------------")
|
||||||
|
println("Expected optimal value = ", expected)
|
||||||
|
println("Optimal value = ", BestProfit)
|
||||||
|
println("Optimal x = ", Bestsol)
|
||||||
|
println("Maximum number of nodes = ", nodes_max)
|
||||||
|
println("Nodes explored = ", current_node_number)
|
||||||
|
if parse(Int64, expected) == BestProfit
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
SolveKnapInstance(ARGS[1])
|
Loading…
Reference in a new issue