{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Evolutionary Algorithm" ] }, { "cell_type": "code", "execution_count": 104, "metadata": {}, "outputs": [ { "data": { "text/html": [ " \n", " " ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import sys\n", "sys.path.append(\"../\")\n", "sys.path.append(\"../RecipeAnalysis/\")\n", "\n", "import settings\n", "\n", "import pycrfsuite\n", "\n", "import json\n", "\n", "import db.db_settings as db_settings\n", "from db.database_connection import DatabaseConnection\n", "\n", "from Tagging.conllu_generator import ConlluGenerator\n", "from Tagging.crf_data_generator import *\n", "\n", "from RecipeAnalysis.Recipe import Ingredient\n", "\n", "from difflib import SequenceMatcher\n", "\n", "import numpy as np\n", "\n", "import plotly.graph_objs as go\n", "from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot\n", "from plotly.subplots import make_subplots\n", "init_notebook_mode(connected=True)\n", "\n", "from graphviz import Digraph\n", "\n", "import itertools\n", "\n", "import random\n", "\n", "import plotly.io as pio\n", "pio.renderers.default = \"jupyterlab\"\n", "\n", "from IPython.display import Markdown, HTML, display\n", "\n", "from copy import deepcopy" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## load adjacency matrices" ] }, { "cell_type": "code", "execution_count": 105, "metadata": {}, "outputs": [], "source": [ "import pickle\n", "m_act = pickle.load(open(\"m_act.pickle\", \"rb\"))\n", "m_mix = pickle.load(open(\"m_mix.pickle\", \"rb\"))\n", "m_base_act = pickle.load(open(\"m_base_act.pickle\", \"rb\"))\n", "m_base_mix = pickle.load(open(\"m_base_mix.pickle\", \"rb\"))\n", "\n", "c_act = m_act.get_csr()\n", "c_mix = m_mix.get_csr()\n", "c_base_act = m_base_act.get_csr()\n", "c_base_mix = m_base_mix.get_csr()\n" ] }, { "cell_type": "code", "execution_count": 106, "metadata": {}, "outputs": [], "source": [ "actions = m_act.get_labels()[0]" ] }, { "cell_type": "code", "execution_count": 107, "metadata": {}, "outputs": [], "source": [ "base_ingredients = m_base_mix.get_labels()" ] }, { "cell_type": "code", "execution_count": 108, "metadata": {}, "outputs": [], "source": [ "sym_label_buffer = {}\n", "fw_label_buffer = {}\n", "bw_label_buffer = {}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### helper functions for adjacency matrices" ] }, { "cell_type": "code", "execution_count": 109, "metadata": {}, "outputs": [], "source": [ "def get_sym_adjacent(key, m, c):\n", " index = m._label_index[key]\n", " i1 = c[index,:].nonzero()[1]\n", " i2 = c[:,index].nonzero()[0]\n", " \n", " i = np.concatenate((i1,i2))\n", " \n", " if m in sym_label_buffer:\n", " names = sym_label_buffer[m][i]\n", " else:\n", " names = np.array(m.get_labels())\n", " sym_label_buffer[m] = names\n", " names = names[i]\n", " \n", " counts = np.concatenate((c[index, i1].toarray().flatten(), c[i2, index].toarray().flatten()))\n", " \n", " s = np.argsort(-counts)\n", " \n", " return names[s], counts[s]" ] }, { "cell_type": "code", "execution_count": 110, "metadata": {}, "outputs": [], "source": [ "def get_forward_adjacent(key, m, c):\n", " index = m._x_label_index[key]\n", " i = c[index,:].nonzero()[1]\n", " \n", " if m in fw_label_buffer:\n", " names = fw_label_buffer[m][i]\n", " else:\n", " names = np.array(m._y_labels)\n", " fw_label_buffer[m] = names\n", " names = names[i]\n", " \n", " \n", " counts = c[index, i].toarray().flatten()\n", " \n", " s = np.argsort(-counts)\n", " \n", " return names[s], counts[s]" ] }, { "cell_type": "code", "execution_count": 111, "metadata": {}, "outputs": [], "source": [ "def get_backward_adjacent(key, m, c):\n", " index = m._y_label_index[key]\n", " i = c[:,index].nonzero()[0]\n", " \n", " if m in bw_label_buffer:\n", " names = bw_label_buffer[m][i]\n", " else:\n", " names = np.array(m._x_labels)\n", " bw_label_buffer[m] = names\n", " names = names[i]\n", " \n", " \n", " counts = c[i, index].toarray().flatten()\n", " \n", " s = np.argsort(-counts)\n", " \n", " return names[s], counts[s]" ] }, { "cell_type": "code", "execution_count": 112, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(array(['heat', 'simmer', 'cook', 'bake', 'boil', 'place', 'cut', 'slice',\n", " 'chop', 'dice', 'pour', 'drain', 'cool', 'refrigerate', 'thicken',\n", " 'warm', 'chill', 'brown', 'blend', 'spread', 'grill', 'fry',\n", " 'saute', 'mash', 'melt', 'whisk', 'peel', 'freeze', 'wash',\n", " 'grate', 'squeeze', 'broil', 'marinate', 'skim', 'soak', 'mince',\n", " 'break', 'open', 'sour', 'thaw', 'beat', 'wipe', 'carve', 'curdle'],\n", " dtype=' 1 and p._single_child)\n", " \n", " for c in childs:\n", " self.remove_child(c)\n", " \n", " if p is not None:\n", " p.remove_child(self)\n", " \n", " if self._single_child and self._child is not None and p._name == self._child._name:\n", " # two adjacent nodes with same name would remain after deletion.\n", " # merge them! (by adding the child's childs to our parent instead of our childs)\n", " childs = self._child.childs()\n", " self._child.remove()\n", " \n", " \n", " for c in childs:\n", " p.add_child(c)\n", " \n", " def insert_before(self, n):\n", " p = self._parent\n", " if p is not None:\n", " p.remove_child(self)\n", " p.add_child(n)\n", " n.add_child(self)\n", " \n", " def mutate(self):\n", " n_node = self.n_node_mutate_options()\n", " n_edge = self.n_edge_mutate_options()\n", " \n", " choice = random.choice(range(n_node + n_edge))\n", " if choice < n_node:\n", " self.mutate_node()\n", " else:\n", " self.mutate_edges()\n", " \n", " def mutate_edges(self):\n", " ings = self.traverse_ingredients()\n", " ing = random.choice(ings)\n", " \n", " a, w = get_backward_adjacent(ing._base_ingredient, m_base_act, c_base_act)\n", " \n", " action = random.choices(a, w)[0]\n", " self.insert_before(ActionNode(action))\n", " \n", " def mutate_node(self):\n", " raise NotImplementedError\n", " \n", " def n_node_mutate_options(self):\n", " \n", " return 0 if self._constant else 1\n", " \n", " def n_edge_mutate_options(self):\n", " n = 1 if self._parent is not None else 0\n", " return n\n", " \n", " def n_mutate_options(self):\n", " return self.n_edge_mutate_options() + self.n_node_mutate_options()\n", " \n", " def dot_node(self, dot):\n", " raise NotImplementedError()\n", " \n", " def dot(self, d=None):\n", " if d is None:\n", " d = Digraph()\n", " self.dot_node(d)\n", " \n", " else:\n", " self.dot_node(d)\n", " if self._parent is not None:\n", " d.edge(self._parent._id, self._id)\n", " \n", " \n", " for c in self.childs():\n", " c.dot(d)\n", " \n", " return d\n", " \n", " def serialize(self):\n", " r = {}\n", " r['type'] = str(self.__class__.__name__)\n", " r['id'] = self._id\n", " r['parent'] = self._parent._id if self._parent is not None else None\n", " r['name'] = self._name\n", " r['childs'] = [c._id for c in self.childs()]\n", " r['constant'] = self._constant\n", " r['single_child'] = self._single_child\n", " \n", " return r\n", " \n", " def node_score(self):\n", " raise NotImplementedError()\n", " \n", " " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Mix Node" ] }, { "cell_type": "code", "execution_count": 119, "metadata": {}, "outputs": [], "source": [ "class MixNode(RecipeTreeNode):\n", " def __init__(self, constant=False):\n", " super().__init__(\"mix\", constant, single_child=False)\n", " \n", " def dot_node(self, dot):\n", " dot.node(self._id, label=f\"{self._name} ({self.node_score()})\", shape=\"diamond\")\n", " \n", " def split(self, set_above, set_below, node_between):\n", " assert len(set_above.difference(self.childs())) == 0\n", " assert len(set_below.difference(self.childs())) == 0\n", " \n", " n_above = MixNode()\n", " n_below = MixNode()\n", " \n", " p = self.parent()\n", " \n", " for c in self.childs().copy():\n", " self.remove_child(c)\n", " self.remove()\n", " \n", " for c in set_below:\n", " n_below.add_child(c)\n", " \n", " for c in set_above:\n", " n_above.add_child(c)\n", " \n", " n_above.add_child(node_between)\n", " node_between.add_child(n_below)\n", " \n", " if p is not None:\n", " p.add_child(n_above)\n", " \n", " # test whether the mix nodes are useless\n", " if len(n_above.childs()) == 1:\n", " n_above.remove()\n", " \n", " if len(n_below.childs()) == 1:\n", " n_below.remove()\n", " \n", " def n_node_mutate_options(self):\n", " return 0 if self._constant or len(self.childs()) <= 2 else len(self.childs())\n", " \n", " def mutate_node(self):\n", " \n", " childs = self.childs()\n", " \n", " if len(childs) <= 2:\n", " print(\"Warning: cannot modify mix node\")\n", " return\n", " \n", " childs = random.sample(childs, len(childs))\n", " \n", " n = random.choice(range(1, len(childs)-1))\n", " \n", " between_node = ActionNode(random.choice(actions))\n", " \n", " self.split(set(childs[:n]), set(childs[n:]), between_node)\n", " \n", " \n", " def node_score(self):\n", " child_ingredients = [c.traverse_ingredients() for c in self.childs()]\n", " \n", " tmp_set = set()\n", " cumulative_sets = []\n", " \n", " pairwise_tuples = []\n", " \n", " for c in child_ingredients:\n", " if len(tmp_set) > 0:\n", " cumulative_sets.append(tmp_set)\n", " pairwise_tuples += [x for x in itertools.product(tmp_set, c)]\n", " tmp_set = tmp_set.union(set(c))\n", " \n", " s_base = 0\n", " s = 0\n", " \n", " for ing_a, ing_b in pairwise_tuples:\n", " try:\n", " #s_base += sym_score(ing_a._base_ingredient, ing_b._base_ingredient, m_base_mix, c_base_mix)\n", " \n", " #s += sym_score(ing_a.to_json(), ing_b.to_json(), m_mix, c_mix)\n", " p1 = sym_p_a_given_b(ing_a.to_json(), ing_b.to_json(), m_mix, c_mix)\n", " p2 = sym_p_a_given_b(ing_b.to_json(), ing_a.to_json(), m_mix, c_mix)\n", " \n", " s += 0.5 * p1 + 0.5 * p2\n", " \n", " except:\n", " pass\n", " \n", " #s_base /= len(pairwise_tuples)\n", " s /= len(pairwise_tuples)\n", " \n", " #return 0.5 * (s_base + s)\n", " return s\n", " \n", " \n", " \n", " " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Ingredient Node Class" ] }, { "cell_type": "code", "execution_count": 120, "metadata": {}, "outputs": [], "source": [ "class IngredientNode(RecipeTreeNode):\n", " def __init__(self, name, constant=False):\n", " super().__init__(name, constant, single_child=True)\n", " \n", " def get_actions(self):\n", " a_list = []\n", " n = self.parent()\n", " while n is not None:\n", " if type(n) == ActionNode:\n", " a_list.append(n.name())\n", " n = n.parent()\n", " return a_list\n", " \n", " def mutate_node(self):\n", " self._name = random.choice(base_ingredients)\n", " #TODO: change w.r.t. mixing probabilities \n", " \n", " def traverse_ingredients(self):\n", " return [Ingredient(self._name)]\n", " \n", " def node_score(self):\n", " actions = self.get_actions()\n", " \n", " if len(actions) == 0:\n", " return 1\n", " \n", " seen_actions = set()\n", " n_duplicates = 0\n", " for act in actions:\n", " if act in seen_actions:\n", " n_duplicates += 1\n", " else:\n", " seen_actions.add(act)\n", " \n", " return len(seen_actions) / len(actions)\n", " \n", " \n", " def dot_node(self, dot):\n", " dot.node(self._id, label=f\"{self._name} ({self.node_score()})\", shape=\"box\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Action Node Class" ] }, { "cell_type": "code", "execution_count": 121, "metadata": {}, "outputs": [], "source": [ "class ActionNode(RecipeTreeNode):\n", " def __init__(self, name, constant=False):\n", " super().__init__(name, constant, single_child=True)\n", " \n", " def n_node_mutate_options(self):\n", " # beacause we can change or remove ourselve!\n", " return 0 if self._constant else 2 \n", " def mutate_node(self):\n", " if random.choice(range(2)) == 0:\n", " # change action\n", " self._name = random.choice(actions)\n", " else:\n", " # delete\n", " self.remove()\n", " \n", " def traverse_ingredients(self):\n", " ingredient_set = super().traverse_ingredients()\n", " for ing in ingredient_set:\n", " ing.apply_action(self._name)\n", " \n", " return ingredient_set\n", " \n", " def node_score(self):\n", " ings = self.child().traverse_ingredients()\n", " \n", " s = 0\n", " \n", " for ing in ings:\n", " try:\n", " #score = asym_score(self._name, ing.to_json(), m_act, c_act)\n", " #base_score = asym_score(self._name, ing._base_ingredient, m_base_act, c_base_act)\n", " \n", " score = fw_p_a_given_b(self._name, ing._base_ingredient, m_base_act, c_base_act)\n", " \n", " s += score\n", " except KeyError as e:\n", " pass\n", " \n", " \n", " return s / len(ings)\n", " \n", " def dot_node(self, dot):\n", " dot.node(self._id, label=f\"{self._name} ({self.node_score()})\", shape=\"ellipse\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Tree Class" ] }, { "cell_type": "code", "execution_count": 122, "metadata": {}, "outputs": [], "source": [ "class Tree(object):\n", " \n", " @staticmethod\n", " def from_ingredients(ingredients: list):\n", " root = MixNode()\n", " \n", " for ing in ingredients:\n", " root.add_child(IngredientNode(ing, constant=True))\n", " \n", " return Tree(root)\n", " \n", " @staticmethod\n", " def from_serialization(s):\n", " def empty_node(raw_n):\n", " if raw_n['type'] == \"MixNode\":\n", " node = MixNode(raw_n['constant'])\n", " elif raw_n['type'] == \"IngredientNode\":\n", " node = IngredientNode(raw_n['name'], raw_n['constant'])\n", " elif raw_n['type'] == \"ActionNode\":\n", " node = ActionNode(raw_n['name'], raw_n['constant'])\n", " else:\n", " print(\"unknown node detected\")\n", " return\n", " \n", " return node\n", " \n", " nodes = {}\n", " for n in s:\n", " nodes[n['id']] = empty_node(n)\n", " \n", " for n in s:\n", " childs = n['childs']\n", " id = n['id']\n", " for c in childs:\n", " nodes[id].add_child(nodes[c])\n", " \n", " return Tree(nodes[s[0]['id']])\n", " \n", " \n", " def __init__(self, root):\n", " # create a dummy entry node\n", " self._root = RecipeTreeNode(\"root\", single_child=True)\n", " self._root.add_child(root)\n", " \n", " def root(self):\n", " return self._root.child()\n", " \n", " def mutate(self):\n", " nodes = self.root().traverse()\n", " weights = [n.n_mutate_options() for n in nodes]\n", " \n", " n = random.choices(nodes, weights)[0]\n", " \n", " n.mutate()\n", " \n", " def dot(self):\n", " return self.root().dot()\n", " \n", " def serialize(self):\n", " return [n.serialize() for n in self.root().traverse()]\n", " \n", " def structure_score(self):\n", " n_duplicates = 0\n", " \n", " \n", " def collect_scores(self):\n", " self._mix_scores = []\n", " self._act_scores = []\n", " self._ing_scores = []\n", " \n", " nodes = self.root().traverse()\n", " self._n_mix_nodes = 0\n", " self._n_act_nodes = 0\n", " self._n_ing_nodes = 0\n", " \n", " s = 0\n", " for n in nodes:\n", " if type(n) == MixNode:\n", " self._mix_scores.append(n.node_score())\n", " self._n_mix_nodes += 1\n", " if type(n) == ActionNode:\n", " self._act_scores.append(n.node_score())\n", " self._n_act_nodes += 1\n", " if type(n) == IngredientNode:\n", " self._ing_scores.append(n.node_score())\n", " self._n_ing_nodes += 1\n", " \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", " self._n_duplicates += 1\n", " else:\n", " seen_actions.add(n.name())\n", " \n", " self._mix_scores = np.array(self._mix_scores)\n", " self._act_scores = np.array(self._act_scores)\n", " self._ing_scores = np.array(self._ing_scores)\n", " \n", " \n", " def mix_scores(self):\n", " return self._mix_scores\n", " \n", " def action_scores(self):\n", " return self._act_scores\n", " \n", " def ing_scores(self):\n", " return self._ing_scores\n", " \n", " def bounds_mix_scores(self):\n", " \n", " nonzeros = self._mix_scores[self._mix_scores > 0]\n", " if len(nonzeros) > 0:\n", " mmax = np.max(nonzeros)\n", " mmin = np.min(nonzeros)\n", " return mmin, mmax\n", " else:\n", " return None, None\n", " \n", " def bounds_act_scores(self):\n", " \n", " if len(self._act_scores) == 0:\n", " return None, None\n", " nonzeros = self._act_scores[self._act_scores > 0]\n", " if len(nonzeros) > 0:\n", " mmax = np.max(nonzeros)\n", " mmin = np.min(nonzeros)\n", " return mmin, mmax\n", " else:\n", " return None, None\n", " \n", " def normalized_mix_scores(self, min, max):\n", " if (max != min):\n", " normalized = (self._mix_scores - min)/(max-min)\n", " normalized[normalized <= 0] = 0\n", " return normalized\n", " else:\n", " return None\n", " \n", " def normalized_act_scores(self, min, max):\n", " if len(self._act_scores) == 0 or max == min:\n", " return None\n", " normalized = (self._act_scores - min)/(max-min)\n", " normalized[normalized <= 0] = 0\n", " return normalized\n", " \n", " def copy(self):\n", " return Tree.from_serialization(self.serialize())\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Population" ] }, { "cell_type": "code", "execution_count": 123, "metadata": {}, "outputs": [], "source": [ "class Population(object):\n", " def __init__(self, start_ingredients, n_population = 10):\n", " self.population = [Tree.from_ingredients(start_ingredients) for i in range(n_population)]\n", " self._n = n_population\n", " self._mix_min = None\n", " self._mix_max = None\n", " self._act_min = None\n", " self._act_max = None\n", " self._mix_scores = None\n", " self._act_scores = None\n", " self._scores = None\n", " \n", " def mutate(self):\n", " for tree in self.population.copy():\n", " t_clone = tree.copy()\n", " t_clone.mutate()\n", " self.population.append(t_clone)\n", " \n", " def pairwise_competition(self):\n", " new_population = []\n", " indices = list(range(len(self.population)))\n", " random.shuffle(indices)\n", " \n", " for i in range(len(self.population) // 2):\n", " i_a = indices[2*i]\n", " i_b = indices[2*i+1]\n", " \n", " if self._scores[i_a] > self._scores[i_b]:\n", " new_population.append(self.population[i_a])\n", " else:\n", " new_population.append(self.population[i_b])\n", " \n", " self.population = new_population\n", " \n", " def hold_best(self, n=10):\n", " sorted_indices = np.argsort(-self._scores)\n", " \n", " self.population = np.array(self.population)[sorted_indices[:n]].tolist()\n", " \n", " def analyse_scores(self):\n", " for tree in self.population:\n", " min, max = tree.bounds_mix_scores()\n", " if min is not None and max is not None:\n", " if self._mix_min is None or min < self._mix_min:\n", " self._mix_min = min\n", " if self._mix_max is None or max > self._mix_max:\n", " self._mix_max = max\n", " \n", " min, max = tree.bounds_act_scores()\n", " if min is not None and max is not None:\n", " if self._act_min is None or min < self._act_min:\n", " self._act_min = min\n", " if self._act_max is None or max > self._act_max:\n", " self._act_max = max\n", " \n", " def single_score(self, mix_scores, act_scores, ing_scores):\n", " return np.average(mix_scores) * np.average(act_scores) * np.average(ing_scores)\n", " \n", " \n", " \n", " def collect_scores(self):\n", " for tree in self.population:\n", " tree.collect_scores()\n", " \n", " self.analyse_scores()\n", " \n", " if self._mix_min is not None and self._mix_max is not None:\n", " self._mix_scores = [t.normalized_mix_scores(self._mix_min, self._mix_max) for t in self.population]\n", " \n", " if self._act_min is not None and self._act_max is not None:\n", " self._act_scores = [t.normalized_act_scores(self._act_min, self._act_max) for t in self.population]\n", " \n", " self._scores = []\n", " for i in range(len(self._mix_scores)):\n", " #print (self._mix_scores[i], self._act_scores[i])\n", " if self._act_scores is None or self._mix_scores is None or self._act_scores[i] is None:\n", " self._scores.append(0)\n", " continue\n", " \n", " self._scores.append(self.single_score(self._mix_scores[i], self._act_scores[i], self.population[i].ing_scores()))\n", " self._scores = np.array(self._scores)\n", " \n", " def run(self, n=50):\n", " for i in range(n):\n", " print(i)\n", " self.mutate()\n", " self.mutate()\n", " self.collect_scores()\n", " #self.pairwise_competition()\n", " #self.collect_scores()\n", " self.hold_best(self._n)\n", " \n", " \n", " \n", " def plot_population(self):\n", " self.collect_scores()\n", " #print(self._mix_scores)\n", " #print(self._act_scores)\n", " #print(self._scores)\n", " for i, t in enumerate(self.population):\n", " print(self._scores[i])\n", " display(t.root().dot())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Run Evolutionary Algorithm" ] }, { "cell_type": "code", "execution_count": 150, "metadata": {}, "outputs": [], "source": [ "p = Population([\"noodle\",\"tomato\", \"onion\"])" ] }, { "cell_type": "code", "execution_count": 154, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "1\n", "2\n", "3\n", "4\n" ] } ], "source": [ "p.run(5)" ] }, { "cell_type": "code", "execution_count": 155, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([1.])" ] }, "execution_count": 155, "metadata": {}, "output_type": "execute_result" } ], "source": [ "p.population[0].action_scores()" ] }, { "cell_type": "code", "execution_count": 156, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0.27112203844434507\n" ] }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "%3\n", "\n", "\n", "\n", "3727\n", "\n", "mix (0.0)\n", "\n", "\n", "\n", "3730\n", "\n", "mix (0.22564102564102564)\n", "\n", "\n", "\n", "3727->3730\n", "\n", "\n", "\n", "\n", "\n", "3728\n", "\n", "noodle (1)\n", "\n", "\n", "\n", "3727->3728\n", "\n", "\n", "\n", "\n", "\n", "3731\n", "\n", "tomato (1)\n", "\n", "\n", "\n", "3730->3731\n", "\n", "\n", "\n", "\n", "\n", "3732\n", "\n", "cook (0.9999999999999999)\n", "\n", "\n", "\n", "3730->3732\n", "\n", "\n", "\n", "\n", "\n", "3733\n", "\n", "onion (1.0)\n", "\n", "\n", "\n", "3732->3733\n", "\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "0.2576130268096809\n" ] }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "%3\n", "\n", "\n", "\n", "3716\n", "\n", "cook (0.9219858156028368)\n", "\n", "\n", "\n", "3717\n", "\n", "bake (0.5054716884821958)\n", "\n", "\n", "\n", "3716->3717\n", "\n", "\n", "\n", "\n", "\n", "3718\n", "\n", "mix (0.0)\n", "\n", "\n", "\n", "3717->3718\n", "\n", "\n", "\n", "\n", "\n", "3721\n", "\n", "simmer (0.6899063929501801)\n", "\n", "\n", "\n", "3718->3721\n", "\n", "\n", "\n", "\n", "\n", "3719\n", "\n", "cut (0.25)\n", "\n", "\n", "\n", "3718->3719\n", "\n", "\n", "\n", "\n", "\n", "3722\n", "\n", "mix (0.3897435897435897)\n", "\n", "\n", "\n", "3721->3722\n", "\n", "\n", "\n", "\n", "\n", "3726\n", "\n", "chop (0.21089630931458697)\n", "\n", "\n", "\n", "3722->3726\n", "\n", "\n", "\n", "\n", "\n", "3723\n", "\n", "tomato (1.0)\n", "\n", "\n", "\n", "3722->3723\n", "\n", "\n", "\n", "\n", "\n", "3724\n", "\n", "onion (1.0)\n", "\n", "\n", "\n", "3726->3724\n", "\n", "\n", "\n", "\n", "\n", "3720\n", "\n", "noodle (1.0)\n", "\n", "\n", "\n", "3719->3720\n", "\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "0.23576471183610126\n" ] }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "%3\n", "\n", "\n", "\n", "3403\n", "\n", "mix (0.0)\n", "\n", "\n", "\n", "3404\n", "\n", "cook (1.0)\n", "\n", "\n", "\n", "3403->3404\n", "\n", "\n", "\n", "\n", "\n", "3407\n", "\n", "mix (0.20029027576197386)\n", "\n", "\n", "\n", "3403->3407\n", "\n", "\n", "\n", "\n", "\n", "3406\n", "\n", "noodle (1.0)\n", "\n", "\n", "\n", "3404->3406\n", "\n", "\n", "\n", "\n", "\n", "3409\n", "\n", "onion (1)\n", "\n", "\n", "\n", "3407->3409\n", "\n", "\n", "\n", "\n", "\n", "3408\n", "\n", "tomato (1)\n", "\n", "\n", "\n", "3407->3408\n", "\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "0.23576471183610126\n" ] }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "%3\n", "\n", "\n", "\n", "3708\n", "\n", "mix (0.0)\n", "\n", "\n", "\n", "3709\n", "\n", "cook (1.0)\n", "\n", "\n", "\n", "3708->3709\n", "\n", "\n", "\n", "\n", "\n", "3712\n", "\n", "mix (0.20029027576197386)\n", "\n", "\n", "\n", "3708->3712\n", "\n", "\n", "\n", "\n", "\n", "3711\n", "\n", "noodle (1.0)\n", "\n", "\n", "\n", "3709->3711\n", "\n", "\n", "\n", "\n", "\n", "3714\n", "\n", "onion (1)\n", "\n", "\n", "\n", "3712->3714\n", "\n", "\n", "\n", "\n", "\n", "3713\n", "\n", "tomato (1)\n", "\n", "\n", "\n", "3712->3713\n", "\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "0.21735554335886978\n" ] }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "%3\n", "\n", "\n", "\n", "4004\n", "\n", "cook (0.9219858156028368)\n", "\n", "\n", "\n", "4006\n", "\n", "mix (0.0)\n", "\n", "\n", "\n", "4004->4006\n", "\n", "\n", "\n", "\n", "\n", "4010\n", "\n", "noodle (1.0)\n", "\n", "\n", "\n", "4006->4010\n", "\n", "\n", "\n", "\n", "\n", "4007\n", "\n", "mix (0.20029027576197386)\n", "\n", "\n", "\n", "4006->4007\n", "\n", "\n", "\n", "\n", "\n", "4009\n", "\n", "tomato (1.0)\n", "\n", "\n", "\n", "4007->4009\n", "\n", "\n", "\n", "\n", "\n", "4008\n", "\n", "onion (1.0)\n", "\n", "\n", "\n", "4007->4008\n", "\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "0.21735554335886978\n" ] }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "%3\n", "\n", "\n", "\n", "3909\n", "\n", "cook (0.9219858156028368)\n", "\n", "\n", "\n", "3911\n", "\n", "mix (0.0)\n", "\n", "\n", "\n", "3909->3911\n", "\n", "\n", "\n", "\n", "\n", "3915\n", "\n", "noodle (1.0)\n", "\n", "\n", "\n", "3911->3915\n", "\n", "\n", "\n", "\n", "\n", "3912\n", "\n", "mix (0.20029027576197386)\n", "\n", "\n", "\n", "3911->3912\n", "\n", "\n", "\n", "\n", "\n", "3913\n", "\n", "onion (1.0)\n", "\n", "\n", "\n", "3912->3913\n", "\n", "\n", "\n", "\n", "\n", "3914\n", "\n", "tomato (1.0)\n", "\n", "\n", "\n", "3912->3914\n", "\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "0.20962497813112532\n" ] }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "%3\n", "\n", "\n", "\n", "3947\n", "\n", "cook (0.9219858156028368)\n", "\n", "\n", "\n", "3948\n", "\n", "bake (0.5054716884821958)\n", "\n", "\n", "\n", "3947->3948\n", "\n", "\n", "\n", "\n", "\n", "3949\n", "\n", "mix (0.0)\n", "\n", "\n", "\n", "3948->3949\n", "\n", "\n", "\n", "\n", "\n", "3950\n", "\n", "cut (0.21044759376285382)\n", "\n", "\n", "\n", "3949->3950\n", "\n", "\n", "\n", "\n", "\n", "3955\n", "\n", "cut (0.25)\n", "\n", "\n", "\n", "3949->3955\n", "\n", "\n", "\n", "\n", "\n", "3951\n", "\n", "mix (0.3897435897435897)\n", "\n", "\n", "\n", "3950->3951\n", "\n", "\n", "\n", "\n", "\n", "3954\n", "\n", "tomato (1.0)\n", "\n", "\n", "\n", "3951->3954\n", "\n", "\n", "\n", "\n", "\n", "3952\n", "\n", "chop (0.21089630931458697)\n", "\n", "\n", "\n", "3951->3952\n", "\n", "\n", "\n", "\n", "\n", "3953\n", "\n", "onion (1.0)\n", "\n", "\n", "\n", "3952->3953\n", "\n", "\n", "\n", "\n", "\n", "3956\n", "\n", "noodle (1.0)\n", "\n", "\n", "\n", "3955->3956\n", "\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "0.18941305549164347\n" ] }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "%3\n", "\n", "\n", "\n", "3870\n", "\n", "mix (0.0)\n", "\n", "\n", "\n", "3873\n", "\n", "mix (0.20029027576197386)\n", "\n", "\n", "\n", "3870->3873\n", "\n", "\n", "\n", "\n", "\n", "3871\n", "\n", "cook (1.0)\n", "\n", "\n", "\n", "3870->3871\n", "\n", "\n", "\n", "\n", "\n", "3874\n", "\n", "onion (1)\n", "\n", "\n", "\n", "3873->3874\n", "\n", "\n", "\n", "\n", "\n", "3875\n", "\n", "tomato (1)\n", "\n", "\n", "\n", "3873->3875\n", "\n", "\n", "\n", "\n", "\n", "3877\n", "\n", "bake (0.6071428571428571)\n", "\n", "\n", "\n", "3871->3877\n", "\n", "\n", "\n", "\n", "\n", "3872\n", "\n", "noodle (1.0)\n", "\n", "\n", "\n", "3877->3872\n", "\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "0.18081651769563872\n" ] }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "%3\n", "\n", "\n", "\n", "3680\n", "\n", "mix (0.0)\n", "\n", "\n", "\n", "3689\n", "\n", "heat (0.969244288224956)\n", "\n", "\n", "\n", "3680->3689\n", "\n", "\n", "\n", "\n", "\n", "3687\n", "\n", "noodle (1)\n", "\n", "\n", "\n", "3680->3687\n", "\n", "\n", "\n", "\n", "\n", "3681\n", "\n", "open (0.009697241645788928)\n", "\n", "\n", "\n", "3689->3681\n", "\n", "\n", "\n", "\n", "\n", "3682\n", "\n", "simmer (0.6899063929501801)\n", "\n", "\n", "\n", "3681->3682\n", "\n", "\n", "\n", "\n", "\n", "3683\n", "\n", "mix (0.22564102564102564)\n", "\n", "\n", "\n", "3682->3683\n", "\n", "\n", "\n", "\n", "\n", "3684\n", "\n", "tomato (1.0)\n", "\n", "\n", "\n", "3683->3684\n", "\n", "\n", "\n", "\n", "\n", "3685\n", "\n", "cook (0.9999999999999999)\n", "\n", "\n", "\n", "3683->3685\n", "\n", "\n", "\n", "\n", "\n", "3686\n", "\n", "onion (1.0)\n", "\n", "\n", "\n", "3685->3686\n", "\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "0.17755644030720744\n" ] }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "%3\n", "\n", "\n", "\n", "3878\n", "\n", "mix (0.0)\n", "\n", "\n", "\n", "3879\n", "\n", "heat (0.969244288224956)\n", "\n", "\n", "\n", "3878->3879\n", "\n", "\n", "\n", "\n", "\n", "3888\n", "\n", "bake (0.6071428571428571)\n", "\n", "\n", "\n", "3878->3888\n", "\n", "\n", "\n", "\n", "\n", "3880\n", "\n", "open (0.009697241645788928)\n", "\n", "\n", "\n", "3879->3880\n", "\n", "\n", "\n", "\n", "\n", "3881\n", "\n", "simmer (0.6899063929501801)\n", "\n", "\n", "\n", "3880->3881\n", "\n", "\n", "\n", "\n", "\n", "3882\n", "\n", "mix (0.22564102564102564)\n", "\n", "\n", "\n", "3881->3882\n", "\n", "\n", "\n", "\n", "\n", "3883\n", "\n", "tomato (1.0)\n", "\n", "\n", "\n", "3882->3883\n", "\n", "\n", "\n", "\n", "\n", "3884\n", "\n", "cook (0.9999999999999999)\n", "\n", "\n", "\n", "3882->3884\n", "\n", "\n", "\n", "\n", "\n", "3885\n", "\n", "onion (1.0)\n", "\n", "\n", "\n", "3884->3885\n", "\n", "\n", "\n", "\n", "\n", "3886\n", "\n", "noodle (1.0)\n", "\n", "\n", "\n", "3888->3886\n", "\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "p.plot_population()" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "ename": "NameError", "evalue": "name 't' is not defined", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mt2\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mTree\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfrom_serialization\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mt\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mserialize\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mNameError\u001b[0m: name 't' is not defined" ] } ], "source": [ "t2 = Tree.from_serialization(t.serialize())" ] }, { "cell_type": "code", "execution_count": 49, "metadata": {}, "outputs": [], "source": [ "t.mutate()" ] }, { "cell_type": "code", "execution_count": 54, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.00499001996007984" ] }, "execution_count": 54, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t.score()" ] }, { "cell_type": "code", "execution_count": 51, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "%3\n", "\n", "\n", "\n", "43\n", "\n", "mix\n", "\n", "\n", "\n", "44\n", "\n", "chocolate\n", "\n", "\n", "\n", "43->44\n", "\n", "\n", "\n", "\n", "\n", "51\n", "\n", "beat\n", "\n", "\n", "\n", "43->51\n", "\n", "\n", "\n", "\n", "\n", "45\n", "\n", "sugar\n", "\n", "\n", "\n", "51->45\n", "\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "execution_count": 51, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t.root().dot()" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'pepper'" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list(t.root().childs())[0]._name" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [], "source": [ "n = IngredientNode(\"test\")" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 43, "metadata": {}, "output_type": "execute_result" } ], "source": [ "n.traverse() == IngredientNode" ] }, { "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.3" }, "toc-autonumbering": false, "toc-showcode": false, "toc-showmarkdowntxt": false, "toc-showtags": false }, "nbformat": 4, "nbformat_minor": 4 }