{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Constrained optimization using scipy\n", "\n", "**Randall Romero Aguilar, PhD**\n", "\n", "This demo is based on the original Matlab demo accompanying the Computational Economics and Finance 2001 textbook by Mario Miranda and Paul Fackler.\n", "\n", "Original (Matlab) CompEcon file: **demopt08.m**\n", "\n", "Running this file requires the Python version of CompEcon. This can be installed with pip by running\n", "\n", " !pip install compecon --upgrade\n", "\n", "Last updated: 2021-Oct-01\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## About\n", "\n", "The problem is\n", "\n", "\\begin{equation*}\n", "\\max\\{-x_0^2 - (x_1-1)^2 - 3x_0 + 2\\}\n", "\\end{equation*}\n", "\n", "subject to\n", "\n", "\\begin{align*}\n", "4x_0 + x_1 &\\leq 0.5\\\\\n", "x_0^2 + x_0x_1 &\\leq 2.0\\\\\n", "x_0 &\\geq 0 \\\\\n", "x_1 &\\geq 0\n", "\\end{align*}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Using scipy\n", "\n", "The **scipy.optimize.minimize** function minimizes functions subject to equality constraints, inequality constraints, and bounds on the choice variables. " ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "from scipy.optimize import minimize\n", "\n", "np.set_printoptions(precision=4,suppress=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* First, we define the objective function, changing its sign so we can minimize it" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "def f(x):\n", " return x[0]**2 + (x[1]-1)**2 + 3*x[0] - 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* Second, we specify the inequality constraints using a tuple of two dictionaries (one per constraint), writing each of them in the form $g_i(x) \\geq 0$, that is\n", "\\begin{align*}\n", "0.5 - 4x_0 - x_1 &\\geq 0\\\\\n", "2.0 - x_0^2 - x_0x_1 &\\geq 0\n", "\\end{align*}" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "cons = ({'type': 'ineq', 'fun': lambda x: 0.5 - 4*x[0] - x[1]},\n", " {'type': 'ineq', 'fun': lambda x: 2.0 - x[0]**2 - x[0]*x[1]})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* Third, we specify the bounds on $x$:\n", "\\begin{align*}\n", "0 &\\leq x_0 \\leq \\infty\\\\\n", "0 &\\leq x_1 \\leq \\infty\n", "\\end{align*}" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "bnds = ((0, None), (0, None))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* Finally, we minimize the problem, using the SLSQP method, starting from $x=[0,1]$" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " fun: -1.7499999999999876\n", " jac: array([ 3., -1.])\n", " message: 'Optimization terminated successfully'\n", " nfev: 10\n", " nit: 3\n", " njev: 3\n", " status: 0\n", " success: True\n", " x: array([0. , 0.5])\n" ] } ], "source": [ "x0 = [0.0, 1.0]\n", "res = minimize(f, x0, method='SLSQP', bounds=bnds, constraints=cons)\n", "print(res)" ] } ], "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.8.5" } }, "nbformat": 4, "nbformat_minor": 4 }