{ "cells": [ { "cell_type": "markdown", "id": "aaaf8e92", "metadata": {}, "source": [ "\n", "*This notebook contains material from [CBE60499](https://ndcbe.github.io/CBE60499);\n", "content is available [on Github](git@github.com:ndcbe/CBE60499.git).*\n" ] }, { "cell_type": "markdown", "id": "d0c85e40", "metadata": {}, "source": [ "\n", "< [3.7 Algorithms Homework 1](https://ndcbe.github.io/CBE60499/03.07-Algorithms1.html) | [Contents](toc.html) | [Tag Index](tag_index.html) | [3.9 Algorithms Homework 3](https://ndcbe.github.io/CBE60499/03.09-Algorithms3.html) >
"
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpages": {
"level": 1,
"link": "[3.8 Algorithms Homework 2](https://ndcbe.github.io/CBE60499/03.08-Algorithms2.html#3.8-Algorithms-Homework-2)",
"section": "3.8 Algorithms Homework 2"
}
},
"source": [
"# 3.8 Algorithms Homework 2"
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpages": {
"level": 1,
"link": "[3.8 Algorithms Homework 2](https://ndcbe.github.io/CBE60499/03.08-Algorithms2.html#3.8-Algorithms-Homework-2)",
"section": "3.8 Algorithms Homework 2"
}
},
"source": [
"**Important for Spring 2021**: We are skipping this homework assignment. The Python solutions will be posted to Sakai. Please use this as exam study material.\n",
"\n",
"Homework solutions are copyright Alex Dowling (2021). You MAY NOT share them with anyone (post online, etc.) without written permission."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"nbpages": {
"level": 1,
"link": "[3.8 Algorithms Homework 2](https://ndcbe.github.io/CBE60499/03.08-Algorithms2.html#3.8-Algorithms-Homework-2)",
"section": "3.8 Algorithms Homework 2"
}
},
"outputs": [],
"source": [
"## Load libraries\n",
"import matplotlib as plat\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"from scipy import linalg\n",
"from mpl_toolkits.mplot3d import Axes3D\n",
"from matplotlib import cm\n",
"import sympy as sym\n",
"# from sympy import symbols, diff"
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpages": {
"level": 2,
"link": "[3.8.1 Finite Difference Approximations](https://ndcbe.github.io/CBE60499/03.08-Algorithms2.html#3.8.1-Finite-Difference-Approximations)",
"section": "3.8.1 Finite Difference Approximations"
}
},
"source": [
"## 3.8.1 Finite Difference Approximations\n",
"\n",
"**Main Idea**: Explore the accuracy of the finite difference approximation for $\\nabla f(x)$ and $\\nabla^2 f(x)$ from Example 2.19."
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpages": {
"level": 3,
"link": "[3.8.1.1 Finite difference order](https://ndcbe.github.io/CBE60499/03.08-Algorithms2.html#3.8.1.1-Finite-difference-order)",
"section": "3.8.1.1 Finite difference order"
},
"tags": [
"gradescope"
]
},
"source": [
"### 3.8.1.1 Finite difference order"
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpages": {
"level": 3,
"link": "[3.8.1.1 Finite difference order](https://ndcbe.github.io/CBE60499/03.08-Algorithms2.html#3.8.1.1-Finite-difference-order)",
"section": "3.8.1.1 Finite difference order"
}
},
"source": [
"Repeat the analysis from class to show the backward and central finite difference truncations errors are $\\mathcal{O}(\\epsilon)$ and $\\mathcal{O}(\\epsilon^2)$, respectively. We discussed these error orders graphically. Please use a Taylor series for your analysis."
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpages": {
"level": 3,
"link": "[3.8.1.2 Provided Codes](https://ndcbe.github.io/CBE60499/03.08-Algorithms2.html#3.8.1.2-Provided-Codes)",
"section": "3.8.1.2 Provided Codes"
}
},
"source": [
"### 3.8.1.2 Provided Codes"
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpages": {
"level": 3,
"link": "[3.8.1.2 Provided Codes](https://ndcbe.github.io/CBE60499/03.08-Algorithms2.html#3.8.1.2-Provided-Codes)",
"section": "3.8.1.2 Provided Codes"
}
},
"source": [
"Please review the following code. You do not need to turn anything in for this section."
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpages": {
"level": 4,
"link": "[3.8.1.2.1 Finite Difference Code](https://ndcbe.github.io/CBE60499/03.08-Algorithms2.html#3.8.1.2.1-Finite-Difference-Code)",
"section": "3.8.1.2.1 Finite Difference Code"
}
},
"source": [
"#### 3.8.1.2.1 Finite Difference Code\n",
"\n",
"The code below has been adapted from the finite difference examples presented in class. Notice the second input is a function."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"nbpages": {
"level": 4,
"link": "[3.8.1.2.1 Finite Difference Code](https://ndcbe.github.io/CBE60499/03.08-Algorithms2.html#3.8.1.2.1-Finite-Difference-Code)",
"section": "3.8.1.2.1 Finite Difference Code"
}
},
"outputs": [],
"source": [
"## Define Python function\n",
"def my_f(x,verbose=False):\n",
" ''' Evaluate function given above at point x\n",
"\n",
" Inputs:\n",
" x - vector with 2 elements\n",
" \n",
" Outputs:\n",
" f - function value (scalar)\n",
" '''\n",
" # Constants\n",
" a = np.array([0.3, 0.6, 0.2])\n",
" b = np.array([5, 26, 3])\n",
" c = np.array([40, 1, 10])\n",
" \n",
" # Intermediates. Recall Python indicies start at 0\n",
" u = x[0] - 0.8\n",
" s = np.sqrt(1-u)\n",
" s2 = np.sqrt(1+u)\n",
" v = x[1] -(a[0] + a[1]*u**2*s-a[2]*u)\n",
" alpha = -b[0] + b[1]*u**2*s2+ b[2]*u \n",
" beta = c[0]*v**2*(1-c[1]*v)/(1+c[2]*u**2)\n",
" \n",
" if verbose:\n",
" print(\"##### my_f at x = \",x, \"#####\")\n",
" print(\"u = \",u)\n",
" print(\"sqrt(1-u) = \",s)\n",
" print(\"sqrt(1+u) = \",s2)\n",
" print(\"v = \",v)\n",
" print(\"alpha = \",alpha)\n",
" print(\"beta = \",beta)\n",
" print(\"f(x) = \",)\n",
" print(\"##### Done. #####\\n\")\n",
" \n",
" return alpha*np.exp(-beta)\n",
"\n",
"## Calculate gradient with central finite difference\n",
"def my_grad_approx(x,f,eps1,verbose=False):\n",
" '''\n",
" Calculate gradient of function my_f using central difference formula\n",
" \n",
" Inputs:\n",
" x - point for which to evaluate gradient\n",
" f - function to consider\n",
" eps1 - perturbation size\n",
" \n",
" Outputs:\n",
" grad - gradient (vector)\n",
" '''\n",
" \n",
" n = len(x)\n",
" grad = np.zeros(n)\n",
" \n",
" if(verbose):\n",
" print(\"***** my_grad_approx at x = \",x,\"*****\")\n",
" \n",
" for i in range(0,n):\n",
" \n",
" # Create vector of zeros except eps in position i\n",
" e = np.zeros(n)\n",
" e[i] = eps1\n",
" \n",
" # Finite difference formula\n",
" my_f_plus = f(x + e)\n",
" my_f_minus = f(x - e)\n",
" \n",
" # Diagnostics\n",
" if(verbose):\n",
" print(\"e[\",i,\"] = \",e)\n",
" print(\"f(x + e[\",i,\"]) = \",my_f_plus)\n",
" print(\"f(x - e[\",i,\"]) = \",my_f_minus)\n",
" \n",
" \n",
" grad[i] = (my_f_plus - my_f_minus)/(2*eps1)\n",
" \n",
" if(verbose):\n",
" print(\"***** Done. ***** \\n\")\n",
" \n",
" return grad\n",
"\n",
"## Calculate gradient using central finite difference and my_hes_approx\n",
"def my_hes_approx(x,grad,eps2):\n",
" '''\n",
" Calculate gradient of function my_f using central difference formula and my_grad\n",
" \n",
" Inputs:\n",
" x - point for which to evaluate gradient\n",
" grad - function to calculate the gradient\n",
" eps2 - perturbation size (for Hessian NOT gradient approximation)\n",
" \n",
" Outputs:\n",
" H - Hessian (matrix)\n",
" '''\n",
" \n",
" n = len(x)\n",
" H = np.zeros([n,n])\n",
" \n",
" for i in range(0,n):\n",
" # Create vector of zeros except eps in position i\n",
" e = np.zeros(n)\n",
" e[i] = eps2\n",
" \n",
" # Evaluate gradient twice\n",
" grad_plus = grad(x + e)\n",
" grad_minus = grad(x - e)\n",
" \n",
" # Notice we are building the Hessian by column (or row)\n",
" H[:,i] = (grad_plus - grad_minus)/(2*eps2)\n",
"\n",
" return H"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"nbpages": {
"level": 4,
"link": "[3.8.1.2.1 Finite Difference Code](https://ndcbe.github.io/CBE60499/03.08-Algorithms2.html#3.8.1.2.1-Finite-Difference-Code)",
"section": "3.8.1.2.1 Finite Difference Code"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"xt = [0 0] \n",
"\n",
"f(xt) = \n",
" 1.6212212164426274e-06 \n",
"\n",
"grad(xt) = [1.49885593e-04 4.20936251e-05] \n",
"\n",
"hes(xt) = \n",
" [[0.00082024 0.00387044]\n",
" [0.00387044 0.00102412]] \n",
"\n"
]
}
],
"source": [
"### Test the functions from above\n",
"\n",
"## Define test point\n",
"xt = np.array([0,0])\n",
"print(\"xt = \",xt,\"\\n\")\n",
"\n",
"print(\"f(xt) = \\n\",my_f([0,0]),\"\\n\")\n",
"\n",
"## Compute gradient\n",
"g = my_grad_approx(xt,my_f,1E-6)\n",
"print(\"grad(xt) = \",g,\"\\n\")\n",
"\n",
"## Compute Hessian\n",
"# Step 1: Create a Lambda (anonymous) function\n",
"calc_grad = lambda x : my_grad_approx(x,my_f,1E-6)\n",
"\n",
"# Step 2: Calculate Hessian approximation\n",
"H = my_hes_approx(xt,calc_grad,1E-6)\n",
"print(\"hes(xt) = \\n\",H,\"\\n\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpages": {
"level": 4,
"link": "[3.8.1.2.2 Analytic Gradient](https://ndcbe.github.io/CBE60499/03.08-Algorithms2.html#3.8.1.2.2-Analytic-Gradient)",
"section": "3.8.1.2.2 Analytic Gradient"
}
},
"source": [
"#### 3.8.1.2.2 Analytic Gradient\n",
"\n",
"It turns out that calculating the analytic gradient with Mathematic quickly becomes a mess. Instead, the following code uses the symbolic computing capabilities in SymPy."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"nbpages": {
"level": 4,
"link": "[3.8.1.2.2 Analytic Gradient](https://ndcbe.github.io/CBE60499/03.08-Algorithms2.html#3.8.1.2.2-Analytic-Gradient)",
"section": "3.8.1.2.2 Analytic Gradient"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The exact gradient is \n",
" [1.49885593e-04 4.20936251e-05]\n"
]
}
],
"source": [
"'''\n",
"Encoding the exact gradient with the long expression above is very time-consuming. This is a trick of calculating the \n",
"symbolic derivative and converting it to an analytic function to be evaluated at a point. \n",
"'''\n",
"\n",
"# Define function to use with symbolic computing framework\n",
"def f(x1,x2):\n",
" a = np.array([0.3, 0.6, 0.2])\n",
" b = np.array([5, 26, 3])\n",
" b1 = 5;\n",
" c = np.array([40, 1, 10])\n",
" u = x1 - 0.8\n",
" v = x2 -(a[0] + a[1]*u**2*(1-u)**0.5-a[2]*u)\n",
" alpha = b[1]*u**2*(1+u)**0.5 + b[2]*u -b[0]\n",
" beta = c[0]*v**2*(1-c[1]*v)/(1+c[2]*u**2)\n",
" return alpha*sym.exp(-1*beta)\n",
"\n",
"# Define function to use later\n",
"def my_grad_exact(x):\n",
" x1, x2 = sym.symbols('x1 x2')\n",
" DerivativeOfF1 = sym.lambdify((x1,x2),sym.diff(f(x1,x2),x1));\n",
" DerivativeOfF2 = sym.lambdify((x1,x2),sym.diff(f(x1,x2),x2));\n",
" #DerivativeOfF2 = sym.lambdify((x1,x2),gradf2(x1,x2));\n",
" #F = sym.lambdify((x1,x2),f(x1,x2));\n",
" return np.array([DerivativeOfF1(x[0],x[1]),DerivativeOfF2(x[0],x[1])])\n",
" \n",
"x = np.array([0,0])\n",
"print(\"The exact gradient is \\n\",my_grad_exact(x))"
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpages": {
"level": 4,
"link": "[3.8.1.2.3 Analytic Hessian](https://ndcbe.github.io/CBE60499/03.08-Algorithms2.html#3.8.1.2.3-Analytic-Hessian)",
"section": "3.8.1.2.3 Analytic Hessian"
}
},
"source": [
"#### 3.8.1.2.3 Analytic Hessian\n",
"\n",
"The code below assembles the analytic Hessian using the symbolic computing framework in NumPy."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"nbpages": {
"level": 4,
"link": "[3.8.1.2.3 Analytic Hessian](https://ndcbe.github.io/CBE60499/03.08-Algorithms2.html#3.8.1.2.3-Analytic-Hessian)",
"section": "3.8.1.2.3 Analytic Hessian"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The exact Hessian is \n",
" [[0.00082025 0.00387044]\n",
" [0.00387044 0.00102412]]\n"
]
}
],
"source": [
"def f(x1,x2):\n",
" \n",
" a = np.array([0.3, 0.6, 0.2])\n",
" b = np.array([5, 26, 3])\n",
" b1 = 5;\n",
" c = np.array([40, 1, 10])\n",
" u = x1 - 0.8\n",
" v = x2 -(a[0] + a[1]*u**2*(1-u)**0.5-a[2]*u)\n",
" alpha = b[1]*u**2*(1+u)**0.5 + b[2]*u -b[0]\n",
" beta = c[0]*v**2*(1-c[1]*v)/(1+c[2]*u**2)\n",
" return alpha*sym.exp(-1*beta)\n",
"\n",
"\n",
"def my_hes_exact(x):\n",
" x1, x2 = sym.symbols('x1 x2')\n",
" HessianOfF11 = sym.lambdify((x1,x2),sym.diff(f(x1,x2),x1,x1));\n",
" HessianOfF12 = sym.lambdify((x1,x2),sym.diff(f(x1,x2),x1,x2));\n",
" HessianOfF21 = sym.lambdify((x1,x2),sym.diff(f(x1,x2),x2,x1));\n",
" HessianOfF22 = sym.lambdify((x1,x2),sym.diff(f(x1,x2),x2,x2));\n",
" #DerivativeOfF2 = sym.lambdify((x1,x2),gradf2(x1,x2));\n",
" #F = sym.lambdify((x1,x2),f(x1,x2));\n",
" return np.array([[HessianOfF11(x[0],x[1]),HessianOfF12(x[0],x[1])],[HessianOfF21(x[0],x[1]),HessianOfF22(x[0],x[1])]])\n",
" \n",
"x = np.array([0,0])\n",
"print(\"The exact Hessian is \\n\",my_hes_exact(x)) "
]
},
{
"cell_type": "markdown",
"metadata": {
"nbpages": {
"level": 3,
"link": "[3.8.1.3 Gradient Finite Difference Comparison](https://ndcbe.github.io/CBE60499/03.08-Algorithms2.html#3.8.1.3-Gradient-Finite-Difference-Comparison)",
"section": "3.8.1.3 Gradient Finite Difference Comparison"
}
},
"source": [
"### 3.8.1.3 Gradient Finite Difference Comparison\n",
"\n",
"Repeat the analysis procedure from the finite difference class notebook to find the value of $\\epsilon_1$ that gives the smallest approximation error. Some tips:\n",
"1. Write a `for` loop to iterate over many values of $\\epsilon_1$\n",
"2. Use $|| \\nabla f(x;\\epsilon_1)_{approx} - \\nabla f(x)_{exact} ||$ to measure the error. Your choice on which norm(s) to use. Please label your plot with the norm(s) you used.\n",
"3. Make a log-log plot"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"nbpages": {
"level": 3,
"link": "[3.8.1.3 Gradient Finite Difference Comparison](https://ndcbe.github.io/CBE60499/03.08-Algorithms2.html#3.8.1.3-Gradient-Finite-Difference-Comparison)",
"section": "3.8.1.3 Gradient Finite Difference Comparison"
}
},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"
"
]
}
],
"metadata": {
"celltoolbar": "Tags",
"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.7.3"
}
},
"nbformat": 4,
"nbformat_minor": 2
}