{
    "nbformat": 4,
    "nbformat_minor": 5,
    "metadata": {
        "kernelspec": {
            "display_name": "Python",
            "language": "python",
            "name": "python"
        },
        "language_info": {
            "name": "python"
        }
    },
    "cells": [
        {
            "id": "61460a60",
            "cell_type": "markdown",
            "source": "<div class='alert alert-warning'>\n\nSciPy's interactive examples with Jupyterlite are experimental and may not always work as expected. Execution of cells containing imports may result in large downloads (up to 60MB of content for the first import from SciPy). Load times when importing from SciPy may take roughly 10-20 seconds. If you notice any problems, feel free to open an [issue](https://github.com/scipy/scipy/issues/new/choose).\n\n</div>",
            "metadata": {}
        },
        {
            "id": "dbaa25b4",
            "cell_type": "markdown",
            "source": "Consider the problem at\nhttps://en.wikipedia.org/wiki/Integer_programming#Example, which is\nexpressed as a maximization problem of two variables. Since `milp` requires\nthat the problem be expressed as a minimization problem, the objective\nfunction coefficients on the decision variables are:\n",
            "metadata": {}
        },
        {
            "id": "e01d32c9",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "import numpy as np\nc = -np.array([0, 1])",
            "outputs": []
        },
        {
            "id": "1a10d495",
            "cell_type": "markdown",
            "source": "Note the negative sign: we maximize the original objective function\nby minimizing the negative of the objective function.\n\nWe collect the coefficients of the constraints into arrays like:\n",
            "metadata": {}
        },
        {
            "id": "55fc2947",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "A = np.array([[-1, 1], [3, 2], [2, 3]])\nb_u = np.array([1, 12, 12])\nb_l = np.full_like(b_u, -np.inf, dtype=float)",
            "outputs": []
        },
        {
            "id": "284f8b85",
            "cell_type": "markdown",
            "source": "Because there is no lower limit on these constraints, we have defined a\nvariable ``b_l`` full of values representing negative infinity. This may\nbe unfamiliar to users of `scipy.optimize.linprog`, which only accepts\n\"less than\" (or \"upper bound\") inequality constraints of the form\n``A_ub @ x <= b_u``. By accepting both ``b_l`` and ``b_u`` of constraints\n``b_l <= A_ub @ x <= b_u``, `milp` makes it easy to specify \"greater than\"\ninequality constraints, \"less than\" inequality constraints, and equality\nconstraints concisely.\n\nThese arrays are collected into a single `LinearConstraint` object like:\n",
            "metadata": {}
        },
        {
            "id": "6d588d71",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "from scipy.optimize import LinearConstraint\nconstraints = LinearConstraint(A, b_l, b_u)",
            "outputs": []
        },
        {
            "id": "0305010a",
            "cell_type": "markdown",
            "source": "The non-negativity bounds on the decision variables are enforced by\ndefault, so we do not need to provide an argument for `bounds`.\n\nFinally, the problem states that both decision variables must be integers:\n",
            "metadata": {}
        },
        {
            "id": "2da18dbc",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "integrality = np.ones_like(c)",
            "outputs": []
        },
        {
            "id": "1edecdde",
            "cell_type": "markdown",
            "source": "We solve the problem like:\n",
            "metadata": {}
        },
        {
            "id": "5df9ce04",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "from scipy.optimize import milp\nres = milp(c=c, constraints=constraints, integrality=integrality)\nres.x",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "[2.0, 2.0]"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "39a1d4d5",
            "cell_type": "markdown",
            "source": "Note that had we solved the relaxed problem (without integrality\nconstraints):\n",
            "metadata": {}
        },
        {
            "id": "1582b2d8",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "res = milp(c=c, constraints=constraints)  # OR:\n# from scipy.optimize import linprog; res = linprog(c, A, b_u)\nres.x",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "[1.8, 2.8]"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "1d660976",
            "cell_type": "markdown",
            "source": "we would not have obtained the correct solution by rounding to the nearest\nintegers.\n\nOther examples are given :ref:`in the tutorial <tutorial-optimize_milp>`.",
            "metadata": {}
        }
    ]
}