{ "cells": [ { "cell_type": "markdown", "id": "e4e72ffb", "metadata": {}, "source": [ "# Running a Solver" ] }, { "cell_type": "markdown", "id": "b54af701", "metadata": {}, "source": [ "It is very simple to directly run a solver on a PyCSP$^3$ model. You just have to call the following function:\n", "\n", " *solve()*\n", "\n", "\n", "This will start the solver ACE on the current problem instance.\n", "The result of this command is the status of the solving operation, which is one of the following constants:\n", "```\n", " UNSAT\n", " SAT\n", " OPTIMUM\n", " UNKNOWN\n", "```\n", "\n", "More specifically, the result is:\n", "- among UNSAT, SAT, and UNKNOWN for a CSP instance\n", "- among UNSAT, SAT, OPTIMUM and UNKNOWN for a COP instance\n" ] }, { "cell_type": "markdown", "id": "77248351", "metadata": {}, "source": [ "This function *solve()* accepts several named parameters:\n", "- solver: name of the solver (ACE or CHOCO)\n", "- options: specific options for the solver\n", "- filename: the filename of the compiled problem instance\n", "- verbose: verbosity level from -1 to 2\n", "- sols: number of solutions to be found (ALL if no limit)\n", "- extraction: True if an unsatisfiable core of constraints must be sought" ] }, { "cell_type": "markdown", "id": "609b3d62", "metadata": {}, "source": [ "To introduce some illustrations, we need first to import the library PyCSP$^3$:" ] }, { "cell_type": "code", "execution_count": 1, "id": "e8035d2b", "metadata": {}, "outputs": [], "source": [ "from pycsp3 import *" ] }, { "cell_type": "markdown", "id": "464055b7", "metadata": {}, "source": [ "As an illustration, let us consider the Warehouse Location Problem (WLP); see the notebook dedicated to this problem for all details. In a first step, we simply consider the decision problem (i.e., the objective is not posted, so, we have a CSP instance). Note that in the model below, we use the function *default_data()* in order to load a JSON file given by an URL. We write:" ] }, { "cell_type": "code", "execution_count": 2, "id": "e575be97", "metadata": {}, "outputs": [], "source": [ "fixed_cost, capacities, costs = data or default_data(\"https://www.cril.univ-artois.fr/~lecoutre/Warehouse_example.json\") \n", "nWarehouses, nStores = len(capacities), len(costs)\n", "\n", "# w[i] is the warehouse supplying the ith store\n", "w = VarArray(size=nStores, dom=range(nWarehouses))\n", "\n", "satisfy(\n", " # capacities of warehouses must not be exceeded\n", " Count(w, value=j) <= capacities[j] for j in range(nWarehouses)\n", ");" ] }, { "cell_type": "markdown", "id": "63faffb6", "metadata": {}, "source": [ "Then, we run the solver and print the solution if the problem instance is satisfiable (by default, only one solution is sought for a CSP instance). Note that we can display the values assigned to the variables of a specified (possibly multi-dimensional) list by calling the function *values()*." ] }, { "cell_type": "code", "execution_count": 3, "id": "0fbcedfc", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0, 1, 1, 1, 1, 2, 2, 3, 4, 4]\n" ] } ], "source": [ "if solve() is SAT:\n", " print(values(w)) " ] }, { "cell_type": "markdown", "id": "658fb939", "metadata": {}, "source": [ "In a terminal, we could execute a command like this one (with a local data file, that has priority over the default remote one):" ] }, { "cell_type": "raw", "id": "ddec9858", "metadata": {}, "source": [ "python Warehouse.py -data=warehouse.json" ] }, { "cell_type": "markdown", "id": "93f3f536", "metadata": {}, "source": [ "The output is not very friendly/readable, but nothing prevents us from improving that aspect. This is what we do now with a Python f-string, getting the value of individual variables with the function *value()*." ] }, { "cell_type": "code", "execution_count": 4, "id": "7767a2ca", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Warehouse supplying the store 0 is 0 with cost 100\n", "Warehouse supplying the store 1 is 1 with cost 27\n", "Warehouse supplying the store 2 is 1 with cost 97\n", "Warehouse supplying the store 3 is 1 with cost 55\n", "Warehouse supplying the store 4 is 1 with cost 96\n", "Warehouse supplying the store 5 is 2 with cost 29\n", "Warehouse supplying the store 6 is 2 with cost 73\n", "Warehouse supplying the store 7 is 3 with cost 43\n", "Warehouse supplying the store 8 is 4 with cost 46\n", "Warehouse supplying the store 9 is 4 with cost 95\n" ] } ], "source": [ "if solve() is SAT:\n", " for i in range(nStores):\n", " print(f\"Warehouse supplying the store {i} is {value(w[i])} with cost {costs[i][value(w[i])]}\")" ] }, { "cell_type": "markdown", "id": "7fdbfb5b", "metadata": {}, "source": [ "Now, we consider the objective function (and so, we have a COP instance). This is the reason why we check if the status returned when calling *solve()* is OPTIMUM. Note that the function *bound()* directly returns the value of the objective function corresponding to the found optimal solution." ] }, { "cell_type": "code", "execution_count": 5, "id": "de87f099", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[4, 1, 4, 0, 4, 1, 1, 2, 1, 2]\n", "Cost of supplying the store 0 is 30\n", "Cost of supplying the store 1 is 27\n", "Cost of supplying the store 2 is 70\n", "Cost of supplying the store 3 is 2\n", "Cost of supplying the store 4 is 4\n", "Cost of supplying the store 5 is 22\n", "Cost of supplying the store 6 is 5\n", "Cost of supplying the store 7 is 13\n", "Cost of supplying the store 8 is 35\n", "Cost of supplying the store 9 is 55\n", "Total supplying cost: 383\n" ] } ], "source": [ "minimize(\n", " # minimizing the overall cost\n", " Sum(costs[i][w[i]] for i in range(nStores)) + NValues(w) * fixed_cost\n", ")\n", "\n", "if solve() is OPTIMUM:\n", " print(values(w))\n", " for i in range(nStores):\n", " print(f\"Cost of supplying the store {i} is {costs[i][value(w[i])]}\")\n", " print(\"Total supplying cost: \", bound())" ] }, { "cell_type": "markdown", "id": "cb716602", "metadata": {}, "source": [ "One may be worried by the fact that the code mixes modeling and solving parts.\n", "Interestingly, we can make a clear separation as described now. \n", "First, we write the model in the file 'Warehouse.py':" ] }, { "cell_type": "raw", "id": "b23acda2", "metadata": { "raw_mimetype": "text/x-python" }, "source": [ "from pycsp3 import *\n", "\n", "fixed_cost, capacities, costs = data \n", "nWarehouses, nStores = len(capacities), len(costs)\n", "\n", "# w[i] is the warehouse supplying the ith store\n", "w = VarArray(size=nStores, dom=range(nWarehouses))\n", "\n", "satisfy(\n", " # capacities of warehouses must not be exceeded\n", " Count(w, value=j) <= capacities[j] for j in range(nWarehouses)\n", ")\n", "\n", "minimize(\n", " # minimizing the overall cost\n", " Sum(costs[i][w[i]] for i in range(nStores)) + NValues(w) * fixed_cost\n", ")" ] }, { "cell_type": "markdown", "id": "059df023", "metadata": {}, "source": [ "Then, we write the solving part in a file 'WarehouseSolving.py':" ] }, { "cell_type": "raw", "id": "a015cbc2", "metadata": { "raw_mimetype": "text/x-python" }, "source": [ "from Warehouse import *\n", "\n", "if solve() is OPTIMUM:\n", " print(values(w))\n", " for i in range(nStores):\n", " print(f\"Cost of supplying the store {i} is {costs[i][value(w[i])]}\")\n", " print(\"Total supplying cost: \", bound())" ] }, { "cell_type": "markdown", "id": "10a762c4", "metadata": {}, "source": [ "Then, in a terminal, we can execute: " ] }, { "cell_type": "raw", "id": "a0cd6316", "metadata": {}, "source": [ "python WarehouseSolving.py -data=warehouse.json" ] }, { "cell_type": "markdown", "id": "372ba258", "metadata": {}, "source": [ "If for some reasons, it is better to set data in the file containing the solving part, we can modify sys.argv\n", "The file 'WarehouseSolving.py' becomes: " ] }, { "cell_type": "raw", "id": "9ac60bba", "metadata": { "raw_mimetype": "text/x-python" }, "source": [ "import sys\n", "\n", "sys.argv.append(\"-data=Warehouse_example.json\")\n", "\n", "from Warehouse import *\n", "\n", "if solve() is OPTIMUM:\n", " print(values(w))\n", " for i in range(nStores):\n", " print(f\"Cost of supplying the store {i} is {costs[i][value(w[i])]}\")\n", " print(\"Total supplying cost: \", bound())" ] }, { "cell_type": "markdown", "id": "c534d280", "metadata": {}, "source": [ "Then, we can simply execute (do note that the option -data is not used):" ] }, { "cell_type": "raw", "id": "97308627", "metadata": {}, "source": [ "python WarehouseSolving.py" ] }, { "cell_type": "markdown", "id": "610b1f1e", "metadata": {}, "source": [ "As another illustration, let us consider one of the two models, introduced (without variants) for the Queens problem; see the notebook dedicated to this problem for all details." ] }, { "cell_type": "code", "execution_count": 6, "id": "e6d33a84", "metadata": {}, "outputs": [], "source": [ "n = data or 8\n", "\n", "# q[i] is the column where is put the ith queen (at row i)\n", "q = VarArray(size=n, dom=range(n))\n", "\n", "if not variant():\n", " satisfy(\n", " AllDifferent(q),\n", "\n", " # controlling no two queens on the same upward diagonal\n", " AllDifferent(q[i] + i for i in range(n)),\n", "\n", " # controlling no two queens on the same downward diagonal\n", " AllDifferent(q[i] - i for i in range(n))\n", " )" ] }, { "cell_type": "markdown", "id": "22be6d48", "metadata": {}, "source": [ "If we write this solving code:" ] }, { "cell_type": "code", "execution_count": 7, "id": "f2fb2a88", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Defaulting to user installation because normal site-packages is not writeable\n", "\u001b[31mERROR: Could not find a version that satisfies the requirement chess.svg (from versions: none)\u001b[0m\n", "\u001b[31mERROR: No matching distribution found for chess.svg\u001b[0m\n", "\u001b[33mWARNING: You are using pip version 21.3.1; however, version 22.3 is available.\n", "You should consider upgrading via the '/usr/bin/python3.7 -m pip install --upgrade pip' command.\u001b[0m\n" ] } ], "source": [ "import sys\n", "# or if you want to use pip\n", "!{sys.executable} -m pip install chess.svg" ] }, { "cell_type": "code", "execution_count": 8, "id": "ad34bbba", "metadata": { "raw_mimetype": "text/x-python" }, "outputs": [], "source": [ "import sys\n", "import chess.svg\n", "\n", "if solve() is SAT:\n", " solution = values(q) # for example: [0, 4, 7, 5, 2, 6, 1, 3]\n", " board = chess.Board(\"/\".join((\"\" if v == 0 else str(v)) + \"q\" + (\"\" if v == n - 1 else str(n - 1 - v)) for v in solution) + ' b KQkq - 0 1')\n", " with open('chess.svg', 'w') as f:\n", " f.write(chess.svg.board(board, size=350))" ] }, { "attachments": { "chess.png": { "image/png": "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" } }, "cell_type": "markdown", "id": "f6d2f873", "metadata": {}, "source": [ "Then, by means of the package chess.svg, we can generate the rendering of the solution to the 8 queens problem in a SVG file: \"Chess\"" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.12" } }, "nbformat": 4, "nbformat_minor": 5 }