{ "nbformat": 4, "nbformat_minor": 0, "metadata": { "colab": { "provenance": [] }, "kernelspec": { "name": "python3", "language": "python", "display_name": "Python 3 (ipykernel)" }, "language_info": { "name": "python" } }, "cells": [ { "cell_type": "markdown", "source": [ "# Nasty Factorial! Assessing the complexity of an ordering problem\n", "## Try me\n", "[![Open In Colab](../../_static/colabs_badge.png)](https://colab.research.google.com/github/ffraile/operations-research-notebooks/blob/main/docs/source/MIP/tutorials/Nasty_factorial.ipynb)[![Binder](../../_static/binder_badge.png)](https://mybinder.org/v2/gh/ffraile/operations-research-notebooks/main?labpath=docs%2Fsource%2FMIP%2Ftutorials%2FNasty_factorial.ipynb)\n", "\n", "## Problem definition\n", "Ordering is not as simple as it seems. Ordering an array of length N implies finding the right sequence of elements out of N! possible sequences. The exclamation mark is the factorial operator, and this makes the size of the problem increase really fast with N.\n", "To illustrate how fast, just try this script, it will represent the number of possible orderings of a set of N elements for N from 1 to 10:" ], "metadata": { "id": "ioUz1baeykn_" } }, { "cell_type": "code", "execution_count": 3, "outputs": [ { "data": { "text/plain": "interactive(children=(IntSlider(value=5, description='set_size', max=10, min=1), Output(layout=Layout(height='…", "application/vnd.jupyter.widget-view+json": { "version_major": 2, "version_minor": 0, "model_id": "54b0fc2054814b32b5964c913a4bce31" } }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import numpy as np\n", "from scipy.special import factorial\n", "from matplotlib import pyplot as plt\n", "from datetime import datetime\n", "import ipywidgets as widgets\n", "from ipywidgets import interactive\n", "#We set the mode inline of matplotlib to get the result at the output of the cell code\n", "%matplotlib inline\n", "\n", "# Plot the number of possible orderings of a set of N elements (set_size = N)\n", "def plot_factorial(set_size):\n", " x = np.arange(1, set_size + 1)\n", " y = factorial(x)\n", " plt.plot(x,y)\n", " plt.xlabel(\"N\")\n", " plt.ylabel(\"N!\")\n", " plt.title(\"Number of possible orderings of a set of N elements\")\n", " plt.show()\n", "\n", "interactive_plot = interactive(plot_factorial, set_size=(1, 100, 1))\n", "output = interactive_plot.children[-1]\n", "output.layout.height = '350px'\n", "interactive_plot\n" ], "metadata": { "collapsed": false, "ExecuteTime": { "end_time": "2024-01-11T19:37:11.265383300Z", "start_time": "2024-01-11T19:37:10.140802Z" } } }, { "cell_type": "markdown", "source": [ "## Complexity\n", "### Assessing the complexity of the problem\n", "Informally, *complexity* relates to how complex it is to solve a problem. Conceptually, this can be estimated by the number of operations that the computer has to do find a solution. We can assume that in a computer, the time used to do an operation is more or less constant, so we are going to estimate the complexity by measuring the time used to solve the problem. To do this, we are going to use the ```datetime``` library of Python. This library allows us to take a reference of the time at the beginning of the execution of a piece of code and another reference at the end of the execution. The difference between the two references is the time used to execute the code.\n", "\n", "Let us see this in action using the library Numpy. First, using the function np.random.shuffle() we are going to generate a random ordering of an array of numbers. Then, we will use the function np.sort() to order the array, and using the ```datetime```function as described above, we are going to measure the time used to sort the array with np.sort():" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "source": [ "N = 10\n", "# Let's generate an array of 10 numbers\n", "x = np.arange(0,N)\n", "# Let's change the order of the numbers randomly\n", "np.random.shuffle(x)\n", "#print(x)\n", "#now, Let's take a reference of the time before sorting\n", "init_time = datetime.now()\n", "# Let's sort, note that the right ordering sequence is 1 out of n!\n", "y = np.sort(x)\n", "#Let's take another reference of the time after sorting and measure the\n", "#difference in seconds:\n", "end_time = datetime.now()\n", "duration = end_time - init_time\n", "print(f\"all righty, i ordered the array in {duration.microseconds} microseconds\")\n", "# print(y)" ], "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "KIACh89Qto0p", "outputId": "dce78794-36b3-4be6-fc40-505dad3b160e", "ExecuteTime": { "end_time": "2024-01-11T19:38:43.571452100Z", "start_time": "2024-01-11T19:38:43.547422400Z" } }, "execution_count": 4, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "all righty, i ordered the array in 0 microseconds\n" ] } ] }, { "cell_type": "markdown", "source": [ "Note that, in the result saved in the notebook, it only took a fraction of a second to order an array of 10 numbers! Ok, but what happens if we increase the size of the problem? Let's use the same function to generate arrays of different sizes and measure how the time used to order them increases with the size of the problem:" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "source": [ "# Let's generate an array of different sizes\n", "n = [10, 100, 1000, 100000]\n", "#Init the computing time\n", "computing_time = np.zeros(len(n))\n", "\n", "# Do the steps in the scripts above for every size in the array n\n", "for i in range(len(n)):\n", " arr_length=n[i]\n", " x_arr = np.arange(0,arr_length)\n", " np.random.shuffle(x_arr)\n", " init_time = datetime.now()\n", " np.sort(x_arr)\n", " end_time = datetime.now()\n", " duration = end_time - init_time\n", " computing_time[i] = duration.microseconds\n", "\n", "#Plot the results\n", "plt.plot(n, computing_time)\n", "plt.xlabel(\"N\")\n", "plt.ylabel(\"Computing time (microseconds)\")" ], "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 282 }, "id": "xKwn6f3Vv-jk", "outputId": "e68ca8ca-2ab7-49e6-ac8a-0dd5ab9eed19", "ExecuteTime": { "end_time": "2024-01-11T19:53:01.397142800Z", "start_time": "2024-01-11T19:53:01.261047200Z" } }, "execution_count": 8, "outputs": [ { "data": { "text/plain": "Text(0, 0.5, 'Computing time (microseconds)')" }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": "
", "image/png": "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\n" }, "metadata": {}, "output_type": "display_data" } ] }, { "cell_type": "markdown", "source": [ "This simple script shows that the time needed by the sorting algorithm used by Numpy can be approximated to a **linear function** of the size of the set N. This is a very efficient algorithm!\n", "\n", "It is not only efficient, also mesmerizing, in the following video you can see it in action:\n", "\n", "[![Sorting algorithms](http://img.youtube.com/vi/kPRA0W1kECg/0.jpg)](http://www.youtube.com/watch?v=kPRA0W1kECg \"Sorting algorithms\")\n", "\n", "We can agree that this problem is not complex, because we have an algorithm that solves it easily. But what would happen if we did not have this algorithm at hand? Imagine that we have to try for instance all the possible orderings of an array of numbers to find the right one. This is called **brute force**. How many operations would we have to do? Let's try to estimate it.\n", "\n", "## Assessing the complexity without an algorithm\n", "Let us assume, that we could generate an ordering and check it, really fast, in one microsecond.\n", "\n", "How many orderings would we have to check? Well, we have N! possible orderings, so we would have to do N! operations. We can use the following script to estimate the computing time needed to solve the problem using brute force, and compare it with the computing time needed by the sorting algorithm of Numpy:\n" ], "metadata": { "id": "hgvmJMn-zgOy" } }, { "cell_type": "code", "execution_count": 6, "outputs": [ { "data": { "text/plain": "" }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": "
", "image/png": "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UlKUkpKi+Ph4FStWTJ07d77hZ65cuVJI6f7n119/1d13362KFSsqKCgoX+u4fPmyY0O5MYoKAKBQ+Pj4KCQkRCEhIapfv74GDx6so0eP6syZM5KkQ4cOyWKxaMmSJWrZsqV8fX21aNEivfHGG6pfv77duqZPn67w8HBJ0htvvKGFCxfq888/t83YJCQkSJKOHj2qhx56SEFBQSpdurS6deumQ4cO5Zrv2vZ///139enTRxaLxTaj8t1336lx48by8fFRaGioBg8erKtXr9o+26pVK/Xv318vvviiypYta7vz7H//+1917txZAQEB8vf3V/PmzfXrr7/aPjdv3jxFRkbK19dXNWvW1Ntvv33zO/oWwy30AaAoMwzpSoZztu1VXLJY8vXR9PR0ffTRR6pWrZrKlClj997gwYM1ZcoURUdHy9fXV++8884N1zVo0CDt2bNHaWlpmj9/viSpdOnSunLlitq1a6cmTZpow4YNKlasmMaMGWM75OTt7W23HqvVqpSUFNWoUUOjRo3Sww8/rMDAQB0/flwdO3ZU79699cEHH2jv3r3q27evfH199cYbb9g+v3DhQj377LO22/AfP35cLVq0UKtWrbRu3ToFBARo06ZNtoKzaNEijRgxQjNnzlR0dLS2bdumvn37qkSJEurVq1e+9uutiKICAEXZlQxpXJhztj30hORdIs+Lf/XVVypZsqQk6Y8//lBoaKi++uoreXjYT+6/+OKLuv/++/O83pIlS8rPz0+ZmZkKCQmxjX/00UfKzs7WvHnzZPn/hWr+/PkKCgpSQkKC2rZta7ceT09PhYSEyGKxKDAw0Laut99+W1arVTNnzpTFYlHNmjV14sQJvfbaaxoxYoQt/2233aZJkyb9b/cMHarAwEDFxcXZHjhYvXp12/uxsbGaMmWK7XeNiIjQ7t279c4771BU/oKiAgAoFHfddZdmz54tSTp37pzefvttdejQQYmJiapcubJtuUaNGjlkez///LMOHDggf39/u/FLly7ZHX75J3v27FGTJk1sZUeSmjVrpvT0dB07dkyVKlWSJDVs2NDuc9u3b1fz5s1zfSryH3/8oV9//VVPPPGE+vbtaxu/evWqAgMD85zNHVBUAKAo8yr+58yGs7ZtQokSJVStWjXb63nz5ikwMFBz587VmDFj7Jb7Kw8PDxmGYTeWl5Ns09PT1bBh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hYWF6fDhw5KkadOm6fPPP3doOAAA4N5MF5XZs2dr4MCB6tChg86dO6esrCxJUqlSpTR9+nRH5wMAAG7MdFGZMWOG5s6dq2HDhtldjtyoUSPt3LnToeEAAIB7M11UkpOTbVf7/JWPj4/++OMPh4QCAACQ8lFUIiIitH379hzjq1atUmRkpCMyAQAASMrHVT8DBw5Uv379dOnSJRmGocTERC1evFjjx4/XvHnzCiIjAABwU6aLypNPPik/Pz+9/vrrysjIUI8ePRQWFqY333xT3bt3L4iMAADATeXrPioxMTGKiYlRRkaG0tPTVb58eUfnAgAAMH+OysWLF5WRkSFJKl68uC5evKjp06drzZo1Dg8HAADcm+mi0q1bN33wwQeS/nwYYePGjTVlyhR169ZNs2fPdnhAAADgvkwXla1bt6p58+aSpE8//VQhISE6fPiwPvjgA7311lsODwgAANyX6aKSkZEhf39/SdKaNWt0//33y8PDQ//6179st9M34/jx43r00UdVpkwZ+fn5KSoqSj/99JPp9QAAgFuP6aJSrVo1rVixQkePHtXq1avVtm1bSdLp06cVEBBgal3nzp1Ts2bN5OXlpa+//lq7d+/WlClTVKpUKbOxAADALcj0VT8jRoxQjx499NJLL+nuu+9WkyZNJP05u5LbHWtvZOLEibJarZo/f75tLCIiwmwkAABwizI9o/Lvf/9bR44c0U8//aTVq1fbxu+55x5NmzbN1Lq++OILNWrUSA8++KDKly+v6OhozZ0712wkAABwi8rXfVRCQkIUEhKiY8eOSZIqVqyoxo0bm17PwYMHbU9jHjp0qJKSkjRgwAB5e3urV69eOZbPzMxUZmam7XVaWlp+4gMAgCLC9IxKdna2Ro0apcDAQFWuXFmVK1dWUFCQRo8erezsbNPratCggcaNG6fo6Gg99dRT6tu3r+bMmZPr8uPHj1dgYKDtx2q1mo0PAACKENNFZdiwYZo5c6YmTJigbdu2adu2bRo3bpxmzJih4cOHm1pXaGioatWqZTcWGRmpI0eO5Lr8kCFDdP78edvP0aNHzcbPG8MomPUCAABTTB/6WbhwoebNm6euXbvaxurWrasKFSroueee09ixY/O8rmbNmmnfvn12Y/v371flypVzXd7Hx0c+Pj5mI+efxVJ42wIAADmYnlE5e/asatasmWO8Zs2aOnv2rKl1vfTSS/rhhx80btw4HThwQB9//LHeffdd9evXz2wsAABwCzJdVOrVq6eZM2fmGJ85c6bq1atnal233367PvvsMy1evFh16tTR6NGjNX36dMXExJiNBQAAbkGmD/1MmjRJnTp10tq1a233UNm8ebOOHj2qlStXmg7QuXNnde7c2fTnAADArc/0jErLli21f/9+3XfffUpNTVVqaqruv/9+7du3z/YMIAAAAEcwNaNy5coVtW/fXnPmzDF10iwAAEB+mJpR8fLy0o4dOwoqCwAAgB3Th34effRRvffeewWRBQAAwI7pk2mvXr2q999/X2vXrlXDhg1VokQJu/enTp3qsHAAAMC9mS4qu3btUoMGDST9eXO2v7JwgzQAAOBApovKt99+WxA5AAAAcjB9jsr58+dzvQPt2bNneZoxAABwKNNFpXv37oqLi8sx/sknn6h79+4OCQUAACDlo6j8+OOPuuuuu3KMt2rVSj/++KNDQgEAAEj5KCqZmZm6evVqjvErV67o4sWLDgkFAAAg5aOoNG7cWO+++26O8Tlz5qhhw4YOCQUAACDl46qfMWPGqHXr1vr55591zz33SJLi4+OVlJSkNWvWODwgAABwX6ZnVJo1a6bNmzfLarXqk08+0Zdffqlq1appx44dPJQQAAA4lOkZFUmqX7++Fi1a5OgsAAAAdvJUVNLS0hQQEGD7841cWw4AAOBm5amolCpVSikpKSpfvryCgoJyvVW+YRiyWCzKyspyeEgAAOCe8lRU1q1bp9KlS0viFvoAAKDw5KmotGzZMtc/AwAAFKR8nUx76dIl7dixQ6dPn1Z2drbde127dnVIMAAAANNFZdWqVerZs6d+++23HO9xjgoAAHAk0/dRef755/Xggw8qJSVF2dnZdj+UFAAA4Eimi8qpU6c0cOBABQcHF0QeAAAAG9NF5d///rcSEhIKIAoAAIA90+eozJw5Uw8++KA2bNigqKgoeXl52b0/YMAAh4UDAADuzXRRWbx4sdasWSNfX18lJCTY3fzNYrFQVAAAgMOYLirDhg3TyJEjNXjwYHl4mD5yVEQYzg4AAACUj3NULl++rIcffvgWLil/lfNRAQAAoPCYbhu9evXSkiVLCiILAACAHdOHfrKysjRp0iStXr1adevWzXEy7dSpUx0WDgAAuDfTRWXnzp2Kjo6WJO3atcvu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6UM/gwYNUqdOnVS1alXVqlVLXl5edu8vX77cYeEAAIB7M11UBgwYoG+//VZ33XWXypQpwwm0AACgwJguKgsXLtSyZcvUqVOngsgDAABgY/ocldKlS6tq1aoFkQUAAMCO6aLyxhtvKDY2VhkZGQWRBwAAwMb0oZ+33npLv/76q4KDgxUeHp7jZNqtW7fmeV3jx4/X8uXLtXfvXvn5+alp06aaOHGiatSoYTYWAAC4BZkuKvfee6/DNv7dd9+pX79+uv3223X16lUNHTpUbdu21e7du1WiRAmHbQcAABRNpotKbGyswza+atUqu9cLFixQ+fLltWXLFrVo0cJh2wEAAEVTvh5KKElbtmzRnj17JEm1a9dWdHT0TYc5f/68pD9P2AUAADBdVE6fPq3u3bsrISFBQUFBkqTU1FTdddddiouLU7ly5fIVJDs7Wy+++KKaNWumOnXq5LpMZmamMjMzba/T0tLytS0AAFA0mL7q5/nnn9eFCxf03//+V2fPntXZs2e1a9cupaWlacCAAfkO0q9fP+3atUtxcXHXXWb8+PEKDAy0/Vit1nxvDwAAuD6LYRiGmQ8EBgZq7dq1uv322+3GExMT1bZtW6WmppoO0b9/f33++edav369IiIirrtcbjMqVqtV58+fV0BAgOntXteu5dKnj0vhzaXeXzluvQAAQGlpaQoMDMzT97fpQz/Z2dk5LkmWJC8vL2VnZ5tal2EYev755/XZZ58pISHhhiVFknx8fOTj42NqGwAAoOgyfejn7rvv1gsvvKATJ07Yxo4fP66XXnpJ99xzj6l19evXTx999JE+/vhj+fv76+TJkzp58qQuXrxoNhYAALgFmS4qM2fOVFpamsLDw1W1alVVrVpVERERSktL04wZM0yta/bs2Tp//rxatWql0NBQ28+SJUvMxgIAALcg04d+rFartm7dqrVr12rv3r2SpMjISLVu3dr0xk2eHgMAANxMvu6jYrFY1KZNG7Vp08bReQAAAGzyfOhn3bp1qlWrVq73Ljl//rxq166tDRs2ODQcAABwb3kuKtOnT1ffvn1zvYwoMDBQTz/9tKZOnerQcAAAwL3luaj8/PPPat++/XXfb9u2rbZs2eKQUAAAAJKJonLq1Klc759yTbFixXTmzBmHhAIAAJBMFJUKFSpo165d131/x44dCg0NdUgo5+NqJAAAXEGe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\n" }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Let's calculate the factorial of N\n", "N_factorial = factorial(n)\n", "\n", "# Since it is in microseconds, we can compare it with the computing time in microseconds obtained before:\n", "\n", "plt.plot(n, computing_time, label=\"Sorting algorithm\")\n", "plt.plot(n, N_factorial, label=\"Brute force\")\n", "plt.xlabel(\"N\")\n", "plt.ylabel(\"Computing time (microseconds)\")\n", "plt.legend()\n" ], "metadata": { "collapsed": false, "ExecuteTime": { "end_time": "2024-01-11T19:51:50.053006300Z", "start_time": "2024-01-11T19:51:49.909239600Z" } } }, { "cell_type": "markdown", "source": [ "Wow, what happened here? The time needed to solve the problem using brute force is so big that it is not even visible in the plot! This is because the factorial function grows so fast that it is not possible to represent it in a number in Python. By comparison, the time needed by the sorting algorithm is negligible. We could try to plot in a log scale to see the difference:\n" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": 7, "outputs": [ { "data": { "text/plain": "
", "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkYAAAG1CAYAAAAcMztGAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8g+/7EAAAACXBIWXMAAA9hAAAPYQGoP6dpAABXuElEQVR4nO3deVxU5f4H8M/MsAmyioLI6poogoKglgpKEpbrrfReS9TCbjeX4tpNWiT9lZSZUUp501wqSzK72q20rijhViiGS+6KisimCCOgLDPz+2NgcmJxDszMmRk+79drXnPmOWfOfDjNy/l2nuecR6JSqVQgIiIiIkjFDkBERERkKlgYEREREdVjYURERERUj4URERERUT0WRkRERET1WBgRERER1WNhRERERFSPhRERERFRPSuxA5gbpVKJa9euwdHRERKJROw4REREpAOVSoVbt27By8sLUmnz54VYGAl07do1+Pj4iB2DiIiIWiEvLw/e3t7NrmdhJJCjoyMA9YF1cnISOQ0RERHpQi6Xw8fHR/M73hwWRgI1dJ85OTmxMCIiIjIz9xoGw8HXRERERPVYGBERERHVY1caERHpRKFQoLa2VuwYRE2ytraGTCZr835YGBERUYtUKhUKCwtRVlYmdhSiFrm4uMDT07NNt9NhYURERC1qKIq6dOkCe3t73sONTI5KpUJVVRWKi4sBAF27dm31vlgYERFRsxQKhaYo6tSpk9hxiJrVoUMHAEBxcTG6dOnS6m41Dr4mIqJmNYwpsre3FzkJ0b01fE/bMhaOhREREd0Tu8/IHOjje8rCiIiIiKgeCyMiIiKieiyMiIiI9CAjIwMSicQkbmsQGRmJ559/3mQ+a8OGDXBxcTFKnrZiYURERBappKQEzz77LHx9fWFrawtPT0/ExMRg//79bd53U8XAsGHDUFBQAGdn5zbv35x88803+L//+z/Na39/f6SkpIgXqI14uT61L9dygG/nAoHjgREvip2GiAzoL3/5C2pqarBx40Z0794dRUVFSE9Px40bN1q9z5qaGtjY2DS5zsbGBp6enq3et7lpOBZubm5iR9ErnjGi9uVCOlB4DMj/TewkRGZLpVKhqqZOlIdKpdIpY1lZGfbu3Yu3334bUVFR8PPzQ3h4OBITEzF+/HjNdleuXMGECRPQsWNHODk54fHHH0dRUZFm/euvv46Q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\n" }, "metadata": {}, "output_type": "display_data" } ], "source": [ "plt.plot(n, computing_time, label=\"Sorting algorithm\")\n", "plt.plot(n, N_factorial, label=\"Brute force\")\n", "plt.xlabel(\"N\")\n", "plt.ylabel(\"Computing time (microseconds)\")\n", "plt.legend()\n", "plt.yscale(\"log\")\n", "plt.xscale(\"log\")\n" ], "metadata": { "collapsed": false, "ExecuteTime": { "end_time": "2024-01-11T19:55:09.060261700Z", "start_time": "2024-01-11T19:55:08.656144500Z" } } }, { "cell_type": "markdown", "source": [ "Wow, it is still impossible to visualize both functions in the same plot! Now in log scale, the brute force solution is a straight line, and the sorting algorithm is more or less constant. This means that the time needed by the brute force algorithm grows **exponentially** with the size of the problem. Since the time needed by the sorting algorithm increases **linearly** with the size of the array to sort, we can conclude that the algorithm is very efficient. In fact, every algorithm that has a complexity that grows slower than any polynomial is considered efficient, and it is called a **polynomial algorithm**. In this case, the sorting algorithm is a **linear algorithm**, and sorting an array of is a **polynomial** (or class P) problem.\n" ], "metadata": { "collapsed": false } }, { "cell_type": "markdown", "source": [ "## Analysis questions\n", "Try to answer the following **analysis questions**. You can use AI assistant to help you, but try to answer them by yourself first and analyze critically the answers given by the AI assistant.\n", "\n", "1. How many microseconds have you lived? Try to find an estimate of the number of microseconds you have lived, and express it as a factorial number. Based on the results of the previous section, what is the largest array you could sort using brute force in your whole life (assuming that you can check an ordering in one microsecond)?\n", "\n", "\n", "\n", "2. Repeat the previous exercise, but now think of the number of microseconds that have passed since the big bang. What is the largest array you could sort using brute force since the big bang (also assuming that you can check an ordering in one microsecond?\n", "\n", "\n", "3. The experiments above might not be accurate, because we provided too few values of N. Modify this line of code ```n = [10, 100, 1000, 100000]``` to include more values of N, and repeat the analysis. What do you observe?\n", "\n", "\n", "4. Note that the time needed by the sorting algorithm might not be exactly constant. Why would you modify the script to deal with this issue?\n", "\n" ], "metadata": { "collapsed": false } } ] }