Better Initialization
This commit is contained in:
		
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										1117
									
								
								EvolutionaryAlgorithm/EvolutionaryAlgorithm.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1117
									
								
								EvolutionaryAlgorithm/EvolutionaryAlgorithm.py
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										5386
									
								
								EvolutionaryAlgorithm/InitializationPlots.ipynb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5386
									
								
								EvolutionaryAlgorithm/InitializationPlots.ipynb
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										371
									
								
								EvolutionaryAlgorithm/InteractiveVersion.ipynb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										371
									
								
								EvolutionaryAlgorithm/InteractiveVersion.ipynb
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,371 @@ | ||||
| { | ||||
|  "cells": [ | ||||
|   { | ||||
|    "cell_type": "markdown", | ||||
|    "metadata": {}, | ||||
|    "source": [ | ||||
|     "# User Interface for the Evolutionary Algorithm" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 1, | ||||
|    "metadata": {}, | ||||
|    "outputs": [ | ||||
|     { | ||||
|      "data": { | ||||
|       "text/html": [ | ||||
|        "        <script type=\"text/javascript\">\n", | ||||
|        "        window.PlotlyConfig = {MathJaxConfig: 'local'};\n", | ||||
|        "        if (window.MathJax) {MathJax.Hub.Config({SVG: {font: \"STIX-Web\"}});}\n", | ||||
|        "        if (typeof require !== 'undefined') {\n", | ||||
|        "        require.undef(\"plotly\");\n", | ||||
|        "        requirejs.config({\n", | ||||
|        "            paths: {\n", | ||||
|        "                'plotly': ['https://cdn.plot.ly/plotly-latest.min']\n", | ||||
|        "            }\n", | ||||
|        "        });\n", | ||||
|        "        require(['plotly'], function(Plotly) {\n", | ||||
|        "            window._Plotly = Plotly;\n", | ||||
|        "        });\n", | ||||
|        "        }\n", | ||||
|        "        </script>\n", | ||||
|        "        " | ||||
|       ] | ||||
|      }, | ||||
|      "metadata": {}, | ||||
|      "output_type": "display_data" | ||||
|     }, | ||||
|     { | ||||
|      "data": { | ||||
|       "text/html": [ | ||||
|        "        <script type=\"text/javascript\">\n", | ||||
|        "        window.PlotlyConfig = {MathJaxConfig: 'local'};\n", | ||||
|        "        if (window.MathJax) {MathJax.Hub.Config({SVG: {font: \"STIX-Web\"}});}\n", | ||||
|        "        if (typeof require !== 'undefined') {\n", | ||||
|        "        require.undef(\"plotly\");\n", | ||||
|        "        requirejs.config({\n", | ||||
|        "            paths: {\n", | ||||
|        "                'plotly': ['https://cdn.plot.ly/plotly-latest.min']\n", | ||||
|        "            }\n", | ||||
|        "        });\n", | ||||
|        "        require(['plotly'], function(Plotly) {\n", | ||||
|        "            window._Plotly = Plotly;\n", | ||||
|        "        });\n", | ||||
|        "        }\n", | ||||
|        "        </script>\n", | ||||
|        "        " | ||||
|       ] | ||||
|      }, | ||||
|      "metadata": {}, | ||||
|      "output_type": "display_data" | ||||
|     }, | ||||
|     { | ||||
|      "name": "stderr", | ||||
|      "output_type": "stream", | ||||
|      "text": [ | ||||
|       "/home/jonas/Dokumente/gitRepos/master_thesis/EvolutionaryAlgorithm/EvolutionaryAlgorithm.py:58: TqdmExperimentalWarning:\n", | ||||
|       "\n", | ||||
|       "Using `tqdm.autonotebook.tqdm` in notebook mode. Use `tqdm.tqdm` instead to force console mode (e.g. in jupyter console)\n", | ||||
|       "\n" | ||||
|      ] | ||||
|     } | ||||
|    ], | ||||
|    "source": [ | ||||
|     "import EvolutionaryAlgorithm" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 2, | ||||
|    "metadata": {}, | ||||
|    "outputs": [], | ||||
|    "source": [ | ||||
|     "import ipywidgets as widgets\n", | ||||
|     "from IPython.display import display, HTML, Markdown" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 3, | ||||
|    "metadata": {}, | ||||
|    "outputs": [], | ||||
|    "source": [ | ||||
|     "# user widgets\n", | ||||
|     "w_result_out = widgets.Output()\n", | ||||
|     "w_ing_list_out = widgets.Output()" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "markdown", | ||||
|    "metadata": {}, | ||||
|    "source": [ | ||||
|     "**setup input ingredients:**" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 4, | ||||
|    "metadata": {}, | ||||
|    "outputs": [ | ||||
|     { | ||||
|      "data": { | ||||
|       "text/markdown": [ | ||||
|        "**number of input ingredients:**" | ||||
|       ], | ||||
|       "text/plain": [ | ||||
|        "<IPython.core.display.Markdown object>" | ||||
|       ] | ||||
|      }, | ||||
|      "metadata": {}, | ||||
|      "output_type": "display_data" | ||||
|     }, | ||||
|     { | ||||
|      "data": { | ||||
|       "application/vnd.jupyter.widget-view+json": { | ||||
|        "model_id": "5796ec52773740c59e747c0e5f77410e", | ||||
|        "version_major": 2, | ||||
|        "version_minor": 0 | ||||
|       }, | ||||
|       "text/plain": [ | ||||
|        "ToggleButtons(index=3, options=('1', '2', '3', '4', '5', '6', '7', '8', '9', '10'), style=ToggleButtonsStyle(b…" | ||||
|       ] | ||||
|      }, | ||||
|      "metadata": {}, | ||||
|      "output_type": "display_data" | ||||
|     }, | ||||
|     { | ||||
|      "data": { | ||||
|       "text/markdown": [ | ||||
|        "**maximum number of additional ingredients:**" | ||||
|       ], | ||||
|       "text/plain": [ | ||||
|        "<IPython.core.display.Markdown object>" | ||||
|       ] | ||||
|      }, | ||||
|      "metadata": {}, | ||||
|      "output_type": "display_data" | ||||
|     }, | ||||
|     { | ||||
|      "data": { | ||||
|       "application/vnd.jupyter.widget-view+json": { | ||||
|        "model_id": "92fd11191481475a9c40ae76201b4772", | ||||
|        "version_major": 2, | ||||
|        "version_minor": 0 | ||||
|       }, | ||||
|       "text/plain": [ | ||||
|        "ToggleButtons(index=3, options=('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'), style=ToggleButtonsStyle(bu…" | ||||
|       ] | ||||
|      }, | ||||
|      "metadata": {}, | ||||
|      "output_type": "display_data" | ||||
|     }, | ||||
|     { | ||||
|      "data": { | ||||
|       "application/vnd.jupyter.widget-view+json": { | ||||
|        "model_id": "618b5a44910843bbaed8b36c3ad2bc46", | ||||
|        "version_major": 2, | ||||
|        "version_minor": 0 | ||||
|       }, | ||||
|       "text/plain": [ | ||||
|        "Output()" | ||||
|       ] | ||||
|      }, | ||||
|      "metadata": {}, | ||||
|      "output_type": "display_data" | ||||
|     }, | ||||
|     { | ||||
|      "data": { | ||||
|       "text/markdown": [ | ||||
|        "**number of evolutionary cycles:**" | ||||
|       ], | ||||
|       "text/plain": [ | ||||
|        "<IPython.core.display.Markdown object>" | ||||
|       ] | ||||
|      }, | ||||
|      "metadata": {}, | ||||
|      "output_type": "display_data" | ||||
|     }, | ||||
|     { | ||||
|      "data": { | ||||
|       "application/vnd.jupyter.widget-view+json": { | ||||
|        "model_id": "301ebb9ed6024493ad85c2b79402345e", | ||||
|        "version_major": 2, | ||||
|        "version_minor": 0 | ||||
|       }, | ||||
|       "text/plain": [ | ||||
|        "ToggleButtons(index=1, options=('0', '5', '10', '15', '20', '25', '30', '35', '40', '45'), style=ToggleButtons…" | ||||
|       ] | ||||
|      }, | ||||
|      "metadata": {}, | ||||
|      "output_type": "display_data" | ||||
|     }, | ||||
|     { | ||||
|      "data": { | ||||
|       "text/markdown": [ | ||||
|        "**population size:**" | ||||
|       ], | ||||
|       "text/plain": [ | ||||
|        "<IPython.core.display.Markdown object>" | ||||
|       ] | ||||
|      }, | ||||
|      "metadata": {}, | ||||
|      "output_type": "display_data" | ||||
|     }, | ||||
|     { | ||||
|      "data": { | ||||
|       "application/vnd.jupyter.widget-view+json": { | ||||
|        "model_id": "c90d303cd2cb43d1aae401ac6226e3a1", | ||||
|        "version_major": 2, | ||||
|        "version_minor": 0 | ||||
|       }, | ||||
|       "text/plain": [ | ||||
|        "ToggleButtons(index=1, options=('5', '10', '15', '20', '25', '30', '35', '40', '45', '50'), style=ToggleButton…" | ||||
|       ] | ||||
|      }, | ||||
|      "metadata": {}, | ||||
|      "output_type": "display_data" | ||||
|     }, | ||||
|     { | ||||
|      "data": { | ||||
|       "application/vnd.jupyter.widget-view+json": { | ||||
|        "model_id": "cea1f9de60344298ac8417d755ad74df", | ||||
|        "version_major": 2, | ||||
|        "version_minor": 0 | ||||
|       }, | ||||
|       "text/plain": [ | ||||
|        "Button(description='run EA', style=ButtonStyle())" | ||||
|       ] | ||||
|      }, | ||||
|      "metadata": {}, | ||||
|      "output_type": "display_data" | ||||
|     }, | ||||
|     { | ||||
|      "data": { | ||||
|       "application/vnd.jupyter.widget-view+json": { | ||||
|        "model_id": "3ac8e962dfeb445fa3417dbdbfd5c44c", | ||||
|        "version_major": 2, | ||||
|        "version_minor": 0 | ||||
|       }, | ||||
|       "text/plain": [ | ||||
|        "Output()" | ||||
|       ] | ||||
|      }, | ||||
|      "metadata": {}, | ||||
|      "output_type": "display_data" | ||||
|     } | ||||
|    ], | ||||
|    "source": [ | ||||
|     "w_number_input_ings = widgets.ToggleButtons(\n", | ||||
|     "    options = [str(i+1) for i in range(10)],\n", | ||||
|     "    value='4')\n", | ||||
|     "w_number_input_ings.style.button_width=\"10px\"\n", | ||||
|     "w_number_additional_ings = widgets.ToggleButtons(options=[str(i) for i  in range(10)], value='3')\n", | ||||
|     "w_number_additional_ings.style.button_width=\"10px\"\n", | ||||
|     "\n", | ||||
|     "'''\n", | ||||
|     "containers = [\n", | ||||
|     "        widgets.Combobox(\n", | ||||
|     "            # value='John',\n", | ||||
|     "            placeholder='Choose Ingredient',\n", | ||||
|     "            options=EvolutionaryAlgorithm.m_base_mix.get_labels(),\n", | ||||
|     "            description=f'Ingredient {i}',\n", | ||||
|     "            ensure_option=True,\n", | ||||
|     "            disabled=False\n", | ||||
|     "        )\n", | ||||
|     "\n", | ||||
|     "    for i in range(10)]\n", | ||||
|     "'''\n", | ||||
|     "\n", | ||||
|     "containers = [\n", | ||||
|     "        widgets.Text(\n", | ||||
|     "            # value='John',\n", | ||||
|     "            placeholder='Choose Ingredient',\n", | ||||
|     "            description=f'Ingredient {i}',\n", | ||||
|     "            disabled=False\n", | ||||
|     "        )\n", | ||||
|     "\n", | ||||
|     "    for i in range(10)]\n", | ||||
|     "\n", | ||||
|     "ingredients = []\n", | ||||
|     "w_ing_container = widgets.VBox(ingredients)\n", | ||||
|     "\n", | ||||
|     "display(Markdown(\"**number of input ingredients:**\"))\n", | ||||
|     "display(w_number_input_ings)\n", | ||||
|     "display(Markdown(\"**maximum number of additional ingredients:**\"))\n", | ||||
|     "display(w_number_additional_ings)\n", | ||||
|     "\n", | ||||
|     "def update_ings(e=None):\n", | ||||
|     "    if len(w_ing_container.children) == int(w_number_input_ings.value):\n", | ||||
|     "        return\n", | ||||
|     "    \n", | ||||
|     "    w_ing_list_out.clear_output()\n", | ||||
|     "    with w_ing_list_out:\n", | ||||
|     "        display(widgets.VBox([containers[i] for i in range(int(w_number_input_ings.value))]))\n", | ||||
|     "\n", | ||||
|     "update_ings()\n", | ||||
|     "display(w_ing_list_out)\n", | ||||
|     "\n", | ||||
|     "# control evo cycle:\n", | ||||
|     "w_number_cycles = widgets.ToggleButtons(options=[str(i*5) for i  in range(10)], value='5')\n", | ||||
|     "w_number_cycles.style.button_width=\"10px\"\n", | ||||
|     "\n", | ||||
|     "w_population_size = widgets.ToggleButtons(options=[str((i+1)*5) for i  in range(10)], value='10')\n", | ||||
|     "w_population_size.style.button_width=\"10px\"\n", | ||||
|     "\n", | ||||
|     "display(Markdown(\"**number of evolutionary cycles:**\"))\n", | ||||
|     "display(w_number_cycles)\n", | ||||
|     "display(Markdown(\"**population size:**\"))\n", | ||||
|     "display(w_population_size)\n", | ||||
|     "\n", | ||||
|     "\n", | ||||
|     "w_run_button = widgets.Button(description=\"run EA\")\n", | ||||
|     "\n", | ||||
|     "def run(e=None):\n", | ||||
|     "    w_result_out.clear_output()\n", | ||||
|     "    with w_result_out:\n", | ||||
|     "        p = EvolutionaryAlgorithm.Population(\n", | ||||
|     "            [containers[i].value for i in range(int(w_number_input_ings.value))],\n", | ||||
|     "            max_additional_ings=int(w_number_additional_ings.value)\n", | ||||
|     "        )\n", | ||||
|     "        p.run(int(w_number_cycles.value))\n", | ||||
|     "        display(Markdown(\"**Population after running EA:**\"))\n", | ||||
|     "        p.plot_population(collect_scores=int(w_population_size.value)>0)\n", | ||||
|     "        \n", | ||||
|     "display(w_run_button)\n", | ||||
|     "display(w_result_out)\n", | ||||
|     "w_run_button.on_click(run)\n", | ||||
|     "\n", | ||||
|     "w_number_input_ings.observe(update_ings)" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": null, | ||||
|    "metadata": {}, | ||||
|    "outputs": [], | ||||
|    "source": [] | ||||
|   } | ||||
|  ], | ||||
|  "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.7.5" | ||||
|   } | ||||
|  }, | ||||
|  "nbformat": 4, | ||||
|  "nbformat_minor": 4 | ||||
| } | ||||
| @ -1,28 +1,8 @@ | ||||
| { | ||||
|  "nbformat": 4, | ||||
|  "nbformat_minor": 2, | ||||
|  "metadata": { | ||||
|   "language_info": { | ||||
|    "name": "python", | ||||
|    "codemirror_mode": { | ||||
|     "name": "ipython", | ||||
|     "version": 3 | ||||
|    } | ||||
|   }, | ||||
|   "orig_nbformat": 2, | ||||
|   "file_extension": ".py", | ||||
|   "mimetype": "text/x-python", | ||||
|   "name": "python", | ||||
|   "npconvert_exporter": "python", | ||||
|   "pygments_lexer": "ipython3", | ||||
|   "version": 3 | ||||
|  }, | ||||
|  "cells": [ | ||||
|   { | ||||
|    "cell_type": "markdown", | ||||
|    "execution_count": null, | ||||
|    "metadata": {}, | ||||
|    "outputs": [], | ||||
|    "source": [ | ||||
|     "# Statistical Tools" | ||||
|    ] | ||||
| @ -33,14 +13,13 @@ | ||||
|    "metadata": {}, | ||||
|    "outputs": [], | ||||
|    "source": [ | ||||
|     "import numpy as np" | ||||
|     "import numpy as np\n", | ||||
|     "import scipy.stats" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "markdown", | ||||
|    "execution_count": null, | ||||
|    "metadata": {}, | ||||
|    "outputs": [], | ||||
|    "source": [ | ||||
|     "* Helper function to calculate the wheel of fortune" | ||||
|    ] | ||||
| @ -61,14 +40,109 @@ | ||||
|    "metadata": {}, | ||||
|    "outputs": [], | ||||
|    "source": [ | ||||
|     "def wheel_of_fortune_selection(items: list, item_scores:list):\n", | ||||
|     "    ordering = np.argsort(item_scores)\n", | ||||
|     "    ordering = ordering + 1\n", | ||||
|     "def wheel_of_fortune_weights(items:list, item_scores:list):\n", | ||||
|     "    rank = scipy.stats.rankdata(item_scores)\n", | ||||
|     "\n", | ||||
|     "    wheel_weights = wheel_of_fortune(ordering, len(ordering))\n", | ||||
|     "    n = len(items)\n", | ||||
|     "\n", | ||||
|     "    return np.random.choice(items, p=wheel_weights)\n" | ||||
|     "    return wheel_of_fortune(rank, n)" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 4, | ||||
|    "metadata": {}, | ||||
|    "outputs": [], | ||||
|    "source": [ | ||||
|     "def wheel_of_fortune_selection(items: list, item_scores:list, num_choices=1):\n", | ||||
|     "    \n", | ||||
|     "    wheel_weights = wheel_of_fortune_weights(items, item_scores)\n", | ||||
|     "    \n", | ||||
|     "    n = min(len(items), num_choices)\n", | ||||
|     "    \n", | ||||
|     "    choice = np.random.choice(items, size=n, replace=False, p=wheel_weights)\n", | ||||
|     "    \n", | ||||
|     "    if num_choices == 1:\n", | ||||
|     "        return choice[0]\n", | ||||
|     "\n", | ||||
|     "    return choice\n" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 5, | ||||
|    "metadata": {}, | ||||
|    "outputs": [], | ||||
|    "source": [ | ||||
|     "def combined_wheel_of_fortune_selection(items_list:list, item_scores_list:list, num_choices=1):\n", | ||||
|     "    \n", | ||||
|     "    scores = {}\n", | ||||
|     "    \n", | ||||
|     "    for i in range(len(items_list)):\n", | ||||
|     "        items = items_list[i]\n", | ||||
|     "        item_scores = item_scores_list[i]\n", | ||||
|     "        \n", | ||||
|     "        w = wheel_of_fortune_weights(items, item_scores)\n", | ||||
|     "        #print(items, item_scores)\n", | ||||
|     "        #print(w)\n", | ||||
|     "        \n", | ||||
|     "        for j, item in enumerate(items):\n", | ||||
|     "            if item in scores:\n", | ||||
|     "                scores[item] += w[j]\n", | ||||
|     "            else:\n", | ||||
|     "                scores[item] = w[j]\n", | ||||
|     "        \n", | ||||
|     "    combined_items = []\n", | ||||
|     "    combined_scores = []\n", | ||||
|     "    \n", | ||||
|     "    for i,s in scores.items():\n", | ||||
|     "        combined_items.append(i)\n", | ||||
|     "        combined_scores.append(s)\n", | ||||
|     "    \n", | ||||
|     "    combined_scores = np.array(combined_scores)\n", | ||||
|     "    \n", | ||||
|     "    #print(combined_scores)\n", | ||||
|     "    #print(np.sum(combined_scores))\n", | ||||
|     "    \n", | ||||
|     "    combined_scores /= len(items_list)\n", | ||||
|     "    \n", | ||||
|     "    #print(combined_scores)\n", | ||||
|     "    \n", | ||||
|     "    #print(np.sum(combined_scores))\n", | ||||
|     "    \n", | ||||
|     "    n = min(len(combined_items), num_choices)\n", | ||||
|     "    \n", | ||||
|     "    return np.random.choice(combined_items, size=n, replace=False, p=combined_scores)\n", | ||||
|     "        \n", | ||||
|     "        " | ||||
|    ] | ||||
|   } | ||||
|  ] | ||||
|  ], | ||||
|  "metadata": { | ||||
|   "file_extension": ".py", | ||||
|   "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.5rc1" | ||||
|   }, | ||||
|   "mimetype": "text/x-python", | ||||
|   "name": "python", | ||||
|   "npconvert_exporter": "python", | ||||
|   "pygments_lexer": "ipython3", | ||||
|   "version": 3 | ||||
|  }, | ||||
|  "nbformat": 4, | ||||
|  "nbformat_minor": 4 | ||||
| } | ||||
| @ -4,6 +4,7 @@ | ||||
| # # Statistical Tools | ||||
|  | ||||
| import numpy as np | ||||
| import scipy.stats | ||||
|  | ||||
|  | ||||
| # * Helper function to calculate the wheel of fortune | ||||
| @ -12,11 +13,67 @@ def wheel_of_fortune(rank_i,n): | ||||
|     return rank_i / (0.5 * n * (n + 1)) | ||||
|  | ||||
|  | ||||
| def wheel_of_fortune_selection(items: list, item_scores:list): | ||||
|     ordering = np.argsort(item_scores) | ||||
|     ordering = ordering + 1 | ||||
| def wheel_of_fortune_weights(items:list, item_scores:list): | ||||
|     rank = scipy.stats.rankdata(item_scores) | ||||
|  | ||||
|     n = len(items) | ||||
|  | ||||
|     return wheel_of_fortune(rank, n) | ||||
|  | ||||
|  | ||||
| def wheel_of_fortune_selection(items: list, item_scores:list, num_choices=1): | ||||
|      | ||||
|     wheel_weights = wheel_of_fortune_weights(items, item_scores) | ||||
|      | ||||
|     n = min(len(items), num_choices) | ||||
|      | ||||
|     choice = np.random.choice(items, size=n, replace=False, p=wheel_weights) | ||||
|      | ||||
|     if num_choices == 1: | ||||
|         return choice[0] | ||||
|  | ||||
|     return choice | ||||
|  | ||||
|  | ||||
| def combined_wheel_of_fortune_selection(items_list:list, item_scores_list:list, num_choices=1): | ||||
|      | ||||
|     scores = {} | ||||
|      | ||||
|     for i in range(len(items_list)): | ||||
|         items = items_list[i] | ||||
|         item_scores = item_scores_list[i] | ||||
|          | ||||
|         w = wheel_of_fortune_weights(items, item_scores) | ||||
|         #print(items, item_scores) | ||||
|         #print(w) | ||||
|          | ||||
|         for j, item in enumerate(items): | ||||
|             if item in scores: | ||||
|                 scores[item] += w[j] | ||||
|             else: | ||||
|                 scores[item] = w[j] | ||||
|          | ||||
|     combined_items = [] | ||||
|     combined_scores = [] | ||||
|      | ||||
|     for i,s in scores.items(): | ||||
|         combined_items.append(i) | ||||
|         combined_scores.append(s) | ||||
|      | ||||
|     combined_scores = np.array(combined_scores) | ||||
|      | ||||
|     #print(combined_scores) | ||||
|     #print(np.sum(combined_scores)) | ||||
|      | ||||
|     combined_scores /= len(items_list) | ||||
|      | ||||
|     #print(combined_scores) | ||||
|      | ||||
|     #print(np.sum(combined_scores)) | ||||
|      | ||||
|     n = min(len(combined_items), num_choices) | ||||
|      | ||||
|     return np.random.choice(combined_items, size=n, replace=False, p=combined_scores) | ||||
|          | ||||
|     wheel_weights = wheel_of_fortune(ordering, len(ordering)) | ||||
|          | ||||
|     return np.random.choice(items, p=wheel_weights) | ||||
|  | ||||
|  | ||||
							
								
								
									
										1
									
								
								RecipeAnalysis/AdjMatrixTests.ipynb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								RecipeAnalysis/AdjMatrixTests.ipynb
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | ||||
| {"cells":[{"cell_type":"code","execution_count":1,"metadata":{},"outputs":[{"data":{"text/html":"        <script type=\"text/javascript\">\n        window.PlotlyConfig = {MathJaxConfig: 'local'};\n        if (window.MathJax) {MathJax.Hub.Config({SVG: {font: \"STIX-Web\"}});}\n        if (typeof require !== 'undefined') {\n        require.undef(\"plotly\");\n        requirejs.config({\n            paths: {\n                'plotly': ['https://cdn.plot.ly/plotly-latest.min']\n            }\n        });\n        require(['plotly'], function(Plotly) {\n            window._Plotly = Plotly;\n        });\n        }\n        </script>\n        "},"metadata":{},"output_type":"display_data"},{"data":{"text/html":"        <script type=\"text/javascript\">\n        window.PlotlyConfig = {MathJaxConfig: 'local'};\n        if (window.MathJax) {MathJax.Hub.Config({SVG: {font: \"STIX-Web\"}});}\n        if (typeof require !== 'undefined') {\n        require.undef(\"plotly\");\n        requirejs.config({\n            paths: {\n                'plotly': ['https://cdn.plot.ly/plotly-latest.min']\n            }\n        });\n        require(['plotly'], function(Plotly) {\n            window._Plotly = Plotly;\n        });\n        }\n        </script>\n        "},"metadata":{},"output_type":"display_data"}],"source":"import sys\nsys.path.append(\"../\")\n\nimport settings\n\nimport pycrfsuite\n\nimport json\n\nimport db.db_settings as db_settings\nfrom db.database_connection import DatabaseConnection\n\nfrom Tagging.conllu_generator import ConlluGenerator\nfrom Tagging.crf_data_generator import *\n\nfrom RecipeAnalysis.Recipe import Ingredient\n\nfrom difflib import SequenceMatcher\n\nimport numpy as np\n\nimport plotly.graph_objs as go\nfrom plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot\nfrom plotly.subplots import make_subplots\ninit_notebook_mode(connected=True)\n\nfrom graphviz import Digraph\n\nimport itertools\n\nimport random\n\nimport plotly.io as pio\npio.renderers.default = \"jupyterlab\"\n\nfrom IPython.display import Markdown, HTML, display\n\nfrom copy import deepcopy"},{"cell_type":"code","execution_count":2,"metadata":{},"outputs":[],"source":"import dill\nm_act = dill.load(open(\"m_act.dill\", \"rb\"))\nm_mix = dill.load(open(\"m_mix.dill\", \"rb\"))\nm_base_act = dill.load(open(\"m_base_act.dill\", \"rb\"))\nm_base_mix = dill.load(open(\"m_base_mix.dill\", \"rb\"))\n\n#m_act.apply_threshold(3)\n#m_mix.apply_threshold(3)\n#m_base_act.apply_threshold(5)\n#m_base_mix.apply_threshold(5)\n\n\n#c_act = m_act.get_csr()\n#c_mix = m_mix.get_csr()\n#c_base_act = m_base_act.get_csr()\n#c_base_mix = m_base_mix.get_csr()\n\nc_act = m_act._csr\nc_mix = m_mix._csr\nc_base_act = m_base_act._csr\nc_base_mix = m_base_mix._csr"},{"cell_type":"code","execution_count":3,"metadata":{},"outputs":[],"source":"base_ingredients = m_base_mix.get_labels()\nactions = m_act.get_labels()[0]"},{"cell_type":"markdown","execution_count":null,"metadata":{},"outputs":[],"source":"## get most used ingredients"},{"cell_type":"code","execution_count":18,"metadata":{},"outputs":[],"source":"ings = []\ning_sum = []\n\nfor ing in base_ingredients:\n    ings.append(ing)\n    ing_sum.append(m_base_mix.get_sum(ing))"},{"cell_type":"code","execution_count":20,"metadata":{},"outputs":[],"source":"ing_sort = np.argsort(-np.array(ing_sum))"},{"cell_type":"code","execution_count":23,"metadata":{},"outputs":[],"source":"w = np.array(ing_sum)[ing_sort[:20]]\ntop_ings = np.array(ings)[ing_sort[:20]]"},{"cell_type":"code","execution_count":24,"metadata":{},"outputs":[{"data":{"text/plain":"array(['salt', 'sugar', 'water', 'butter', 'onion', 'egg', 'flour',\n       'olive oil', 'milk', 'sprinkle', 'pepper', 'cream', 'garlic clove',\n       'cheese', 'tomato', 'dough', 'sauce', 'black pepper', 'roll',\n       'vanilla extract'], dtype='<U148')"},"execution_count":24,"metadata":{},"output_type":"execute_result"}],"source":"top_ings"},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":""}],"nbformat":4,"nbformat_minor":2,"metadata":{"language_info":{"name":"python","codemirror_mode":{"name":"ipython","version":3}},"orig_nbformat":2,"file_extension":".py","mimetype":"text/x-python","name":"python","npconvert_exporter":"python","pygments_lexer":"ipython3","version":3}} | ||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										355
									
								
								RecipeAnalysis/AdjacencyMatrixRefinement.ipynb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										355
									
								
								RecipeAnalysis/AdjacencyMatrixRefinement.ipynb
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,355 @@ | ||||
| { | ||||
|  "cells": [ | ||||
|   { | ||||
|    "cell_type": "markdown", | ||||
|    "metadata": {}, | ||||
|    "source": [ | ||||
|     "# Further Refinement of raw Adjacency Matrices" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 1, | ||||
|    "metadata": {}, | ||||
|    "outputs": [], | ||||
|    "source": [ | ||||
|     "import sys\n", | ||||
|     "sys.path.append(\"../\")" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 2, | ||||
|    "metadata": {}, | ||||
|    "outputs": [ | ||||
|     { | ||||
|      "name": "stderr", | ||||
|      "output_type": "stream", | ||||
|      "text": [ | ||||
|       "/home/jonas/.local/lib/python3.7/site-packages/ipykernel_launcher.py:5: TqdmExperimentalWarning: Using `tqdm.autonotebook.tqdm` in notebook mode. Use `tqdm.tqdm` instead to force console mode (e.g. in jupyter console)\n", | ||||
|       "  \"\"\"\n" | ||||
|      ] | ||||
|     }, | ||||
|     { | ||||
|      "data": { | ||||
|       "text/html": [ | ||||
|        "        <script type=\"text/javascript\">\n", | ||||
|        "        window.PlotlyConfig = {MathJaxConfig: 'local'};\n", | ||||
|        "        if (window.MathJax) {MathJax.Hub.Config({SVG: {font: \"STIX-Web\"}});}\n", | ||||
|        "        if (typeof require !== 'undefined') {\n", | ||||
|        "        require.undef(\"plotly\");\n", | ||||
|        "        requirejs.config({\n", | ||||
|        "            paths: {\n", | ||||
|        "                'plotly': ['https://cdn.plot.ly/plotly-latest.min']\n", | ||||
|        "            }\n", | ||||
|        "        });\n", | ||||
|        "        require(['plotly'], function(Plotly) {\n", | ||||
|        "            window._Plotly = Plotly;\n", | ||||
|        "        });\n", | ||||
|        "        }\n", | ||||
|        "        </script>\n", | ||||
|        "        " | ||||
|       ] | ||||
|      }, | ||||
|      "metadata": {}, | ||||
|      "output_type": "display_data" | ||||
|     } | ||||
|    ], | ||||
|    "source": [ | ||||
|     "import dill\n", | ||||
|     "import numpy as np\n", | ||||
|     "import settings\n", | ||||
|     "import AdjacencyMatrix\n", | ||||
|     "from tqdm.autonotebook import tqdm\n", | ||||
|     "from Recipe import Ingredient" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 3, | ||||
|    "metadata": {}, | ||||
|    "outputs": [], | ||||
|    "source": [ | ||||
|     "m_act = dill.load(open(\"m_act_raw.dill\", \"rb\"))\n", | ||||
|     "m_mix = dill.load(open(\"m_mix_raw.dill\", \"rb\"))\n", | ||||
|     "m_base_act = dill.load(open(\"m_base_act_raw.dill\", \"rb\"))\n", | ||||
|     "m_base_mix = dill.load(open(\"m_base_mix_raw.dill\", \"rb\"))" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "markdown", | ||||
|    "metadata": {}, | ||||
|    "source": [ | ||||
|     "## Grouping Actions" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 4, | ||||
|    "metadata": {}, | ||||
|    "outputs": [], | ||||
|    "source": [ | ||||
|     "groups = {\n", | ||||
|     "    'place':None,\n", | ||||
|     "     'heat':'heat',\n", | ||||
|     "     'cook':'heat',\n", | ||||
|     "     'bake':'heat',\n", | ||||
|     "     'grill':'heat',\n", | ||||
|     "     'melt':'heat',\n", | ||||
|     "     'blend':None,\n", | ||||
|     "     'beat':'prepare',\n", | ||||
|     "     'spread':None,\n", | ||||
|     "     'cool':'cool',\n", | ||||
|     "     'brown':'heat',\n", | ||||
|     "     'cut':'prepare',\n", | ||||
|     "     'chill':'cool',\n", | ||||
|     "     'drain':None,\n", | ||||
|     "     'boil':'heat',\n", | ||||
|     "     'simmer':'heat',\n", | ||||
|     "     'pour':None,\n", | ||||
|     "     'freeze':'cool',\n", | ||||
|     "     'saute':'heat',\n", | ||||
|     "     'rinse':'prepare',\n", | ||||
|     "     'warm':'heat',\n", | ||||
|     "     'wash':'prepare',\n", | ||||
|     "     'knead':'prepare',\n", | ||||
|     "     'peel':'prepare',\n", | ||||
|     "     'parboil':'heat',\n", | ||||
|     "     'break':'prepare',\n", | ||||
|     "     'broil':'heat',\n", | ||||
|     "     'scorch':'heat',\n", | ||||
|     "     'skim':None,\n", | ||||
|     "     'fry':'heat',\n", | ||||
|     "     'refrigerate':'cool',\n", | ||||
|     "     'burn':'heat',\n", | ||||
|     "     'thicken':None,\n", | ||||
|     "     'grate':'prepare',\n", | ||||
|     "     'brush':'prepare',\n", | ||||
|     "     'open':'prepare',\n", | ||||
|     "     'crack':'prepare',\n", | ||||
|     "     'poach':'heat',\n", | ||||
|     "     'slice':'prepare',\n", | ||||
|     "     'whisk':None,\n", | ||||
|     "     'dice':'prepare',\n", | ||||
|     "     'marinate':None,\n", | ||||
|     "     'whip':None,\n", | ||||
|     "     'sour':None,\n", | ||||
|     "     'soak':None,\n", | ||||
|     "     'steam':'heat',\n", | ||||
|     "     'chop':'prepare',\n", | ||||
|     "     'mince':None,\n", | ||||
|     "     'mash':'prepare',\n", | ||||
|     "     'squeeze':'prepare',\n", | ||||
|     "     'wipe':'prepare',\n", | ||||
|     "     'thaw':'prepare',\n", | ||||
|     "     'curdle':'heat',\n", | ||||
|     "     'sweeten':None,\n", | ||||
|     "     'baste':None,\n", | ||||
|     "     'carve':None,\n", | ||||
|     "     'grind':'prepare',\n", | ||||
|     "     'debone':'prepare',\n", | ||||
|     "     'steep':None,\n", | ||||
|     "     'clarify':None,\n", | ||||
|     "     'macerate':'prepare',\n", | ||||
|     "     'crumple':'prepare',\n", | ||||
|     "     'braise':'heat',\n", | ||||
|     "     'gut':None,\n", | ||||
|     "     'bury':None\n", | ||||
|     "}" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "markdown", | ||||
|    "metadata": {}, | ||||
|    "source": [ | ||||
|     "* now refactor the matrices to new versions that only contain those groups" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 5, | ||||
|    "metadata": {}, | ||||
|    "outputs": [], | ||||
|    "source": [ | ||||
|     "# create new matrices:\n", | ||||
|     "m_grouped_act = AdjacencyMatrix.adj_matrix()\n", | ||||
|     "m_grouped_mix = AdjacencyMatrix.adj_matrix(True)\n", | ||||
|     "m_grouped_base_act = AdjacencyMatrix.adj_matrix()\n", | ||||
|     "#m_grouped_base_mix = AdjacencyMatrix.adj_matrix(True)" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 6, | ||||
|    "metadata": {}, | ||||
|    "outputs": [ | ||||
|     { | ||||
|      "data": { | ||||
|       "application/vnd.jupyter.widget-view+json": { | ||||
|        "model_id": "2db5dd15c87740729f16f5c258707db2", | ||||
|        "version_major": 2, | ||||
|        "version_minor": 0 | ||||
|       }, | ||||
|       "text/plain": [ | ||||
|        "HBox(children=(IntProgress(value=0, max=741659), HTML(value='')))" | ||||
|       ] | ||||
|      }, | ||||
|      "metadata": {}, | ||||
|      "output_type": "display_data" | ||||
|     }, | ||||
|     { | ||||
|      "name": "stdout", | ||||
|      "output_type": "stream", | ||||
|      "text": [ | ||||
|       "\n" | ||||
|      ] | ||||
|     } | ||||
|    ], | ||||
|    "source": [ | ||||
|     "c = m_act.get_csr()\n", | ||||
|     "\n", | ||||
|     "label_acts, labels_ings = m_act.get_labels()\n", | ||||
|     "acts, ings = c.nonzero()\n", | ||||
|     "for i_act,j_ing in tqdm(zip(acts,ings), total=len(acts)):\n", | ||||
|     "    ing = Ingredient.from_json(labels_ings[j_ing])\n", | ||||
|     "    act = label_acts[i_act]\n", | ||||
|     "    \n", | ||||
|     "    grouped_ing = Ingredient(ing._base_ingredient)\n", | ||||
|     "    for a in ing._action_set:\n", | ||||
|     "        grouped_ing.apply_action(groups[a])\n", | ||||
|     "    \n", | ||||
|     "    grouped_act = groups[act]\n", | ||||
|     "    \n", | ||||
|     "    m_grouped_act.add_entry(grouped_act, grouped_ing.to_json(),1)\n", | ||||
|     "    " | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 7, | ||||
|    "metadata": {}, | ||||
|    "outputs": [ | ||||
|     { | ||||
|      "data": { | ||||
|       "application/vnd.jupyter.widget-view+json": { | ||||
|        "model_id": "1d3f802944654954a6abbf8cb70f116e", | ||||
|        "version_major": 2, | ||||
|        "version_minor": 0 | ||||
|       }, | ||||
|       "text/plain": [ | ||||
|        "HBox(children=(IntProgress(value=0, max=4472620), HTML(value='')))" | ||||
|       ] | ||||
|      }, | ||||
|      "metadata": {}, | ||||
|      "output_type": "display_data" | ||||
|     }, | ||||
|     { | ||||
|      "name": "stdout", | ||||
|      "output_type": "stream", | ||||
|      "text": [ | ||||
|       "\n" | ||||
|      ] | ||||
|     } | ||||
|    ], | ||||
|    "source": [ | ||||
|     "c = m_mix.get_csr()\n", | ||||
|     "\n", | ||||
|     "labels_ings = m_mix.get_labels()\n", | ||||
|     "ings_a, ings_b = c.nonzero()\n", | ||||
|     "for i_ing,j_ing in tqdm(zip(ings_a,ings_b), total=len(ings_a)):\n", | ||||
|     "    ing_a = Ingredient.from_json(labels_ings[i_ing])\n", | ||||
|     "    ing_b = Ingredient.from_json(labels_ings[j_ing])\n", | ||||
|     "    \n", | ||||
|     "    grouped_ing_a = Ingredient(ing_a._base_ingredient)\n", | ||||
|     "    for a in ing_a._action_set:\n", | ||||
|     "        grouped_ing_a.apply_action(groups[a])\n", | ||||
|     "    \n", | ||||
|     "    grouped_ing_b = Ingredient(ing_b._base_ingredient)\n", | ||||
|     "    for a in ing_b._action_set:\n", | ||||
|     "        grouped_ing_b.apply_action(groups[a])\n", | ||||
|     "        \n", | ||||
|     "    m_grouped_mix.add_entry(grouped_ing_a.to_json(), grouped_ing_b.to_json(),1)" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 8, | ||||
|    "metadata": {}, | ||||
|    "outputs": [ | ||||
|     { | ||||
|      "data": { | ||||
|       "application/vnd.jupyter.widget-view+json": { | ||||
|        "model_id": "92548999e3a6427bb33af20d3e53d9ef", | ||||
|        "version_major": 2, | ||||
|        "version_minor": 0 | ||||
|       }, | ||||
|       "text/plain": [ | ||||
|        "HBox(children=(IntProgress(value=0, max=114804), HTML(value='')))" | ||||
|       ] | ||||
|      }, | ||||
|      "metadata": {}, | ||||
|      "output_type": "display_data" | ||||
|     }, | ||||
|     { | ||||
|      "name": "stdout", | ||||
|      "output_type": "stream", | ||||
|      "text": [ | ||||
|       "\n" | ||||
|      ] | ||||
|     } | ||||
|    ], | ||||
|    "source": [ | ||||
|     "c = m_base_act.get_csr()\n", | ||||
|     "\n", | ||||
|     "label_acts, labels_ings = m_base_act.get_labels()\n", | ||||
|     "acts, ings = c.nonzero()\n", | ||||
|     "for i_act,j_ing in tqdm(zip(acts,ings), total=len(acts)):\n", | ||||
|     "    base_ing = labels_ings[j_ing]\n", | ||||
|     "    act = label_acts[i_act]\n", | ||||
|     "    \n", | ||||
|     "    grouped_act = groups[act]\n", | ||||
|     "    \n", | ||||
|     "    m_grouped_base_act.add_entry(grouped_act, base_ing,1)" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": 9, | ||||
|    "metadata": {}, | ||||
|    "outputs": [], | ||||
|    "source": [ | ||||
|     "dill.dump(m_grouped_act, file=open(\"m_grouped_act_raw.dill\", 'wb'))\n", | ||||
|     "dill.dump(m_grouped_mix, file=open(\"m_grouped_mix_raw.dill\", 'wb'))\n", | ||||
|     "dill.dump(m_grouped_base_act, file=open(\"m_grouped_base_act_raw.dill\", 'wb'))" | ||||
|    ] | ||||
|   }, | ||||
|   { | ||||
|    "cell_type": "code", | ||||
|    "execution_count": null, | ||||
|    "metadata": {}, | ||||
|    "outputs": [], | ||||
|    "source": [] | ||||
|   } | ||||
|  ], | ||||
|  "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.7.5" | ||||
|   } | ||||
|  }, | ||||
|  "nbformat": 4, | ||||
|  "nbformat_minor": 4 | ||||
| } | ||||
| @ -64,7 +64,7 @@ | ||||
|    "name": "python", | ||||
|    "nbconvert_exporter": "python", | ||||
|    "pygments_lexer": "ipython3", | ||||
|    "version": "3.7.3" | ||||
|    "version": "3.7.5rc1" | ||||
|   } | ||||
|  }, | ||||
|  "nbformat": 4, | ||||
|  | ||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @ -264,6 +264,8 @@ | ||||
|     "        \n", | ||||
|     "        if touch:\n", | ||||
|     "            self._last_touched_instruction = instruction_number\n", | ||||
|     "        \n", | ||||
|     "        return self\n", | ||||
|     "    \n", | ||||
|     "    def similarity(self, ingredient, use_actions=False, action_factor = 0.5):\n", | ||||
|     "        sim,_,_ = string_similarity(self._base_ingredient, ingredient._base_ingredient)\n", | ||||
| @ -1434,7 +1436,7 @@ | ||||
|    "name": "python", | ||||
|    "nbconvert_exporter": "python", | ||||
|    "pygments_lexer": "ipython3", | ||||
|    "version": "3.7.3" | ||||
|    "version": "3.7.5" | ||||
|   } | ||||
|  }, | ||||
|  "nbformat": 4, | ||||
|  | ||||
| @ -161,6 +161,8 @@ class Ingredient(object): | ||||
|         if touch: | ||||
|             self._last_touched_instruction = instruction_number | ||||
|          | ||||
|         return self | ||||
|      | ||||
|     def similarity(self, ingredient, use_actions=False, action_factor = 0.5): | ||||
|         sim,_,_ = string_similarity(self._base_ingredient, ingredient._base_ingredient) | ||||
|         if not use_actions: | ||||
|  | ||||
		Reference in New Issue
	
	Block a user