diff --git a/Labs/Lab.3/Lab3-RobertCocker.ipynb b/Labs/Lab.3/Lab3-RobertCocker.ipynb new file mode 100644 index 0000000..8d8113f --- /dev/null +++ b/Labs/Lab.3/Lab3-RobertCocker.ipynb @@ -0,0 +1,839 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 55, + "metadata": {}, + "outputs": [], + "source": [ + "# Robert Cocker\n", + "# Dr. Farbin\n", + "# DATA-3402\n", + "# Lab 3\n", + "# 2/16/2024" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Lab 3" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Uniform Distribution\n", + "Lets start with generating some fake random data. You can get a random number between 0 and 1 using the python random module as follow:" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The Value of x is 0.15390961701777806\n" + ] + } + ], + "source": [ + "import random\n", + "x=random.random()\n", + "print(\"The Value of x is\", x)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Everytime you call random, you will get a new number.\n", + "\n", + "*Exercise 1:* Using random, write a function `generate_uniform(N, mymin, mymax)`, that returns a python list containing N random numbers between specified minimum and maximum value. Note that you may want to quickly work out on paper how to turn numbers between 0 and 1 to between other values. " + ] + }, + { + "cell_type": "code", + "execution_count": 94, + "metadata": {}, + "outputs": [], + "source": [ + "def generate_uniform(N,x_min,x_max):\n", + " out = []\n", + " for _ in range(N):\n", + " random_number = random.random()\n", + " scaled_number = random_number * (x_max - x_min) + x_min\n", + " out.append(scaled_number)\n", + " return out" + ] + }, + { + "cell_type": "code", + "execution_count": 95, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Data Type: \n", + "Data Length: 1000\n", + "Type of Data Contents: \n", + "Data Minimum: -9.988731443994007\n", + "Data Maximum: 9.93791001990514\n" + ] + } + ], + "source": [ + "# Test your solution here\n", + "data=generate_uniform(1000,-10,10)\n", + "print (\"Data Type:\", type(data))\n", + "print (\"Data Length:\", len(data))\n", + "if len(data)>0: \n", + " print (\"Type of Data Contents:\", type(data[0]))\n", + " print (\"Data Minimum:\", min(data))\n", + " print (\"Data Maximum:\", max(data))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "*Exercise 2a:* \n", + "Write a function that computes the mean of values in a list. Recall the equation for the mean of a random variable $\\bf{x}$ computed on a data set of $n$ values $\\{ x_i \\} = \\{x_1, x_2, ..., x_n\\}$ is ${\\bf\\bar{x}} = \\frac{1}{n} \\sum_i^n x_i$." + ] + }, + { + "cell_type": "code", + "execution_count": 96, + "metadata": {}, + "outputs": [], + "source": [ + "def mean(Data):\n", + " m=0.\n", + " \n", + " if not Data:\n", + " return None # Return None if list is empty\n", + " \n", + " # Calculate sum of values\n", + " total_sum = sum(Data)\n", + " \n", + " # Calculate mean\n", + " m = total_sum / len(Data)\n", + "\n", + " return m" + ] + }, + { + "cell_type": "code", + "execution_count": 97, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Mean of Data: 0.03207328365953548\n" + ] + } + ], + "source": [ + "# Test your solution here\n", + "print (\"Mean of Data:\", mean(data))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "*Exercise 2b:* \n", + "Write a function that computes the variance of values in a list. Recall the equation for the variance of a random variable $\\bf{x}$ computed on a data set of $n$ values $\\{ x_i \\} = \\{x_1, x_2, ..., x_n\\}$ is ${\\bf\\langle x \\rangle} = \\frac{1}{n} \\sum_i^n (x_i - {\\bf\\bar{x}})$." + ] + }, + { + "cell_type": "code", + "execution_count": 98, + "metadata": {}, + "outputs": [], + "source": [ + "# Skeleton\n", + "def variance(Data):\n", + " m=0.\n", + " \n", + " ### BEGIN SOLUTION\n", + "\n", + " n = len(Data)\n", + " mean = sum(Data) / n\n", + " deviations = [(x - mean) ** 2 for x in Data]\n", + " m = sum(deviations) / n\n", + " \n", + " ### END SOLUTION\n", + " \n", + " return m" + ] + }, + { + "cell_type": "code", + "execution_count": 99, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Variance of Data: 34.79037978973739\n" + ] + } + ], + "source": [ + "# Test your solution here\n", + "print (\"Variance of Data:\", variance(data))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Histogramming" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "*Exercise 3:* Write a function that bins the data so that you can create a histogram. An example of how to implement histogramming is the following logic:\n", + "\n", + "* User inputs a list of values `x` and optionally `n_bins` which defaults to 10.\n", + "* If not supplied, find the minimum and maximum (`x_min`,`x_max`) of the values in x.\n", + "* Determine the bin size (`bin_size`) by dividing the range of the function by the number of bins.\n", + "* Create an empty list of zeros of size `n_bins`, call it `hist`.\n", + "* Loop over the values in `x`\n", + " * Loop over the values in `hist` with index `i`:\n", + " * If x is between `x_min+i*bin_size` and `x_min+(i+1)*bin_size`, increment `hist[i].` \n", + " * For efficiency, try to use continue to goto the next bin and data point.\n", + "* Return `hist` and the list corresponding of the bin edges (i.e. of `x_min+i*bin_size`). " + ] + }, + { + "cell_type": "code", + "execution_count": 100, + "metadata": {}, + "outputs": [], + "source": [ + "# Solution\n", + "def histogram(x, n_bins=10, x_min=None, x_max=None):\n", + " ### BEGIN SOLUTION\n", + "\n", + " if x_min is None:\n", + " x_min = min(x)\n", + " if x_max is None:\n", + " x_max = max(x)\n", + "\n", + " bin_size = (x_max - x_min) / n_bins\n", + " hist = [0] * n_bins\n", + " bin_edges = [x_min + i * bin_size for i in range(n_bins + 1)]\n", + "\n", + " for value in x:\n", + " for i in range(n_bins):\n", + " if x_min + i * bin_size <= value < x_min + (i + 1) * bin_size:\n", + " hist[i] += 1\n", + " break\n", + "\n", + " ### END SOLUTION\n", + "\n", + " return hist, bin_edges" + ] + }, + { + "cell_type": "code", + "execution_count": 101, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[11, 15, 10, 11, 8, 17, 10, 19, 10, 13, 12, 6, 6, 8, 6, 9, 8, 11, 11, 7, 14, 14, 3, 13, 5, 9, 7, 11, 14, 11, 8, 10, 7, 8, 10, 11, 9, 6, 8, 12, 6, 6, 12, 8, 13, 5, 11, 6, 9, 8, 13, 7, 11, 7, 7, 17, 11, 7, 7, 8, 15, 17, 10, 7, 9, 11, 6, 12, 9, 4, 14, 11, 10, 13, 8, 7, 14, 17, 11, 8, 12, 14, 9, 8, 9, 11, 5, 15, 15, 10, 6, 6, 18, 16, 9, 14, 8, 7, 10, 7]\n" + ] + } + ], + "source": [ + "# Test your solution here\n", + "h,b=histogram(data,100)\n", + "print(h)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "*Exercise 4:* Write a function that uses the histogram function in the previous exercise to create a text-based \"graph\". For example the output could look like the following:\n", + "```\n", + "[ 0, 1] : ######\n", + "[ 1, 2] : #####\n", + "[ 2, 3] : ######\n", + "[ 3, 4] : ####\n", + "[ 4, 5] : ####\n", + "[ 5, 6] : ######\n", + "[ 6, 7] : #####\n", + "[ 7, 8] : ######\n", + "[ 8, 9] : ####\n", + "[ 9, 10] : #####\n", + "```\n", + "\n", + "Where each line corresponds to a bin and the number of `#`'s are proportional to the value of the data in the bin. " + ] + }, + { + "cell_type": "code", + "execution_count": 102, + "metadata": {}, + "outputs": [], + "source": [ + "# Solution\n", + "def draw_histogram(x, n_bins, x_min=None, x_max=None, character=\"#\", max_character_per_line=20):\n", + " hist, bin_edges = histogram(x, n_bins, x_min, x_max)\n", + "\n", + " max_value = max(hist)\n", + " scale = max_value / max_character_per_line\n", + "\n", + " for i in range(n_bins):\n", + " print(f'[{bin_edges[i]:3.0f}, {bin_edges[i+1]:3.0f}] : {character * int(hist[i]//scale)}')\n", + "\n", + " return hist, bin_edges\n" + ] + }, + { + "cell_type": "code", + "execution_count": 103, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[-10, -9] : ###############\n", + "[ -9, -8] : ###################\n", + "[ -8, -7] : ###########\n", + "[ -7, -6] : #############\n", + "[ -6, -5] : ##############\n", + "[ -5, -4] : ###############\n", + "[ -4, -3] : ############\n", + "[ -3, -2] : #############\n", + "[ -2, -1] : #############\n", + "[ -1, -0] : ###########\n", + "[ -0, 1] : #############\n", + "[ 1, 2] : ##############\n", + "[ 2, 3] : ################\n", + "[ 3, 4] : ############\n", + "[ 4, 5] : ################\n", + "[ 5, 6] : ################\n", + "[ 6, 7] : ###############\n", + "[ 7, 8] : ################\n", + "[ 8, 9] : ###############\n", + "[ 9, 10] : #############\n" + ] + } + ], + "source": [ + "# Test your solution here\n", + "h,b=draw_histogram(data,20)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Functional Programming\n", + "\n", + "*Exercise 5:* Write a function the applies a booling function (that returns true/false) to every element in data, and return a list of indices of elements where the result was true. Use this function to find the indices of entries greater than 0.5. " + ] + }, + { + "cell_type": "code", + "execution_count": 104, + "metadata": {}, + "outputs": [], + "source": [ + "def where(mylist, myfunc):\n", + " out = []\n", + " for i, x in enumerate(mylist):\n", + " if myfunc(x):\n", + " out.append(i)\n", + " return out" + ] + }, + { + "cell_type": "code", + "execution_count": 105, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[1, 2, 4]\n" + ] + } + ], + "source": [ + "# Test your solution here\n", + "data = [0.2, 0.6, 0.8, 0.3, 0.9, 0.1]\n", + "greater_than_0_5 = where(data, lambda x: x > 0.5)\n", + "print(greater_than_0_5)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "*Exercise 6:* The `inrange(mymin,mymax)` function below returns a function that tests if it's input is between the specified values. Write corresponding functions that test:\n", + "* Even\n", + "* Odd\n", + "* Greater than\n", + "* Less than\n", + "* Equal\n", + "* Divisible by" + ] + }, + { + "cell_type": "code", + "execution_count": 106, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True True False False False\n", + "False False True True False\n", + "Number of Entries passing F1: 6\n", + "Number of Entries passing F2: 0\n" + ] + } + ], + "source": [ + "def inrange(mymin,mymax):\n", + " def testrange(x):\n", + " return x=mymin\n", + " return testrange\n", + "\n", + "# Examples:\n", + "F1=inrange(0,10)\n", + "F2=inrange(10,20)\n", + "\n", + "# Test of inrange\n", + "print (F1(0), F1(1), F1(10), F1(15), F1(20))\n", + "print (F2(0), F2(1), F2(10), F2(15), F2(20))\n", + "\n", + "print (\"Number of Entries passing F1:\", len(where(data,F1)))\n", + "print (\"Number of Entries passing F2:\", len(where(data,F2)))" + ] + }, + { + "cell_type": "code", + "execution_count": 107, + "metadata": {}, + "outputs": [], + "source": [ + "### BEGIN SOLUTION\n", + "def is_even():\n", + " def test_even(x):\n", + " return x % 2 == 0\n", + " return test_even\n", + "\n", + "def is_odd():\n", + " def test_odd(x):\n", + " return x % 2 != 0\n", + " return test_odd\n", + "\n", + "def greater_than(n):\n", + " def test_greater(x):\n", + " return x > n\n", + " return test_greater\n", + "\n", + "def less_than(n):\n", + " def test_less(x):\n", + " return x < n\n", + " return test_less\n", + "\n", + "def equal_to(n):\n", + " def test_equal(x):\n", + " return x == n\n", + " return test_equal\n", + "\n", + "def divisible_by(n):\n", + " def test_divisible(x):\n", + " return x % n == 0\n", + " return test_divisible \n", + " \n", + "### END SOLUTION" + ] + }, + { + "cell_type": "code", + "execution_count": 108, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True False True False True\n", + "False False False True True\n", + "Number of Entries passing F1: 3\n", + "Number of Entries passing F2: 2\n" + ] + } + ], + "source": [ + "# Test your solution\n", + "# Examples:\n", + "F1 = is_even()\n", + "F2 = greater_than(10)\n", + "\n", + "# Test of is_even and greater_than\n", + "print(F1(0), F1(1), F1(10), F1(15), F1(20))\n", + "print(F2(0), F2(1), F2(10), F2(15), F2(20))\n", + "\n", + "# Assuming 'data' is a list of numbers\n", + "data = [0, 1, 10, 15, 20]\n", + "print(\"Number of Entries passing F1:\", len([x for x in data if F1(x)]))\n", + "print(\"Number of Entries passing F2:\", len([x for x in data if F2(x)])) " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "*Exercise 7:* Repeat the previous exercise using `lambda` and the built-in python functions sum and map instead of your solution above. " + ] + }, + { + "cell_type": "code", + "execution_count": 109, + "metadata": {}, + "outputs": [], + "source": [ + "### BEGIN SOLUTION\n", + "def is_even():\n", + " return lambda x: x % 2 == 0\n", + "\n", + "def is_odd():\n", + " return lambda x: x % 2 != 0\n", + "\n", + "def greater_than(n):\n", + " return lambda x: x > n\n", + "\n", + "def less_than(n):\n", + " return lambda x: x < n\n", + "\n", + "def equal_to(n):\n", + " return lambda x: x == n\n", + "\n", + "def divisible_by(n):\n", + " return lambda x: x % n == 0 \n", + " \n", + "### END SOLUTION" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Monte Carlo\n", + "\n", + "*Exercise 7:* Write a \"generator\" function called `generate_function(func,x_min,x_max,N)`, that instead of generating a flat distribution, generates a distribution with functional form coded in `func`. Note that `func` will always be > 0. \n", + "\n", + "Use the test function below and your histogramming functions above to demonstrate that your generator is working properly.\n", + "\n", + "Hint: A simple, but slow, solution is to a draw random number `test_x` within the specified range and another number `p` between the `min` and `max` of the function (which you will have to determine). If `p<=function(test_x)`, then place `test_x` on the output. If not, repeat the process, drawing two new numbers. Repeat until you have the specified number of generated numbers, `N`. For this problem, it's OK to determine the `min` and `max` by numerically sampling the function. " + ] + }, + { + "cell_type": "code", + "execution_count": 110, + "metadata": {}, + "outputs": [], + "source": [ + "import random\n", + "import numpy as np\n", + "\n", + "def generate_function(func, x_min, x_max, N=1000):\n", + " out = list()\n", + " x = np.linspace(x_min, x_max, 1000)\n", + " y = func(x)\n", + " max_y = max(y)\n", + " while len(out) < N:\n", + " test_x = random.uniform(x_min, x_max)\n", + " p = random.uniform(0, max_y)\n", + " if p <= func(test_x):\n", + " out.append(test_x)\n", + " return out" + ] + }, + { + "cell_type": "code", + "execution_count": 111, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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1ASu6gEAAOevbgsot99+u06cOKFHH31UDodDI0aM0Lvvvqusbp77/2w2m03z589v9hFTT8H+RbeevH89ed8k9i/asX9dL8YwIjTbEwAAQBt1yxgUAACAlhBQAACA6RBQAACA6RBQAACA6Zz3AeWJJ57QuHHj1KtXr7CTv5WWlmry5Mnq1auXMjMzNWfOHPn9zZcZP5PT6dTUqVNlt9uVmpqq6dOny+12d8EetM/GjRsVExMT8rZt27aw97v++uub1f/0pz+NYM/b5sILL2zWzyefbHlBuLq6OhUUFCg9PV3JycmaMmVKs0kEzeDQoUOaPn26Bg0apMTERF188cWaP3++vN6WVxI287FbtmyZLrzwQiUkJGjMmDH6+OOPW6xfvXq1hgwZooSEBA0bNkxvv/12hHraPoWFhfra176m3r17KzMzU7fccov27dvX4n1WrVrV7DglJCREqMft89hjjzXr65AhQ1q8T7QcOyn060hMTIwKCgpC1pv92H3wwQe66aablJOTo5iYGL3xxhtB7YZh6NFHH1W/fv2UmJioCRMmaP/+/aEf7Aztff6213kfULxer2677TbNmDEjZHt9fb0mT54sr9erzZs368UXX9SqVav06KOPtvi4U6dO1e7du7Vu3TqtWbNGH3zwge69tw0LpXWxcePG6fjx40G3H//4xxo0aJCuueaaFu97zz33BN1v8eLFEep1+yxcuDCon/fdd1+L9Q888ID+8pe/aPXq1dq0aZOOHTumW2+9NUK9bbu9e/eqoaFBL7zwgnbv3q2lS5dq+fLleuSRR1q9rxmP3R/+8AfNnj1b8+fP144dO3TVVVcpPz9fFRWhV4TevHmz7rzzTk2fPl07d+7ULbfcoltuuUWff/55hHveuk2bNqmgoEBbtmzRunXr5PP5NHHiRNXUhF6AtIndbg86TocPH45Qj9vviiuuCOrrhx9+GLY2mo6dJG3bti1o39ata1zR+rbbbgt7HzMfu5qaGl111VVatmxZyPbFixfrmWee0fLly7V161YlJSUpPz9fdXV1YR+zvc/fDumU1f96gJUrVxopKSnNtr/99ttGbGys4XA4Atuef/55w263Gx6PJ+Rj7dmzx5BkbNu2LbDtnXfeMWJiYoyysrJO7/u58Hq9RkZGhrFw4cIW66677jrj/vvvj0ynzsHAgQONpUuXtrm+srLS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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# A test function\n", + "def test_func(x,a=1,b=1):\n", + " return abs(a*x+b)\n", + "\n", + "# Generate numbers using the test function\n", + "x_min = -10\n", + "x_max = 10\n", + "N = 10000\n", + "numbers = generate_function(test_func, x_min, x_max, N)\n", + "\n", + "# Generate histogram using your function\n", + "hist, bin_edges = histogram(numbers, n_bins=50)\n", + "\n", + "# Plot the histogram\n", + "plt.bar(bin_edges[:-1], hist, width=np.diff(bin_edges), edgecolor=\"black\", alpha=0.6)\n", + "\n", + "# Plot the test function\n", + "x = np.linspace(x_min, x_max, 1000)\n", + "y = test_func(x)\n", + "plt.plot(x, y, 'r-')\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "*Exercise 8:* Use your function to generate 1000 numbers that are normal distributed, using the `gaussian` function below. Confirm the mean and variance of the data is close to the mean and variance you specify when building the Gaussian. Histogram the data. " + ] + }, + { + "cell_type": "code", + "execution_count": 112, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "\n", + "def gaussian(mean, sigma):\n", + " def f(x):\n", + " return np.exp(-((x-mean)**2)/(2*sigma**2))/np.sqrt(math.pi*sigma)\n", + " return f\n", + "\n", + "# Example Instantiation\n", + "g1=gaussian(0,1)\n", + "g2=gaussian(10,3)" + ] + }, + { + "cell_type": "code", + "execution_count": 113, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Mean: 0.00047575876080266876\n", + "Variance: 1.0581827537528683\n" + ] + }, + { + "data": { + "image/png": "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IyyBD4xRQuFj//79qq+v18GDB7V3716FQiF9/vOfl8/ni73ngQce0K5du7Rz507t379f7e3tWrZsWdIbB4DxlldUIkdpRWzLdZRY3RIwKSR022X37t1xr5955hlNmzZNhw8f1mc/+1n19fVp27Zt2rFjh5YsWSJJ2r59u6688kodPHhQixYtSl7nAAAgJY1pzEdfX58kyel0SpIOHz6sUCik2tra2Htmz56t6upqHThwYNjwEQgEFAh8eP/U4/GMpSUgKdxut7xe75B6fn5+7OcdADA6ow4fg4ODamho0A033KCrr75aktTR0aGsrCwVFRXFvbesrEwdHR3DHqepqUmPPvroaNsAks7tdqth9cNyewaG7HMW5mrzhvUEEAAYg1GHj/r6er311lv69a9/PaYG1qxZo8bGxthrj8ejqqqqMR0TGAuv1yu3Z0Al8+qUV1waq/vOdqvnyB55vV7CBwCMwajCx3333ad/+7d/06uvvqrp06fH6uXl5QoGg+rt7Y27+tHZ2any8vJhj2W322W320fTBjCu8opL5SitiKv1WNQLAEwmCc12iUajuu+++/TCCy/oP/7jPzRz5sy4/fPnz1dmZqb27dsXqx07dkynTp1STU1NcjoGAAApLaErH/X19dqxY4deeuklFRQUxMZxOBwO5eTkyOFwaOXKlWpsbJTT6VRhYaFWrVqlmpoaZroAAABJCYaPLVu2SJIWL14cV9++fbvuuusuSdKmTZuUlpam5cuXKxAIqK6uTk899VRSmgVSzXCzZliiGxcy0kwridlWmDwSCh/RaPRj35Odna3m5mY1NzePuilgMhhp1gxLdGMkF5ppJTHbCpMHz3YBxslIs2Y621oUaj3BEt0YYqSfGYnZVphcCB/AOPvorJl+d5eF3SAVDDfTSmK2FSaPhGa7AAAAjBXhAwAAGEX4AAAARhE+AACAUYQPAABgFOEDAAAYRfgAAABGET4AAIBRhA8AAGAU4QMAABhF+AAAAEYRPgAAgFGEDwAAYBThAwAAGEX4AAAARhE+AACAUYQPAABgFOEDAAAYRfgAAABGET4AAIBRhA8AAGAU4QMAABhF+AAAAEYRPgAAgFGEDwAAYBThAwAAGEX4AAAARhE+AACAUYQPAABgVIbVDQCTgdvtltfrjau5XC4FQ0GLOgKAiYvwAYyR2+1Ww+qH5fYMxNXP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HPqANiSuublZn/jEJ5Sdna2FCxfqt78d4YF4GJWmpiZdf/31Kigo0LRp07R06VIdO3bM6rYmvSeeeEI2m00NDQ1Wt5IyCB8paPXq1Re1fC0S984772hwcFBPP/203n77bW3atElbt27Vww+P/Dh2XJznnntOjY2NWrdunY4cOaJrrrlGdXV16uqy9vHrk8n+/ftVX1+vgwcPau/evQqFQvr85z8vn89ndWuT1qFDh/T0009rzpw5VreSWpLzODmY8qtf/So6e/bs6Ntvvx2VFP3d735ndUuT3oYNG6IzZ860uo2Ut2DBgmh9fX3sdSQSiVZWVkabmpos7Gpy6+rqikqK7t+/3+pWJqX+/v7orFmzonv37o1+7nOfi95///1Wt5QyuPKRQjo7O3XPPffon/7pn5Sbm2t1O1NGX1+fnE6n1W2ktGAwqMOHD6u2tjZWS0tLU21trQ4cOGBhZ5NbX1+fJPHzO07q6+v1xS9+Me7nGhfH8qfa4uJEo1Hddddd+su//Etdd911OnnypNUtTQnHjx/Xk08+qe9973tWt5LS3n//fUUikSGrHJeVlemdd96xqKvJbXBwUA0NDbrhhht09dVXW93OpPPss8/qyJEjOnTokNWtpCSufFjsoYceks1mu+D2zjvv6Mknn1R/f7/WrFljdcsp6WLP859yuVz6whe+oK985Su65557LOocGJ36+nq99dZbevbZZ61uZdI5ffq07r//fv385z9Xdna21e2kJJZXt1h3d7d6enou+J5LL71Ut99+u3bt2iWbzRarRyIRpaen684779RPfvKT8W41pV3sec7KypIktbe3a/HixVq0aJGeeeYZpaWR08ciGAwqNzdXzz//vJYuXRqrr1ixQr29vXrppZesa24Suu+++/TSSy/p1Vdf1cyZM61uZ9J58cUX9eUvf1np6emxWiQSkc1mU1pamgKBQNw+DEX4SBGnTp2Sx+OJvW5vb1ddXZ2ef/55LVy4UNOnT7ewu8nF5XLppptu0vz58/Wzn/2MXyJJsnDhQi1YsEBPPvmkpPO3Baqrq3XffffpoYcesri7ySEajWrVqlV64YUX9Morr2jWrFlWtzQp9ff367333our3X333Zo9e7YefPBBbnNdBMZ8pIjq6uq41/n5+ZKkyy67jOCRRC6XS4sXL9aMGTP0ve99T93d3bF95eXlFnaW+hobG7VixQpdd911WrBggTZv3iyfz6e7777b6tYmjfr6eu3YsUMvvfSSCgoK1NHRIUlyOBzKycmxuLvJo6CgYEjAyMvLU0lJCcHjIhE+gD+xd+9eHT9+XMePHx8S6rhIODZ33HGHuru79cgjj6ijo0PXXnutdu/ePWQQKkZvy5YtkqTFixfH1bdv36677rrLfEPACLjtAgAAjGIUHQAAMIrwAQAAjCJ8AAAAowgfAADAKMIHAAAwivABAACMInwAAACjCB8AAMAowgcAADCK8AEAAIwifAAAAKMIHwAAwKj/D9TLXWfBMkNkAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "\n", + "# Instantiate your Gaussian function\n", + "mean = 0\n", + "sigma = 1\n", + "g1 = gaussian(mean, sigma)\n", + "\n", + "# Generate numbers using the Gaussian function\n", + "N = 1000\n", + "numbers = generate_function(g1, mean - 5*sigma, mean + 5*sigma, N)\n", + "\n", + "# Confirm the mean and variance\n", + "print(\"Mean:\", np.mean(numbers))\n", + "print(\"Variance:\", np.var(numbers))\n", + "\n", + "# Generate histogram using your function\n", + "hist, bin_edges = histogram(numbers, n_bins=50)\n", + "\n", + "# Plot the histogram\n", + "plt.bar(bin_edges[:-1], hist, width=np.diff(bin_edges), edgecolor=\"black\", alpha=0.6)\n", + "\n", + "# Plot the Gaussian function\n", + "x = np.linspace(mean - 5*sigma, mean + 5*sigma, 1000)\n", + "y = [g1(xi) for xi in x]\n", + "plt.plot(x, y, 'r-')\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 91, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Mean: -0.01694690058429054\n", + "Variance: 1.0464121622833251\n" + ] + } + ], + "source": [ + "import numpy as np\n", + "\n", + "print(\"Mean:\", np.mean(data))\n", + "print(\"Variance:\", np.var(data))" + ] + }, + { + "cell_type": "code", + "execution_count": 92, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "\n", + "plt.hist(data, bins=30)\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "*Exercise 9:* Combine your `generate_function`, `where`, and `inrange` functions above to create an integrate function. Use your integrate function to show that approximately 68% of Normal distribution is within one variance." + ] + }, + { + "cell_type": "code", + "execution_count": 121, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "\n", + "def gaussian(mean, sigma):\n", + " def f(x):\n", + " return np.exp(-((x-mean)**2)/(2*sigma**2))/np.sqrt(2*np.pi*sigma**2)\n", + " return f\n", + "\n", + "def integrate(func, x_min, x_max, N=1000):\n", + " def generate_uniform(N, x_min, x_max):\n", + " return np.linspace(x_min, x_max, N)\n", + "\n", + " def inrange(mymin, mymax):\n", + " def testrange(x):\n", + " return x=mymin\n", + " return testrange\n", + "\n", + " def where(mylist, myfunc):\n", + " out = []\n", + " for i, x in enumerate(mylist):\n", + " if myfunc(x):\n", + " out.append(i)\n", + " return out\n", + "\n", + " x = generate_uniform(N, x_min, x_max)\n", + " y = [func(xi) for xi in x]\n", + " in_range = inrange(x_min, x_max)\n", + " valid_indices = where(x, in_range)\n", + " y = [y[i] if i in valid_indices else 0 for i in range(N)]\n", + " integral = sum(y) * (x_max - x_min) / N\n", + " return integral" + ] + }, + { + "cell_type": "code", + "execution_count": 124, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Integral within one variance: 0.6820066411696352\n" + ] + } + ], + "source": [ + "# Instantiate Gaussian function\n", + "g1 = gaussian(0, 1)\n", + "\n", + "# Calculate integral within one standard variance\n", + "integral = integrate(g1, -1, 1, N=1000)\n", + "\n", + "print(\"Integral within one variance:\", integral)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.11.8" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +}