{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Semidefinite program"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A semidefinite program (SDP) is an optimization problem of the form\n",
    "$$  \n",
    "    \\begin{array}{ll}\n",
    "    \\mbox{minimize}   & \\mathbf{tr}(CX) \\\\\n",
    "    \\mbox{subject to} & \\mathbf{tr}(A_iX) = b_i, \\quad i=1,\\ldots,p \\\\\n",
    "                      & X \\succeq 0,\n",
    "    \\end{array}\n",
    "$$\n",
    "where $\\mathbf{tr}$ is the trace function, $X \\in \\mathcal{S}^{n}$ is the optimization variable and $C, A_1, \\ldots, A_p \\in \\mathcal{S}^{n}$, and $b_1, \\ldots, b_p \\in \\mathcal{R}$ are problem data, and $X \\succeq 0$ is a matrix inequality. Here $\\mathcal{S}^{n}$ denotes the set of $n$-by-$n$ symmetric matrices.\n",
    "\n",
    "An example of an SDP is to complete a covariance matrix $\\tilde \\Sigma \\in \\mathcal{S}^{n}_+$ with missing entries $M \\subset \\{1,\\ldots,n\\} \\times \\{1,\\ldots,n\\}$:\n",
    "$$  \n",
    "    \\begin{array}{ll}\n",
    "    \\mbox{minimize}   & 0 \\\\\n",
    "    \\mbox{subject to} & \\Sigma_{ij} = \\tilde \\Sigma_{ij}, \\quad (i,j) \\notin M \\\\\n",
    "                      & \\Sigma \\succeq 0,\n",
    "    \\end{array}\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Example"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In the following code, we solve a SDP with CVXPY."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The optimal value is 2.654348003008652\n",
      "A solution X is\n",
      "[[ 1.6080571  -0.59770202 -0.69575904]\n",
      " [-0.59770202  0.22228637  0.24689205]\n",
      " [-0.69575904  0.24689205  1.39679396]]\n"
     ]
    }
   ],
   "source": [
    "# Import packages.\n",
    "import cvxpy as cp\n",
    "import numpy as np\n",
    "\n",
    "# Generate a random SDP.\n",
    "n = 3\n",
    "p = 3\n",
    "np.random.seed(1)\n",
    "C = np.random.randn(n, n)\n",
    "A = []\n",
    "b = []\n",
    "for i in range(p):\n",
    "    A.append(np.random.randn(n, n))\n",
    "    b.append(np.random.randn())\n",
    "\n",
    "# Define and solve the CVXPY problem.\n",
    "# Create a symmetric matrix variable.\n",
    "X = cp.Variable((n,n), symmetric=True)\n",
    "# The operator >> denotes matrix inequality.\n",
    "constraints = [X >> 0]\n",
    "constraints += [\n",
    "    cp.trace(A[i]@X) == b[i] for i in range(p)\n",
    "]\n",
    "prob = cp.Problem(cp.Minimize(cp.trace(C@X)),\n",
    "                  constraints)\n",
    "prob.solve()\n",
    "\n",
    "# Print result.\n",
    "print(\"The optimal value is\", prob.value)\n",
    "print(\"A solution X is\")\n",
    "print(X.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
}
