{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Quadratic program"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A quadratic program is an optimization problem with a quadratic objective and affine equality and inequality constraints. A common standard form is the following:\n",
    "$$  \n",
    "    \\begin{array}{ll}\n",
    "    \\mbox{minimize}   & (1/2)x^TPx + q^Tx\\\\\n",
    "    \\mbox{subject to} & Gx \\leq h \\\\\n",
    "                      & Ax = b.\n",
    "    \\end{array}\n",
    "$$\n",
    "Here $P \\in \\mathcal{S}^{n}_+$, $q \\in \\mathcal{R}^n$, $G \\in \\mathcal{R}^{m \\times n}$, $h \\in \\mathcal{R}^m$, $A \\in \\mathcal{R}^{p \\times n}$, and $b \\in \\mathcal{R}^p$ are problem data and $x \\in \\mathcal{R}^{n}$ is the optimization variable. The inequality constraint $Gx \\leq h$ is elementwise.\n",
    "\n",
    "A simple example of a quadratic program arises in finance. Suppose we have $n$ different stocks, an estimate $r \\in \\mathcal{R}^n$ of the expected return on each stock, and an estimate $\\Sigma \\in \\mathcal{S}^{n}_+$ of the covariance of the returns. Then we solve the optimization problem\n",
    "$$  \n",
    "    \\begin{array}{ll}\n",
    "    \\mbox{minimize}   & (1/2)x^T\\Sigma x - r^Tx\\\\\n",
    "    \\mbox{subject to} & x \\geq 0 \\\\\n",
    "                      & \\mathbf{1}^Tx = 1,\n",
    "    \\end{array}\n",
    "$$\n",
    "to find a nonnegative portfolio allocation $x \\in \\mathcal{R}^n_+$ that optimally balances expected return and variance of return.\n",
    "\n",
    "When we solve a quadratic program, in addition to a solution $x^\\star$, we obtain a dual solution $\\lambda^\\star$ corresponding to the inequality constraints. A positive entry $\\lambda^\\star_i$ indicates that the constraint $g_i^Tx \\leq h_i$ holds with equality for $x^\\star$ and suggests that changing $h_i$ would change the optimal value."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Example"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In the following code, we solve a quadratic program with CVXPY."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "The optimal value is 86.89141585569918\n",
      "A solution x is\n",
      "[-1.68244521  0.29769913 -2.38772183 -2.79986015  1.18270433 -0.20911897\n",
      " -4.50993526  3.76683701 -0.45770675 -3.78589638]\n",
      "A dual solution corresponding to the inequality constraints is\n",
      "[ 0.          0.          0.          0.          0.         10.45538054\n",
      "  0.          0.          0.         39.67365045  0.          0.\n",
      "  0.         20.79927156  6.54115873]\n"
     ]
    }
   ],
   "source": [
    "# Import packages.\n",
    "import cvxpy as cp\n",
    "import numpy as np\n",
    "\n",
    "# Generate a random non-trivial quadratic program.\n",
    "m = 15\n",
    "n = 10\n",
    "p = 5\n",
    "np.random.seed(1)\n",
    "P = np.random.randn(n, n)\n",
    "P = P.T@P\n",
    "q = np.random.randn(n)\n",
    "G = np.random.randn(m, n)\n",
    "h = G@np.random.randn(n)\n",
    "A = np.random.randn(p, n)\n",
    "b = np.random.randn(p)\n",
    "\n",
    "# Define and solve the CVXPY problem.\n",
    "x = cp.Variable(n)\n",
    "prob = cp.Problem(cp.Minimize((1/2)*cp.quad_form(x, P) + q.T@x),\n",
    "                 [G@x <= h,\n",
    "                  A@x == b])\n",
    "prob.solve()\n",
    "\n",
    "# Print result.\n",
    "print(\"\\nThe optimal value is\", prob.value)\n",
    "print(\"A solution x is\")\n",
    "print(x.value)\n",
    "print(\"A dual solution corresponding to the inequality constraints is\")\n",
    "print(prob.constraints[0].dual_value)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "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.5.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
