diff --git a/exp-345.ipynb b/exp-345.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..45ed46107fbb32abb9b35c77f3d033533c75ef1b
--- /dev/null
+++ b/exp-345.ipynb
@@ -0,0 +1,162 @@
+{
+  "cells": [
+    {
+      "cell_type": "markdown",
+      "metadata": {},
+      "source": [
+        "### IPython notebook for Example 3.4.5 from the lecture"
+      ]
+    },
+    {
+      "cell_type": "code",
+      "metadata": {},
+      "source": [
+        "import numpy as np\n",
+        "import matplotlib.pyplot as plt\n",
+        "from IPython.display import set_matplotlib_formats, display, Math\n",
+        "set_matplotlib_formats('svg')\n",
+        "\n",
+        "\n",
+        "def k(s, t, d):\n",
+        "    return d / np.power(d**2 + (s-t)**2, 3/2)\n",
+        "\n",
+        "\n",
+        "d = 0.1\n",
+        "n = 80\n",
+        "h = 1/n\n",
+        "\n",
+        "display(Math(r'\\text{Create }A\\text{ from Example 1.7.1, }\\xi_j=\\begin{cases}2&1\\leq j\\leq40\\\\1&41\\leq j\\leq80\\end{cases},\\ y=A\\xi'))\n",
+        "A = np.zeros((n, n))\n",
+        "for i in range(n):\n",
+        "    for j in range(n):\n",
+        "        A[i, j] = h * k((i+0.5)*h, (j+0.5)*h, d)\n",
+        "\n",
+        "xi = np.ones(n)\n",
+        "xi[:n//2] = 2\n",
+        "y = np.matmul(A, xi)\n",
+        "\n",
+        "j = np.arange(1, n+1)\n",
+        "plt.title(r\"$xi$\")\n",
+        "plt.plot(j, xi, 'kx')\n",
+        "plt.show()\n",
+        "plt.close()\n",
+        "plt.title(r\"$y=A\\xi$\")\n",
+        "plt.plot(j, y, 'kx')\n",
+        "plt.show()\n",
+        "plt.close()"
+      ],
+      "outputs": [],
+      "execution_count": null
+    },
+    {
+      "cell_type": "code",
+      "metadata": {},
+      "source": [
+        "display(Math(r'\\tilde y= y+\\delta y'))\n",
+        "np.random.seed(0)\n",
+        "y_tilde = y + 0.02*(np.random.rand(n)-0.5)\n",
+        "print('||y_tilde-y||/||y|| = {:.4f}'.format(np.linalg.norm(y_tilde-y)/np.linalg.norm(y)))\n",
+        "\n",
+        "plt.title(r\"$\\tilde \\xi = $numpy.linalg.solve$(A, \\tilde y)$\")\n",
+        "plt.plot(j, np.linalg.solve(A, y_tilde), 'k+')\n",
+        "plt.show()\n",
+        "plt.close()"
+      ],
+      "outputs": [],
+      "execution_count": null
+    },
+    {
+      "cell_type": "code",
+      "metadata": {},
+      "source": [
+        "error = np.zeros(100)\n",
+        "alphas = np.zeros(100)\n",
+        "for i in range(1, 101):\n",
+        "    alpha = 0.005*i\n",
+        "    A_Tikh = np.concatenate((A, np.diag(alpha*np.ones(n))), axis=0)\n",
+        "    y_tilde_Tikh = np.concatenate((y_tilde, np.zeros(n)), axis=0)\n",
+        "    xi_alpha = np.linalg.lstsq(A_Tikh, y_tilde_Tikh, rcond=0)[0]\n",
+        "    alphas[i-1] = alpha\n",
+        "    error[i-1] = np.linalg.norm(xi_alpha-xi)\n",
+        "    if i == 1 or i == 8 or i == 100:\n",
+        "        plt.title(r\"Tikhonov, $\\alpha$ = {}\".format(alpha))\n",
+        "        plt.plot(j, xi_alpha, 'kx')\n",
+        "        plt.show()\n",
+        "        plt.close()\n",
+        "\n",
+        "plt.title(\"Tikhonov, error\")\n",
+        "plt.xlabel(r'$\\alpha$')\n",
+        "plt.ylabel(r'$||\\tilde \\xi_{\\alpha}- \\xi||_2$')\n",
+        "plt.plot(alphas, error, 'k+')\n",
+        "plt.show()\n",
+        "plt.close()\n",
+        "print('alpha_opt = {}'.format(alphas[np.argmin(error)]))"
+      ],
+      "outputs": [],
+      "execution_count": null
+    },
+    {
+      "cell_type": "code",
+      "metadata": {},
+      "source": [
+        "# CGNE\n",
+        "xi_tilde = np.zeros(n)\n",
+        "# xi_tilde is zero, so the initial residuum is the input data.\n",
+        "r = y_tilde.copy()\n",
+        "d = np.matmul(A.T, r)\n",
+        "p = d.copy()\n",
+        "p_norm = np.linalg.norm(p)\n",
+        "error = np.zeros(201)\n",
+        "error[0] = np.linalg.norm(xi_tilde-xi)\n",
+        "for k in range(1, 201):\n",
+        "    q = np.matmul(A, d)\n",
+        "    beta = (np.linalg.norm(p)/np.linalg.norm(q))**2\n",
+        "    xi_tilde += beta * d\n",
+        "    r += -beta*q\n",
+        "    p = np.matmul(A.T, r)\n",
+        "    p_norm_new = np.linalg.norm(p)\n",
+        "    gamma = (p_norm_new/p_norm)**2\n",
+        "    p_norm = p_norm_new\n",
+        "    d = p + gamma*d\n",
+        "    if k == 5 or k == 40 or k == 200:\n",
+        "        plt.title(r\"CGNE, $k$ = {}\".format(k))\n",
+        "        plt.plot(j, xi_tilde, 'kx')\n",
+        "        plt.show()\n",
+        "        plt.close()\n",
+        "    error[k] = np.linalg.norm(xi_tilde-xi)\n",
+        "\n",
+        "plt.title(\"CGNE, error\")\n",
+        "plt.xlabel(r'$k$')\n",
+        "plt.ylabel(r'$||\\tilde \\xi_k- \\xi||_2$')\n",
+        "plt.plot(error, 'k+')\n",
+        "plt.show()\n",
+        "plt.close()\n",
+        "print('k_opt = {}'.format(np.argmin(error)))\n"
+      ],
+      "outputs": [],
+      "execution_count": null
+    }
+  ],
+  "metadata": {
+    "anaconda-cloud": {},
+    "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.6.1"
+    }
+  },
+  "nbformat": 4,
+  "nbformat_minor": 1
+}
\ No newline at end of file