{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2023年度計算機演習A・B\n",
    "\n",
    "# 第7回：関数の積分"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1. 積分の概念\n",
    "\n",
    "### 1.1. 関数の定積分\n",
    "\n",
    "関数 $f:\\mathbb{R}\\to\\mathbb{R}$ と区間 $[a,b]\\subset\\mathbb{R}$ を考えます。\n",
    "\n",
    "このとき、関数 $f$ の区間 $[a,b]$ における**定積分（definite integral）**\n",
    "\n",
    "$$\n",
    "\\int_a^b f(x)\\,dx\n",
    "$$\n",
    "\n",
    "は、下図のように $x$-$y$ 平面において $y=f(x)$、$x$ 軸、$x=a$、$x=b$ によって囲まれる領域の符号付き面積を意味します。\n",
    "\n",
    "<div align=\"center\"><img src=\"https://www.ces-alpha.org/course/file_serve/5683504192946176/figure7-1.png\" width=\"500\"></div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "定積分の定義方法はリーマン積分やルベーグ積分など複数存在しますが、以下では**リーマン積分（Riemann integral）**の考え方について詳しく見ていきます。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1.2. リーマン積分の考え方\n",
    "\n",
    "区間 $[a,b]$ を、\n",
    "\n",
    "$$\n",
    "a=x_0<x_1<x_2<\\cdots<x_{n-1}<x_n=b\n",
    "$$\n",
    "\n",
    "によって $n$ 個の小区間 $[x_0,x_1],[x_1,x_2],\\ldots,[x_{n-1},x_n]$ に分割します。\n",
    "\n",
    "各 $i=1,\\ldots,n$ に対して点 $t_i\\in[x_{i-1},x_i]$ を与えるとき、\n",
    "\n",
    "$$\n",
    "\\sum_{i=1}^n f(t_i)(x_i-x_{i-1})\n",
    "$$\n",
    "\n",
    "を $f$ の考えている点付き分割に関する**リーマン和（Riemann sum）**と呼びます。下図のように、リーマン和は長方形の面積の和に相当します。\n",
    "\n",
    "<div align=\"center\"><img src=\"https://www.ces-alpha.org/course/file_serve/5135715918675968/figure7-2.png\" width=\"500\"></div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "特に、各 $t_i$ を小区間の左端に取る（すなわち $t_i=x_{i-1}$ である）場合のリーマン和を**左リーマン和**、小区間の右端に取る（すなわち $t_i=x_i$ である）場合のリーマン和を**右リーマン和**と呼びます。\n",
    "\n",
    "**関数 $f$ が単調増加であるならば、左リーマン和は求める面積の下界、右リーマン和は求める面積の上界を与えます。**\n",
    "\n",
    "$n\\to\\infty$ としたときに点付き分割の取り方によらずにリーマン和が一定の値に収束するとき、その極限の値を関数 $f$ の区間 $[a,b]$ におけるリーマン積分と呼びます。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. 定積分の近似計算\n",
    "\n",
    "ここでは、上記の「単調増加関数に対する左リーマン和と右リーマン和の性質」を利用して、定積分の近似計算を行います。\n",
    "\n",
    "例として、関数 $f(x)=\\sqrt{x}+1$ の区間 $[0,1]$ における定積分を考えます。明らかに、$f$ は $[0,1]$ において単調増加です。\n",
    "\n",
    "まず、$f(x)$ を計算する関数`f(x)`および $f$ の $[0,1]$ におけるグラフを描画する関数`draw_f()`を定義します。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import math\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "def f(x):\n",
    "    return math.sqrt(x)+1\n",
    "\n",
    "def draw_f():\n",
    "    x_list = []\n",
    "    y_list = []\n",
    "    for i in range(201):\n",
    "        x = i/200\n",
    "        x_list.append(x)\n",
    "        y_list.append(f(x))\n",
    "    plt.plot(x_list,y_list,\"k-\")\n",
    "    #後の都合のため、plt.show()は関数定義に含めない\n",
    "\n",
    "draw_f()  #関数draw_f()を呼び出してグラフを描画する\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "次に、分割数 $1$ の等分割（すなわち、$[0,1]$ のまま）に関する左リーマン和と右リーマン和を考えます。\n",
    "\n",
    "このときの左リーマン和に対応する図は、次のようになります。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "draw_f()\n",
    "plt.fill([0,1,1,0],[0,0,f(0),f(0)],\"r\",alpha=0.5)\n",
    "#点(0,0),(1,0),(1,f(0)),(0,f(0))で囲まれる領域を赤色（不透明度0.5）で塗りつぶす\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "ここで、関数`plt.fill`は\n",
    "\n",
    "```\n",
    "plt.fill(x_list,y_list,色を表す文字列,alpha=不透明度)\n",
    "```\n",
    "\n",
    "のように使用し、x_listとy_listが表す複数の点によって囲まれる領域を指定の色と不透明度（0～1）で塗りつぶすことができます。ただし、点の順番には注意が必要であり、順番通りに線分で結んでできる領域の塗りつぶしになります。\n",
    "\n",
    "左リーマン和の値はこの赤色の領域の面積に等しいので、次のように求まります。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(\"分割数1の等分割に関する左リーマン和の値は\",f(0)*1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "右リーマン和に対応する図は、次のようになります。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "draw_f()\n",
    "plt.fill([0,1,1,0],[0,0,f(1),f(1)],\"g\",alpha=0.5)\n",
    "#点(0,0),(1,0),(1,f(1)),(0,f(1))で囲まれる領域を緑色（不透明度0.5）で塗りつぶす\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "右リーマン和の値はこの緑色の領域の面積に等しいので、次のように求まります。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(\"分割数1の等分割に関する右リーマン和の値は\",f(1)*1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "同様にして、分割数 $2$ の等分割に関する左リーマン和と右リーマン和を考えると、次のようになります。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "draw_f()\n",
    "plt.fill([0,1/2,1/2,0],[0,0,f(0),f(0)],\"r\",alpha=0.5)\n",
    "plt.fill([1/2,1,1,1/2],[0,0,f(1/2),f(1/2)],\"r\",alpha=0.5)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(\"分割数2の等分割に関する左リーマン和の値は\",f(0)*(1/2)+f(1/2)*(1/2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "draw_f()\n",
    "plt.fill([0,1/2,1/2,0],[0,0,f(1/2),f(1/2)],\"g\",alpha=0.5)\n",
    "plt.fill([1/2,1,1,1/2],[0,0,f(1),f(1)],\"g\",alpha=0.5)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(\"分割数2の等分割に関する右リーマン和の値は\",f(1/2)*(1/2)+f(1)*(1/2))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 演習1\n",
    "\n",
    "関数 $f(x)=\\sqrt{x}+1$ に対して、区間 $[0,1]$ の分割数 $3$ の等分割に関する左リーマン和と右リーマン和を考えます。\n",
    "\n",
    "それぞれに対応する図を描画した上で値を求めるコードを書いてください。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#演習1のコード\n",
    "import math\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "def f(x):\n",
    "    return math.sqrt(x)+1\n",
    "\n",
    "def draw_f():\n",
    "    x_list = []\n",
    "    y_list = []\n",
    "    for i in range(201):\n",
    "        x = i/200\n",
    "        x_list.append(x)\n",
    "        y_list.append(f(x))\n",
    "    plt.plot(x_list,y_list,\"k-\")\n",
    "\n",
    "#ここに、コードを書く"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 演習2\n",
    "\n",
    "関数 $f(x)=\\sqrt{x}+1$ に対して、区間 $[0,1]$ の分割数 $n$ の等分割に関する左リーマン和と右リーマン和を考えます。\n",
    "\n",
    "左リーマン和に対応する図を描画する関数`draw_left_RS(n)`、左リーマン和の値を返す関数`calc_left_RS(n)`、右リーマン和に対応する図を描画する関数`draw_right_RS(n)`、右リーマン和の値を返す関数`calc_right_RS(n)`を定義してください。\n",
    "\n",
    "$n=4$ の場合に、定義したそれぞれの関数を呼び出してください。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#演習2のコード\n",
    "import math\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "def f(x):\n",
    "    return math.sqrt(x)+1\n",
    "\n",
    "def draw_f():\n",
    "    x_list = []\n",
    "    y_list = []\n",
    "    for i in range(201):\n",
    "        x = i/200\n",
    "        x_list.append(x)\n",
    "        y_list.append(f(x))\n",
    "    plt.plot(x_list,y_list,\"k-\")\n",
    "\n",
    "def draw_left_RS(n):\n",
    "    draw_f()\n",
    "    #ここに、関数の処理を書く\n",
    "    plt.show()\n",
    "\n",
    "def calc_left_RS(n):\n",
    "    value = 0\n",
    "    #ここに、関数の処理を書く\n",
    "    return value\n",
    "\n",
    "def draw_right_RS(n):\n",
    "    draw_f()\n",
    "    #ここに、関数の処理を書く\n",
    "    plt.show()\n",
    "\n",
    "def calc_right_RS(n):\n",
    "    value = 0\n",
    "    #ここに、関数の処理を書く\n",
    "    return value\n",
    "\n",
    "n = 4\n",
    "draw_left_RS(n)\n",
    "print(\"分割数\",n,\"の等分割に関する左リーマン和の値は\",calc_left_RS(n))\n",
    "draw_right_RS(n)\n",
    "print(\"分割数\",n,\"の等分割に関する右リーマン和の値は\",calc_right_RS(n))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 演習3（オプション）\n",
    "\n",
    "関数 $f(x)=\\sqrt{x}+1$ に対して、区間 $[0,1]$ の分割数 $n$ の等分割に関する左リーマン和と右リーマン和を考えます。\n",
    "\n",
    "右リーマン和と左リーマン和の差が $0.01$ より小さくなるような最小の $n$ を求めるコードを書いてください。\n",
    "\n",
    "また、定積分 $\\int_0^1 \\left(\\sqrt{x}+1\\right)\\,dx$ の値を手計算で求め、上記の $n$ に対する左リーマン和および右リーマン和の値と比較して考察してください。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#演習3のコード"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 第7回レポート課題\n",
    "\n",
    "演習1～演習3に取り組んでください。"
   ]
  }
 ],
 "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.8.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
