{ "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": 2, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32m\u001b[1m Updating\u001b[22m\u001b[39m registry at `~/.julia/registries/General`\n", "\u001b[32m\u001b[1m Resolving\u001b[22m\u001b[39m package versions...\n", "\u001b[32m\u001b[1m No Changes\u001b[22m\u001b[39m to `~/.julia/environments/v1.6/Project.toml`\n", "\u001b[32m\u001b[1m No Changes\u001b[22m\u001b[39m to `~/.julia/environments/v1.6/Manifest.toml`\n", "\u001b[32m\u001b[1mPrecompiling\u001b[22m\u001b[39m project...\n", "\u001b[32m ✓ \u001b[39mTestOptinum\n", " 1 dependency successfully precompiled in 6 seconds (158 already precompiled)\n", "\u001b[32m\u001b[1m Resolving\u001b[22m\u001b[39m package versions...\n", "\u001b[32m\u001b[1m No Changes\u001b[22m\u001b[39m to `~/.julia/environments/v1.6/Project.toml`\n", "\u001b[32m\u001b[1m No Changes\u001b[22m\u001b[39m to `~/.julia/environments/v1.6/Manifest.toml`\n", "\u001b[32m\u001b[1mPrecompiling\u001b[22m\u001b[39m project...\n", "\u001b[32m ✓ \u001b[39mTestOptinum\n", " 1 dependency successfully precompiled in 2 seconds (158 already precompiled)\n" ] } ], "source": [ "import Pkg; \n", "Pkg.add(\"GraphRecipes\"); 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": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "readKnapInstance (generic function with 1 method)" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "function readKnapInstance(filename)\n", " price=[]\n", " weight=[]\n", " capacity = -1\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", " capacity = parse(Int64, tok[2])\n", " else\n", " println(\"Unknown read :\", tok)\n", " end \n", " end\n", " end\n", " \n", " return price, weight, capacity\n", "end\n", "\n", "# readKnapInstance(\"data/test.opb\")\n", "# readKnapInstance(\"data/almost_strongly_correlated/knapPI_5_50_1000_1_-2096.opb\")" ] }, { "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": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "TestsSondabilite_relaxlin (generic function with 1 method)" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "function TestsSondabilite_relaxlin(x, price, weight, capacity, BestProfit, Bestsol)\n", " TA, TO, TR = false, false, false\n", " if (!Constraints(x, weight, capacity)) # Test de faisabilite\n", " TA = true\n", " println(\"TA\")\n", " elseif (Objective(x, price) <= BestProfit) # Test d'optimalite\n", " TO = true\n", " println(\"TO\")\n", " elseif (AllDef(x)) # Test de resolution\n", " TR = true\n", " println(\"TR\")\n", " #if (value(benef) >= BestProfit)\n", " if (Objective(x, price) >= BestProfit)\n", " println(\"oiuiiiiii\")\n", " Bestsol = x\n", " #BestProfit=value(benef)\n", " BestProfit = Objective(x, price)\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": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "ExplorerAutreNoeud_relaxlin (generic function with 1 method)" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "\n", "function SeparerNoeud_relaxlin(price, listvars, listvals)\n", " # le noeud est non-sondable. Appliquer le critère de séparation pour le séparer en sous-noeuds et choisir un noeud-fils le plus à gauche \n", "\n", " # Cas du noeud le plus à gauche\n", " predX = first(listvars)\n", " n = length(predX)\n", " nextX0 = predX\n", " nextX1 = predX\n", " val0 = 0\n", " val1 = 0\n", " for i in 1:n\n", " if predX[i] == -1\n", " nextX0[i] = 0\n", " nextX1[i] = 1\n", "\n", " val0 = Objective(nextX0, price)\n", " val1 = Objective(nextX1, price)\n", " break\n", " end\n", " end\n", "\n", " push!(listvars, nextX0)\n", " push!(listvars, nextX1)\n", " push!(listvals, val0)\n", " push!(listvals, val1)\n", " listvars, listvals\n", "end\n", "\n", "\n", "function ExplorerAutreNoeud_relaxlin(listvars, listvals)\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", " val = pop!(listvals)\n", " else\n", " # the root node was sondable\n", " println(\"\\nFINISHED\")\n", " stop = true\n", " end\n", " listvars, listvals, stop \n", "end" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "true" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# fonction objectif que l'on souhaite maximiser/minimiser\n", "Objective(x, price) = \n", " sum(\n", " if x[i] < 0\n", " 1\n", " else\n", " price[i]*x[i] \n", " end\n", " for i in 1:length(x)\n", " )\n", "\n", "# fonction permettant de vérfier toutes les contraintes du modèle\n", "Constraints(x, weight, capacity) =\n", " sum(\n", " if x[i] < 0\n", " 0\n", " else \n", " weight[i]*x[i]\n", " end\n", " for i in 1:length(x)\n", " ) <= capacity\n", "\n", "\n", "AllDef(x) =\n", " for xi in x\n", " if xi < 0\n", " return false\n", " end\n", " end\n", " return true" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Node number 0: \n", "-----\n", "\n", "\n", "Noeud actuel\tx_1 = -1\tx_2 = -1\tx_3 = -1\tx_4 = -1 \n", "\n", "Previous Solution memorized Any[] with bestprofit -1\n", "\n", "non sondable\n", "\n", "Node number 1: \n", "-----\n", "\n", "\n", "Noeud actuel\tx_1 = 1\tx_2 = -1\tx_3 = -1\tx_4 = -1 \n", "\n", "Previous Solution memorized Any[] with bestprofit -1\n", "\n", "non sondable\n", "\n", "Node number 2: \n", "-----\n", "\n", "\n", "Noeud actuel : NOT AVAILABLE (probably infeasible or ressources limit reached) \n", "\n", "Previous Solution memorized Any[] with bestprofit -1\n", "\n", "TA\n", "\n", "Node number 3: \n", "-----\n", "\n", "\n", "Noeud actuel : NOT AVAILABLE (probably infeasible or ressources limit reached) \n", "\n", "Previous Solution memorized Any[] with bestprofit -1\n", "\n", "TA\n", "\n", "Node number 4: \n", "-----\n", "\n", "\n", "Noeud actuel : NOT AVAILABLE (probably infeasible or ressources limit reached) \n", "\n", "Previous Solution memorized Any[] with bestprofit -1\n", "\n", "TA\n", "\n", "Node number 5: \n", "-----\n", "\n", "\n", "Noeud actuel : NOT AVAILABLE (probably infeasible or ressources limit reached) \n", "\n", "Previous Solution memorized Any[] with bestprofit -1\n", "\n", "TA\n", "\n", "Node number 6: \n", "-----\n", "\n", "\n", "Noeud actuel : NOT AVAILABLE (probably infeasible or ressources limit reached) \n", "\n", "Previous Solution memorized Any[] with bestprofit -1\n", "\n", "TA\n", "\n", "FINISHED\n", "\n", "******\n", "\n", "Optimal value = -1\n", "\n", "Optimal x=Any[]\n" ] }, { "data": { "text/plain": [ "(-1, Any[], Int64[], Int64[], Any[])" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "function SolveKnapInstance(filename)\n", "\n", " price, weight, capacity = readKnapInstance(filename)\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", "\n", " BestProfit=-1\n", " Bestsol=[]\n", "\n", " current_node_number=0\n", " stop = false\n", "\n", " push!(listvars, [-1 for p in price])\n", " push!(listvals, Objective(first(listvars), price))\n", "\n", " while (!stop)\n", "\n", " println(\"\\nNode number \", current_node_number, \": \\n-----\\n\")\n", "\n", " x = first(listvars)\n", "\n", " print(\"\\nNoeud actuel\"); \n", " if (!Constraints(x, weight, capacity)) # (has_values(model2))\n", " print(\" : NOT AVAILABLE (probably infeasible or ressources limit reached)\")\n", " else\n", " [print(\"\\tx_\", i, \" = \", x[i]) for i in 1:length(x)] \n", " end\n", " println(\" \");\n", " println(\"\\nPrevious Solution memorized \", Bestsol, \" with bestprofit \", BestProfit, \"\\n\")\n", "\n", " TA, TO, TR, Bestsol, BestProfit = TestsSondabilite_relaxlin(x, price, weight, capacity, BestProfit, Bestsol)\n", " \n", " is_node_sondable = TA || TO || TR\n", "\n", " if (!is_node_sondable)\n", " listvars, listvals = SeparerNoeud_relaxlin(price, listvars, listvals)\n", " else\n", " listvars, listvals, stop = ExplorerAutreNoeud_relaxlin(listvars, listvals)\n", " end\n", "\n", " 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", "\n", "end\n", "\n", "SolveKnapInstance(\"data/test.opb\")" ] } ], "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.4" } }, "nbformat": 4, "nbformat_minor": 4 }