From 5903c9036db11ba158d44ee1033980055b8257f4 Mon Sep 17 00:00:00 2001 From: Jonas Weinz Date: Sun, 19 Jan 2020 20:55:27 +0100 Subject: [PATCH] better stabilized score mechanisms --- Evaluation/GeneratedRecipes.ipynb | 366 + .../EvolutionaryAlgorithm.ipynb | 6639 +++++++++++++---- .../EvolutionaryAlgorithm.py | 874 ++- 3 files changed, 5994 insertions(+), 1885 deletions(-) create mode 100644 Evaluation/GeneratedRecipes.ipynb diff --git a/Evaluation/GeneratedRecipes.ipynb b/Evaluation/GeneratedRecipes.ipynb new file mode 100644 index 0000000..77893bf --- /dev/null +++ b/Evaluation/GeneratedRecipes.ipynb @@ -0,0 +1,366 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Generated Recipes for evaluation" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "import sys\n", + "sys.path.append(\"../\")\n", + "sys.path.append(\"../EvolutionaryAlgorithm/\")" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "import EvolutionaryAlgorithm as EA" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Noodle recipes\n", + "* generate noodle recipes with a population size of 50 over 50 cycles and choose randomly 5 from the 20 best" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "p = EA.Population([\"noodle\"],['noodle'], min_additional=4, max_additional=13, n_population = 50)\n", + "\n", + "p.run(50)\n", + "\n", + "samples = EA.np.random.choice(p.population[:10], 5)\n", + "\n", + "for i, s in enumerate(samples):\n", + " display(EA.Markdown(f\"### Noodle Recipe {i+1}\"))\n", + " display(s.root().to_instruction().to_markdown())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Rice recipes\n", + "* generate noodle recipes with a population size of 50 over 50 cycles and choose randomly 5 from the 20 best" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "791ec7b41eb94717b800e114d9f56861", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "HBox(children=(FloatProgress(value=0.0, description='build initial population', max=50.0, style=ProgressStyle(…" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "da397fc1a8cf4cc9b760f9c000351682", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "HBox(children=(FloatProgress(value=0.0, description='run evolutionary cycles', max=50.0, style=ProgressStyle(d…" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n" + ] + }, + { + "data": { + "text/markdown": [ + "### Rice Recipe 1" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Ingredients**:\n", + " * rice\n", + " * olive oil\n", + " * chicken broth\n", + " * celery\n", + " * mushroom soup\n", + "\n", + "\n", + "**Instructions**:\n", + "\n", + "| Step | Instruction |\n", + "| ----:|:----------- |\n", + "| 1 | chop celery and mix it with chicken broth and mushroom soup. Then simmer it. |\n", + "| 2 | Mix rice and olive oil. Then warm it. |\n", + "| 3 | Mix together the results of step 1 and step 2. |\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "### Rice Recipe 2" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Ingredients**:\n", + " * soy sauce\n", + " * spinach\n", + " * garlic\n", + " * rice\n", + " * olive oil\n", + " * onion\n", + " * clove garlic\n", + " * chicken\n", + " * red kidney bean\n", + " * tomato\n", + " * celery\n", + " * cheese\n", + " * mushroom soup\n", + "\n", + "\n", + "**Instructions**:\n", + "\n", + "| Step | Instruction |\n", + "| ----:|:----------- |\n", + "| 1 | heat and simmer clove garlic |\n", + "| 2 | cut and cut tomato |\n", + "| 3 | wash chicken, grate onion, cut celery, chop spinach, slice olive oil and mix it with garlic, soy sauce, rice, red kidney bean and mushroom soup and mix it together with the results of step 1 and step 2. Then cook it. |\n", + "| 4 | grate cheese and mix it together with the results of step 3. |\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "### Rice Recipe 3" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Ingredients**:\n", + " * green pea\n", + " * rice\n", + " * water\n", + " * olive oil\n", + " * onion\n", + " * chicken broth\n", + " * clove garlic\n", + " * chicken\n", + " * chicken soup\n", + " * pepper\n", + " * ground beef\n", + "\n", + "\n", + "**Instructions**:\n", + "\n", + "| Step | Instruction |\n", + "| ----:|:----------- |\n", + "| 1 | saute and slice olive oil |\n", + "| 2 | boil and heat clove garlic |\n", + "| 3 | pour chicken soup, pour chicken broth, grate onion, brown rice, chop chicken and mix it with ground beef, water, pepper and green pea and mix it together with the results of step 1 and step 2. Then heat it. |\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "### Rice Recipe 4" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Ingredients**:\n", + " * green pea\n", + " * corn\n", + " * garlic\n", + " * rice\n", + " * olive oil\n", + " * sprout\n", + " * onion\n", + " * chicken broth\n", + " * clove garlic\n", + " * pepper\n", + " * ground beef\n", + "\n", + "\n", + "**Instructions**:\n", + "\n", + "| Step | Instruction |\n", + "| ----:|:----------- |\n", + "| 1 | grate onion, chop clove garlic, cook chicken broth, heat corn and mix it with olive oil. Then simmer it. |\n", + "| 2 | chop garlic, refrigerate rice and mix it with sprout, ground beef, pepper and green pea and mix it together with the results of step 1. Then heat it. |\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "### Rice Recipe 5" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Ingredients**:\n", + " * green pea\n", + " * garlic\n", + " * rice\n", + " * water\n", + " * olive oil\n", + " * onion\n", + " * chicken broth\n", + " * clove garlic\n", + " * chicken\n", + " * pepper\n", + " * ground beef\n", + "\n", + "\n", + "**Instructions**:\n", + "\n", + "| Step | Instruction |\n", + "| ----:|:----------- |\n", + "| 1 | grate onion, chop chicken, place chicken broth, warm water, heat garlic and mix it with green pea, clove garlic, rice, olive oil, pepper and ground beef. Then heat it. |\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "p = EA.Population([\"rice\"],['rice'], min_additional=4, max_additional=13, n_population = 50)\n", + "\n", + "p.run(50)\n", + "\n", + "samples = EA.np.random.choice(p.population[:10], 5)\n", + "\n", + "for i, s in enumerate(samples):\n", + " display(EA.Markdown(f\"### Rice Recipe {i+1}\"))\n", + " display(s.root().to_instruction().to_markdown())" + ] + }, + { + "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 +} diff --git a/EvolutionaryAlgorithm/EvolutionaryAlgorithm.ipynb b/EvolutionaryAlgorithm/EvolutionaryAlgorithm.ipynb index 9073b22..d5bea7b 100644 --- a/EvolutionaryAlgorithm/EvolutionaryAlgorithm.ipynb +++ b/EvolutionaryAlgorithm/EvolutionaryAlgorithm.ipynb @@ -488,7 +488,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 219, "metadata": {}, "outputs": [], "source": [ @@ -499,8 +499,15 @@ "HEAT_SCORE_EPS = 0.1\n", "\n", "def prepare_ratio(ing:str):\n", - " keys, values = m_grouped_act.get_backward_adjacent(Ingredient(ing).to_json())\n", + " try:\n", + " keys, values = m_grouped_act.get_backward_adjacent(Ingredient(ing).to_json())\n", + " except KeyError:\n", + " return 0\n", " action_dict = dict(zip(keys,values))\n", + " if 'prepare' not in action_dict:\n", + " return 0\n", + " if 'heat' not in action_dict:\n", + " return 1\n", " return action_dict['prepare'] / action_dict['heat']\n", "\n", "def random_prepare(ing:str):\n", @@ -511,8 +518,17 @@ " return prepare_ratio(ing) > np.random.normal(PREPARE_RATIO_THRESHOLD,0.1)\n", "\n", "def heat_ratio(ingredient:str):\n", - " action_set, action_weights = m_grouped_base_act.get_backward_adjacent(ingredient)\n", + " try:\n", + " action_set, action_weights = m_grouped_base_act.get_backward_adjacent(ingredient)\n", + " except KeyError:\n", + " return 0\n", " d = dict(zip(action_set, action_weights))\n", + " \n", + " if 'prepare' not in d:\n", + " return 1\n", + " if 'heat' not in d:\n", + " return 0\n", + " \n", " ratio = 1 - d['prepare'] / d['heat']\n", " \n", " return ratio\n", @@ -698,7 +714,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 196, "metadata": {}, "outputs": [], "source": [ @@ -830,9 +846,14 @@ " ing = random.choice(ings)\n", " \n", " a, w = get_backward_adjacent(ing._base_ingredient, m_base_act, c_base_act)\n", + " \n", + " if len(a) > 0:\n", " \n", - " action = random.choices(a, w)[0]\n", - " self.insert_before(ActionNode(action))\n", + " action = ea_tools.wheel_of_fortune_selection(a,w)\n", + " self.insert_before(ActionNode(action))\n", + " \n", + " else:\n", + " print(\"Warning: cannot find matching action node for mutation\")\n", " \n", " def mutate_node(self):\n", " raise NotImplementedError\n", @@ -909,7 +930,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 197, "metadata": {}, "outputs": [], "source": [ @@ -1083,7 +1104,7 @@ " text = \"Mix \" + english_enum([state.text_by_nodeid[c._id] for c in ingredient_childs])\n", " \n", " if len(instruction_childs) > 0:\n", - " if len(base_childs) == 0:\n", + " if len(base_childs) == 0 and len(ingredient_childs) == 0:\n", " text = \"Mix together the results of \"\n", " else:\n", " text += \" and mix it together with the results of \"\n", @@ -1114,7 +1135,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 198, "metadata": {}, "outputs": [], "source": [ @@ -1135,7 +1156,11 @@ " return a_list\n", " \n", " def mutate_node(self):\n", - " pass\n", + " if self._constant:\n", + " return\n", + " mixes, weights = m_base_mix.get_adjacent(self._name)\n", + " self._name = ea_tools.wheel_of_fortune_selection(mixes, weights)\n", + " \n", " #self._name = random.choice(base_ingredients)\n", " #TODO: change w.r.t. mixing probabilities \n", " \n", @@ -1177,7 +1202,7 @@ " heat = heat_score(ing)\n", " prepare = prepare_score(ing)\n", " \n", - " score = (heat + prepare + self.duplicate_groups_score(actions)) / 3\n", + " score = (heat + prepare) / 2\n", " score *= self.duplicate_actions_score(actions)\n", " \n", " return score\n", @@ -1221,7 +1246,7 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 199, "metadata": {}, "outputs": [], "source": [ @@ -1235,7 +1260,14 @@ " def mutate_node(self):\n", " if random.choice(range(2)) == 0:\n", " # change action\n", - " self._name = random.choice(actions)\n", + " ings = self.traverse_ingredients()\n", + " ing = np.random.choice(ings)\n", + " base_ing = ing._base_ingredient\n", + " try:\n", + " a, w = m_base_act.get_backward_adjacent(base_ing)\n", + " self._name = ea_tools.wheel_of_fortune_selection(a,w)\n", + " except ValueError:\n", + " print(\"Warning: cannot mutate given node\")\n", " else:\n", " # delete\n", " self.remove()\n", @@ -1322,13 +1354,13 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 200, "metadata": {}, "outputs": [], "source": [ "class Tree(object):\n", " @staticmethod\n", - " def build_initial_tree(ingredients: list, main_ingredients: list, max_n = 5, wheel_turns = 2):\n", + " def build_initial_tree(ingredients: list, main_ingredients: list, max_n = 20, wheel_turns = 2):\n", " \n", " assert set(main_ingredients).issubset(set(ingredients))\n", "\n", @@ -1363,7 +1395,7 @@ "\n", " # create ingredient nodes:\n", " for ing in ingredients:\n", - " new_node = IngredientNode(ing, constant=True)\n", + " new_node = IngredientNode(ing, constant=False)\n", "\n", " # check if we should do a preparation step\n", " if random_prepare(ing):\n", @@ -1455,7 +1487,7 @@ "\n", " \n", " @staticmethod\n", - " def find_ingredients(constant_ingredients, main_ingredients, min_additional:int, max_additional:int, top_ings:int=3):\n", + " def find_ingredients(constant_ingredients, main_ingredients, min_additional:int, max_additional:int, top_ings:int=3, ing_range=50):\n", " '''\n", " create an initial set of ingredients, based on given constant ingredients.\n", " min_additional and max_additional gives the range of ingredients that are added to our set\n", @@ -1484,8 +1516,8 @@ "\n", " for ing in main_ingredients:\n", " candidates, weights = normalized_score(ing, m_base_mix)\n", - " extra_candidates.append(candidates[:10])\n", - " extra_weights.append(weights[:10])\n", + " extra_candidates.append(candidates[:ing_range])\n", + " extra_weights.append(weights[:ing_range])\n", "\n", " extra_ingredients = ea_tools.combined_wheel_of_fortune_selection(extra_candidates,\n", " extra_weights,\n", @@ -1516,13 +1548,13 @@ " return list(constant_ingredients) + list(additional_ingredients) + list(extra_ingredients)\n", "\n", " @staticmethod\n", - " def from_ingredients(ingredients: list, main_ingredients: list, additional_ings=0):\n", + " def from_ingredients(ingredients: list, main_ingredients: list, min_additional=0, max_additional=10):\n", " root = None\n", " \n", " constant_ingredients = ingredients\n", " \n", - " if additional_ings > 0:\n", - " ingredients = Tree.find_ingredients(ingredients, main_ingredients, min_additional=0, max_additional=additional_ings)\n", + " if max_additional > 0:\n", + " ingredients = Tree.find_ingredients(ingredients, main_ingredients, min_additional=min_additional, max_additional=max_additional)\n", " \n", " \n", " root = Tree.build_initial_tree(ingredients, main_ingredients)\n", @@ -1583,7 +1615,7 @@ " n.mutate()\n", " \n", " # check for simplification after modification\n", - " self.root().simplify()\n", + " # self.root().simplify()\n", " \n", " def dot(self):\n", " return self.root().dot()\n", @@ -1617,15 +1649,15 @@ " self._ing_scores.append(n.node_score())\n", " self._n_ing_nodes += 1\n", " \n", + " seen_ingredients = set()\n", " self._n_duplicates = 0\n", - " seen_actions = set()\n", " \n", " for n in nodes:\n", - " if type(n) == ActionNode:\n", - " if n.name() in seen_actions:\n", + " if type(n) == IngredientNode:\n", + " if n.name() in seen_ingredients:\n", " self._n_duplicates += 1\n", " else:\n", - " seen_actions.add(n.name())\n", + " seen_ingredients.add(n.name())\n", " \n", " self._mix_scores = np.array(self._mix_scores)\n", " self._act_scores = np.array(self._act_scores)\n", @@ -1669,7 +1701,7 @@ " self._score = 0\n", " else: \n", " self._score = (sum_mix + sum_act + sum_ing) / n\n", - " self._score *= (len(s_act) - self._n_duplicates) / len(s_act)\n", + " self._score *= (len(s_ing) - self._n_duplicates) / len(s_ing)\n", "\n", " return self._score\n", " \n", @@ -1686,21 +1718,23 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 201, "metadata": {}, "outputs": [], "source": [ "class Population(object):\n", - " def __init__(self, start_ingredients, main_ingredients, n_population = 50, max_additional_ings=0):\n", + " def __init__(self, start_ingredients, main_ingredients, n_population = 50, min_additional=0, max_additional=15):\n", " self.population = []\n", " for i in tqdm(range(n_population), desc=\"build initial population\"):\n", - " self.population.append(Tree.from_ingredients(start_ingredients, main_ingredients, additional_ings=max_additional_ings))\n", + " self.population.append(Tree.from_ingredients(start_ingredients, main_ingredients, min_additional=min_additional, max_additional=max_additional))\n", " self._n = n_population\n", " \n", " def mutate(self):\n", " for tree in self.population.copy():\n", " t_clone = tree.copy()\n", " t_clone.mutate()\n", + " t_clone.mutate()\n", + " #t_clone.mutate()\n", " self.population.append(t_clone)\n", " \n", " def pairwise_competition(self):\n", @@ -1745,7 +1779,7 @@ " ii = np.argsort(-np.array(scores))[:n_best]\n", "\n", " for i in ii:\n", - " \n", + " self.population[i].root().simplify()\n", " display(self.population[i].root().dot())\n", " display(Markdown(f\"**Recipe Score**: {scores[i]}\"))\n", " display(self.population[i].root().to_instruction().to_markdown())" @@ -1760,18 +1794,18 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 234, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "76982efe704f44abace8fba9f981c760", + "model_id": "a046248de69941e4b79b4e04892c5422", "version_major": 2, "version_minor": 0 }, "text/plain": [ - "HBox(children=(FloatProgress(value=0.0, description='build initial population', max=25.0, style=ProgressStyle(…" + "HBox(children=(FloatProgress(value=0.0, description='build initial population', max=50.0, style=ProgressStyle(…" ] }, "metadata": {}, @@ -1786,12 +1820,12 @@ } ], "source": [ - "p = Population([\"spaghetti\"],['spaghetti'], max_additional_ings=6, n_population = 25)" + "p = Population([\"noodle\"],['noodle'], min_additional=4, max_additional=13, n_population = 50)" ] }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 226, "metadata": {}, "outputs": [], "source": [ @@ -1800,18 +1834,18 @@ }, { "cell_type": "code", - "execution_count": 37, + "execution_count": 236, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "68939d53ea85488cbbbb674bfd34afa6", + "model_id": "5ba684f7821c4fc397afc1931fc74fc0", "version_major": 2, "version_minor": 0 }, "text/plain": [ - "HBox(children=(FloatProgress(value=0.0, description='run evolutionary cycles', max=10.0, style=ProgressStyle(d…" + "HBox(children=(FloatProgress(value=0.0, description='run evolutionary cycles', max=50.0, style=ProgressStyle(d…" ] }, "metadata": {}, @@ -1826,12 +1860,12 @@ } ], "source": [ - "p.run(10)" + "p.run(50)" ] }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 239, "metadata": {}, "outputs": [ { @@ -1843,531 +1877,226 @@ "\n", "\n", - "\n", + "\n", "\n", "%3\n", - "\n", - "\n", + "\n", + "\n", "\n", - "115\n", - "\n", - " \n", - "mix\n", - "node score: 1.0000\n", + "274478\n", + "\n", + " \n", + "mix\n", + "node score: 1.0000\n", "\n", - "\n", + "\n", "\n", - "111\n", - "\n", - " \n", - "boil\n", - "node score: 1.0000\n", + "274493\n", + "\n", + " \n", + "cheese\n", + "node score:1.0000\n", "\n", - "\n", + "\n", "\n", - "115->111\n", - "\n", - "\n", + "274478->274493\n", + "\n", + "\n", "\n", - "\n", - "\n", - "113\n", - "\n", - " \n", - "bake\n", - "node score: 1.0000\n", - "\n", - "\n", - "\n", - "115->113\n", - "\n", - "\n", - "\n", - "\n", + "\n", "\n", - "112\n", - "\n", - " \n", - "mix\n", - "node score: 1.0000\n", + "274491\n", + "\n", + " \n", + "slice\n", + "node score: 1.0000\n", "\n", - "\n", + "\n", "\n", - "111->112\n", - "\n", - "\n", + "274478->274491\n", + "\n", + "\n", "\n", - "\n", - "\n", - "109\n", - "\n", - " \n", - "slice\n", - "node score: 1.0000\n", - "\n", - "\n", - "\n", - "112->109\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "107\n", - "\n", - " \n", - "spaghetti\n", - "node score:1.0000\n", - "\n", - "\n", - "\n", - "112->107\n", - "\n", - "\n", - "\n", - "\n", + "\n", "\n", - "108\n", - "\n", - " \n", - "mushroom\n", - "node score:1.0000\n", + "274479\n", + "\n", + " \n", + "heat\n", + "node score: 1.0000\n", "\n", - "\n", + "\n", "\n", - "109->108\n", - "\n", - "\n", + "274478->274479\n", + "\n", + "\n", "\n", - "\n", - "\n", - "110\n", - "\n", - " \n", - "pasta sauce\n", - "node score:1.0000\n", - "\n", - "\n", - "\n", - "113->110\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/markdown": [ - "**Recipe Score**: 1.0" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/markdown": [ - "**Ingredients**:\n", - " * mushroom\n", - " * spaghetti\n", - " * pasta sauce\n", - "\n", - "\n", - "**Instructions**:\n", - "\n", - "| Step | Instruction |\n", - "| ----:|:----------- |\n", - "| 1 | slice mushroom and mix it with spaghetti. Then boil it. |\n", - "| 2 | bake pasta sauce and mix it together with the results of step 1. |\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "%3\n", - "\n", - "\n", - "\n", - "135\n", - "\n", - " \n", - "mix\n", - "node score: 1.0000\n", - "\n", - "\n", - "\n", - "133\n", - "\n", - " \n", - "cook\n", - "node score: 1.0000\n", - "\n", - "\n", - "\n", - "135->133\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "130\n", - "\n", - " \n", - "grate\n", - "node score: 1.0000\n", - "\n", - "\n", - "\n", - "135->130\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "134\n", - "\n", - " \n", - "mix\n", - "node score: 0.5000\n", - "\n", - "\n", - "\n", - "133->134\n", - "\n", - "\n", - "\n", - "\n", + "\n", "\n", - "127\n", - "\n", - " \n", - "chop\n", - "node score: 1.0000\n", + "274492\n", + "\n", + " \n", + "zucchini\n", + "node score:1.0000\n", "\n", - "\n", + "\n", "\n", - "134->127\n", - "\n", - "\n", + "274491->274492\n", + "\n", + "\n", "\n", - "\n", + "\n", "\n", - "132\n", - "\n", - " \n", - "tomato sauce\n", - "node score:1.0000\n", + "274480\n", + "\n", + " \n", + "mix\n", + "node score: 0.8571\n", "\n", - "\n", + "\n", "\n", - "134->132\n", - "\n", - "\n", + "274479->274480\n", + "\n", + "\n", "\n", - "\n", + "\n", "\n", - "131\n", - "\n", - " \n", - "pasta sauce\n", - "node score:1.0000\n", - "\n", - "\n", - "\n", - "134->131\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "125\n", - "\n", - " \n", - "spaghetti\n", - "node score:1.0000\n", - "\n", - "\n", - "\n", - "134->125\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "128\n", - "\n", - " \n", - "ground beef\n", - "node score:1.0000\n", - "\n", - "\n", - "\n", - "134->128\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "126\n", - "\n", - " \n", - "garlic clove\n", - "node score:1.0000\n", - "\n", - "\n", - "\n", - "127->126\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "129\n", - "\n", - " \n", - "cheese\n", - "node score:1.0000\n", - "\n", - "\n", - "\n", - "130->129\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/markdown": [ - "**Recipe Score**: 0.9545454545454546" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/markdown": [ - "**Ingredients**:\n", - " * pasta sauce\n", - " * ground beef\n", - " * spaghetti\n", - " * tomato sauce\n", - " * cheese\n", - " * garlic clove\n", - "\n", - "\n", - "**Instructions**:\n", - "\n", - "| Step | Instruction |\n", - "| ----:|:----------- |\n", - "| 1 | chop garlic clove and mix it with tomato sauce, pasta sauce, spaghetti and ground beef. Then cook it. |\n", - "| 2 | grate cheese and mix it together with the results of step 1. |\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "%3\n", - "\n", - "\n", - "\n", - "223\n", - "\n", - " \n", - "cook\n", - "node score: 0.6667\n", - "\n", - "\n", - "\n", - "224\n", - "\n", - " \n", - "mix\n", - "node score: 0.8000\n", - "\n", - "\n", - "\n", - "223->224\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "214\n", + "274484\n", "\n", - " \n", - "spaghetti\n", + " \n", + "salt\n", "node score:1.0000\n", "\n", - "\n", - "\n", - "224->214\n", - "\n", - "\n", + "\n", + "\n", + "274480->274484\n", + "\n", + "\n", "\n", - "\n", - "\n", - "218\n", - "\n", - " \n", - "cut\n", - "node score: 1.0000\n", + "\n", + "\n", + "274486\n", + "\n", + " \n", + "noodle\n", + "node score:1.0000\n", "\n", - "\n", - "\n", - "224->218\n", - "\n", - "\n", + "\n", + "\n", + "274480->274486\n", + "\n", + "\n", "\n", - "\n", - "\n", - "222\n", - "\n", - " \n", - "tomato sauce\n", - "node score:1.0000\n", + "\n", + "\n", + "274489\n", + "\n", + " \n", + "chop\n", + "node score: 1.0000\n", "\n", - "\n", - "\n", - "224->222\n", - "\n", - "\n", + "\n", + "\n", + "274480->274489\n", + "\n", + "\n", "\n", - "\n", - "\n", - "216\n", + "\n", + "\n", + "274481\n", "\n", " \n", "chop\n", "node score: 1.0000\n", "\n", - "\n", - "\n", - "224->216\n", - "\n", - "\n", + "\n", + "\n", + "274480->274481\n", + "\n", + "\n", "\n", - "\n", - "\n", - "220\n", + "\n", + "\n", + "274487\n", "\n", - " \n", - "wash\n", + " \n", + "chop\n", "node score: 1.0000\n", "\n", - "\n", - "\n", - "224->220\n", - "\n", - "\n", + "\n", + "\n", + "274480->274487\n", + "\n", + "\n", "\n", - "\n", - "\n", - "221\n", + "\n", + "\n", + "274485\n", "\n", - " \n", - "pasta sauce\n", + " \n", + "garlic\n", "node score:1.0000\n", "\n", - "\n", - "\n", - "224->221\n", - "\n", - "\n", + "\n", + "\n", + "274480->274485\n", + "\n", + "\n", "\n", - "\n", - "\n", - "217\n", - "\n", - " \n", - "onion\n", - "node score:1.0000\n", + "\n", + "\n", + "274483\n", + "\n", + " \n", + "sauce\n", + "node score:1.0000\n", "\n", - "\n", - "\n", - "218->217\n", - "\n", - "\n", + "\n", + "\n", + "274480->274483\n", + "\n", + "\n", "\n", - "\n", - "\n", - "215\n", + "\n", + "\n", + "274490\n", + "\n", + " \n", + "chicken\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "274489->274490\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "274482\n", "\n", - " \n", - "cheese\n", + " \n", + "spinach\n", "node score:1.0000\n", "\n", - "\n", - "\n", - "216->215\n", + "\n", + "\n", + "274481->274482\n", "\n", "\n", "\n", - "\n", - "\n", - "219\n", + "\n", + "\n", + "274488\n", "\n", - " \n", - "mushroom\n", + " \n", + "tomato\n", "node score:1.0000\n", "\n", - "\n", - "\n", - "220->219\n", + "\n", + "\n", + "274487->274488\n", "\n", "\n", "\n", @@ -2375,7 +2104,7 @@ "\n" ], "text/plain": [ - "" + "" ] }, "metadata": {}, @@ -2384,7 +2113,7 @@ { "data": { "text/markdown": [ - "**Recipe Score**: 0.9515151515151515" + "**Recipe Score**: 0.9910714285714286" ], "text/plain": [ "" @@ -2397,19 +2126,23 @@ "data": { "text/markdown": [ "**Ingredients**:\n", - " * pasta sauce\n", - " * mushroom\n", - " * spaghetti\n", - " * tomato sauce\n", + " * noodle\n", + " * garlic\n", + " * spinach\n", + " * chicken\n", + " * zucchini\n", " * cheese\n", - " * onion\n", + " * sauce\n", + " * salt\n", + " * tomato\n", "\n", "\n", "**Instructions**:\n", "\n", "| Step | Instruction |\n", "| ----:|:----------- |\n", - "| 1 | cut onion, chop cheese, wash mushroom and mix it with spaghetti, tomato sauce and pasta sauce. Then cook it. |\n" + "| 1 | chop chicken, chop spinach, chop tomato and mix it with salt, noodle, garlic and sauce. Then heat it. |\n", + "| 2 | slice zucchini and mix it with cheese and mix it together with the results of step 1. |\n" ], "text/plain": [ "" @@ -2427,192 +2160,234 @@ "\n", "\n", - "\n", + "\n", "\n", "%3\n", - "\n", - "\n", + "\n", + "\n", "\n", - "26\n", - "\n", - " \n", - "mix\n", - "node score: 0.9167\n", + "269335\n", + "\n", + " \n", + "mix\n", + "node score: 1.0000\n", "\n", - "\n", + "\n", "\n", - "15\n", - "\n", - " \n", - "cut\n", - "node score: 1.0000\n", + "269336\n", + "\n", + " \n", + "heat\n", + "node score: 1.0000\n", "\n", - "\n", + "\n", "\n", - "26->15\n", - "\n", - "\n", + "269335->269336\n", + "\n", + "\n", "\n", - "\n", - "\n", - "24\n", - "\n", - " \n", - "simmer\n", - "node score: 1.0000\n", + "\n", + "\n", + "269349\n", + "\n", + " \n", + "slice\n", + "node score: 1.0000\n", "\n", - "\n", - "\n", - "26->24\n", - "\n", - "\n", + "\n", + "\n", + "269335->269349\n", + "\n", + "\n", "\n", - "\n", - "\n", - "22\n", - "\n", - " \n", - "boil\n", - "node score: 1.0000\n", + "\n", + "\n", + "269348\n", + "\n", + " \n", + "cheese\n", + "node score:1.0000\n", "\n", - "\n", - "\n", - "26->22\n", - "\n", - "\n", + "\n", + "\n", + "269335->269348\n", + "\n", + "\n", "\n", - "\n", - "\n", - "18\n", - "\n", - " \n", - "grate\n", - "node score: 1.0000\n", - "\n", - "\n", - "\n", - "26->18\n", - "\n", - "\n", - "\n", - "\n", + "\n", "\n", - "14\n", - "\n", - " \n", - "onion\n", - "node score:0.6667\n", + "269337\n", + "\n", + " \n", + "mix\n", + "node score: 0.8571\n", "\n", - "\n", + "\n", "\n", - "15->14\n", - "\n", - "\n", + "269336->269337\n", + "\n", + "\n", "\n", - "\n", - "\n", - "21\n", - "\n", - " \n", - "pasta sauce\n", - "node score:1.0000\n", + "\n", + "\n", + "269345\n", + "\n", + " \n", + "chop\n", + "node score: 1.0000\n", "\n", - "\n", - "\n", - "24->21\n", - "\n", - "\n", + "\n", + "\n", + "269337->269345\n", + "\n", + "\n", "\n", - "\n", + "\n", + "\n", + "269340\n", + "\n", + " \n", + "sauce\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "269337->269340\n", + "\n", + "\n", + "\n", + "\n", "\n", - "23\n", - "\n", - " \n", - "mix\n", - "node score: 0.6667\n", + "269339\n", + "\n", + " \n", + "salt\n", + "node score:1.0000\n", "\n", - "\n", + "\n", "\n", - "22->23\n", - "\n", - "\n", + "269337->269339\n", + "\n", + "\n", "\n", - "\n", + "\n", "\n", - "13\n", - "\n", - " \n", - "spaghetti\n", - "node score:1.0000\n", + "269347\n", + "\n", + " \n", + "garlic\n", + "node score:1.0000\n", "\n", - "\n", + "\n", "\n", - "23->13\n", - "\n", - "\n", + "269337->269347\n", + "\n", + "\n", "\n", - "\n", + "\n", "\n", - "20\n", - "\n", - " \n", - "slice\n", - "node score: 1.0000\n", + "269338\n", + "\n", + " \n", + "noodle\n", + "node score:1.0000\n", "\n", - "\n", + "\n", "\n", - "23->20\n", - "\n", - "\n", + "269337->269338\n", + "\n", + "\n", "\n", - "\n", - "\n", - "16\n", - "\n", - " \n", - "tomato sauce\n", - "node score:1.0000\n", - "\n", - "\n", - "\n", - "23->16\n", - "\n", - "\n", - "\n", - "\n", + "\n", "\n", - "19\n", - "\n", - " \n", - "mushroom\n", - "node score:1.0000\n", + "269341\n", + "\n", + " \n", + "chop\n", + "node score: 1.0000\n", "\n", - "\n", + "\n", "\n", - "20->19\n", - "\n", - "\n", + "269337->269341\n", + "\n", + "\n", "\n", - "\n", + "\n", + "\n", + "269343\n", + "\n", + " \n", + "chop\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "269337->269343\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "269346\n", + "\n", + " \n", + "spinach\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "269345->269346\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "269342\n", + "\n", + " \n", + "tomato\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "269341->269342\n", + "\n", + "\n", + "\n", + "\n", "\n", - "17\n", - "\n", - " \n", - "cheese\n", - "node score:1.0000\n", + "269344\n", + "\n", + " \n", + "chicken\n", + "node score:1.0000\n", "\n", - "\n", + "\n", "\n", - "18->17\n", - "\n", - "\n", + "269343->269344\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "269350\n", + "\n", + " \n", + "zucchini\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "269349->269350\n", + "\n", + "\n", "\n", "\n", "\n" ], "text/plain": [ - "" + "" ] }, "metadata": {}, @@ -2621,7 +2396,7 @@ { "data": { "text/markdown": [ - "**Recipe Score**: 0.9423076923076923" + "**Recipe Score**: 0.9910714285714286" ], "text/plain": [ "" @@ -2634,20 +2409,23 @@ "data": { "text/markdown": [ "**Ingredients**:\n", - " * pasta sauce\n", - " * mushroom\n", - " * spaghetti\n", - " * tomato sauce\n", + " * noodle\n", + " * garlic\n", + " * spinach\n", + " * chicken\n", + " * zucchini\n", + " * sauce\n", " * cheese\n", - " * onion\n", + " * salt\n", + " * tomato\n", "\n", "\n", "**Instructions**:\n", "\n", "| Step | Instruction |\n", "| ----:|:----------- |\n", - "| 1 | slice mushroom and mix it with spaghetti and tomato sauce. Then boil it. |\n", - "| 2 | cut onion, simmer pasta sauce, grate cheese and mix it together with the results of step 1. |\n" + "| 1 | chop spinach, chop tomato, chop chicken and mix it with sauce, salt, garlic and noodle. Then heat it. |\n", + "| 2 | slice zucchini and mix it with cheese and mix it together with the results of step 1. |\n" ], "text/plain": [ "" @@ -2665,404 +2443,234 @@ "\n", "\n", - "\n", + "\n", "\n", "%3\n", - "\n", - "\n", + "\n", + "\n", "\n", - "96\n", - "\n", - " \n", - "mix\n", - "node score: 0.9286\n", + "227019\n", + "\n", + " \n", + "mix\n", + "node score: 1.0000\n", "\n", - "\n", + "\n", "\n", - "92\n", - "\n", - " \n", - "boil\n", - "node score: 1.0000\n", + "227017\n", + "\n", + " \n", + "heat\n", + "node score: 1.0000\n", "\n", - "\n", + "\n", "\n", - "96->92\n", - "\n", - "\n", + "227019->227017\n", + "\n", + "\n", "\n", - "\n", - "\n", - "87\n", - "\n", - " \n", - "parsley\n", - "node score:0.6667\n", + "\n", + "\n", + "227011\n", + "\n", + " \n", + "cheese\n", + "node score:1.0000\n", "\n", - "\n", - "\n", - "96->87\n", - "\n", - "\n", + "\n", + "\n", + "227019->227011\n", + "\n", + "\n", "\n", - "\n", - "\n", - "94\n", - "\n", - " \n", - "bake\n", - "node score: 1.0000\n", + "\n", + "\n", + "227013\n", + "\n", + " \n", + "slice\n", + "node score: 1.0000\n", "\n", - "\n", - "\n", - "96->94\n", - "\n", - "\n", + "\n", + "\n", + "227019->227013\n", + "\n", + "\n", "\n", - "\n", + "\n", "\n", - "93\n", - "\n", - " \n", - "mix\n", - "node score: 0.6667\n", + "227018\n", + "\n", + " \n", + "mix\n", + "node score: 0.8571\n", "\n", - "\n", + "\n", "\n", - "92->93\n", - "\n", - "\n", + "227017->227018\n", + "\n", + "\n", "\n", - "\n", + "\n", "\n", - "84\n", + "227004\n", "\n", - " \n", - "spaghetti\n", + " \n", + "noodle\n", "node score:1.0000\n", "\n", - "\n", + "\n", "\n", - "93->84\n", - "\n", - "\n", + "227018->227004\n", + "\n", + "\n", "\n", - "\n", + "\n", "\n", - "89\n", + "227014\n", "\n", - " \n", - "olive oil\n", + " \n", + "salt\n", "node score:1.0000\n", "\n", - "\n", + "\n", "\n", - "93->89\n", - "\n", - "\n", + "227018->227014\n", + "\n", + "\n", "\n", - "\n", + "\n", "\n", - "88\n", + "227005\n", "\n", - " \n", - "garlic clove\n", - "node score:0.6667\n", + " \n", + "sauce\n", + "node score:1.0000\n", "\n", - "\n", + "\n", "\n", - "93->88\n", - "\n", - "\n", + "227018->227005\n", + "\n", + "\n", "\n", - "\n", + "\n", "\n", - "86\n", + "227009\n", "\n", - " \n", - "slice\n", + " \n", + "chop\n", "node score: 1.0000\n", "\n", - "\n", + "\n", "\n", - "93->86\n", - "\n", - "\n", + "227018->227009\n", + "\n", + "\n", "\n", - "\n", + "\n", + "\n", + "227007\n", + "\n", + " \n", + "chop\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "227018->227007\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "227016\n", + "\n", + " \n", + "chop\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "227018->227016\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "227010\n", + "\n", + " \n", + "garlic\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "227018->227010\n", + "\n", + "\n", + "\n", + "\n", "\n", - "85\n", + "227008\n", "\n", - " \n", - "onion\n", + " \n", + "tomato\n", "node score:1.0000\n", "\n", - "\n", + "\n", "\n", - "86->85\n", + "227009->227008\n", "\n", "\n", "\n", - "\n", - "\n", - "95\n", - "\n", - " \n", - "mix\n", - "node score: 1.0000\n", - "\n", - "\n", - "\n", - "94->95\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "90\n", - "\n", - " \n", - "cheese\n", - "node score:1.0000\n", - "\n", - "\n", - "\n", - "95->90\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "91\n", - "\n", - " \n", - "pasta sauce\n", - "node score:1.0000\n", - "\n", - "\n", - "\n", - "95->91\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/markdown": [ - "**Recipe Score**: 0.9175824175824174" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/markdown": [ - "**Ingredients**:\n", - " * pasta sauce\n", - " * olive oil\n", - " * spaghetti\n", - " * parsley\n", - " * cheese\n", - " * garlic clove\n", - " * onion\n", - "\n", - "\n", - "**Instructions**:\n", - "\n", - "| Step | Instruction |\n", - "| ----:|:----------- |\n", - "| 1 | slice onion and mix it with spaghetti, olive oil and garlic clove. Then boil it. |\n", - "| 2 | Mix cheese and pasta sauce. Then bake it. |\n", - "| 3 | Mix together the results of step 1 and step 2. |\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "%3\n", - "\n", - "\n", - "\n", - "199\n", - "\n", - " \n", - "mix\n", - "node score: 0.7500\n", - "\n", - "\n", - "\n", - "190\n", - "\n", - " \n", - "slice\n", - "node score: 1.0000\n", - "\n", - "\n", - "\n", - "199->190\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "197\n", - "\n", - " \n", - "heat\n", - "node score: 1.0000\n", - "\n", - "\n", - "\n", - "199->197\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "194\n", - "\n", - " \n", - "tomato sauce\n", - "node score:0.6667\n", - "\n", - "\n", - "\n", - "199->194\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "195\n", - "\n", - " \n", - "simmer\n", - "node score: 0.6667\n", - "\n", - "\n", - "\n", - "199->195\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "189\n", - "\n", - " \n", - "mushroom\n", - "node score:0.6667\n", - "\n", - "\n", - "\n", - "190->189\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "193\n", - "\n", - " \n", - "pasta sauce\n", - "node score:1.0000\n", - "\n", - "\n", - "\n", - "197->193\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "196\n", - "\n", - " \n", - "mix\n", - "node score: 0.6667\n", - "\n", - "\n", - "\n", - "195->196\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "188\n", - "\n", - " \n", - "spaghetti\n", - "node score:1.0000\n", - "\n", - "\n", - "\n", - "196->188\n", - "\n", - "\n", - "\n", - "\n", + "\n", "\n", - "192\n", - "\n", - " \n", - "olive oil\n", - "node score:1.0000\n", + "227006\n", + "\n", + " \n", + "chicken\n", + "node score:1.0000\n", "\n", - "\n", + "\n", "\n", - "196->192\n", - "\n", - "\n", + "227007->227006\n", + "\n", + "\n", "\n", - "\n", - "\n", - "191\n", - "\n", - " \n", - "cheese\n", - "node score:1.0000\n", + "\n", + "\n", + "227015\n", + "\n", + " \n", + "spinach\n", + "node score:1.0000\n", "\n", - "\n", - "\n", - "196->191\n", - "\n", - "\n", + "\n", + "\n", + "227016->227015\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "227012\n", + "\n", + " \n", + "zucchini\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "227013->227012\n", + "\n", + "\n", "\n", "\n", "\n" ], "text/plain": [ - "" + "" ] }, "metadata": {}, @@ -3071,7 +2679,7 @@ { "data": { "text/markdown": [ - "**Recipe Score**: 0.856060606060606" + "**Recipe Score**: 0.9910714285714286" ], "text/plain": [ "" @@ -3084,20 +2692,23 @@ "data": { "text/markdown": [ "**Ingredients**:\n", - " * pasta sauce\n", - " * olive oil\n", - " * mushroom\n", - " * spaghetti\n", - " * tomato sauce\n", + " * noodle\n", + " * garlic\n", + " * spinach\n", + " * chicken\n", + " * zucchini\n", + " * sauce\n", " * cheese\n", + " * salt\n", + " * tomato\n", "\n", "\n", "**Instructions**:\n", "\n", "| Step | Instruction |\n", "| ----:|:----------- |\n", - "| 1 | Mix spaghetti, olive oil and cheese. Then simmer it. |\n", - "| 2 | slice mushroom, heat pasta sauce and mix it with tomato sauce and mix it together with the results of step 1. |\n" + "| 1 | chop tomato, chop chicken, chop spinach and mix it with noodle, salt, sauce and garlic. Then heat it. |\n", + "| 2 | slice zucchini and mix it with cheese and mix it together with the results of step 1. |\n" ], "text/plain": [ "" @@ -3115,178 +2726,1321 @@ "\n", "\n", - "\n", + "\n", "\n", "%3\n", - "\n", - "\n", + "\n", + "\n", "\n", - "178\n", - "\n", - " \n", - "mix\n", - "node score: 0.5000\n", + "261127\n", + "\n", + " \n", + "mix\n", + "node score: 0.9333\n", "\n", - "\n", + "\n", "\n", - "174\n", - "\n", - " \n", - "boil\n", - "node score: 0.7500\n", + "261140\n", + "\n", + " \n", + "cheese\n", + "node score:1.0000\n", "\n", - "\n", + "\n", "\n", - "178->174\n", - "\n", - "\n", + "261127->261140\n", + "\n", + "\n", "\n", - "\n", - "\n", - "176\n", - "\n", - " \n", - "brown\n", - "node score: 0.0000\n", - "\n", - "\n", - "\n", - "178->176\n", - "\n", - "\n", - "\n", - "\n", + "\n", "\n", - "175\n", - "\n", - " \n", - "mix\n", - "node score: 0.6667\n", + "261128\n", + "\n", + " \n", + "heat\n", + "node score: 1.0000\n", "\n", - "\n", + "\n", "\n", - "174->175\n", - "\n", - "\n", + "261127->261128\n", + "\n", + "\n", "\n", - "\n", + "\n", + "\n", + "261141\n", + "\n", + " \n", + "slice\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "261127->261141\n", + "\n", + "\n", + "\n", + "\n", "\n", - "172\n", + "261129\n", + "\n", + " \n", + "mix\n", + "node score: 0.8571\n", + "\n", + "\n", + "\n", + "261128->261129\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "261137\n", "\n", - " \n", - "wash\n", + " \n", + "chop\n", "node score: 1.0000\n", "\n", - "\n", - "\n", - "175->172\n", - "\n", - "\n", + "\n", + "\n", + "261129->261137\n", + "\n", + "\n", "\n", - "\n", + "\n", + "\n", + "261135\n", + "\n", + " \n", + "chop\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "261129->261135\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "261130\n", + "\n", + " \n", + "noodle\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "261129->261130\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "261139\n", + "\n", + " \n", + "extra-virgin olive oil\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "261129->261139\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "261144\n", + "\n", + " \n", + "place\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "261129->261144\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "261131\n", + "\n", + " \n", + "salt\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "261129->261131\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "261133\n", + "\n", + " \n", + "chop\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "261129->261133\n", + "\n", + "\n", + "\n", + "\n", "\n", - "166\n", + "261138\n", + "\n", + " \n", + "spinach\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "261137->261138\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "261136\n", + "\n", + " \n", + "chicken\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "261135->261136\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "261132\n", + "\n", + " \n", + "sauce\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "261144->261132\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "261134\n", + "\n", + " \n", + "tomato\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "261133->261134\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "261142\n", + "\n", + " \n", + "zucchini\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "261141->261142\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Recipe Score**: 0.9876750700280112" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Ingredients**:\n", + " * noodle\n", + " * spinach\n", + " * chicken\n", + " * zucchini\n", + " * cheese\n", + " * sauce\n", + " * salt\n", + " * tomato\n", + " * extra-virgin olive oil\n", + "\n", + "\n", + "**Instructions**:\n", + "\n", + "| Step | Instruction |\n", + "| ----:|:----------- |\n", + "| 1 | chop spinach, chop chicken, place sauce, chop tomato and mix it with noodle, extra-virgin olive oil and salt. Then heat it. |\n", + "| 2 | slice zucchini and mix it with cheese and mix it together with the results of step 1. |\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "%3\n", + "\n", + "\n", + "\n", + "227713\n", + "\n", + " \n", + "mix\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "227711\n", + "\n", + " \n", + "bake\n", + "node score: 0.8000\n", + "\n", + "\n", + "\n", + "227713->227711\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "227706\n", + "\n", + " \n", + "break\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "227713->227706\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "227704\n", + "\n", + " \n", + "slice\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "227713->227704\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "227712\n", + "\n", + " \n", + "mix\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "227711->227712\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "227700\n", + "\n", + " \n", + "noodle\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "227712->227700\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "227707\n", + "\n", + " \n", + "tomato sauce\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "227712->227707\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "227702\n", + "\n", + " \n", + "dice\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "227712->227702\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "227708\n", + "\n", + " \n", + "water\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "227712->227708\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "227710\n", + "\n", + " \n", + "cut\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "227712->227710\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "227701\n", + "\n", + " \n", + "onion\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "227702->227701\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "227709\n", + "\n", + " \n", + "shrimp\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "227710->227709\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "227705\n", + "\n", + " \n", + "egg\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "227706->227705\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "227703\n", + "\n", + " \n", + "tomato\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "227704->227703\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Recipe Score**: 0.9857142857142858" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Ingredients**:\n", + " * noodle\n", + " * tomato sauce\n", + " * egg\n", + " * tomato\n", + " * shrimp\n", + " * onion\n", + " * water\n", + "\n", + "\n", + "**Instructions**:\n", + "\n", + "| Step | Instruction |\n", + "| ----:|:----------- |\n", + "| 1 | dice onion, cut shrimp and mix it with noodle, tomato sauce and water. Then bake it. |\n", + "| 2 | break egg, slice tomato and mix it together with the results of step 1. |\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "%3\n", + "\n", + "\n", + "\n", + "275736\n", + "\n", + " \n", + "mix\n", + "node score: 0.8462\n", + "\n", + "\n", + "\n", + "275740\n", + "\n", + " \n", + "heat\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "275736->275740\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "275752\n", + "\n", + " \n", + "bake\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "275736->275752\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "275739\n", + "\n", + " \n", + "mozzarella cheese\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "275736->275739\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "275741\n", + "\n", + " \n", + "mix\n", + "node score: 0.8667\n", + "\n", + "\n", + "\n", + "275740->275741\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "275749\n", + "\n", + " \n", + "cut\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "275741->275749\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "275746\n", + "\n", + " \n", + "chop\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "275741->275746\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "275742\n", + "\n", + " \n", + "blend\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "275741->275742\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "275748\n", + "\n", + " \n", + "noodle\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "275741->275748\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "275744\n", + "\n", + " \n", + "cheese\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "275741->275744\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "275745\n", + "\n", + " \n", + "spaghetti sauce\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "275741->275745\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "275750\n", + "\n", + " \n", + "chicken\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "275749->275750\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "275747\n", + "\n", + " \n", + "garlic clove\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "275746->275747\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "275743\n", + "\n", + " \n", + "water\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "275742->275743\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "275737\n", + "\n", + " \n", + "cream\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "275752->275737\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Recipe Score**: 0.980854700854701" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Ingredients**:\n", + " * noodle\n", + " * spaghetti sauce\n", + " * mozzarella cheese\n", + " * garlic clove\n", + " * chicken\n", + " * cream\n", + " * cheese\n", + " * water\n", + "\n", + "\n", + "**Instructions**:\n", + "\n", + "| Step | Instruction |\n", + "| ----:|:----------- |\n", + "| 1 | cut chicken, chop garlic clove, blend water and mix it with noodle, cheese and spaghetti sauce. Then heat it. |\n", + "| 2 | bake cream and mix it with mozzarella cheese and mix it together with the results of step 1. |\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "%3\n", + "\n", + "\n", + "\n", + "270872\n", + "\n", + " \n", + "mix\n", + "node score: 0.8667\n", + "\n", + "\n", + "\n", + "270874\n", + "\n", + " \n", + "slice\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "270872->270874\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "270889\n", + "\n", + " \n", + "place\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "270872->270889\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "270876\n", + "\n", + " \n", + "heat\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "270872->270876\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "270875\n", + "\n", + " \n", + "zucchini\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "270874->270875\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "270873\n", + "\n", + " \n", + "cheese\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "270889->270873\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "270877\n", + "\n", + " \n", + "mix\n", + "node score: 0.7619\n", + "\n", + "\n", + "\n", + "270876->270877\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "270880\n", + "\n", + " \n", + "chop\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "270877->270880\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "270887\n", "\n", - " \n", - "spaghetti\n", + " \n", + "salt\n", "node score:1.0000\n", "\n", - "\n", - "\n", - "175->166\n", - "\n", - "\n", + "\n", + "\n", + "270877->270887\n", + "\n", + "\n", "\n", - "\n", + "\n", + "\n", + "270879\n", + "\n", + " \n", + "garlic\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "270877->270879\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "270886\n", + "\n", + " \n", + "pepper\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "270877->270886\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "270885\n", + "\n", + " \n", + "coriander\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "270877->270885\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "270884\n", + "\n", + " \n", + "noodle\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "270877->270884\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "270882\n", + "\n", + " \n", + "break\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "270877->270882\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "270881\n", + "\n", + " \n", + "spinach\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "270880->270881\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "270883\n", + "\n", + " \n", + "tomato\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "270882->270883\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Recipe Score**: 0.9774509803921569" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Ingredients**:\n", + " * pepper\n", + " * garlic\n", + " * noodle\n", + " * spinach\n", + " * coriander\n", + " * zucchini\n", + " * cheese\n", + " * salt\n", + " * tomato\n", + "\n", + "\n", + "**Instructions**:\n", + "\n", + "| Step | Instruction |\n", + "| ----:|:----------- |\n", + "| 1 | chop spinach, break tomato and mix it with salt, garlic, pepper, coriander and noodle. Then heat it. |\n", + "| 2 | slice zucchini, place cheese and mix it together with the results of step 1. |\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "%3\n", + "\n", + "\n", + "\n", + "259778\n", + "\n", + " \n", + "mix\n", + "node score: 0.8667\n", + "\n", + "\n", + "\n", + "259781\n", + "\n", + " \n", + "cheese\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "259778->259781\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "259779\n", + "\n", + " \n", + "slice\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "259778->259779\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "259782\n", + "\n", + " \n", + "heat\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "259778->259782\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "259780\n", + "\n", + " \n", + "zucchini\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "259779->259780\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "259783\n", + "\n", + " \n", + "mix\n", + "node score: 0.7143\n", + "\n", + "\n", + "\n", + "259782->259783\n", + "\n", + "\n", + "\n", + "\n", "\n", - "168\n", + "259784\n", + "\n", + " \n", + "break\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "259783->259784\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "259792\n", + "\n", + " \n", + "noodle\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "259783->259792\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "259789\n", "\n", " \n", "chop\n", "node score: 1.0000\n", "\n", - "\n", - "\n", - "175->168\n", - "\n", - "\n", + "\n", + "\n", + "259783->259789\n", + "\n", + "\n", "\n", - "\n", - "\n", - "173\n", + "\n", + "\n", + "259786\n", "\n", - " \n", - "tomato sauce\n", + " \n", + "coriander\n", "node score:1.0000\n", "\n", - "\n", - "\n", - "175->173\n", - "\n", - "\n", + "\n", + "\n", + "259783->259786\n", + "\n", + "\n", "\n", - "\n", - "\n", - "171\n", + "\n", + "\n", + "259793\n", + "\n", + " \n", + "seasoning\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "259783->259793\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "259791\n", + "\n", + " \n", + "garlic\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "259783->259791\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "259787\n", + "\n", + " \n", + "salt\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "259783->259787\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "259785\n", "\n", - " \n", - "mushroom\n", + " \n", + "tomato\n", "node score:1.0000\n", "\n", - "\n", - "\n", - "172->171\n", + "\n", + "\n", + "259784->259785\n", "\n", "\n", "\n", - "\n", - "\n", - "167\n", + "\n", + "\n", + "259790\n", "\n", - " \n", - "parsley\n", + " \n", + "spinach\n", "node score:1.0000\n", "\n", - "\n", - "\n", - "168->167\n", + "\n", + "\n", + "259789->259790\n", "\n", "\n", "\n", - "\n", - "\n", - "170\n", - "\n", - " \n", - "cut\n", - "node score: 1.0000\n", - "\n", - "\n", - "\n", - "176->170\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "169\n", - "\n", - " \n", - "cheese\n", - "node score:1.0000\n", - "\n", - "\n", - "\n", - "170->169\n", - "\n", - "\n", - "\n", "\n", "\n" ], "text/plain": [ - "" + "" ] }, "metadata": {}, @@ -3295,7 +4049,7 @@ { "data": { "text/markdown": [ - "**Recipe Score**: 0.8263888888888888" + "**Recipe Score**: 0.9729166666666667" ], "text/plain": [ "" @@ -3308,20 +4062,23 @@ "data": { "text/markdown": [ "**Ingredients**:\n", - " * mushroom\n", - " * spaghetti\n", - " * tomato sauce\n", - " * parsley\n", + " * noodle\n", + " * garlic\n", + " * spinach\n", + " * coriander\n", + " * zucchini\n", " * cheese\n", + " * salt\n", + " * seasoning\n", + " * tomato\n", "\n", "\n", "**Instructions**:\n", "\n", "| Step | Instruction |\n", "| ----:|:----------- |\n", - "| 1 | wash mushroom, chop parsley and mix it with spaghetti and tomato sauce. Then boil it. |\n", - "| 2 | cut and brown cheese |\n", - "| 3 | Mix together the results of step 1 and step 2. |\n" + "| 1 | break tomato, chop spinach and mix it with noodle, coriander, seasoning, garlic and salt. Then heat it. |\n", + "| 2 | slice zucchini and mix it with cheese and mix it together with the results of step 1. |\n" ], "text/plain": [ "" @@ -3339,359 +4096,220 @@ "\n", "\n", - "\n", - "\n", - "%3\n", - "\n", - "\n", - "\n", - "37\n", - "\n", - " \n", - "mix\n", - "node score: 0.6667\n", - "\n", - "\n", - "\n", - "33\n", - "\n", - " \n", - "boil\n", - "node score: 1.0000\n", - "\n", - "\n", - "\n", - "37->33\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "35\n", - "\n", - " \n", - "heat\n", - "node score: 0.0000\n", - "\n", - "\n", - "\n", - "37->35\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "34\n", - "\n", - " \n", - "mix\n", - "node score: 0.3333\n", - "\n", - "\n", - "\n", - "33->34\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "29\n", - "\n", - " \n", - "olive oil\n", - "node score:1.0000\n", - "\n", - "\n", - "\n", - "34->29\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "28\n", - "\n", - " \n", - "spaghetti\n", - "node score:1.0000\n", - "\n", - "\n", - "\n", - "34->28\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "30\n", - "\n", - " \n", - "ground beef\n", - "node score:1.0000\n", - "\n", - "\n", - "\n", - "34->30\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "32\n", - "\n", - " \n", - "beat\n", - "node score: 1.0000\n", - "\n", - "\n", - "\n", - "35->32\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "31\n", - "\n", - " \n", - "cheese\n", - "node score:1.0000\n", - "\n", - "\n", - "\n", - "32->31\n", - "\n", - "\n", - "\n", - "\n", - "\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/markdown": [ - "**Recipe Score**: 0.7777777777777778" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/markdown": [ - "**Ingredients**:\n", - " * ground beef\n", - " * spaghetti\n", - " * olive oil\n", - " * cheese\n", - "\n", - "\n", - "**Instructions**:\n", - "\n", - "| Step | Instruction |\n", - "| ----:|:----------- |\n", - "| 1 | Mix olive oil, spaghetti and ground beef. Then boil it. |\n", - "| 2 | beat and heat cheese |\n", - "| 3 | Mix together the results of step 1 and step 2. |\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - "\n", - "\n", + "\n", "\n", "%3\n", - "\n", - "\n", + "\n", + "\n", "\n", - "212\n", - "\n", - " \n", - "mix\n", - "node score: 0.8333\n", + "226899\n", + "\n", + " \n", + "mix\n", + "node score: 0.6250\n", "\n", - "\n", + "\n", "\n", - "210\n", - "\n", - " \n", - "bake\n", - "node score: 1.0000\n", + "226891\n", + "\n", + " \n", + "beat\n", + "node score: 1.0000\n", "\n", - "\n", + "\n", "\n", - "212->210\n", - "\n", - "\n", + "226899->226891\n", + "\n", + "\n", "\n", - "\n", - "\n", - "208\n", - "\n", - " \n", - "warm\n", - "node score: 0.0000\n", - "\n", - "\n", - "\n", - "212->208\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "211\n", - "\n", - " \n", - "mix\n", - "node score: 1.0000\n", - "\n", - "\n", - "\n", - "210->211\n", - "\n", - "\n", - "\n", - "\n", + "\n", "\n", - "206\n", - "\n", - " \n", - "pasta sauce\n", - "node score:1.0000\n", + "226897\n", + "\n", + " \n", + "cook\n", + "node score: 1.0000\n", "\n", - "\n", + "\n", "\n", - "211->206\n", - "\n", - "\n", + "226899->226897\n", + "\n", + "\n", "\n", - "\n", + "\n", + "\n", + "226890\n", + "\n", + " \n", + "cream cheese\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "226891->226890\n", + "\n", + "\n", + "\n", + "\n", "\n", - "207\n", - "\n", - " \n", - "ground beef\n", - "node score:1.0000\n", + "226898\n", + "\n", + " \n", + "mix\n", + "node score: 0.9643\n", "\n", - "\n", + "\n", "\n", - "211->207\n", - "\n", - "\n", + "226897->226898\n", + "\n", + "\n", "\n", - "\n", - "\n", - "209\n", - "\n", - " \n", - "mix\n", - "node score: 0.6667\n", + "\n", + "\n", + "226895\n", + "\n", + " \n", + "dice\n", + "node score: 1.0000\n", "\n", - "\n", - "\n", - "208->209\n", - "\n", - "\n", + "\n", + "\n", + "226898->226895\n", + "\n", + "\n", "\n", - "\n", + "\n", "\n", - "205\n", - "\n", - " \n", - "cut\n", - "node score: 1.0000\n", + "226886\n", + "\n", + " \n", + "tomato sauce\n", + "node score:1.0000\n", "\n", - "\n", + "\n", "\n", - "209->205\n", - "\n", - "\n", + "226898->226886\n", + "\n", + "\n", "\n", - "\n", - "\n", - "203\n", - "\n", - " \n", - "cut\n", - "node score: 1.0000\n", - "\n", - "\n", - "\n", - "209->203\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "201\n", - "\n", - " \n", - "spaghetti\n", - "node score:1.0000\n", - "\n", - "\n", - "\n", - "209->201\n", - "\n", - "\n", - "\n", - "\n", + "\n", "\n", - "204\n", - "\n", - " \n", - "mushroom\n", - "node score:1.0000\n", + "226885\n", + "\n", + " \n", + "noodle\n", + "node score:1.0000\n", "\n", - "\n", + "\n", "\n", - "205->204\n", - "\n", - "\n", + "226898->226885\n", + "\n", + "\n", "\n", - "\n", + "\n", + "\n", + "226896\n", + "\n", + " \n", + "sausage\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "226898->226896\n", + "\n", + "\n", + "\n", + "\n", "\n", - "202\n", - "\n", - " \n", - "garlic clove\n", - "node score:1.0000\n", + "226889\n", + "\n", + " \n", + "slice\n", + "node score: 1.0000\n", "\n", - "\n", + "\n", "\n", - "203->202\n", - "\n", - "\n", + "226898->226889\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "226892\n", + "\n", + " \n", + "basil\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "226898->226892\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "226893\n", + "\n", + " \n", + "milk\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "226898->226893\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "226887\n", + "\n", + " \n", + "salt\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "226898->226887\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "226894\n", + "\n", + " \n", + "onion\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "226895->226894\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "226888\n", + "\n", + " \n", + "carrot\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "226889->226888\n", + "\n", + "\n", "\n", "\n", "\n" ], "text/plain": [ - "" + "" ] }, "metadata": {}, @@ -3700,7 +4318,7 @@ { "data": { "text/markdown": [ - "**Recipe Score**: 0.65625" + "**Recipe Score**: 0.9726190476190477" ], "text/plain": [ "" @@ -3713,20 +4331,23 @@ "data": { "text/markdown": [ "**Ingredients**:\n", - " * pasta sauce\n", - " * mushroom\n", - " * spaghetti\n", - " * ground beef\n", - " * garlic clove\n", + " * noodle\n", + " * carrot\n", + " * tomato sauce\n", + " * milk\n", + " * basil\n", + " * cream cheese\n", + " * salt\n", + " * onion\n", + " * sausage\n", "\n", "\n", "**Instructions**:\n", "\n", "| Step | Instruction |\n", "| ----:|:----------- |\n", - "| 1 | Mix pasta sauce and ground beef. Then bake it. |\n", - "| 2 | cut mushroom, cut garlic clove and mix it with spaghetti. Then warm it. |\n", - "| 3 | Mix together the results of step 1 and step 2. |\n" + "| 1 | dice onion, slice carrot and mix it with tomato sauce, noodle, sausage, basil, milk and salt. Then cook it. |\n", + "| 2 | beat cream cheese and mix it together with the results of step 1. |\n" ], "text/plain": [ "" @@ -3744,164 +4365,1560 @@ "\n", "\n", - "\n", - "\n", + "\n", + "\n", "%3\n", - "\n", - "\n", + "\n", + "\n", "\n", - "153\n", - "\n", - " \n", - "heat\n", - "node score: 1.0000\n", + "269763\n", + "\n", + " \n", + "mix\n", + "node score: 0.6250\n", "\n", - "\n", + "\n", "\n", - "154\n", - "\n", - " \n", - "mix\n", - "node score: 0.8667\n", + "269766\n", + "\n", + " \n", + "cook\n", + "node score: 1.0000\n", "\n", - "\n", + "\n", "\n", - "153->154\n", - "\n", - "\n", + "269763->269766\n", + "\n", + "\n", "\n", - "\n", + "\n", + "\n", + "269764\n", + "\n", + " \n", + "beat\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "269763->269764\n", + "\n", + "\n", + "\n", + "\n", "\n", - "149\n", + "269767\n", + "\n", + " \n", + "mix\n", + "node score: 0.9643\n", + "\n", + "\n", + "\n", + "269766->269767\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "269768\n", "\n", - " \n", - "slice\n", + " \n", + "dice\n", "node score: 1.0000\n", "\n", - "\n", - "\n", - "154->149\n", - "\n", - "\n", + "\n", + "\n", + "269767->269768\n", + "\n", + "\n", "\n", - "\n", + "\n", + "\n", + "269772\n", + "\n", + " \n", + "sausage\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "269767->269772\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "269777\n", + "\n", + " \n", + "salt\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "269767->269777\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "269776\n", + "\n", + " \n", + "milk\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "269767->269776\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "269773\n", + "\n", + " \n", + "slice\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "269767->269773\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "269770\n", + "\n", + " \n", + "tomato sauce\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "269767->269770\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "269775\n", + "\n", + " \n", + "basil\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "269767->269775\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "269771\n", + "\n", + " \n", + "noodle\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "269767->269771\n", + "\n", + "\n", + "\n", + "\n", "\n", - "152\n", + "269769\n", + "\n", + " \n", + "onion\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "269768->269769\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "269774\n", + "\n", + " \n", + "carrot\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "269773->269774\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "269765\n", + "\n", + " \n", + "cream cheese\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "269764->269765\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Recipe Score**: 0.9726190476190477" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Ingredients**:\n", + " * noodle\n", + " * carrot\n", + " * tomato sauce\n", + " * milk\n", + " * basil\n", + " * salt\n", + " * cream cheese\n", + " * onion\n", + " * sausage\n", + "\n", + "\n", + "**Instructions**:\n", + "\n", + "| Step | Instruction |\n", + "| ----:|:----------- |\n", + "| 1 | dice onion, slice carrot and mix it with sausage, salt, milk, tomato sauce, basil and noodle. Then cook it. |\n", + "| 2 | beat cream cheese and mix it together with the results of step 1. |\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "%3\n", + "\n", + "\n", + "\n", + "271608\n", + "\n", + " \n", + "mix\n", + "node score: 0.6923\n", + "\n", + "\n", + "\n", + "271609\n", + "\n", + " \n", + "cream\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "271608->271609\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "271621\n", + "\n", + " \n", + "melt\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "271608->271621\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "271610\n", + "\n", + " \n", + "heat\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "271608->271610\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "271622\n", + "\n", + " \n", + "mozzarella cheese\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "271621->271622\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "271611\n", + "\n", + " \n", + "mix\n", + "node score: 0.8667\n", + "\n", + "\n", + "\n", + "271610->271611\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "271619\n", + "\n", + " \n", + "blend\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "271611->271619\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "271612\n", + "\n", + " \n", + "cheese\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "271611->271612\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "271617\n", + "\n", + " \n", + "spaghetti sauce\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "271611->271617\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "271624\n", + "\n", + " \n", + "chop\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "271611->271624\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "271618\n", + "\n", + " \n", + "noodle\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "271611->271618\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "271613\n", + "\n", + " \n", + "cut\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "271611->271613\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "271620\n", + "\n", + " \n", + "water\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "271619->271620\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "271616\n", + "\n", + " \n", + "garlic clove\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "271624->271616\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "271614\n", + "\n", + " \n", + "chicken\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "271613->271614\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Recipe Score**: 0.9705982905982906" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Ingredients**:\n", + " * spaghetti sauce\n", + " * noodle\n", + " * mozzarella cheese\n", + " * garlic clove\n", + " * chicken\n", + " * cream\n", + " * cheese\n", + " * water\n", + "\n", + "\n", + "**Instructions**:\n", + "\n", + "| Step | Instruction |\n", + "| ----:|:----------- |\n", + "| 1 | blend water, chop garlic clove, cut chicken and mix it with cheese, spaghetti sauce and noodle. Then heat it. |\n", + "| 2 | melt mozzarella cheese and mix it with cream and mix it together with the results of step 1. |\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "%3\n", + "\n", + "\n", + "\n", + "277707\n", + "\n", + " \n", + "mix\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "277708\n", + "\n", + " \n", + "bake\n", + "node score: 0.6000\n", + "\n", + "\n", + "\n", + "277707->277708\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "277717\n", + "\n", + " \n", + "break\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "277707->277717\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "277719\n", + "\n", + " \n", + "slice\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "277707->277719\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "277709\n", + "\n", + " \n", + "mix\n", + "node score: 0.9000\n", + "\n", + "\n", + "\n", + "277708->277709\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "277712\n", + "\n", + " \n", + "dice\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "277709->277712\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "277715\n", + "\n", + " \n", + "cut\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "277709->277715\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "277714\n", + "\n", + " \n", + "water\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "277709->277714\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "277722\n", + "\n", + " \n", + "boil\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "277709->277722\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "277710\n", + "\n", + " \n", + "noodle\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "277709->277710\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "277713\n", + "\n", + " \n", + "onion\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "277712->277713\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "277716\n", + "\n", + " \n", + "shrimp\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "277715->277716\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "277711\n", + "\n", + " \n", + "oil\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "277722->277711\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "277718\n", + "\n", + " \n", + "egg\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "277717->277718\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "277720\n", + "\n", + " \n", + "tomato\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "277719->277720\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Recipe Score**: 0.9666666666666667" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Ingredients**:\n", + " * noodle\n", + " * egg\n", + " * tomato\n", + " * shrimp\n", + " * onion\n", + " * water\n", + " * oil\n", + "\n", + "\n", + "**Instructions**:\n", + "\n", + "| Step | Instruction |\n", + "| ----:|:----------- |\n", + "| 1 | dice onion, cut shrimp, boil oil and mix it with water and noodle. Then bake it. |\n", + "| 2 | break egg, slice tomato and mix it together with the results of step 1. |\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "%3\n", + "\n", + "\n", + "\n", + "266228\n", + "\n", + " \n", + "mix\n", + "node score: 0.6923\n", + "\n", + "\n", + "\n", + "266229\n", + "\n", + " \n", + "cream\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "266228->266229\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "266231\n", + "\n", + " \n", + "heat\n", + "node score: 0.8333\n", + "\n", + "\n", + "\n", + "266228->266231\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "266242\n", + "\n", + " \n", + "melt\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "266228->266242\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "266232\n", + "\n", + " \n", + "mix\n", + "node score: 0.8667\n", + "\n", + "\n", + "\n", + "266231->266232\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "266234\n", + "\n", + " \n", + "cheese\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "266232->266234\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "266238\n", + "\n", + " \n", + "cut\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "266232->266238\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "266235\n", + "\n", + " \n", + "mash\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "266232->266235\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "266233\n", + "\n", + " \n", + "spaghetti sauce\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "266232->266233\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "266240\n", + "\n", + " \n", + "noodle\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "266232->266240\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "266243\n", + "\n", + " \n", + "blend\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "266232->266243\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "266239\n", + "\n", + " \n", + "chicken\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "266238->266239\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "266236\n", + "\n", + " \n", + "garlic clove\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "266235->266236\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "266237\n", + "\n", + " \n", + "water\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "266243->266237\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "266230\n", + "\n", + " \n", + "mozzarella cheese\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "266242->266230\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Recipe Score**: 0.9594871794871795" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Ingredients**:\n", + " * spaghetti sauce\n", + " * noodle\n", + " * mozzarella cheese\n", + " * garlic clove\n", + " * chicken\n", + " * cream\n", + " * cheese\n", + " * water\n", + "\n", + "\n", + "**Instructions**:\n", + "\n", + "| Step | Instruction |\n", + "| ----:|:----------- |\n", + "| 1 | cut chicken, mash garlic clove, blend water and mix it with cheese, spaghetti sauce and noodle. Then heat it. |\n", + "| 2 | melt mozzarella cheese and mix it with cream and mix it together with the results of step 1. |\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "%3\n", + "\n", + "\n", + "\n", + "277090\n", + "\n", + " \n", + "cook\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "277108\n", + "\n", + " \n", + "mix\n", + "node score: 0.8611\n", + "\n", + "\n", + "\n", + "277090->277108\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "277096\n", + "\n", + " \n", + "noodle\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "277108->277096\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "277094\n", + "\n", + " \n", + "chop\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "277108->277094\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "277092\n", + "\n", + " \n", + "cheese\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "277108->277092\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "277102\n", + "\n", + " \n", + "extra-virgin olive oil\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "277108->277102\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "277100\n", + "\n", + " \n", + "chop\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "277108->277100\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "277103\n", + "\n", + " \n", + "tomato\n", + "node score:0.5000\n", + "\n", + "\n", + "\n", + "277108->277103\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "277098\n", + "\n", + " \n", + "place\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "277108->277098\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "277097\n", + "\n", + " \n", + "salt\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "277108->277097\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "277104\n", + "\n", + " \n", + "slice\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "277108->277104\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "277095\n", + "\n", + " \n", + "chicken\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "277094->277095\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "277101\n", + "\n", + " \n", + "spinach\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "277100->277101\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "277099\n", + "\n", + " \n", + "sauce\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "277098->277099\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "277105\n", + "\n", + " \n", + "zucchini\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "277104->277105\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Recipe Score**: 0.9537815126050421" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Ingredients**:\n", + " * noodle\n", + " * spinach\n", + " * chicken\n", + " * zucchini\n", + " * cheese\n", + " * sauce\n", + " * salt\n", + " * tomato\n", + " * extra-virgin olive oil\n", + "\n", + "\n", + "**Instructions**:\n", + "\n", + "| Step | Instruction |\n", + "| ----:|:----------- |\n", + "| 1 | chop chicken, chop spinach, place sauce, slice zucchini and mix it with noodle, cheese, extra-virgin olive oil, tomato and salt. Then cook it. |\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "%3\n", + "\n", + "\n", + "\n", + "273415\n", + "\n", + " \n", + "cook\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "273416\n", + "\n", + " \n", + "mix\n", + "node score: 0.8611\n", + "\n", + "\n", + "\n", + "273415->273416\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "273426\n", + "\n", + " \n", + "chop\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "273416->273426\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "273417\n", "\n", " \n", "slice\n", "node score: 1.0000\n", "\n", - "\n", + "\n", "\n", - "154->152\n", - "\n", - "\n", + "273416->273417\n", + "\n", + "\n", "\n", - "\n", + "\n", "\n", - "144\n", + "273425\n", "\n", - " \n", - "spaghetti\n", + " \n", + "noodle\n", "node score:1.0000\n", "\n", - "\n", + "\n", "\n", - "154->144\n", - "\n", - "\n", + "273416->273425\n", + "\n", + "\n", "\n", - "\n", + "\n", "\n", - "146\n", - "\n", - " \n", - "slice\n", - "node score: 1.0000\n", + "273432\n", + "\n", + " \n", + "salt\n", + "node score:1.0000\n", "\n", - "\n", + "\n", "\n", - "154->146\n", - "\n", - "\n", + "273416->273432\n", + "\n", + "\n", "\n", - "\n", - "\n", - "150\n", - "\n", - " \n", - "ground beef\n", - "node score:1.0000\n", + "\n", + "\n", + "273422\n", + "\n", + " \n", + "place\n", + "node score: 1.0000\n", "\n", - "\n", - "\n", - "154->150\n", - "\n", - "\n", + "\n", + "\n", + "273416->273422\n", + "\n", + "\n", "\n", - "\n", + "\n", "\n", - "147\n", - "\n", - " \n", - "pasta sauce\n", - "node score:1.0000\n", + "273424\n", + "\n", + " \n", + "extra-virgin olive oil\n", + "node score:1.0000\n", "\n", - "\n", + "\n", "\n", - "154->147\n", - "\n", - "\n", + "273416->273424\n", + "\n", + "\n", "\n", - "\n", + "\n", + "\n", + "273419\n", + "\n", + " \n", + "cheese\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "273416->273419\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "273428\n", + "\n", + " \n", + "chop\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "273416->273428\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "273431\n", + "\n", + " \n", + "tomato\n", + "node score:0.5000\n", + "\n", + "\n", + "\n", + "273416->273431\n", + "\n", + "\n", + "\n", + "\n", "\n", - "148\n", + "273427\n", "\n", - " \n", - "cheese\n", + " \n", + "chicken\n", "node score:1.0000\n", "\n", - "\n", + "\n", "\n", - "149->148\n", + "273426->273427\n", "\n", "\n", "\n", - "\n", + "\n", "\n", - "151\n", + "273418\n", "\n", - " \n", - "mushroom\n", + " \n", + "zucchini\n", "node score:1.0000\n", "\n", - "\n", + "\n", "\n", - "152->151\n", + "273417->273418\n", "\n", "\n", "\n", - "\n", - "\n", - "145\n", - "\n", - " \n", - "onion\n", - "node score:1.0000\n", + "\n", + "\n", + "273423\n", + "\n", + " \n", + "sauce\n", + "node score:1.0000\n", "\n", - "\n", - "\n", - "146->145\n", - "\n", - "\n", + "\n", + "\n", + "273422->273423\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "273429\n", + "\n", + " \n", + "spinach\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "273428->273429\n", + "\n", + "\n", "\n", "\n", "\n" ], "text/plain": [ - "" + "" ] }, "metadata": {}, @@ -3910,7 +5927,7 @@ { "data": { "text/markdown": [ - "**Recipe Score**: 0.49393939393939396" + "**Recipe Score**: 0.9514880952380953" ], "text/plain": [ "" @@ -3923,11 +5940,862 @@ "data": { "text/markdown": [ "**Ingredients**:\n", - " * pasta sauce\n", - " * mushroom\n", - " * spaghetti\n", - " * ground beef\n", + " * noodle\n", + " * spinach\n", + " * chicken\n", + " * zucchini\n", + " * sauce\n", " * cheese\n", + " * salt\n", + " * tomato\n", + " * extra-virgin olive oil\n", + "\n", + "\n", + "**Instructions**:\n", + "\n", + "| Step | Instruction |\n", + "| ----:|:----------- |\n", + "| 1 | chop chicken, slice zucchini, place sauce, chop spinach and mix it with noodle, salt, extra-virgin olive oil, cheese and tomato. Then cook it. |\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "%3\n", + "\n", + "\n", + "\n", + "269585\n", + "\n", + " \n", + "mix\n", + "node score: 0.9333\n", + "\n", + "\n", + "\n", + "269586\n", + "\n", + " \n", + "cream\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "269585->269586\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "269587\n", + "\n", + " \n", + "heat\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "269585->269587\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "269600\n", + "\n", + " \n", + "grill\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "269585->269600\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "269588\n", + "\n", + " \n", + "mix\n", + "node score: 0.8571\n", + "\n", + "\n", + "\n", + "269587->269588\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "269594\n", + "\n", + " \n", + "chop\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "269588->269594\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "269598\n", + "\n", + " \n", + "break\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "269588->269598\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "269589\n", + "\n", + " \n", + "salt\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "269588->269589\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "269590\n", + "\n", + " \n", + "noodle\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "269588->269590\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "269596\n", + "\n", + " \n", + "chicken\n", + "node score:0.5000\n", + "\n", + "\n", + "\n", + "269588->269596\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "269597\n", + "\n", + " \n", + "sauce\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "269588->269597\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "269593\n", + "\n", + " \n", + "garlic\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "269588->269593\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "269595\n", + "\n", + " \n", + "spinach\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "269594->269595\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "269599\n", + "\n", + " \n", + "tomato\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "269598->269599\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "269601\n", + "\n", + " \n", + "cheese\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "269600->269601\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Recipe Score**: 0.9506238859180035" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Ingredients**:\n", + " * noodle\n", + " * garlic\n", + " * spinach\n", + " * chicken\n", + " * cream\n", + " * sauce\n", + " * cheese\n", + " * salt\n", + " * tomato\n", + "\n", + "\n", + "**Instructions**:\n", + "\n", + "| Step | Instruction |\n", + "| ----:|:----------- |\n", + "| 1 | chop spinach, break tomato and mix it with salt, noodle, chicken, sauce and garlic. Then heat it. |\n", + "| 2 | grill cheese and mix it with cream and mix it together with the results of step 1. |\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "%3\n", + "\n", + "\n", + "\n", + "277864\n", + "\n", + " \n", + "mix\n", + "node score: 0.6250\n", + "\n", + "\n", + "\n", + "277865\n", + "\n", + " \n", + "beat\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "277864->277865\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "277867\n", + "\n", + " \n", + "cook\n", + "node score: 0.7500\n", + "\n", + "\n", + "\n", + "277864->277867\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "277866\n", + "\n", + " \n", + "cream cheese\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "277865->277866\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "277868\n", + "\n", + " \n", + "mix\n", + "node score: 0.6071\n", + "\n", + "\n", + "\n", + "277867->277868\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "277869\n", + "\n", + " \n", + "dice\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "277868->277869\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "277872\n", + "\n", + " \n", + "noodle\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "277868->277872\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "277874\n", + "\n", + " \n", + "slice\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "277868->277874\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "277873\n", + "\n", + " \n", + "sausage\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "277868->277873\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "277878\n", + "\n", + " \n", + "salt\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "277868->277878\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "277871\n", + "\n", + " \n", + "tomato sauce\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "277868->277871\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "277881\n", + "\n", + " \n", + "knead\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "277868->277881\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "277880\n", + "\n", + " \n", + "refrigerate\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "277868->277880\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "277870\n", + "\n", + " \n", + "onion\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "277869->277870\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "277875\n", + "\n", + " \n", + "carrot\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "277874->277875\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "277877\n", + "\n", + " \n", + "milk\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "277881->277877\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "277876\n", + "\n", + " \n", + "basil\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "277880->277876\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Recipe Score**: 0.9401260504201681" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Ingredients**:\n", + " * noodle\n", + " * carrot\n", + " * tomato sauce\n", + " * milk\n", + " * basil\n", + " * cream cheese\n", + " * salt\n", + " * onion\n", + " * sausage\n", + "\n", + "\n", + "**Instructions**:\n", + "\n", + "| Step | Instruction |\n", + "| ----:|:----------- |\n", + "| 1 | dice onion, slice carrot, knead milk, refrigerate basil and mix it with noodle, sausage, salt and tomato sauce. Then cook it. |\n", + "| 2 | beat cream cheese and mix it together with the results of step 1. |\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "%3\n", + "\n", + "\n", + "\n", + "276821\n", + "\n", + " \n", + "mix\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "276837\n", + "\n", + " \n", + "boil\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "276821->276837\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "276823\n", + "\n", + " \n", + "cook\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "276821->276823\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "276822\n", + "\n", + " \n", + "cream cheese\n", + "node score:0.0000\n", + "\n", + "\n", + "\n", + "276837->276822\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "276824\n", + "\n", + " \n", + "mix\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "276823->276824\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "276825\n", + "\n", + " \n", + "noodle\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "276824->276825\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "276830\n", + "\n", + " \n", + "salt\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "276824->276830\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "276836\n", + "\n", + " \n", + "bake\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "276824->276836\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "276828\n", + "\n", + " \n", + "slice\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "276824->276828\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "276827\n", + "\n", + " \n", + "tomato sauce\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "276824->276827\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "276833\n", + "\n", + " \n", + "dice\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "276824->276833\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "276832\n", + "\n", + " \n", + "basil\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "276824->276832\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "276831\n", + "\n", + " \n", + "milk\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "276824->276831\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "276826\n", + "\n", + " \n", + "sugar\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "276836->276826\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "276829\n", + "\n", + " \n", + "carrot\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "276828->276829\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "276834\n", + "\n", + " \n", + "onion\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "276833->276834\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Recipe Score**: 0.9375" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Ingredients**:\n", + " * noodle\n", + " * carrot\n", + " * tomato sauce\n", + " * milk\n", + " * basil\n", + " * sugar\n", + " * salt\n", + " * cream cheese\n", " * onion\n", "\n", "\n", @@ -3935,7 +6803,575 @@ "\n", "| Step | Instruction |\n", "| ----:|:----------- |\n", - "| 1 | slice cheese, slice mushroom, slice onion and mix it with spaghetti, ground beef and pasta sauce. Then heat it. |\n" + "| 1 | bake sugar, slice carrot, dice onion and mix it with noodle, salt, tomato sauce, basil and milk. Then cook it. |\n", + "| 2 | boil cream cheese and mix it together with the results of step 1. |\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "%3\n", + "\n", + "\n", + "\n", + "275914\n", + "\n", + " \n", + "mix\n", + "node score: 0.8750\n", + "\n", + "\n", + "\n", + "275916\n", + "\n", + " \n", + "cook\n", + "node score: 0.7500\n", + "\n", + "\n", + "\n", + "275914->275916\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "275915\n", + "\n", + " \n", + "cream cheese\n", + "node score:0.5000\n", + "\n", + "\n", + "\n", + "275914->275915\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "275917\n", + "\n", + " \n", + "mix\n", + "node score: 0.8571\n", + "\n", + "\n", + "\n", + "275916->275917\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "275918\n", + "\n", + " \n", + "noodle\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "275917->275918\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "275925\n", + "\n", + " \n", + "basil\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "275917->275925\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "275930\n", + "\n", + " \n", + "cool\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "275917->275930\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "275924\n", + "\n", + " \n", + "milk\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "275917->275924\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "275923\n", + "\n", + " \n", + "salt\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "275917->275923\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "275921\n", + "\n", + " \n", + "slice\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "275917->275921\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "275929\n", + "\n", + " \n", + "drain\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "275917->275929\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "275920\n", + "\n", + " \n", + "tomato sauce\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "275917->275920\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "275926\n", + "\n", + " \n", + "dice\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "275930->275926\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "275927\n", + "\n", + " \n", + "onion\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "275926->275927\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "275922\n", + "\n", + " \n", + "carrot\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "275921->275922\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "275919\n", + "\n", + " \n", + "sugar\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "275929->275919\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Recipe Score**: 0.9363839285714286" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Ingredients**:\n", + " * noodle\n", + " * carrot\n", + " * tomato sauce\n", + " * milk\n", + " * basil\n", + " * sugar\n", + " * salt\n", + " * cream cheese\n", + " * onion\n", + "\n", + "\n", + "**Instructions**:\n", + "\n", + "| Step | Instruction |\n", + "| ----:|:----------- |\n", + "| 1 | dice and cool onion |\n", + "| 2 | slice carrot, drain sugar and mix it with noodle, basil, milk, salt and tomato sauce and mix it together with the results of step 1. Then cook it. |\n", + "| 3 | Mix cream cheese and mix it together with the results of step 2. |\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "%3\n", + "\n", + "\n", + "\n", + "274285\n", + "\n", + " \n", + "mix\n", + "node score: 0.6250\n", + "\n", + "\n", + "\n", + "274288\n", + "\n", + " \n", + "cook\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "274285->274288\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "274286\n", + "\n", + " \n", + "beat\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "274285->274286\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "274303\n", + "\n", + " \n", + "mix\n", + "node score: 0.7857\n", + "\n", + "\n", + "\n", + "274288->274303\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "274291\n", + "\n", + " \n", + "noodle\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "274303->274291\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "274296\n", + "\n", + " \n", + "place\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "274303->274296\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "274292\n", + "\n", + " \n", + "slice\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "274303->274292\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "274300\n", + "\n", + " \n", + "salt\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "274303->274300\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "274299\n", + "\n", + " \n", + "tomato sauce\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "274303->274299\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "274298\n", + "\n", + " \n", + "lime juice\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "274303->274298\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "274290\n", + "\n", + " \n", + "milk\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "274303->274290\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "274294\n", + "\n", + " \n", + "saute\n", + "node score: 1.0000\n", + "\n", + "\n", + "\n", + "274303->274294\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "274297\n", + "\n", + " \n", + "sausage\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "274296->274297\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "274293\n", + "\n", + " \n", + "carrot\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "274292->274293\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "274295\n", + "\n", + " \n", + "onion\n", + "node score:0.5000\n", + "\n", + "\n", + "\n", + "274294->274295\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "274287\n", + "\n", + " \n", + "cream cheese\n", + "node score:1.0000\n", + "\n", + "\n", + "\n", + "274286->274287\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Recipe Score**: 0.9354575163398693" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Ingredients**:\n", + " * noodle\n", + " * carrot\n", + " * tomato sauce\n", + " * milk\n", + " * salt\n", + " * cream cheese\n", + " * onion\n", + " * sausage\n", + " * lime juice\n", + "\n", + "\n", + "**Instructions**:\n", + "\n", + "| Step | Instruction |\n", + "| ----:|:----------- |\n", + "| 1 | place sausage, slice carrot, saute onion and mix it with noodle, salt, tomato sauce, lime juice and milk. Then cook it. |\n", + "| 2 | beat cream cheese and mix it together with the results of step 1. |\n" ], "text/plain": [ "" @@ -3946,44 +7382,9 @@ } ], "source": [ - "p.plot_population()" + "p.plot_population(n_best=20)" ] }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, { "cell_type": "code", "execution_count": null, diff --git a/EvolutionaryAlgorithm/EvolutionaryAlgorithm.py b/EvolutionaryAlgorithm/EvolutionaryAlgorithm.py index 9235744..f4b8362 100644 --- a/EvolutionaryAlgorithm/EvolutionaryAlgorithm.py +++ b/EvolutionaryAlgorithm/EvolutionaryAlgorithm.py @@ -39,6 +39,8 @@ from difflib import SequenceMatcher import numpy as np +import ActionGroups as AG + import plotly.graph_objs as go from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot from plotly.subplots import make_subplots @@ -104,6 +106,11 @@ c_base_act = m_base_act._csr c_base_mix = m_base_mix._csr +c_grouped_mix = m_grouped_mix._csr +c_grouped_act = m_grouped_act._csr +c_grouped_base_act = m_grouped_base_act._csr + + actions = m_act.get_labels()[0] @@ -186,6 +193,16 @@ def bw_sum(key, m, c): return np.sum(get_backward_adjacent(key,m,c)[1]) +def to_grouped_ingredient(ing:Ingredient): + groups = set() + for act in ing._action_set: + groups.add(AG.groups[act]) + grouped_ingredient = Ingredient(ing._base_ingredient) + for g in groups: + grouped_ingredient.apply_action(g) + return grouped_ingredient + + # #### different score functions # ##### normalizations @@ -272,10 +289,184 @@ def p_ingredient_unprepared(base_ing): return specialized_sum / base_sum -def p_heat(base_ing): - heat_actions = ["heat","cook","simmer","bake"] - heat_sum = 0 - m +# **new probability for preprocess ingredients:** + +PREPARE_RATIO_THRESHOLD = 0.35 +HEAT_RATIO_THRESHOLD = 0.65 + +PREPARE_SCORE_EPS = 0.1 +HEAT_SCORE_EPS = 0.1 + +def prepare_ratio(ing:str): + try: + keys, values = m_grouped_act.get_backward_adjacent(Ingredient(ing).to_json()) + except KeyError: + return 0 + action_dict = dict(zip(keys,values)) + if 'prepare' not in action_dict: + return 0 + if 'heat' not in action_dict: + return 1 + return action_dict['prepare'] / action_dict['heat'] + +def random_prepare(ing:str): + """ + returns randomly a boolean value if ing should be prepared, w.r.t. the prepare_ration function + """ + + return prepare_ratio(ing) > np.random.normal(PREPARE_RATIO_THRESHOLD,0.1) + +def heat_ratio(ingredient:str): + try: + action_set, action_weights = m_grouped_base_act.get_backward_adjacent(ingredient) + except KeyError: + return 0 + d = dict(zip(action_set, action_weights)) + + if 'prepare' not in d: + return 1 + if 'heat' not in d: + return 0 + + ratio = 1 - d['prepare'] / d['heat'] + + return ratio + +def random_heated(ingredient:str): + ratio = heat_ratio(ingredient) + + return ratio > np.random.normal(HEAT_RATIO_THRESHOLD,0.15) + +def prepare_score(ingredient:Ingredient): + ing_str = ingredient._base_ingredient + + g_ing = to_grouped_ingredient(ingredient) + + ratio = prepare_ratio(ing_str) + + if ratio > PREPARE_RATIO_THRESHOLD + PREPARE_SCORE_EPS: + if 'prepare' not in g_ing._action_set: + return 0 + + if ratio < PREPARE_RATIO_THRESHOLD - PREPARE_SCORE_EPS: + if 'prepare' in g_ing._action_set: + return 0 + + return 1 + +def heat_score(ingredient:Ingredient): + ing_str = ingredient._base_ingredient + + g_ing = to_grouped_ingredient(ingredient) + + ratio = heat_ratio(ing_str) + + if ratio > HEAT_RATIO_THRESHOLD + HEAT_SCORE_EPS: + if 'heat' not in g_ing._action_set: + return 0 + + if ratio < HEAT_RATIO_THRESHOLD - HEAT_SCORE_EPS: + if 'heat' in g_ing._action_set: + return 0 + + return 1 + + +def relative_action_rank(ingredient:str, action:str): + action_set, action_weights = m_base_act.get_backward_adjacent(ingredient) + if action not in action_set or len(action_set) <= 1: + return 0 + return 1 - action_set.tolist().index(action) / (len(action_set) - 1) + + +def filter_set_by_group(act_set, act_w, group): + new_act_set = [] + new_act_w = [] + for i in range(len(act_set)): + if act_set[i] in AG.inverse_groups[group]: + new_act_set.append(act_set[i]) + new_act_w.append(act_w[i]) + return np.array(new_act_set), np.array(new_act_w) + + +# ## better normalized scores: + +def normalized_score(key, matrix): + sum_key = matrix.get_sum(key) + keys, values = matrix.get_adjacent(key) + normalized_values = np.array([(values[i] / matrix.get_sum(keys[i])) * (values[i] / sum_key) for i in range(len(keys))]) + sort = np.argsort(-normalized_values) + return keys[sort], normalized_values[sort] + +def forward_normalized_score(key, matrix): + sum_key = matrix.get_fw_sum(key) + keys, values = matrix.get_forward_adjacent(key) + normalized_values = np.array([(values[i] / matrix.get_bw_sum(keys[i])) * (values[i] / sum_key) for i in range(len(keys))]) + sort = np.argsort(-normalized_values) + return keys[sort], normalized_values[sort] + +def backward_normalized_score(key, matrix): + sum_key = matrix.get_bw_sum(key) + keys, values = matrix.get_backward_adjacent(key) + normalized_values = np.array([(values[i] / matrix.get_fw_sum(keys[i])) * (values[i] / sum_key) for i in range(len(keys))]) + sort = np.argsort(-normalized_values) + return keys[sort], normalized_values[sort] + + +# ## Helper class for instructions + +class RecipeInstructionState(object): + def __init__(self): + self.current_step = 1 + self.id_to_state = {} + self.instructions_by_step = {} + self.step_by_nodeid = {} + self.text_by_nodeid = {} + self.ingredients = set() + + def _add_instruction(self, node_id): + s = self.text_by_nodeid[node_id] + self.instructions_by_step[self.current_step] = s + self.step_by_nodeid[node_id] = self.current_step + self.current_step += 1 + return self.current_step - 1 + + def add_text(self, node_id, text, is_instruction=False, is_ingredient=False): + self.text_by_nodeid[node_id] = text + if is_instruction: + self._add_instruction(node_id) + if is_ingredient: + self.ingredients.add(text) + + def exists_any_instruction(self, node_ids:list): + """check if any instruction exists for list of id's + """ + + for node_id in node_ids: + if node_id in self.step_by_nodeid: + return True + return False + + def to_markdown(self): + + md_text = "**Ingredients**:\n" + + for ing in self.ingredients: + md_text += f" * {ing}\n" + + md_text += "\n\n**Instructions**:\n\n" + md_text += "| Step | Instruction |\n" + md_text += "| ----:|:----------- |\n" + + for step in range(1, self.current_step): + md_text += f"| {step} | {self.instructions_by_step[step]} |\n" + + return Markdown(md_text) + + + + + # ## Recipe Tree @@ -409,9 +600,14 @@ class RecipeTreeNode(object): ing = random.choice(ings) a, w = get_backward_adjacent(ing._base_ingredient, m_base_act, c_base_act) + + if len(a) > 0: - action = random.choices(a, w)[0] - self.insert_before(ActionNode(action)) + action = ea_tools.wheel_of_fortune_selection(a,w) + self.insert_before(ActionNode(action)) + + else: + print("Warning: cannot find matching action node for mutation") def mutate_node(self): raise NotImplementedError @@ -446,6 +642,11 @@ class RecipeTreeNode(object): return d + def simplify(self): + # simplify nodes (mainly used to delete doubled Mix Nodes) + for c in self.childs().copy(): + c.simplify() + def serialize(self): r = {} r['type'] = str(self.__class__.__name__) @@ -461,6 +662,10 @@ class RecipeTreeNode(object): def node_score(self): raise NotImplementedError() + def to_instruction(self, state:RecipeInstructionState): + # create an instruction out of a recipe Tree + raise NotImplementedError() + # ### Mix Node @@ -555,11 +760,13 @@ class MixNode(RecipeTreeNode): #p2 = sym_p_a_given_b(ing_b.to_json(), ing_a.to_json(), m_mix, c_mix) #s += 0.5 * p1 + 0.5 * p2 + grouped_ing_a = to_grouped_ingredient(ing_a) + grouped_ing_b = to_grouped_ingredient(ing_b) - ia = m_mix._label_index[ing_a.to_json()] - ib = m_mix._label_index[ing_b.to_json()] + ia = m_grouped_mix._label_index[grouped_ing_a.to_json()] + ib = m_grouped_mix._label_index[grouped_ing_b.to_json()] - if c_mix[ia,ib] > 0 or c_mix[ib,ia] > 0: + if c_grouped_mix[ia,ib] > 0 or c_grouped_mix[ib,ia] > 0: s += 1 @@ -573,12 +780,96 @@ class MixNode(RecipeTreeNode): #return 0.5 * (s_base + s) return s + def simplify(self): + for c in self.childs().copy(): + c.simplify() + + # if our parent is also a Mix Node, we can just delete ourselve + p = self.parent() + + if p is not None: + if type(p) == MixNode: + # just delete ourselve + self.remove() + + def to_instruction(self, state:RecipeInstructionState = None): + """ + returns a RecipeInstructionState + """ + + def english_enum(items, use_and=True): + if len(items) > 1 and use_and: + return ", ".join(items[:-1]) + " and " + items[-1] + return ", ".join(items) + + if state is None: + state = RecipeInstructionState() + + for c in self.childs(): + c.to_instruction(state) + + + text = "" + + # children with instructions + instruction_childs = [] + + # children without instructions + base_childs = [] + + # childre without instructions that are ingredients + ingredient_childs = [] + + for c in self.childs(): + assert type(c) != MixNode + if type(c) == IngredientNode: + ingredient_childs.append(c) + elif c._id not in state.step_by_nodeid: + # action node with no step so far, so a base child + base_childs.append(c) + else: + instruction_childs.append(c) + + if len(base_childs) > 0: + use_and= len(ingredient_childs)==0 and len(instruction_childs)==0 + text = english_enum([state.text_by_nodeid[c._id] for c in base_childs], use_and=use_and) + + + if len(ingredient_childs) > 0: + if len(base_childs) > 0: + text += " and mix it with " + english_enum([state.text_by_nodeid[c._id] for c in ingredient_childs]) + + else: + text = "Mix " + english_enum([state.text_by_nodeid[c._id] for c in ingredient_childs]) + + if len(instruction_childs) > 0: + if len(base_childs) == 0 and len(ingredient_childs) == 0: + text = "Mix together the results of " + else: + text += " and mix it together with the results of " + + text += english_enum([f"step {state.step_by_nodeid[c._id]}" for c in instruction_childs]) + + text += "." + + if type(self.parent()) == ActionNode: + state.add_text(self._id, text, is_instruction=False) + else: + state.add_text(self._id, text, is_instruction=True) + + + return state + + # ### Ingredient Node Class +n_wanted_actions = 2 +gaussian_normalize_factor = 1 / gaussian(n_wanted_actions, n_wanted_actions, 1) + class IngredientNode(RecipeTreeNode): def __init__(self, name, constant=False): super().__init__(name, constant, single_child=True) @@ -593,15 +884,60 @@ class IngredientNode(RecipeTreeNode): return a_list def mutate_node(self): - self._name = random.choice(base_ingredients) + if self._constant: + return + mixes, weights = m_base_mix.get_adjacent(self._name) + self._name = ea_tools.wheel_of_fortune_selection(mixes, weights) + + #self._name = random.choice(base_ingredients) #TODO: change w.r.t. mixing probabilities def traverse_ingredients(self): return [Ingredient(self._name)] + def duplicate_actions_score(self, actions): + + if len(actions) == 0: + return 1 + + seen_actions = set() + n_duplicates = 0 + for act in actions: + if act in seen_actions: + n_duplicates += 1 + else: + seen_actions.add(act) + + duplicate_actions_score = len(seen_actions) / len(actions) + + return duplicate_actions_score + + def duplicate_groups_score(self, actions): + if len(actions) == 0: + return 1 + groups = [AG.groups[a] for a in actions] + groups_set = set(groups) + + return len(groups_set) / len(groups) + def node_score(self): actions = self.get_actions() + ing = Ingredient(self._name) + for a in actions: + ing.apply_action(a) + + heat = heat_score(ing) + prepare = prepare_score(ing) + + score = (heat + prepare) / 2 + score *= self.duplicate_actions_score(actions) + + return score + + """ + actions = self.get_actions() + if len(actions) == 0: if p_ingredient_unprepared(self._name) < 0.2: return 0 @@ -618,10 +954,15 @@ class IngredientNode(RecipeTreeNode): duplicate_actions_score = len(seen_actions) / len(actions) return duplicate_actions_score + """ def dot_node(self, dot): dot.node(self._id, label=f"< {self._name}
node score:{self.node_score():.4f}>", shape="box", style="filled", color="#ffe6cc") + + def to_instruction(self, state:RecipeInstructionState = None): + state.add_text(self._id, self._name, is_instruction=False, is_ingredient=True) + return state # ### Action Node Class @@ -636,7 +977,14 @@ class ActionNode(RecipeTreeNode): def mutate_node(self): if random.choice(range(2)) == 0: # change action - self._name = random.choice(actions) + ings = self.traverse_ingredients() + ing = np.random.choice(ings) + base_ing = ing._base_ingredient + try: + a, w = m_base_act.get_backward_adjacent(base_ing) + self._name = ea_tools.wheel_of_fortune_selection(a,w) + except ValueError: + print("Warning: cannot mutate given node") else: # delete self.remove() @@ -653,6 +1001,20 @@ class ActionNode(RecipeTreeNode): s = 0 + for ing in ings: + try: + + i_act = m_act._x_label_index[self.name()] + i_ing = m_act._y_label_index[ing.to_json()] + + if c_act[i_act,i_ing] > 0: + s += 1 + + except KeyError as e: + #print(f"WARNING: no entry found for: {str(e)}") + pass + + ''' # old method: for ing in ings: try: #score = asym_score(self._name, ing.to_json(), m_act, c_act) @@ -663,176 +1025,215 @@ class ActionNode(RecipeTreeNode): s += score except KeyError as e: pass + ''' return s / len(ings) def dot_node(self, dot): dot.node(self._id, label=f"< {self._name}
node score: {self.node_score():.4f}>", shape="ellipse", style="filled", color="#dae8fc") + + def to_instruction(self, state:RecipeInstructionState = None): + + if state is None: + state = RecipeInstructionState() + + for c in self.childs(): + c.to_instruction(state) + + c = self._child + + if type(c) == MixNode: + text = state.text_by_nodeid[c._id] + f" Then {self._name} it." + state.add_text(self._id, text, True) + elif type(c) == IngredientNode: + text = f"{self._name} {state.text_by_nodeid[c._id]}" + state.add_text(self._id, text, False) + + elif type(c) == ActionNode: + if c._id in state.step_by_nodeid: + text = f"{self._name} the result of step {state.step_by_nodeid[c._id]}" + else: + prev_words = state.text_by_nodeid[c._id].split() + text = f"{prev_words[0]} and {self._name} {' '.join(prev_words[1:])}" + state.add_text(self._id, text, True) + + return state + # ### Tree Class class Tree(object): @staticmethod - def build_initial_tree(ingredients: list, main_ingredients: list, max_n = 4, wheel_turns = 2): + def build_initial_tree(ingredients: list, main_ingredients: list, max_n = 20, wheel_turns = 2): - ''' - # get action sets for ingredients - possible_actions = {} - for ing in ingredients: - action_set, action_weights = m_base_act.get_backward_adjacent(ing) - possible_actions[ing] = set(action_set.tolist()[:5]) - - # now find actions with the same subset - - ings_for_acts = {} - - for ing, acts in possible_actions.items(): - for a in acts: - if a not in ings_for_acts: - ings_for_acts[a] = set() - - ings_for_acts[a].add(ing) + assert set(main_ingredients).issubset(set(ingredients)) + + def does_action_match(ingredient:str, action:str, t = 0.6): + return relative_action_rank(ingredient, action) > t + - ''' # choose randomly an action for each ingredient by the "wheel of fortune" method actions_for_ing = {} for ing in ingredients: actions_for_ing[ing] = set() action_set, action_weights = m_base_act.get_backward_adjacent(ing) - for i in range(wheel_turns): - action = ea_tools.wheel_of_fortune_selection(action_set[:max_n], action_weights[:max_n]) - actions_for_ing[ing].add(action) + if random_heated(ing): + #print(action_set) + action_set, action_weights = filter_set_by_group(action_set, action_weights, "heat") + #print(action_set) + for i in range(wheel_turns): + if ing in main_ingredients: + # if main ingredient: choose by action probability + w = np.array(list(action_weights), dtype=float) + w *= (1.0 / np.sum(w)) + action = np.random.choice(list(action_set), size=1, replace=False, p=w)[0] + else: + # else: choose rank based + action = ea_tools.wheel_of_fortune_selection(action_set[:max_n], action_weights[:max_n]) + actions_for_ing[ing].add(action) + #print(f"action {action} for ing {ing}") #print(ing, action) - ings_for_acts = {} - - for ing, acts in actions_for_ing.items(): - for a in acts: - if a not in ings_for_acts: - ings_for_acts[a] = set() - - ings_for_acts[a].add(ing) - - # now looking for the largest subset and choose one of them randomly - - action_keys = np.array(list(ings_for_acts.keys())) - set_lengths = np.array([len(ings_for_acts[a]) for a in action_keys]) - - # sort lengths - sorted_length_indices = np.argsort(-set_lengths) - - # now perform the following steps: - # * go through all unprocessed ingredients - # * for each ing: find largest action set that is suitable - # * perform this action on all it's ingredients. - # * continue until no ingredient is left - - unprocessed_ings = set(ingredients) - unprocessed_actions = set(ings_for_acts.keys()) - + # create ingredient nodes: ingredient_nodes = {} - + # create ingredient nodes: for ing in ingredients: - ingredient_nodes[ing] = IngredientNode(ing, constant=True) - - i = 0 - - while len(unprocessed_ings) > 0: - - # select random ingredient: - ing = np.random.choice(list(unprocessed_ings)) - - sorted_actions = action_keys[sorted_length_indices] - selected_action = None - - for action in sorted_actions: - if ing in ings_for_acts[action]: - selected_action = action - break - - # found best action. apply it to all matching ingredients - if selected_action is not None: - matching_ingredients = ings_for_acts[selected_action] - - # debugging: - ''' - print(f"choose {selected_action}") - print(f"matching ingredients {matching_ingredients}") - ''' - - if len(matching_ingredients) == 1: - ing = list(matching_ingredients)[0] - ing_node = ingredient_nodes[ing].root() - action_node = ActionNode(selected_action) - action_node.add_child(ing_node) + new_node = IngredientNode(ing, constant=False) + + # check if we should do a preparation step + if random_prepare(ing): + # choose a preparation cooking action + action_set, action_weights = m_act.get_backward_adjacent(Ingredient(ing).to_json()) + action_set, action_weights = filter_set_by_group(action_set, action_weights, "prepare") + if len(action_set) > 0: + action = ea_tools.wheel_of_fortune_selection(action_set[:max_n], action_weights[:max_n]) + act_node = ActionNode(action) + act_node.add_child(new_node) + new_node = act_node + + + ingredient_nodes[ing] = new_node + + # starting now with the actions found for the main ingredients and try to match all ingredients together + # with that: + + unprocessed_ings = set(filter(lambda x: len(actions_for_ing[x]) > 0, ingredients)) + unprocessed_main_ings = set(filter(lambda x: len(actions_for_ing[x]) > 0, main_ingredients)) + + while len(unprocessed_main_ings) > 0: + main_ing = unprocessed_main_ings.pop() + + # random action for that ing: + act = actions_for_ing[main_ing].pop() + + act_node = ActionNode(act) + mix_node = MixNode() + mix_node.add_child(ingredient_nodes[main_ing]) + act_node.add_child(mix_node) + ingredient_nodes[main_ing] = act_node + + unprocessed_ings.remove(main_ing) + + for ing in unprocessed_ings.copy(): + if does_action_match(ing, act): + mix_node.add_child(ingredient_nodes[ing]) + ingredient_nodes[ing] = act_node unprocessed_ings.remove(ing) - #display(action_node.dot()) - - else: - - nodes_to_mix = set() + if ing in unprocessed_main_ings: + unprocessed_main_ings.remove(ing) + + if len(mix_node.childs()) == 1: + mix_node.remove() + + # now make the same with all remaining ingredients: + while len(unprocessed_ings) > 0: + current_ing = unprocessed_ings.pop() + + # random action for that ing: + act = actions_for_ing[current_ing].pop() + + act_node = ActionNode(act) + mix_node = MixNode() + mix_node.add_child(ingredient_nodes[current_ing]) + act_node.add_child(mix_node) + + ingredient_nodes[current_ing] = act_node + + + for ing in unprocessed_ings.copy(): + if does_action_match(ing, act): + mix_node.add_child(ingredient_nodes[ing]) + ingredient_nodes[ing] = act_node + unprocessed_ings.remove(ing) + + if len(mix_node.childs()) == 1: + mix_node.remove() - mix_node = MixNode() - action_node = ActionNode(selected_action) - action_node.add_child(mix_node) - - for ing in matching_ingredients: - nodes_to_mix.add(ingredient_nodes[ing].root()) - - if ing in unprocessed_ings: - unprocessed_ings.remove(ing) - for node in nodes_to_mix: - mix_node.add_child(node) - #display(action_node.dot()) - - # debugging: - ''' - tmp = set([n.root() for n in ingredient_nodes.values()]) - print(f"iteration {i}:") - for n in tmp: - print(n.name()) - display(n.dot()) - ''' - i += 1 - - root_layer = set([n.root() for n in ingredient_nodes.values()]) root_layer_without_parents = [] for node in root_layer: if node.parent() is None: root_layer_without_parents.append(node) - + if len(root_layer_without_parents) == 1: - return root_layer_without_parents[0] - - root_node = MixNode() - for r in root_layer_without_parents: - root_node.add_child(r) + root_node = root_layer_without_parents[0] + + else: + root_node = MixNode() + for r in root_layer_without_parents: + root_node.add_child(r) return root_node + + @staticmethod - def find_ingredients(constant_ingredients, min_additional:int, max_additional:int, top_ings:int=3): + def find_ingredients(constant_ingredients, main_ingredients, min_additional:int, max_additional:int, top_ings:int=3, ing_range=50): ''' create an initial set of ingredients, based on given constant ingredients. min_additional and max_additional gives the range of ingredients that are added to our set ''' seen_items = set(constant_ingredients) - + items = [] scores = [] - + + assert set(main_ingredients).issubset(set(constant_ingredients)) + + # additional ingredients are choosen w.r.t all given ingredients + n_additional_ings = np.random.randint(min_additional, max_additional + 1) + + # extra ings are ingredients choosen specially for the main ingredient + n_extra_ings = int((len(main_ingredients) / len(constant_ingredients)) * n_additional_ings) + + if n_extra_ings > n_additional_ings: + n_extra_ings = n_additional_ings + + + # choose extra ingredients + extra_candidates = [] + extra_weights = [] + + for ing in main_ingredients: + candidates, weights = normalized_score(ing, m_base_mix) + extra_candidates.append(candidates[:ing_range]) + extra_weights.append(weights[:ing_range]) + + extra_ingredients = ea_tools.combined_wheel_of_fortune_selection(extra_candidates, + extra_weights, + n_extra_ings) + for ing in constant_ingredients: # find best matching ingredients best_items = [] best_scores = [] - + candidates, weights = m_base_mix.get_adjacent(ing) i = 0 while i < len(candidates) and len(best_items) < top_ings: @@ -840,32 +1241,29 @@ class Tree(object): best_items.append(candidates[i]) best_scores.append(weights[i]) i += 1 - + items.append(best_items) scores.append(best_scores) - + #TODO: error handling if too few options are availabale! - + additional_ingredients = ea_tools.combined_wheel_of_fortune_selection(items, scores, - np.random.randint( - min_additional, - max_additional + 1 - )) + n_additional_ings - n_extra_ings) - return list(constant_ingredients) + list(additional_ingredients) + return list(constant_ingredients) + list(additional_ingredients) + list(extra_ingredients) @staticmethod - def from_ingredients(ingredients: list, main_ingredients: list, additional_ings=0): + def from_ingredients(ingredients: list, main_ingredients: list, min_additional=0, max_additional=10): root = None constant_ingredients = ingredients - if additional_ings > 0: - ingredients = Tree.find_ingredients(ingredients, min_additional=0, max_additional=additional_ings) + if max_additional > 0: + ingredients = Tree.find_ingredients(ingredients, main_ingredients, min_additional=min_additional, max_additional=max_additional) - root = Tree.build_initial_tree(ingredients) + root = Tree.build_initial_tree(ingredients, main_ingredients) # mark initial ingredient nodes as constant: nodes = root.traverse() @@ -908,17 +1306,22 @@ class Tree(object): # create a dummy entry node self._root = RecipeTreeNode("root", single_child=True) self._root.add_child(root) + self._touched = True def root(self): return self._root.child() def mutate(self): + self._touched = True nodes = self.root().traverse() weights = [n.n_mutate_options() for n in nodes] n = random.choices(nodes, weights)[0] n.mutate() + + # check for simplification after modification + # self.root().simplify() def dot(self): return self.root().dot() @@ -952,15 +1355,15 @@ class Tree(object): self._ing_scores.append(n.node_score()) self._n_ing_nodes += 1 + seen_ingredients = set() self._n_duplicates = 0 - seen_actions = set() for n in nodes: - if type(n) == ActionNode: - if n.name() in seen_actions: + if type(n) == IngredientNode: + if n.name() in seen_ingredients: self._n_duplicates += 1 else: - seen_actions.add(n.name()) + seen_ingredients.add(n.name()) self._mix_scores = np.array(self._mix_scores) self._act_scores = np.array(self._act_scores) @@ -976,42 +1379,37 @@ class Tree(object): def ing_scores(self): return self._ing_scores - def bounds_mix_scores(self): + def score(self): + if not self._touched: + return self._score - nonzeros = self._mix_scores[self._mix_scores > 0] - if len(nonzeros) > 0: - mmax = np.max(nonzeros) - mmin = np.min(nonzeros) - return mmin, mmax - else: - return None, None - - def bounds_act_scores(self): + self.collect_scores() + s_mix = self.mix_scores() + s_act = self.action_scores() + s_ing = self.ing_scores() - if len(self._act_scores) == 0: - return None, None - nonzeros = self._act_scores[self._act_scores > 0] - if len(nonzeros) > 0: - mmax = np.max(nonzeros) - mmin = np.min(nonzeros) - return mmin, mmax - else: - return None, None - - def normalized_mix_scores(self, min, max): - if (max != min): - normalized = (self._mix_scores - min)/(max-min) - normalized[normalized <= 0] = 0 - return normalized - else: - return None - - def normalized_act_scores(self, min, max): - if len(self._act_scores) == 0 or max == min: - return None - normalized = (self._act_scores - min)/(max-min) - normalized[normalized <= 0] = 0 - return normalized + n = len(s_mix) + len(s_act) + len(s_ing) + + avg_mix = np.average(s_mix) if len(s_mix) > 0 else 1 + avg_act = np.average(s_act) if len(s_act) > 0 else 1 + avg_ing = np.average(s_ing) if len(s_ing) > 0 else 1 + + sum_mix = np.sum(s_mix) if len(s_mix) > 0 else 0 + sum_act = np.sum(s_act) if len(s_act) > 0 else 0 + sum_ing = np.sum(s_ing) if len(s_ing) > 0 else 0 + + self._touched = False + + # boost creativity + if len(s_act) < 3: + self._score = 0 + elif len(s_ing) < 3: + self._score = 0 + else: + self._score = (sum_mix + sum_act + sum_ing) / n + self._score *= (len(s_ing) - self._n_duplicates) / len(s_ing) + + return self._score def copy(self): return Tree.from_serialization(self.serialize()) @@ -1020,21 +1418,18 @@ class Tree(object): # ## Population class Population(object): - def __init__(self, start_ingredients, main_ingredients, n_population = 10, max_additional_ings=0): - self.population = [Tree.from_ingredients(start_ingredients, main_ingredients, additional_ings=max_additional_ings) for i in range(n_population)] + def __init__(self, start_ingredients, main_ingredients, n_population = 50, min_additional=0, max_additional=15): + self.population = [] + for i in tqdm(range(n_population), desc="build initial population"): + self.population.append(Tree.from_ingredients(start_ingredients, main_ingredients, min_additional=min_additional, max_additional=max_additional)) self._n = n_population - self._mix_min = None - self._mix_max = None - self._act_min = None - self._act_max = None - self._mix_scores = None - self._act_scores = None - self._scores = None def mutate(self): for tree in self.population.copy(): t_clone = tree.copy() t_clone.mutate() + t_clone.mutate() + #t_clone.mutate() self.population.append(t_clone) def pairwise_competition(self): @@ -1046,7 +1441,8 @@ class Population(object): i_a = indices[2*i] i_b = indices[2*i+1] - if self._scores[i_a] > self._scores[i_b]: + + if self.population[i_a].score() > self.population[i_b].score(): new_population.append(self.population[i_a]) else: new_population.append(self.population[i_b]) @@ -1054,102 +1450,48 @@ class Population(object): self.population = new_population def hold_best(self, n=10): - sorted_indices = np.argsort(-self._scores) + scores = [tree.score() for tree in self.population] + + sorted_indices = np.argsort(-scores) self.population = np.array(self.population)[sorted_indices[:n]].tolist() - def analyse_scores(self): - for tree in self.population: - min, max = tree.bounds_mix_scores() - if min is not None and max is not None: - if self._mix_min is None or min < self._mix_min: - self._mix_min = min - if self._mix_max is None or max > self._mix_max: - self._mix_max = max - - min, max = tree.bounds_act_scores() - if min is not None and max is not None: - if self._act_min is None or min < self._act_min: - self._act_min = min - if self._act_max is None or max > self._act_max: - self._act_max = max - - def single_score(self, mix_scores, act_scores, ing_scores): - if mix_scores is None or act_scores is None or ing_scores is None: - return 0 - score = (0.5 * np.average(mix_scores) + 0.5 * np.average(act_scores)) * np.average(ing_scores) - # judging also how many actions we have. So far use a gaussian with mean at number of ingredients - - score *= gaussian(len(act_scores), len(mix_scores), 1) - return score - - - - def collect_scores(self): - for tree in tqdm(self.population, desc="evaluate population scores", leave=False): - tree.collect_scores() - - self.analyse_scores() - - if self._mix_min is not None and self._mix_max is not None: - self._mix_scores = [t.normalized_mix_scores(self._mix_min, self._mix_max) for t in self.population] - else: - # if no normalization can be done, all values are the same or 0. - # in this case just fill in zeros as score - self._mix_scores = [np.zeros(shape=t._mix_scores.shape) for t in self.population] - - if self._act_min is not None and self._act_max is not None: - self._act_scores = [t.normalized_act_scores(self._act_min, self._act_max) for t in self.population] - else: - self._act_scores = [np.zeros(shape=t._act_scores) for t in self.population] - - self._scores = [] - for i in range(len(self._mix_scores)): - #print (self._mix_scores[i], self._act_scores[i]) - if self._act_scores is None or self._mix_scores is None or self._act_scores[i] is None: - self._scores.append(0) - continue - - s = self.single_score(self._mix_scores[i], self._act_scores[i], self.population[i].ing_scores()) - self._scores.append(s) - self._scores = np.array(self._scores) - def run(self, n=50): for i in tqdm(range(n), desc="run evolutionary cycles"): self.mutate() - self.mutate() - self.collect_scores() - - #self.pairwise_competition() + #self.mutate() #self.collect_scores() - self.hold_best(self._n) + + self.pairwise_competition() + #self.collect_scores() + #self.hold_best(self._n) - def plot_population(self, collect_scores=True): - if (collect_scores): - self.collect_scores() - #print(self._mix_scores) - #print(self._act_scores) - #print(self._scores) - for i, t in enumerate(self.population): - if (collect_scores): - display(self._scores[i]) - display(t.root().dot()) + def plot_population(self, n_best=10): + scores = [tree.score() for tree in self.population] + + ii = np.argsort(-np.array(scores))[:n_best] + + for i in ii: + self.population[i].root().simplify() + display(self.population[i].root().dot()) + display(Markdown(f"**Recipe Score**: {scores[i]}")) + display(self.population[i].root().to_instruction().to_markdown()) # ## Run Evolutionary Algorithm -#p = Population(["bacon", "tomato", "onion"],['noodle'], max_additional_ings=6) +# p = Population(["noodle"],['noodle'], min_additional=4, max_additional=13, n_population = 50) #p_ingredient_unprepared(list(p.population[0].root().childs())[0]._name) < 0.2 -#p.run(100) +# p.run(50) -#p.plot_population(collect_scores=False) +# p.plot_population(n_best=20)