Great Deal! Get Instant $10 FREE in Account on First Order + 10% Cashback on Every Order Order Now

{ "nbformat": 4, "nbformat_minor": 0, "metadata": { "colab": { "name": "“Homework_11_Scheduling_with_Dependencies.ipynb”的副本", "provenance": [], "collapsed_sections": [] }, "kernelspec": {...

1 answer below »
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"name": "“Homework_11_Scheduling_with_Dependencies.ipynb”的副本",
"provenance": [],
"collapsed_sections": []
},
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemi
or_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.3"
},
"test_info": {
"id": "4adb3d5055da02e7ae8251ca99f4acfa901ab256"
}
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "IIqniH2KkacL"
},
"source": [
"Before you turn this problem in, make sure everything runs as expected. First, **restart the kernel** (in the menubar, select Kernel$\\righta
ow$Restart) and then **run all cells** (in the menubar, select Cell$\\righta
ow$Run All).\n",
"\n",
"Make sure you fill in any place that says `YOUR CODE HERE` or \"YOUR ANSWER HERE\", as well as your name and collaborators below:"
]
},
{
"cell_type": "code",
"metadata": {
"id": "vZ2QllLpkacL"
},
"source": [
"NAME = \"Yuxuan Guo\"\n",
"COLLABORATORS = \"\""
],
"execution_count": 1,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "JhnyL4GOkacL"
},
"source": [
"---"
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"nbgrader": {
"checksum": "767690caa09bf309165134adec898cd2",
"grade": false,
"grade_id": "cell-fc6b5241f439f72f",
"locked": true,
"schema_version": 1,
"solution": false
},
"id": "cU91rlxQkacM"
},
"source": [
"# Homework 11: Scheduling with Dependencies\n",
"\n",
"Copyright Luca de Alfaro, XXXXXXXXXXn",
"License: [CC-BY-NC-ND](https:
creativecommons.org/licenses
y-nc-nd/4.0/)."
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"nbgrader": {
"checksum": "93460885ba39aaf770
cf46acb31f4a",
"grade": false,
"grade_id": "cell-a13bd1c44a595199",
"locked": true,
"schema_version": 1,
"solution": false
},
"id": "ica_ZmxrkacM"
},
"source": [
"## Submission\n",
"\n",
"[Please submit to this Google Form](https:
docs.google.com/forms/d/e/1FAIpQLSdVfcA_LZdtjJoLKBSkyHwbvxXvow-CX4pQEMmW3UVm7X_JrA/viewform?usp=sf_link).\n",
"\n",
"Deadline: Friday December 4, 11pm (check on Canvas for updated information)."
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"nbgrader": {
"checksum": "90a74a81d08e34489013a1201369ad0a",
"grade": false,
"grade_id": "cell-dcea49d1e015f68d",
"locked": true,
"schema_version": 1,
"solution": false
},
"id": "Kny6AHUmkacM"
},
"source": [
"## Test Format\n",
"\n",
"This test contains 4 questions, for a total of 90 points. "
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"nbgrader": {
"checksum": "637cf59cf5df5ba15cbc30a73b035287",
"grade": false,
"grade_id": "cell-7783f146ca3d6158",
"locked": true,
"schema_version": 1,
"solution": false
},
"id": "FKxK7Pb0kacM"
},
"source": [
"Assume you have to prepare Pasta Ca
onara. My version of the recipe goes like this: \n",
"\n",
"> Dice onions and pancetta, and fry in a mix of olive oil and butter, slowly. Separately, put in a bowl as many eggs as there are dinner guests; you can either put in the bowls the yolks only, or you can add a few whites if you wish. Beat the eggs. \n",
"> Bring water to a boil, and when it boils, salt it. Put the pasta in (I like Penne Rigate). When cooked, colander the water away, and quickly unite in the bowl the beaten eggs, the pasta, and the pancetta. Mix well and serve immediately. \n",
"\n",
"If you have to invite people over, you could do this recipe sequentially, and first wo
y about cooking the pasta: warming the water, putting the pasta in, then colandering it. Then you could wo
y about cooking the pancetta and onions. When that's done, you can start to beat the eggs. Finally, you could unite everything. Technically, that would work, but there would be two problems. The first is that, of course, the pasta would be rather cold by the time it would be served, a capital sin (pasta must be served immediately after it is cooked). Secondly, even if you rehash the order so that you first cook the pancetta, then beat the eggs, then cook the pasta, then technically this works -- but it would take you well over one hour to have everything ready. You want to do things in parallel, cooking the pancetta while heating up the water for the pasta, and so forth. You want to discover what are the things that need to be done one after the other, and what are the things that can be done in parallel, and in which order to do everything. \n",
"\n",
"Great cooking, by the way, is much about the perfect timing, not only the perfect preparation. You have to have the various preparations ready at the same time, to unite them just right. We will wo
y about timing in the second part of this chapter; first, we wo
y about what we can do and in which order.\n",
"\n",
"As an aside for those of you who are more interested in compiling code than in cooking, the problem of how to compile C or C++ code is very similar. A makefile defines dependencies between tasks: you have to have compiled
Answered Same Day Dec 03, 2021

Solution

Swapnil answered on Dec 05 2021
162 Votes
Assign/.ipynb_checkpoints/Question File-checkpoint.ipynb{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "IIqniH2KkacL"
},
"source": [
"Before you turn this problem in, make sure everything runs as expected. First, **restart the kernel** (in the menubar, select Kernel$\\righta
ow$Restart) and then **run all cells** (in the menubar, select Cell$\\righta
ow$Run All).\n",
"\n",
"Make sure you fill in any place that says `YOUR CODE HERE` or \"YOUR ANSWER HERE\", as well as your name and collaborators below:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"id": "vZ2QllLpkacL"
},
"outputs": [],
"source": [
"NAME = \"Yuxuan Guo\"\n",
"COLLABORATORS = \"\""
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "JhnyL4GOkacL"
},
"source": [
"---"
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"id": "cU91rlxQkacM",
"nbgrader": {
"checksum": "767690caa09bf309165134adec898cd2",
"grade": false,
"grade_id": "cell-fc6b5241f439f72f",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"source": [
"# Homework 11: Scheduling with Dependencies\n",
"\n",
"Copyright Luca de Alfaro, 2019-20. \n",
"License: [CC-BY-NC-ND](https:
creativecommons.org/licenses
y-nc-nd/4.0/)."
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"id": "ica_ZmxrkacM",
"nbgrader": {
"checksum": "93460885ba39aaf770
cf46acb31f4a",
"grade": false,
"grade_id": "cell-a13bd1c44a595199",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"source": [
"## Submission\n",
"\n",
"[Please submit to this Google Form](https:
docs.google.com/forms/d/e/1FAIpQLSdVfcA_LZdtjJoLKBSkyHwbvxXvow-CX4pQEMmW3UVm7X_JrA/viewform?usp=sf_link).\n",
"\n",
"Deadline: Friday December 4, 11pm (check on Canvas for updated information)."
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"id": "Kny6AHUmkacM",
"nbgrader": {
"checksum": "90a74a81d08e34489013a1201369ad0a",
"grade": false,
"grade_id": "cell-dcea49d1e015f68d",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"source": [
"## Test Format\n",
"\n",
"This test contains 4 questions, for a total of 90 points. "
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"id": "FKxK7Pb0kacM",
"nbgrader": {
"checksum": "637cf59cf5df5ba15cbc30a73b035287",
"grade": false,
"grade_id": "cell-7783f146ca3d6158",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"source": [
"Assume you have to prepare Pasta Ca
onara. My version of the recipe goes like this: \n",
"\n",
"> Dice onions and pancetta, and fry in a mix of olive oil and butter, slowly. Separately, put in a bowl as many eggs as there are dinner guests; you can either put in the bowls the yolks only, or you can add a few whites if you wish. Beat the eggs. \n",
"> Bring water to a boil, and when it boils, salt it. Put the pasta in (I like Penne Rigate). When cooked, colander the water away, and quickly unite in the bowl the beaten eggs, the pasta, and the pancetta. Mix well and serve immediately. \n",
"\n",
"If you have to invite people over, you could do this recipe sequentially, and first wo
y about cooking the pasta: warming the water, putting the pasta in, then colandering it. Then you could wo
y about cooking the pancetta and onions. When that's done, you can start to beat the eggs. Finally, you could unite everything. Technically, that would work, but there would be two problems. The first is that, of course, the pasta would be rather cold by the time it would be served, a capital sin (pasta must be served immediately after it is cooked). Secondly, even if you rehash the order so that you first cook the pancetta, then beat the eggs, then cook the pasta, then technically this works -- but it would take you well over one hour to have everything ready. You want to do things in parallel, cooking the pancetta while heating up the water for the pasta, and so forth. You want to discover what are the things that need to be done one after the other, and what are the things that can be done in parallel, and in which order to do everything. \n",
"\n",
"Great cooking, by the way, is much about the perfect timing, not only the perfect preparation. You have to have the various preparations ready at the same time, to unite them just right. We will wo
y about timing in the second part of this chapter; first, we wo
y about what we can do and in which order.\n",
"\n",
"As an aside for those of you who are more interested in compiling code than in cooking, the problem of how to compile C or C++ code is very similar. A makefile defines dependencies between tasks: you have to have compiled pathlib.c before you can link the result together with something else. The task of the make program is to figure out how to parallelize the compilation, so that independent tasks can happen in different processes (possibly on different CPU cores), while respecting the precedence constraints between tasks. We will mention this application in some of the exercises of the chapter. \n",
"\n",
"\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"id": "ZDoY3oEIkacM",
"nbgrader": {
"checksum": "c746ef312885249b098a4a4fbf9f588c",
"grade": false,
"grade_id": "cell-fe45e7ce127db0d4",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"source": [
"## Scheduling dependent tasks"
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"id": "cIxy_GYJkacM",
"nbgrader": {
"checksum": "13ab8e8184a5ce432629a168358998e9",
"grade": false,
"grade_id": "cell-ac839becba0a561a",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"source": [
"We first disregard the problem of cooking (or compiling) time, and ask about the order in which we should be doing the tasks. We want to create a _Scheduler_ object, that can tell us what to do at the same time. What operations should this object support? \n",
"\n",
"* **add_task:** we should be able to add a task, along with the task dependencies. \n",
"* **reset:** indicating that we are about to run the sequences of tasks again.\n",
"* **available_tasks:** this property should return the set of things that we can do in parallel. \n",
"* **mark_completed:** used to notify the scheduler that we have completed a task. This should return the set of new tasks that we can do due to this task being completed; we can do these tasks in parallel alongside with the others that we are already doing. \n",
"* **all_done:** returns True/False according to whether we have completed all tasks. \n",
"\n",
"Choosing these operations is perhaps the most important step in the design of the scheduler. The operations need to have a simple, clear definition, and be useful in a concrete implementation of the service which will run the tasks. Of the above operations, they are all uncontroversial, except for the choice of behavior of _completed_. In theory, there is no need for _completed_ to return the set of _new_ tasks that can now be undertaken. If one remembers the set of tasks $T_1$ one can a do before a task $t \\in T_1$ is completed, and marks $t$ as completed, one can simply ask the scheduler for the set of tasks $T_2$ that can now be done, and add those in $T_{21t} = T_2 \\setminus (\\{t\\} \\cup T_1)$ for execution. However, we guess (as we have not yet written the task execution engine) that being told this set of tasks directly will simplify the design of the task execution engine. "
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"id": "yk-RsN-TkacM",
"nbgrader": {
"checksum": "79aecd3e08b0a5afe9f42889882e0bda",
"grade": false,
"grade_id": "cell-307dbeebce53643f",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"source": [
"Our scheduler class will be implemented in similar fashion to our graph class, with tasks co
esponding to graph vertices, and dependencies represented as edges.\n",
"The difference is that here, given a vertex (that is, a task) $v$, it will be useful to be able to access both:\n",
"\n",
"* the _predecessors_ of $v$, that is, the tasks $u$ that are declared as prerequisites of $v$, and \n",
"* the _successors_ of $v$, that is, the tasks $u$ such that $v$ was declared as a prerequisite for $u$. \n",
"\n",
"When we add a task, we would have to initialize its set of successors and predecessors to empty. This is somewhat tedious, and so we resort to a defaultdict, which is a special type of dictionary such that, if the mapping for a key has not been defined, it returns a default value; in our case, an empty set. [You can read more about defaultdict and related types here](https:
docs.python.org/3.7/li
ary/collections.html#collections.defaultdict). \n",
"\n",
"Our first implementation of the class is as follows. We let you complete the `available_tasks` and `mark_completed` methods. \n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"deletable": false,
"editable": false,
"id": "_yCelWBbkacM",
"nbgrader": {
"checksum": "a3122da716c36329d70b6398881d9f6c",
"grade": false,
"grade_id": "cell-c1f62e6e5511e278",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"outputs": [],
"source": [
"from collections import defaultdict\n",
"import networkx as nx # Li
ary for displaying graphs.\n",
"import matplotlib.pyplot as plt\n",
"\n",
"class DependencyScheduler(object):\n",
"\n",
" def __init__(self):\n",
" self.tasks = set()\n",
" # The successors of a task are the tasks that depend on it, and can\n",
" # only be done once the task is completed.\n",
" self.successors = defaultdict(set)\n",
" # The predecessors of a task have to be done before the task.\n",
" self.predecessors = defaultdict(set)\n",
" self.completed_tasks = set() # completed tasks\n",
"\n",
" def add_task(self, t, dependencies):\n",
" \"\"\"Adds a task t with given dependencies.\"\"\"\n",
" # Makes sure we know about all tasks mentioned.\n",
" assert t not in self.tasks or len(self.predecessors[t]) == 0, \"The task was already present.\"\n",
" self.tasks.add(t)\n",
" self.tasks.update(dependencies)\n",
" # The predecessors are the tasks that need to be done before.\n",
" self.predecessors[t] = set(dependencies)\n",
" # The new task is a successor of its dependencies.\n",
" for u in dependencies:\n",
" self.successors[u].add(t)\n",
"\n",
" def reset(self):\n",
" self.completed_tasks = set()\n",
"\n",
" @property\n",
" def done(self):\n",
" return self.completed_tasks == self.tasks\n",
"\n",
"\n",
" def show(self):\n",
" \"\"\"We use the nx graph to display the graph.\"\"\"\n",
" g = nx.DiGraph()\n",
" g.add_nodes_from(self.tasks)\n",
" g.add_edges_from([(u, v) for u in self.tasks for v in self.successors[u]])\n",
" node_colors = ''.join([('g' if v in self.completed_tasks else 'r')\n",
" for v in self.tasks])\n",
" nx.draw(g, with_labels=True, node_color=node_colors)\n",
" plt.show()\n",
"\n",
" @property\n",
" def uncompleted(self):\n",
" \"\"\"Returns the tasks that have not been completed.\n",
" This is a property, so you can say scheduler.uncompleted rather than\n",
" scheduler.uncompleted()\"\"\"\n",
" return self.tasks - self.completed_tasks\n",
"\n",
" def _check(self):\n",
" \"\"\"We check that if t is a successor of u, then u is a predecessor\n",
" of t.\"\"\"\n",
" for u in self.tasks:\n",
" for t in self.successors[u]:\n",
" assert u in self.predecessors[t]\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"id": "WxGmfJPCkacM",
"nbgrader": {
"checksum": "f7194367628d4362f83e04121a68a6e4",
"grade": false,
"grade_id": "cell-1d75cf1333aa8c76",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"source": [
"## Question 1: implement `available_tasks` and `mark_completed`. "
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"deletable": false,
"id": "W3lz1UGRkacM",
"nbgrader": {
"checksum": "f830262ac9c7f13eb8f07e85e0e1ac11",
"grade": false,
"grade_id": "cell-5c9e5f503f616888",
"locked": false,
"schema_version": 1,
"solution": true
}
},
"outputs": [],
"source": [
"### Implementation of `available_tasks` and `mark_completed`.\n",
"\n",
"def scheduler_available_tasks(self):\n",
" \"\"\"Returns the set of tasks that can be done in parallel.\n",
" A task can be done if all its predecessors have been completed.\n",
" And of course, we don't return any task that has already been\n",
" completed.\"\"\"\n",
" # YOUR CODE HERE\n",
" return ({t for t in self.tasks \n",
" if self.predecessors[t].issubset(self.completed_tasks)}\n",
" - self.completed_tasks)\n",
"\n",
"def scheduler_mark_completed(self, t):\n",
" \"\"\"Marks the task t as completed, and returns the additional\n",
" set of tasks that can be done (and that could not be\n",
" previously done) once t is completed.\"\"\"\n",
" # YOUR CODE HERE\n",
" for p in self.predecessors[t]:\n",
" if p in self.uncompleted:\n",
" raise IllegalCompletion(t)\n",
" \n",
" self.completed_tasks.add(t)\n",
" return {u for u in self.successors[t] \n",
" if self.predecessors[u].issubset(self.completed_tasks)}\n",
"\n",
"DependencyScheduler.available_tasks = property(scheduler_available_tasks)\n",
"DependencyScheduler.mark_completed = scheduler_mark_completed\n"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"deletable": false,
"id": "RnTGjkVhkacM",
"nbgrader": {
"checksum": "9cbfd3fceef4fc700ee6fd8765c94e66",
"grade": false,
"grade_id": "cell-ab6c2cd521650cd4",
"locked": false,
"schema_version": 1,
"solution": true
}
},
"outputs": [],
"source": [
"# Here is a place where you can test your code. \n",
"\n",
"# YOUR CODE HERE"
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"id": "fbDAHS7IkacM",
"nbgrader": {
"checksum": "9abc
7a57e188e7f19741fdef160c7f",
"grade": false,
"grade_id": "cell-3e19369eeb9a643d",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"source": [
"Let us check if this works."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"colab": {
"base_uri": "https:
localhost:8080/"
},
"deletable": false,
"editable": false,
"id": "5OGt-_BgkacM",
"nbgrader": {
"checksum": "34c28ee0d4c755735562b962526341d2",
"grade": false,
"grade_id": "cell-92b59a47fe7f0336",
"locked": true,
"schema_version": 1,
"solution": false
},
"outputId": "ac6123c0-6313-4ebd-c8e5-4a85b59bc0a6"
},
"outputs": [],
"source": [
"# Let us ensure that nose is installed.\n",
"try:\n",
" from nose.tools import assert_equal, assert_true\n",
" from nose.tools import assert_false, assert_almost_equal\n",
"except:\n",
" !pip install nose\n",
" from nose.tools import assert_equal, assert_true\n",
" from nose.tools import assert_false, assert_almost_equal\n"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"colab": {
"base_uri": "https:
localhost:8080/",
"height": 353
},
"deletable": false,
"editable": false,
"id": "6vuF6du9kacM",
"nbgrader": {
"checksum": "af201e981d4b861bf954b7e2384b3e9a",
"grade": false,
"grade_id": "cell-d9857dde3e277260",
"locked": true,
"schema_version": 1,
"solution": false
},
"outputId": "1f85633c-afa2-40fb-e026-17c3729ff9d6"
},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAd0AAAE/CAYAAAADsRnnAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAIABJREFUeJzt3Xl0lPXd9/FPyAJkY98JJIAsoWJFqiwlYQnBQGbwRrmlhQcLR8Fzq1BRyqO0j8V6rJweit51Qcstp2oFSqU6E8KSGwiJgEVwQwRZyhIKsoUlK1lmnj/GGQNMQpaZ65pJ3q9zPEFyJflwPIePv+v6
5XiNPpdAoAAPhdM7MDAADQVFC6AAAYhNIFAMAglC4AAAahdAEAMAilCwCAQShdAAAMQukCAGAQShcAAINQugAAGITSBQDAIJQuAAAGoXQBADAIpQsAgEEoXQAADELpAgBgEEoXAACDULoAABiE0gUAwCCULgAABqF0AQAwSJjZAYJCQYG0a5eUny81aya1by+NGCE1b252MgBAEKF0a/L119KyZdKqVVJ4uOR0SiEhrs85ndLs2dLjj0vx8abGBAAEhxCn0+k0O0TAqaiQHn5Y+tvfpLIyqbLS+3UREa6V74IF0uLFPxQyAABeULo3qqiQ0tOl3FypuLh2XxMZKU2fLi1fTvECAKrFRqobPfFE3QpXcl373nvSH
ov1wAgKDHSreq06elXr2ka9fq9/XR0dK5c1LLlr7NBQBoFFjpVvXGGw3/HmvXNvx7AAAaJVa6bhUVUocO0uXLXj99WtITknIkRUt6UtJcbxcOGCB9842/UgIAghgrXbdjx6Tycq+fckiySLpD0r8lbZH0sqRN3i4+eLDa7wMAaNooXbfLl6Uw78eWP5V0XtL/kxQhqZekRySt9nZxRIR05YqfQgIAghnDMdwiIlwDL7w4Idft5dZVfq9S0khvFzscru8FAMANKF23zp2r3bUcJylB0uHafJ+QECkmxofBAACNBbeX3Tp1kgYN8vqpuyXFSloiqUSuVe7Xct12vk6zZtIDDzAgAwDgFaVb1cKFXlepoZLskr6Qa8XbXtLDkm56ctuihfTUU34OCQAIVhwZqqq83HWbOT+/7l8bEiIlJrpekgAAgBesdKsKD5fWravfRKnoaAZjAABqROneKDnZ9Sq/yMjaXR8SIsXGSps2uQZjAABQDUrXm0mTpK1bpcGDXave0NC
4mIcD3DTU6WPv1UGjbM+JwAgKDCM91b2
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
+bWXa5xhYfr91avq2rWr0tLS9MY
+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
ynbDa
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\n",
"text/plain": [
"
"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"from nose.tools import assert_true, assert_false, assert_equal\n",
"\n",
"s = DependencyScheduler()\n",
"s.add_task('a', ['b', 'c'])\n",
"s.add_task('b', ['c', 'e'])\n",
"s._check()\n",
"s.show()\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"id": "giXGuSh2kacM",
"nbgrader": {
"checksum": "b6d6104b2ca8bd21eb6fc98c96471d59",
"grade": false,
"grade_id": "cell-236e1fcb5f373d17",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"source": [
"We note that in the above drawing, the edges denote temporal succession, that is, an edge from $c$ to $a$ means that $c$ must happen before $a$. \n",
"Let us execute the schedule manually."
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"id": "aMadMw9OkacM",
"nbgrader": {
"checksum": "ff1dbebea8f5468f341e70ee112d2541",
"grade": false,
"grade_id": "cell-a448f628a33f1655",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"source": [
"Here are some tests for `available_tasks` and `mark_completed`. "
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"deletable": false,
"editable": false,
"id": "DmB_OitvkacM",
"nbgrader": {
"checksum": "87f4aef1da9401c8b1e14ea98c65e07b",
"grade": true,
"grade_id": "cell-97a947c37868d065",
"locked": true,
"points": 5,
"schema_version": 1,
"solution": false
}
},
"outputs": [],
"source": [
"### Simple tests. 5 points. \n",
"\n",
"s = DependencyScheduler()\n",
"s.add_task('a', [])\n",
"assert_equal(s.available_tasks, {'a'})\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"deletable": false,
"editable": false,
"id": "63Y9m0-ekacM",
"nbgrader": {
"checksum": "1c260d93e494b94353ee43c9986a912b",
"grade": true,
"grade_id": "cell-e63ce
9c5161e17",
"locked": true,
"points": 10,
"schema_version": 1,
"solution": false
}
},
"outputs": [],
"source": [
"### Slightly more complicated. 10 points. \n",
"\n",
"s = DependencyScheduler()\n",
"s.add_task('a', ['b', 'c'])\n",
"s.add_task('b', ['c', 'e'])\n",
"assert_equal(s.available_tasks, {'e', 'c'})\n",
"\n",
"s = DependencyScheduler()\n",
"s.add_task('a', ['b'])\n",
"s.add_task('b', ['a'])\n",
"assert_equal(s.available_tasks, set())\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"deletable": false,
"editable": false,
"id": "_emz5xo7kacM",
"nbgrader": {
"checksum": "3d976d40ecb3e0aea04ab706c381b6a0",
"grade": true,
"grade_id": "cell-fdc5d30f849014af",
"locked": true,
"points": 5,
"schema_version": 1,
"solution": false
}
},
"outputs": [],
"source": [
"### Now, let's test `mark_completed`. Simple tests first. 5 points. \n",
"\n",
"s = DependencyScheduler()\n",
"s.add_task('a', [])\n",
"assert_equal(s.available_tasks, {'a'})\n",
"r = s.mark_completed('a')\n",
"assert_equal(r, set())\n",
"\n",
"s = DependencyScheduler()\n",
"s.add_task('a', ['b'])\n",
"assert_equal(s.available_tasks, {'b'})\n",
"r = s.mark_completed('b')\n",
"assert_equal(r, {'a'})\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"deletable": false,
"editable": false,
"id": "iUfccczckacM",
"nbgrader": {
"checksum": "bc1219453bf2f8e01785141255fd7f1d",
"grade": true,
"grade_id": "cell-71c82e71e3d5c769",
"locked": true,
"points": 10,
"schema_version": 1,
"solution": false
}
},
"outputs": [],
"source": [
"### Slightly more complicated. 10 points. \n",
"\n",
"s = DependencyScheduler()\n",
"s.add_task('a', ['b', 'c'])\n",
"assert_equal(s.available_tasks, {'b', 'c'})\n",
"r = s.mark_completed('b')\n",
"assert_equal(r, set())\n",
"assert_equal(s.available_tasks, {'c'})\n",
"r = s.mark_completed('c')\n",
"assert_equal(r, {'a'})\n",
"\n",
"s = DependencyScheduler()\n",
"s.add_task('a', ['b', 'c'])\n",
"s.add_task('b', ['c', 'e'])\n",
"s.add_task('c', [])\n",
"assert_equal(s.available_tasks, {'c', 'e'})\n",
"r = s.mark_completed('e')\n",
"assert_equal(r, set())\n",
"r = s.mark_completed('c')\n",
"assert_equal(r, {'b'})\n",
"r = s.mark_completed('b')\n",
"assert_equal(r, {'a'})\n",
"r = s.mark_completed('a')\n",
"assert_equal(r, set())\n",
"assert_equal(s.available_tasks, set())\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"id": "4Si-0n65kacM",
"nbgrader": {
"checksum": "c0e617b3ab44b02e965cd7181c719847",
"grade": false,
"grade_id": "cell-1fdbf05f74676a81",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"source": [
"## Executing the tasks\n",
"\n",
"Here is an execution engine for our tasks with dependencies."
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"deletable": false,
"editable": false,
"id": "03fwlwB-kacM",
"nbgrader": {
"checksum": "121aee66c911faf16ef686e9fcffa102",
"grade": false,
"grade_id": "cell-c285056
c55c15",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"outputs": [],
"source": [
"import random\n",
"\n",
"def execute_schedule(s, show=False):\n",
" s.reset()\n",
" in_process = s.available_tasks\n",
" print(\"Starting by doing:\", in_process)\n",
" while len(in_process) > 0:\n",
" # Picks one random task to be the first to be completed.\n",
" t = random.choice(list(in_process))\n",
" print(\"Completed:\", t)\n",
" in_process = in_process - {t} | s.mark_completed(t)\n",
" print(\"Now doing:\", in_process)\n",
" if show:\n",
" s.show()\n",
" # Have we done all?\n",
" if not s.done:\n",
" print(\"E
or, there are tasks that could not be completed:\", s.uncompleted)\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"id": "JTZ1_0ffkacM",
"nbgrader": {
"checksum": "0b89ce00f896cfb7dd641a00c2c61d86",
"grade": false,
"grade_id": "cell-5c41d5760a16bd50",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"source": [
"Let's try it on our old schedule:"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"colab": {
"base_uri": "https:
localhost:8080/",
"height": 353
},
"deletable": false,
"editable": false,
"id": "fwFI8zF5kacM",
"nbgrader": {
"checksum": "438c73779c99e682ebebf7c068db85c2",
"grade": false,
"grade_id": "cell-47bed31601afff35",
"locked": true,
"schema_version": 1,
"solution": false
},
"outputId": "5b02df8d-780a-4e28-eb73-28333d7383d1"
},
"outputs": [
{
"data": {
"image/png": "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
xASEmJ1NLkOnrKJClS6IuLBioqKmDx5M
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
8Pf3t
LEJOEh4ezbds22rdvb3WUeqfSFbHYunXriIuLu/T7gIAA0tLSePTRRyE1FWbMgBMnHKPeH
PNTjYsYY7bBgsXQrNm5ucvn7YbDaKiopqnb6+eCRgbZu82rVr55EHKXgju91OYGAgZ8+eJTAw0Oo49U6lK+ICHn30Uf72t78B0LZtW44ePfqvpwIZBuTkODZXbd/ueLauv7/jofX
u/w3HNuW7bX68KFCxw9evSKMr781yUlJYSHh9c6fd2mTRvtvHYTp06d4o477uD06dNWR2kQWtMVsdjSpUvZvXs33bt3Z8+ePcycOfPKx/D5+MADD8D
I91IS0WEBBAx44d6dixo9PXKysrKSwsvGJ0fPntUeXl5bRv377W6euwsDCVsovw5PVcUOmKWMZmszF9+nQyMzPJyckhLCyMadOm8fzzz1sdze0EBgZy5513cueddzp9/fvvv6ewsPCK0fGOHTsu
66utrpPcoXf92sWTOTvyLvpdIVkXpXXl7OyJEjqaqqIjs7+9I39ffee8/iZJ4pJCSEu+66i7vuusvp62VlZVdNW2/ZsuXSn/n5+dW6ntyhQwdCQkJM/oo8l0pXROrVkSNHGDJkCL179+btt9/WrlwX0LRpU7p160a3bt2ues0wDE6fPn3FKDkvL4+MjIxLfxYSElJrIXfo0MEjNwQ1lOLiYo89jQpUuiKm2rlzJ0OHDmXatGnMmDFD64huwMfHh7CwMMLCwujRo8dVrxuGwYkTJ65YT/7nP
Jxo0bKSgo4Ntvv6VFixa1rieHh4cTEBBgwVfmYgwDvv+eM99+S9tOnaxO02C0e1nEJKmpqUyYMIEVK1Z45Ek74pzNZqO4uLjW26GOHTvG
feWuvxmrfddpvn3g5lGLBpEyxYAJs3g48PNTYbvj4++D78MPzXf8GAAdc8j9zdqHRFGphhGLz++ussXryYtLQ0p6Ml8V7V1dUcPXq01oNDvvvuO372s5/Veu51mzZtrtzt7i42bXKcEV5Wdun5z1cJCYHQUFi1Ch55xNx8DUSlK9KAqqurmTJlCrm5uXz88ceEh4f/9JtELlNVVcW3335b60i5rKyM22+/vdad161atXK9ZYw1a2DixOs7bQ0gKAjefhuefbZhc5lApSvSQEpLSxk+fDgBAQH8+c9/JjQ01OpI4oHOnTt36XYoZ8VcWVlZ687riIgImjVrZm4pf/IJDB16/YV7UVAQrF8Pgwc3TC6TqHRFGkBBQQFDhgyhf
+vPHGG/j5ac+iWOPs2bMcPnz4qjK++MPHx6fWndcRERH1+38WbTbHGeGnTt3Y+5s3dxyJ6sY7/lW6IvUsJyeHp556ildeeYWpU6daHUekVoZhcObMmVrXkw8fPkxQUFCthdy+ffu6PbLxww9h9GgoL7+xwBfXd5966sbe7wJUuiL1aN26dUydOpVVq1Yx2M2nwUQMw+C7776rtZALCwtp1qxZrSPl22+
cpHNkZHQ3a207
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
164dhGGzevFmFKyLiYVS6LuK
76hd+/e9O/fn5SUFIKCgqyOJCIi9UzTyy5g06ZNjBo1ioULFzJmzBir44iISAPRSNdi77zzD
+9a9Zv369CldExMNppGsRu93OrFmzSE1NZevWrXTp0sXqSCIi0sBUuhY4d+4co0ePpqSkhJycHMLCwqyOJCIiJtD0ssmKi4t56KGHCA0N5ZNPPlHhioh4EZWuifbs2UOfPn0YOnQoq1evpnHjxlZHEhERE2l62STp6emMGzeOJUuWEBcXZ3UcERGxgErXBG+
TZJSUmkpaURFRVldRwREbGISrcB2Ww2XnzxRT799FO2b99ORESE1ZFERMRCKt0GUl5ezsiRI6mqqiI7O5tmzZpZHUlERCym0r0eFRWwYwecPg2+vtCyJfTpAwEBTi8/cuQIjz/+OL169eLtt9/G39/f5MAiIuKKVLrXkpcHb74J778Pfj/6R+XjA5MmweTJEB5+6Y937drFk08+ybRp05gxYwY+Pj4mhxYREVflYxiGYXUIl1NTA
xH7B2LVRXO37vTOPGjvL97W/hd78jNS2NCRMmsGLFCmJjY83NLCIiLk+l+2M2GzzxBGzZAufOXddbjCZN2N2tG48XFpKamkqPHj0aNqOIiLglHY7xY9Om1alwAXwqKrgzJ4e948ercEVEpFYa6V6uuBgiIqCq6sbeHxIC330HgYH1m0tERDyCRrqXW7bMsUZ7Mz74oH6yiIiIx9FI96KaGmjdGs6ccfryMWAqkAWEANOBF5xdeNdd8NVXDZVSRETcmEa6Fx0+DBcuOH3JDjwOdAOKgE3Am8DfnF389de173YWERGvptK9qLT06ntxf/B34DsgAQgAOgITgD87uzggwPFZIiIiP6LDMS7y94daZtoLcUwvX36Qow2IcXax3V7rSVUiIuLdVLoX3Xp
uWw4EI4OD1flZoaD2FEhERT6Lp5YvatIG773b6Ui/gFuA14DyOUe5XOKadr+DrC089dfM7oEVExCOpdC/38stOR6mNgI+A3ThGvC2B8UDZjy8MCoIZMxo4pIiIuCvdMnS56mrHNHMttw1dk48P/Pznjt3LIiIiTmikezl/f8fhFkFBdX9vkyawfn39ZxIREY+h0v2xfv0cj/ILDr6+6318HFPS
u/joMxREREaqHSdeapp+DTT+Heex3l26jR1df4+zvOWH7gAfjiC4iONj+niIi4Fa3p/pQvv4Q33oD0dPj+e8cO5VtugaefhqlToVMnqxOKiIibUOmKiIiYRNPLIiIiJlHpioiImESlKyIiYhKVroiIiElUuiIiIiZR6YqIiJhEpSsiImISla6IiIhJVLoiIiImUemKiIiYRKUrIiJiEpWuiIiISVS6IiIiJlHpioiImESlKyIiYhKVroiIiElUuiIiIiZR6YqIiJhEpSsiImISla6IiIhJVLoiIiImUemKiIiYRKUrIiJiEpWuiIiISVS6IiIiJlHpioiImESlKyIiYhKVroiIiElUuiIiIiZR6YqIiJhEpSsiImISla6IiIhJVLoiIiImUemKiIiYRKUrIiJiEpWuiIiISVS6IiIiJlHpioiImESlKyIiYpL/D8HepvQA0zT0AAAAAElFTkSuQmCC\n",
"text/plain": [
"
"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"s = DependencyScheduler()\n",
"s.add_task('a', ['b', 'c'])\n",
"s.add_task('b', ['c', 'e'])\n",
"s._check()\n",
"s.show()\n"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"colab": {
"base_uri": "https:
localhost:8080/",
"height": 1000
},
"deletable": false,
"editable": false,
"id": "8GLvAT5MkacM",
"nbgrader": {
"checksum": "49402dc6b29c411541e4c9eb0d59eaa7",
"grade": false,
"grade_id": "cell-cb9ee8db2218be70",
"locked": true,
"schema_version": 1,
"solution": false
},
"outputId": "a26e52ce-2f7b-4886-d5da-f97f008d6ad0"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Starting by doing: {'e', 'c'}\n",
"Completed: e\n",
"Now doing: {'c'}\n"
]
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAd0AAAE/CAYAAAADsRnnAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAIABJREFUeJzt3XmcjXXjxvHPzBjM2KmsCZHlISmNfRmJ0JgZ+1iyy5Z9ZipKhTLHvkWyxsxgmM0ykn2bhZSQJRKFSMg6+/n94cmvnmZkOefcZ85c79fL6+lx7uWaVNf53vf3/t5OZrPZjIiIiFids9EBREREsguVroiIiI2odEVERGxEpSsiImIjKl0REREbUemKiIjYiEpXRETERlS6IiIiNqLSFRERsRGVroiIiI2odEVERGxEpSsiImIjKl0REREbUemKiIjYiEpXRETERlS6IiIiNqLSFRERsRGVroiIiI2odEVERGxEpSsiImIjKl0REREbyWF0gCzhxg2IjYUrV8DZGZ54AurVg1y5jE4mIiJZiEr3fg4fhmnTIDQUXF3BbAYnp7ufmc3Qrx8MHgxlyhgaU0REsgYns9lsNjqE3UlNhT59YNUqSE6GtLSMt8uZ8+7I198fPvzw/wtZREQkAyrd/5WaCq+/Drt2we3bD7aPuzt07Qrz5ql4RUQkU5pI9
eeuvhChfu
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
sMTqaiDiA32
Tq0Ftfjx6o
WrgAt1Nuc+jSIeotqve30bC9UOnaKTc3NyIjI5k9ezZRUVFGx/lXhQsX5r333uP06dO89tprdOvWjXr16hEdHW3Y88cikvX5rPDh4s2LpKanPvA+yWnJ/HT1J96IeMOKyR6NLi
uYSEBFq1asWWLVt4/vnnjY7zwFJTU1mzZg1BQUEkJibi7+9Ply5dyJkzp9HRRCSLOHTxELUW1HqgEW5Gcrnk4uSQk5TKbz/zTTTStXMeHh7MmDEDb29vfvvtN6PjPLAcOXLce4/vzJkzCQ0NpVy5ckyePJnr168bHU9EsoBpcdNISU/J+MPrwErABEwH4jLe7NN9n1on3CPSSDeLGD16NLt27WLz5s1ZdrR44MABJk2axFdffUXfvn0ZOnQoxYoVMzqWiNihOyl3KGIqkvEoNx34HKgI1OduAX8BvA6U
umBXMV5ErgFbuZkKqRbhYxbtw4ChcuzMCBA7PskowvvvgioaGhJCQkcP36dSpXrky/fv04ceKE0dFExM5cuHkBF+dMVr87D9wCGgM5gMLAS8Dhf256K+UWN5JvWCnlw1PpZhHOzs4sX76chIQEZs6caXScx1KuXDnmzJnDiRMnKFasGPXq1aNt27YkJCQYHU1E7MSNpBs4O2VSUdeAG8Anf/m1C8hgsrKriyvXk+znlpYuL2cxP/30E3Xq1GHJkiU0b97c6DgWcfPmTRYuXMjUqVMpV64cAQEBvPbaa3ZzOUhEbO/UlVNUn1edWym3/vnhz0AEMOTfj+Pq7Mpv
9RIHcBS0d8JBrpZjFlypRh1apVdOvWjePHjxsdxyLy5s3L0KFDOXnyJL179yYwMJAXXniB4OBgUlIymUQhIg6teL7ipJnTMv6wJJAL2A2kcPce70Xg3D83dcvhRr5c+awV86GpdLOgBg0a8Mknn+Dl5cXVq1eNjmMxrq6u997jO3HiRD7
HMqVKjAzJkzuXUrg2+7IuKw3F3daV+lPS5OGdzXdQb8gF+5O3PZBEQDiX/fLKdLTt6s+Wbml6kNoMvLWdjw4cM5fPgwMTEx5MiRw+g4VhEfH4/JZGLnzp0MHDiQwYMH8+STTxodS0Rs4Ntfv6XeonrcTrn9SPvnzpGbY4OO8UzBZyyc7NHZT/3LQ5s0aRIuLi6MGDHC6ChWU6tWLdasWcOePXu4cOECzz33HIMHD+bHH380OpqIWNkLxV6g2lPVcHV2feh9c7nk4pWyr9hV4YJKN0vLkSMHK1asYNOmTcyfP9/oOFb13HPPMX/+fL7
nvy5cvHyy+/jJ+fH998843R0UTEiqI6RVHYrTBO5gefWOnq7ErJ/CUJaRtixWSPRqWbxRUsWJC1a9fy3nvvsWPHDqPjWF3x4sX55JNPOH36NC+99BJeXl40a9aMLVu2ZNnnl0Ukc0XzFmVsibE433Qml8u/v67PLYcbFZ+oSGzvWPLnym+DhA9H93QdxObNm+natSt79+6lXLlyRsexmaSkJEJCQjCZTOTJk4eAgADatGnjsPe4RbKbQ4cO0aRJE1avXc2elD1Mj5tOYmriPxa8yJszL/lz5WdUnVG8WfNN3F3dDUp8fypdBzJ79mzmzZvH3r17yZ/f
7hWVN6ej
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
l+
RccQgKSkpdOjQgc6dO9O+fXurnuvixYt4enpSqFAhNmzYQIFM3iIk9k+Xl0Uegdlspn
pw/f57IyEhc9OhFtvPWW2/x448/Eh0dbdU
6NHj9KqVSu6d+/O+++
93XAorVaaQr8gicnJyYNWsW169fZ/To0UbHERtbtGgRmzZtIiQkxKqFu2PHDho3bsz777/P2LFjVbgOQCNdkcdw+fJlPDw8+PDDD+nWrZvRccQG4uLiaN26NTt37qRSpUpWO09ISAjDhg0jJCSEpk2bWu08Ylt6yl/kMTzxxBNER0fj6elJhQoVqF27ttGRxIrOnz9Pu3btWLhwodUK12w288knn/DZZ5+xZcsWqlWrZpXziDE00hWxgLVr19K/f3/i4uJ4+umnjY4jVpCUlETjxo1p1aoVY8aMsco5UlJSGDhwIPv372f9+vWUKFHCKucR46h0RSzEZDKxYsUKdu3aRZ48eYyOIxZkNpvp06cPf/zxB2FhYVa5t3rjxg3at2+Ps7MzK1euJF++fBY/hxhPE6lELMTf35+qVavSo0cP0tPTjY4jFvTpp5+SkJDAkiVLrFK4586do0GDBpQpU4bo6GgVrgNT6YpYiJOTE/Pnz+fnn39m3LhxRscRC9mxYwcfffQRkZGR5M3sRfCP4dChQ9SpUwc/Pz/mzp2rF2o4OP3pilhQ7ty5iYyMxMPDg
85z+0a9fO6EjyGM6cOUOnTp0IDg7m2Weftfjxv
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\n",
"text/plain": [
"
"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Completed: c\n",
"Now doing: {'b'}\n"
]
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAd0AAAE/CAYAAAADsRnnAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAIABJREFUeJzt3Xl0VPX9
FnVpJA2EFWQUQpixRZhCRAQhIEQiAssqhsUpjUWlEPSlvr0lp/Wj1fqBZFMgFiVIIQkH2RJSyBBGQVkEVAIgJiCHsIWWd+f0RvQQKyJHNnJq/HOZwjzJ3MK9Xyyvt+PvdeD7vdbkdERETKnKfZAURERMoLla6IiIiDqHRFREQcRKUrIiLiICpdERERB1HpioiIOIhKV0RExEFUuiIiIg6i0hUREXEQla6IiIiDqHRFREQcRKUrIiLiICpdERERB1HpioiIOIhKV0RExEFUuiIiIg6i0hUREXEQla6IiIiDqHRFREQcRKUrIiLiICpdERERB/E2O4CIiMjtyM7PJv2HdM5cOYOnhyc1/GsQcm8Ift5+Zkf7TSpdERFxCftP7+e9ze/x2Z7P8Pb0xm63A+Dh4YHNbuMPD/+BcR3H0aRaE5OT3piH/ZfUIiIiTqjIVsSflv6JT3d/SkFRAYX2whKP8/H0wcvTi+c6PsfbEW/j4eHh4KS/TaUrIiJOq8hWRL/Z/Ug5mkJOQc4tvSfAJ4DBLQYzI2aG0xWvNlKJiIjTGr9y/G0VLkBOQQ5z9s3h7Y1vl2GyO6NJV0REnFLm5UwavdeI3MLcO3p/gE8AmS9mUtG3Yiknu3OadEVExClZt1vv6v0eeJC0J6mU0pQOTboiIuJ0imxF1JlYh6ycrJIPuAgsB74HfIFOP
6lfur3c/hcYfLLOft0iVDIiLidE5cOkFO/g3WcW3ALKAZMJDiAv4EqAk0vfbQjPMZ5BTkEOATUIZpb51OL4uIiNM5n3seb68bzIUngctAGMWjY3WgHbD3+kN9vXw5n3u+jFLePk26IiLidHy9fLnh6ud54BJw9eZkO3Dv9Yfa7DZ8vXxLP+AdUumKiIjTqV2xNnlFeSW/WAWoBoz77a9js9uo6le1NKPdFZ1eFhERp+Nn96ORd6OSX6wPVAA2AgUU
H+BJy49jBPD0/6NuuLt6fzzJcqXRERcRp79uxh3LhxNGzYkMp7KuPv6X/9QZ7A48Ap4D3gXWAR8KvLef29/Xkx+MWyjnxbnKf+RUSkXMrJyWHOnDlYrVaOHTvGH/7wB3bs2EGDhg2oN6keVy5fuf5NlYHHbv516wXWo2P9jmWS+U7pOl0RETHF7t27sVqtzJo1i6CgICwWC1FRUXh7/28eTPshjchPIrlSWELx3kQln0qkj0mnVe1WpR37ruj0soiIOMzly5dJSEigU6dOREVFUbNmTXbu3MmSJUvo27fvNYULENwwmORBybd8na0HHgT6BrLsyWVOV7igSVdERBzg66+/NqbakJAQLBYLvXr1uq5kb2T7ye08vfRp9mbuLfHxfr5evnh6eNKhXgfiouNoXqt5WXwbd02lKyIiZeLy5cvMnj0bq9XKiRMnGDNmDKNHj6Zhw4Z3/DX3n97Pe1veY9HBRVzKu4SHhwdVKlRhUMtBPPvIs079AHtQ6YqISCnbtWsXVquVzz
nM6dO2OxWOjZs+ctT7XuTP8LiIjIXcvOzmb27NnExcVx6tQpxowZw+7du2nQoIHZ0ZyKJl0REbljO3fuxGq1Mnv2bLp06WJMtV5eXmZHc0qadEVE5LZkZ2fz+eefExcXR2Zmpqba26BJV0REbsmOHTuMqTY0NBSLxUKPHj001d4GTboiInJDly5dMqba06dPM3bsWPbu3Uv9+vXNjuaSNOmKiMh1tm/fjtVqZc6cOYSFhREbG0v37t011d4lTboiIgIUT7VJSUlYrVbOnDnD2LFj+ea
6hXr57Z0dyGJl0RkXLM
cbU21ycjLh4eFYLBYiIyM11ZYBTboiIuXQxYsXjan23LlzjB07ln379lG3bl2zo7k1TboiIuWE3W5n27ZtWK1W5s6dS3h4OLGxsURGRuLpqeffOIImXRERN3fhwgVjqr1w4YKmWhNp0hURcUN2u52tW7ditVqZN28ekZGRWCwWIiIiNNWaSJOuiIgbuXDhAjNnzsRqtXLp0iXGjh3L/v37qVOnjtnRBE26IiIuz26389VXXxEXF8cXX3zBo48+isViITw8XFOtk9GkKyLios6fP29MtZcvX2bs2LEcPHiQe+65x+xocgOadEVEXIjdbmfLli1YrVbmz59vTLXdunXTVOsCVLoiIi7g/PnzfPbZZ1itVq5cuYLFYmHkyJHUrl3b7GhyG1S6IiJOym63k56ejtVqZcGCBfTs2ROLxUJYWJimWhel0hURcTLnzp0zptq8vDxjqq1Vq5bZ0eQuqXRFRJyA3W4nLS0Nq9XKwoUL6dWrlzHVenh4mB1PSolKV0TEROfOnePTTz/FarVSUFCAxWJhxIgRmmrdlEpXRMTB7HY7mzZtwmq1smjRIqKiorBYLISGhmqqdXMqXRERBzl79qwx1RYVFRlTbc2aNc2OJg6i0hURKUN2u52NGzditVpZvHgxvXv3xmKx0LVrV0215ZBKV0SkDJw5c8aYau12OxaLheHDh2uqLedUuiIipcRut5OamorVamXJkiVER0djsVjo0qWLploBVLoiInftzJkzfPLJJ1itVjw8PIyptkaNGmZHEyejBx6IiNwBu93Ohg0bsFqtLF26lD59+hAfH09ISIimWrkhTboiIrchKyuLxMRE4uPj8fT0JDY2luHDh1O9enWzo4kL0KQrIvIb7HY769evx2q1smzZMmJiYpg+fTrBwcGaauW2aNIVEbmBrKwsPv74Y+Lj4/H29iY2NpZhw4ZpqpU7pklXROQqdruddevWYbVaWb58OTExMSQkJBAUFKSpVu6aJl0RESAzM9NYq61QoQIWi4Vhw4ZRrVo1s6OJG9GkKyLlls1mM6baFStW0L9/fxITE+nUqZOmWikTmnRFpNzJzMw01mr9/PyM62qrVq1qdjRxc5p0RaRcsNlsrF27lri4OFauXMmAAQP49NNP6dixo6ZacRhNuiLi1n766Sdjqg0ICCA2NpYnn3xSU62YQpOuiLgdm81GSkoKVquVVatWMWDAAGbOnMkjjzyiqVZMpUlXRNzGqVOnjKm2UqVKxlRbpUoVs6OJAJp0RcTF2Ww21qxZQ1xcHGvWrGHgwIHMmjWLDh06aKoVp6NJV0Rc0qlTp0hISCA+Pp4qVaoQGxvLE088QeXKlc2OJnJDmnRFxGXYbDZWrVqF1WolJSWFxx57jNmzZ9O+fXtNteISNOmKiNP78ccfjam2WrVqxMbG8vjjj2uqFZejSVdEnJLNZmPlypVYrVbWrl3LoEGDSE5Opl27dppqxWVp0hURp3Ly5Eljqq1Ro4Yx1QYGBpodTeSuadIVEdMVFRUZU+26desYPHgw8+bNo127dmZHEylVmnRFxDQnT55kxowZTJs2jVq1amGxWBg6dKimWnFbmnRFxKGKior48ssvsVqtrF+/niFDhvDFF1/Qtm1bs6OJlDlNuiLiECdOnDCm2tq1axMbG8vQoUOpVKmS2dFEHEaTroiUmaKiIlasWIHVaiU1NZUhQ4Ywf/58TbVSbmnSFZFSd/z4cWOqrVu3LhaLhSFDhmiqlXJPk66IlIqioiKWL1+O1Wpl48aNDB06lEWLFtGmTRuzo4k4DU26InJXfvjhB6ZPn8706dOpX7++MdVWrFjR7GgiTkeTrojctsLCQmOq3bRpE48
jhLlizh97
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
8XbW6tZItpIJXfsX
6F3v37mXWrFkqXLlOgwYNSE1N5ciRI8TExJCdnW12JBHTqXTljnzyySckJCSwePFiKlasaHYccVKVK1dmyZIl1K1bl65du3Ly5EmzI4mYSqUrty0lJYWXXnqJZcuWUadOHbPjiJPz8fEhPj6exx57jODgYPbu3Wt2JBHTaE1XbsvevXsJDw8nOTmZ0NBQs+OIi0lKSuL5558nKSmJyMhIs+OIOJwmXbllJ0+epHfv3vznP/9R4codeeKJJ5g7dy5PPvkkCQkJZscRcThNunJLsrOz6dq1KwMHDuTvf/+72XHExR04cICoqCiGDRvGP
5T11SJOWGSld+U2FhITExMdSrVw+r1aq/IKVUZGZm0qdPHx588EGmT5+Or6+v2ZFEypxOL8tN2e12/vznP1NUVMSUKVNUuFJqateuzdq1a7l8+TI9evTg3LlzZkcSKXMqXbmpd999l82bNzNnzhx8fHzMjiNuJiAggOTkZB5++GFCQkLIyMgwO5JImdItYuSGPv/8cz788EPS09OpXLmy2XHETXl5eTFp0iTuu+8+goODWbhwIR06dLjh8ccvHudU9ikKigqo6leVptWb4uOlHwjFNWhNV0qUmprKwIEDWb16Na1btzY7jpQTCxcuZMyYMUybNo2YmBjjz/MK85i3fx7vbHyHb89+i6+XLx54YLPb8PTw5On2T/PMI8/QoHIDE9OL/DaVrlzn4MGDhIaG8umnn9K9e3ez40g5s3XrVvr168df
pXnn32WVYeWcng5MHY7DYu5V8q8T0VvCoAMLLNSD6M+hBvT53EE+ek0pVrZGZmEhQUxCuvvMJTTz1ldhwppzIyMoiKiqJxdGPWVVnHlcIrt/S+AJ8AOt
maVPLFXxilNS6YohJyeHbt260aNHD9544w2z40g5t2zvMvrM6YPNy3Zb7wvwCWBwi8Ek9NPNN8T5qHQFgKKiIh577DECAwNJTEzUpUFiulZTWvHN6W/u6L3+3v5st2ynea3mpZxK5O7okiEBYPz48Vy4cIFp06apcMV0O37cwdHzR+/4/QVFBby3+b1STCRSOlS6wvvvv8+qVav44osvdFcgcQqT0ieRV5h34wMuAJ8D7wLvAEuvfbnQXshnez4jO1/P8BXnop0G5dz8+fN59913SUtLo2rVqmbHEQHgy8NfUmQvKvlFG5AE3AcMADyAEh7T6+Ppw1cnviL8vvAyyylyu1S65djmzZuxWCysWLGCRo0amR1HxHCjS4MAOAFcAroDXj
WQn/+dqxc
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
wWnJKSQlBQEFOnTqV9+
4+PiUQlgREXE1mnR/UVgItWvDuXMlvvxvIB7IBBoC/w/oX8JxtubNCfz+e3Jzc/Hz8yM/P5+ioiJOnDhB3bp1yyy+iIg4P026v8jIgPz8G758P5AK1AGSgWHAYeDXNep54ACX8/M5n53Ntm3b2LJlC1u2bCH/Jl9bRETKB026v9i2DSIj4cKFWzq8DfBPIObXL1SoAMePF99AQ0RE5CqeZgdwGj4+cJOfPz6huGi
vxrL5BV0oE22zV3qhIREfmFTi
4p57
hr+XtgLLAGCAK8KC7gG1Z0YGAZBBQREVenSfcXdepAq1YlvnQZ8ABq/fz7BIon3et4esLAgXe/A1pERNySSvdqf/lLiVNqC2A8xVPuPcAeoMTH0vv7w/jxZZlQRERcmDZSXa2goPg08w0uG7opDw/43e+glJ8sJCIi7kOT7tV8fGDu3OKJ9XZVrAjJyaWfSURE3IZK99fCw4sf5XerT/Px8Cg+Jb1iBbRsW
ZRETEpal0SzJwIKxaBa1bF5evl9f1x/j4gJ8fBAfDV19BSImrvCIiIgat6f6Wr7+GSZNg2TLIzi7eoVy5MgwZUvxEovvvNzuhiIi4CJWuiIiIg+j0soiIiIOodEVERBxEpSsiIuIgKl0REREHUemKiIg4iEpXRETEQVS6IiIiDqLSFRERcRCVroiIiIOodEVERBxEpSsiIuIgKl0REREHUemKiIg4iEpXRETEQVS6IiIiDqLSFRERcRCVroiIiIOodEVERBxEpSsiIuIgKl0REREHUemKiIg4iEpXRETEQVS6IiIiDqLSFRERcRCVroiIiIOodEVERBxEpSsiIuIgKl0REREHUemKiIg4iEpXRETEQVS6IiIiDqLSFRERcRCVroiIiIOodEVERBxEpSsiIuIgKl0REREHUemKiIg4iEpXRETEQVS6IiIiDvL/AZYE1e+qiuGPAAAAAElFTkSuQmCC\n",
"text/plain": [
"
"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Completed: b\n",
"Now doing: {'a'}\n"
]
},
{
"data": {
"image/png": "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
zzflcOrpSTk0OdOnXYs2cPjzzyiNlx3E
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
165qS9FN2u53Lly8Xa5V3aGhosaa8w8LC9P
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
+d+x2O
5n/9pdhQREfFQml4ugut519lxegdXblwhMCCQ6qHV6VC3AyFBIQCkpKTw7LPPkpycTIMGDcwNKyIiHksLqe7h8KXDTNk+hYRvEigT+NO/qgACeOOX
Bay9cYNmwY
d
6fCFRGRe9JItxB2p53xq8Yz/5v55DvzsTvthR5XNqgsdrudZheasS9mH4GBmq0XEZG7U0v8jMPpoP+i/izYt4Ab9ht3LVyAXEcujgAHx+scJ3JNpBtTioiIN1Lp/szkNZPZeHwj2fnZRX5Ntj0b214b1h1WFyYTERFvp+nl25zNPEtDa0NyHbklen2FkApc/N1FypUpV8rJRETEF2ike5vpX09/4JsTLD24tJTSiIiIr9FI9wd2p52af6vJ1ZyrhR9wDfgCOAGEAB1++PMzT9R4gv1v7ndZThER8V66ZOgHx9OPk+fIK/ydTmAh0AwYREEBzwWqA41/eujBiwexO+13XGIkIiKi6eUfpOek370ozwDXge4U/JpSFWgLFDKgDQkKIT0n3UUpRUTEm2k49oPgwGAM7jLTng5kAh/f9pwBPHLnoU7DeWunKhERkdupdH/wUIWHyLXfZdVyJaAKUMRLccNDwksrloiI+BBNL/+gVoVatKjZovB31gHKAluAfArO8Z4HTv/0sMCAQAY1H/TAK6BFRMQ3qXRv83bntwsfpQYCLwPngCnA/w+sAHJ+elj5MuV5q9N
o4pIiJeSpcM3Sbfkc9D
vQ3S8buocAAnis+mMcnHDQBclERMQXaKR7m+CgYJYOXUr5MuWL/dqwkDCWDFniglQiIuIrVLo/07NhTxIGJhBaJrRIxwcQQHhIOGuGreGJmk+4OJ2IiHgzTS/fxVenvmL8qvGkXkkl156Lw3D85P3BgcEEBQbR9uG2zOo3i8eqP2ZSUhER8RYq3ftIOZfC37f/ndXfrSYrL4vAgEAqhlTkpRYvMan9JB6t+qjZEUVExEuodEVERNxE53RFRETcRKUrIiLiJipdERERN1HpioiIuIlKV0RExE1UuiIiIm6i0hUREXETla6IiIibqHRFRETcRKUrIiLiJipdERERN1HpioiIuIlKV0RExE1UuiIiIm6i0hUREXETla6IiIibqHRFRETcRKUrIiLiJipdERERN1HpioiIuIlKV0RExE1UuiIiIm6i0hUREXETla6IiIibqHRFRETcRKUrIiLiJipdERERN1HpioiIuIlKV0RExE1UuiIiIm6i0hUREXETla6IiIibqHRFRETcRKUrIiLiJipdERERN1HpioiIuIlKV0RExE1UuiIiIm6i0hUREXGT/wc7nWO2LCMYOwAAAABJRU5ErkJggg==\n",
"text/plain": [
"
"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Completed: a\n",
"Now doing: set()\n"
]
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAeQAAAE/CAYAAACXV7AVAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAIABJREFUeJzt3Xd0VOWixuE3HVIEpBOaBFIoimBFQzsC0sKxAIZgoapLvSgKCYiAFDGogBw5NlAXXKooIqKCHDqIIlIE0ggQQhECmpBGksns+4cHrpiACSTZe2Z+z1quILMnvqHk9St7f26GYRgCAACmcjc7AAAAoJABALAEChkAAAugkAEAsAAKGQAAC6CQAQCwAAoZAAALoJABALAAChkAAAugkAEAsAAKGQAAC6CQAQCwAAoZAAALoJABALAAChkAAAugkAEAsAAKGQAAC6CQAQCwAAoZAAALoJABALAAChkAAAvwNDsAAABlwTAM7Tq1S6kZqcopyFGVSlV0S+1b1KBKA7OjlQiFDABwaOfzzmv+3vl6Y/sb+i33N7m7ucswDLm7uSuvME93179bo+8Zra5BXeXuZt2JYTfDMAyzQwAAcC2+S/5ODy57UIZhKLsg+4rX+Xv7q1GVRlr32DrV8a9TgQlLjkIGADikFXErNPDzgcqx5ZToei93L1X3ra5dw3epXkC9ck5XehQyAMDh7Dq5S+0
l/iMr7I091TTao10b6n9snH06ec0l0b606mAwBwBTH/iSl1GUuSzW7TycyT+izus3JIdX0oZACAQ0nNSNXWY1uv+f1Z+VmK3RpbhonKBrusAQAOZc7OO
iaut5Sd9ISpHkLemu
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
ffflszZsxQv379tH
ftWtW1eGYejQ+UNambCyxLulfTx81LhqY33e
NyTg1XxggZgFOx2Wz64IMPFBwcrD179mj79u3697
p160r6Y3PX/z74vxrUepB8vXzl7nb1b4P+3v66te6t+mHoDwrwucLWa6AMcNoTAKdgGIY+
xzjR07VvXr19f
7+u22+
arv2XVyl976/i2tiF8hT3dP5RfmyzAMeXl4yW7YdXu92xV9T7Tub3q/PNw9KugrgauikAE4vI0bNyo6Olr5+fmKjY1Vly5dSnVO8W+5v+mbpG+UlpMmm92mapWqqYlHE/W8u6d++uknNW/evBzTA3+gkAE4rL1792rMmDGKj4/X1KlT1b9/f7m7l81K3IYNG9S5c2f5+/tr+
tatWqVZl8XuBKWEMG4HCOHDmiRx99VN26dVP37t0VHx+vyMjIMitjSTp69Ki8vLyUlZWle++9V7t27Sqzzw0Uh0IG4DDS0tL0/PPP67
lNQUJCSkpL03HPPydv7rzcWX7/Dhw/LZrNJkjIzM9W5c+dL/w6UBwoZgOVlZWVp8uTJCg0NVWFhoQ4ePKiJEycqIKD8dj3Hx8fLw8NDHh4euv/++7V+/Xp5enKnKMoPa8gALKugoEAffvihpkyZoo4dO2ry5MkKCgqqkP/2tm3blJubq4SEBG3dulWLFy+ukP8uXBeFDMBy7Ha7Pv30U40bN05NmjTRtGnT1KZNG1OynD17Vk2bNtXx48fl7+9vSga4BuZfAFjKf/7zH0VHR0uS3n33Xd13332m5qlRo4buvfdeffHFFxo4cKCpWeDcWEMGYAk
yzunbtqqeeekqjR4/Wjz/+aHoZXxQVFaVFixaZHQNOjilrAKZKTk7WuHHjtHHjRo0fP15Dhw6Vl5eX2bEuk52drcDAQCUmJqpWrVpmx4GTYoQMwBSnT5/Wc889pzvvvFMtWrRQUlKSnn76acuVsST5+fmpZ8+e+vTTT82OAidGIQOoUJmZmZo4caKaN28uDw8PxcXFady4cZbfMMW0NcobhQygQuTn5+tf
qXmjVrpuTkZP3000+aNWuWatasaXa0EunSpYsSExN15MgRs6PASVHIAMqV3W7XokWLFBoaqm+++UZr1qzRggULdNNNN5kdrVS8vLzUt29f7kdGuWFTF4ByYRiG1q5dq5iYGHl7eys2NlYdO3Y0O9Z12bZtm4YPH679+/eX6jQpoCS4DxlAmdu5c6diYmJ0/PhxTZs2TQ888IBTFNjdd9+t7Oxs7du3T7fccovZceBkmLIGUGaSkpLUr18
fOf/1T
v114MABPfjgg05RxpLk7u6uyMhINnehXFDIAK7bqVOn9PTTT6tdu3a69dZblZSUpOHDhzvlYQxRUVFavHix7Ha72VHgZChkANcsIyND48aNU8uWLeXn56f4+HiNGTNGvr6+ZkcrNy1btlTVqlW1detWs6PAyVDIAEotLy9PM2fOVHBwsE6cOKHdu3frzTffVPXq1c2OViG4JxnlgV3WAEqssLBQixYt0iuvvKJWrVrptddeU6tWrcyOVeFSUlLUtm1bnTx5Ut7e3mbHgZNwvgUeAGXOMAx98803iomJkb+/vxYsWKDw8HCzY5mmUaNGCgsL05o1a9S7d2+z48BJMEIGcFU7duxQdHS00tLSNG3aNEVERDjNrunr8d5772njxo1asmSJ2VHgJChkAMWKj4/Xyy+
B9
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
DLtkfS9pPT
nu+pJyil7m7ucvbw1s+Pj7q3r27unfvrsLCQuXnX2HkDQBwKRRyCdQNqKsj6UeKvpAuaZWkxyQ10B+j5HclFbMq7+3hrdp+tS/7OQ8PD57xDACQxJR1iQxvM1z+3v5FX7g4uL34QKvdkq4wA22z29SjWY9ySAcAcAYUcgn0a9Gv+BdqSWonaa6kNySdltSw6GWebp4a0GqAAny4RxgAUDxueyqh5799Xu/99J7yCvNK/d7KnpW1c9hOtajVohySAQCcASPkEprcabIaVmkoD7fSHS/o6+Wr6HuiKWMAwFVRyCUU4BOgTU9sUuOqjeXj4VOi9/h6+WpYm2Ea32F8OacDADg6pqxL6XzeeT2z+hktj1sud7krx1b0Hid
3/5efnptX+8psG3DjYhJQDA0VDI1+j33N/18Z6PNWfnHJ3JPqP8wnz5efmpdZ3WGn3PaHUN6ip3NyYgAAAlQyEDAGABDOEAALAAChkAAAugkAEAsAAKGQAAC6CQAQCwAAoZAAALoJABALAAChkAAAugkAEAsAAKGQAAC6CQAQCwAAoZAAALoJABALAAChkAAAugkAEAsAAKGQAAC6CQAQCwAAoZAAALoJABALAAChkAAAugkAEAsAAKGQAAC6CQAQCwAAoZAAALoJABALAAChkAAAugkAEAsAAKGQAAC6CQAQCwAAoZAAALoJABALAAChkAAAugkAEAsAAKGQAAC6CQAQCwAAoZAAALoJABALAAChkAAAugkAEAsID/A4HT+ZrajIqaAAAAAElFTkSuQmCC\n",
"text/plain": [
"
"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"execute_schedule(s, show=True)\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"id": "lAyaUHLmkacN",
"nbgrader": {
"checksum": "a3c215f20358f8f865a4b0090cf010ab",
"grade": false,
"grade_id": "cell-9c9e6ce16186ae03",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"source": [
"What happens if there is a loop? "
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"colab": {
"base_uri": "https:
localhost:8080/"
},
"deletable": false,
"editable": false,
"id": "BjwBKj05kacN",
"nbgrader": {
"checksum": "1a72092331547b48af83b369cef694b7",
"grade": false,
"grade_id": "cell-2dc9924f19540ab3",
"locked": true,
"schema_version": 1,
"solution": false
},
"outputId": "97c8c6d9-520d-488d-d20b-817c552d
08"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Starting by doing: set()\n",
"E
or, there are tasks that could not be completed: {'b', 'c', 'a'}\n"
]
}
],
"source": [
"s = DependencyScheduler()\n",
"s.add_task('a', ['b'])\n",
"s.add_task('b', ['a'])\n",
"s.add_task('c', ['a'])\n",
"execute_schedule(s)\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"id": "Y7SYMbISkacN",
"nbgrader": {
"checksum": "4b32a15d1debae4980463aa52d8c7d01",
"grade": false,
"grade_id": "cell-1d09ba345dc1de32",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"source": [
"Ok, this is reasonable! Let us now encode our Ca
onara pasta recipe. "
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {
"colab": {
"base_uri": "https:
localhost:8080/",
"height": 353
},
"deletable": false,
"editable": false,
"id": "B4HKEQVukacN",
"nbgrader": {
"checksum": "a08bcaa837cddd038962a11f91fb8343",
"grade": false,
"grade_id": "cell-bc314c96d21a34c7",
"locked": true,
"schema_version": 1,
"solution": false
},
"outputId": "10b6b2d6-fff5-4f5f-fbe1-fcb6b8afeaa9"
},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAeQAAAE/CAYAAACXV7AVAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAIABJREFUeJzs3XlYFfX3wPE3ArJdlFUEQRSXXCrTUhEX0NRKzbJcyhXNfvrN3Rb3fcn9W7ao3ywtFXMvlUzTFHHNLDWXTE0BJVNwAWSH8/vj4g0UFAwE5Lye5z4P987MZ85c4J47M2fOmImIoJRSSqlCVaqwA1BKKaWUJmSllFKqSNCErJRSShUBmpCVUkqpIkATslJKKVUEaEJWSimligBNyEoppVQRoAlZKaWUKgI0ISullFJFgCZkpZRSqgjQhKyUUkoVAZqQlVJKqSJAE7JSSilVBGhCVkoppYoATchKKaVUEaAJWSmllCoCNCErpZRSRYAmZKWUUqoI0ISslFJKFQGakJVSSqkiQBOyUkopVQRYFHYASqmH6MIFOH4cbt4EW1vw9oa6dcHMrLAjU6rE04Ss1KMuLQ2+/x5mzoRDh8DKCtLTjUk4LQ3c3OC996BbNzAYCjtapUosMxGRwg5CKVVALl6EFi3g8mWIjc15Pjs7MDeHjRvB3
hxaeUMtGErNSjKjwcnn4arl837gnnho0NrFsHL7xQsLEppe6iRV1K5dLp06epW7cu9vb2zJ8/n/79+zNlyhQAdu3ahaenp2neSpUqsX379sIKFeLjjXu6OSTjUOCx7JZLSICOHbmwdStmZmakpqYWdKRKqQx6DlmpXJo1axYBAQH8+uuvhRZDQEAA3bt3p2/fvveeccUKuHo1xz3jpsDpTM8rAYuBlmBMynPn5ke4ebJr1y66d+/OxYsXH/q6lSoKdA9ZqVwKCwujdu3ahR3G/YkYC7hu3Xrw5UNC8jemh0D35lVxpwlZqVxo0aIFO3fuZODAgRgMBv744w8CAwMZO3ZsnscKDAykf
+tGrVCnt7e/z9/QkLCzNN37dvH/Xr16ds2bLUr1+fffv2ATBmzBhCQ0NNMQwcOPCusXv16sXcIUPg8mUuAWbApxnTzgJOgAC7gNsH2HsA4cCLgAGYlWm8FStWULFiRVxcXJg2bVq223P+/HkcHBxIT08HoG/fvpQrV840vXv37nzwwQcALFmyhJo1a2Jvb4+Pjw+LFi0C4NatW7zwwgtERkZiMBgwGAxERkaSnp7OjBkzqFKlCs7OznTu3Jlr164BcOHCBczMzPj888+pWLEiLVq0yNX7r1RRpQlZqVz48ccfadq0KR9
DFxcXFUr179X423YsUKxo0bR1RUFE899RTdunUD4Nq1a7Rt25bBgwcTHR3N8OHDadu2LdHR0UybNi1LDB9
PFd4
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
7Hz169GDdunWajJVSBUb3kJXKQXp6OiNGjOD
78lNDSUatWqFXZISqlHmCZkpbIRHx9P9+7diY6OZv/+/Tg7Oxd2SEqpR5weslbqDpcvXyYgIAA7Ozu2bdumyVgp9VBoQlYqk+PHj+Pr60u7du346quvtJJaKfXQ6CFrpTJs3bqVHj168MEHH9C1a9fCDkcpVcLoHrJSwMKFC+nVqxfr16/XZKyUKhS6h6xKtLS0NN577z02b97Mnj17qFq1amGHpJQqoTQhqxLr1q1bdOvWjZs3b7J
36cnJwKOySlVAmmh6xViRQZGYm/vz8ODg5s3bpVk7FSqtBpQlYlzrFjx2jUqBEdOnRgyZIllC5durBDUkopPWStSpYtW7bQs2dPPvroI1577bXCDkcppUw0IasS49NPP2XKlCl8++23+Pn5FXY4qihKT4e
4YbN8DKClxdwd6+sKNSJYQmZPXIS0tL45133mHLli3s2bOHKlWqFHZIqqiJioLPPoMPPoCYGLC0BBFITgZ/f3jvPWjRAkrpWT5VcMxERAo7CKUKSlxcHN26dSM2NpZ169bh6OhY2CGpoiQtDd55BxYuBDMzSEjIfj6DARwc4NtvoV69hxujKjH06556ZEVGRtKsWTOcnZ35/vvvNRm
FJT4aWX4H
g8TEnJMxQFwcXLwIzZrBzp0PL0ZVomhCVo+kI0eO4OvrS6dOnfj888+1krqYCwwMZOzYsQCEhoby2GOP/ftB+/UzJtf4+Nwvc+sWtG8Px4+bXsq3eFSJpwlZPRJ++uknxo4di4gQHBxMq1atmD17NqNGjcLMzKyww1P5qGnTppw+ffrfDXLsGKxcmbdkfFtcHAwcmL/xKIUWdalHxIgRIwgNDeXo0aP8/PPPbNy4kUaNGhV2WKqo+u9/jQVbD+rgQTh/HipXzr+YVImne8iqaDp/HoYPB29vYzGNoyNUqgTvvgthYVlm/fPPPzlw4ABpaWkEBwczbtw4TcbF3K+
kq9evWwt7enS5cuJCYmmqbt2rULT09P0/OIiAheeeUVXF1dcXZ2ZmCmvdcvvviCmjVr4ujoyHPPPUdYWJixiv
40FXZlsBGoDDkAAcCrTtErAHOBJoCzQJTmZxA8+yDaeU6dOERAQgIODA7Vr12bjxo2maYGBgQwYMIC2bdtib29Pw4YNOXfuHAAiwrBhwyhXrhxly5blySef5HimQ+OqBBClipLjx0X8/UWsrUVKlxYxXnzyz6N0aeO05s1FTp4UEZH+/fuLmZmZAAKIpaWlhIeHF+52qAeWlJQkFStWlHnz5klycrKsWbNGLCwsZMyYMSIisnPnTqlQoYKIiKSmpsqTTz4pQ4cOlbi4OElISJDQ0FAREdmwYYNUqVJFTp48KSkpKTJlyhRp1KiRyKZNImXKZPm7Og1iC7INJBlkJkgVkKSM6d4g9UEugUSD1ABZ4OR0VzzJyclSpUoVmTZtmiQlJcmOHTvEYDDI77
LiIivXr1EkdHRzl48KCkpKRI165dpUuXLiIi8v3330u9evXk+vXrkp6eLidPnpTIyMiH+t6rwqUJWRUdO3eKGAwiZmZ3J+I7H2ZmIvb2kvLjj1KqVCkxMzMTZ2dn6dixoyxZskRSUlIKe2vUAwoJCRF3d3dJT083vdaoUaNsE/K+ffvExcUl29/3888/L4sXLzY9T0tLExsbG7kwd67x7yzT39NkkE6ZnqeBeIDszJSQl2Wa/i5Iv9Kl74pn9+7d4ubmJmlpaab1vvbaazJhwgQRMSbkN954wzQtODhYHnvsMRER2bFjh1SrVk3279+fZXlVcugh64ekUqVKbN++PdfzP6qVm3v37qVatWoYDAa++eabfyb8+iu0a2csmMnNpfEiEBuL+Ysv8vmQIZw7d46oqCjWrFlDYGAgFhbFtzzizkOgebFixQpat25tem5mZsbZs2fzK7SHIjIykgoVKmQpxvP29s523oiICLy9vbP9fYeFhTFkyBAcHBxwcHDAyckJEeHS9et3rxPIvIZSgBdwKdNr5TP9bAvE5RC7l5cXpTI1EPH29ubSpX9GKl/+n5FsbW2JizOO1KJFCwYOHMiAAQNwc3Pj
7v/4iJicl2u9WjSRNyEVVUKzfz+sXiTuPHj2fgwIHExcXx8ssvG18UgZdfNl5Skkdmt24R+O23VK5UyfTaxIkT6d69+wPHmJ2CGLMgdOvWjW3bthV2GP+Ku7s7ly5dQjJ9MQsPD892Xi8vL8LDw0lNTc122qJFi7hx44bpkZCQgJ+v710dtzyAzJUJAkQAFe4VqKXlXS95eHgQERFBenp6ltgrVLjnSCaDBw/m8OHDnDhxgj/++IPZs2fnajn1aNCEXARl9+HyqAgLC6N27dpZX9y5E65de/BBr1yBPXv+XWCZPMrvf3HQqFEjLCwsmD9/Pqmpqaxfv56ffvop23kbNGiAu7s7I0eO5NatWyQmJrJ3714A+vfvz/vvv8+JEycAuHnzJmvWrDG2wrzjd9wZCAZ2ACnAXMAKyLHjealSxoLDOzRs2BA7OztmzZpFSkoKu3btYtOmTbm6kcmhQ4c4ePAgKSkp2NnZYW1tjbm5+X2XU48OTcgP0aFDh6hVqxaOjo707t3bVDl6+xDlzJkzKV++PL17977rsGWlSpWYM2cOTz75JGXLlr2r8nTWrFm4u7vj4eHB4sWL73moMiAggFGjRtGgQQPKli3LSy+9xLVMCXHjxo3Url0bBwcHAgICOHXKWG/ao0cPwsPDefHFFzEYDMyaNSvb8T/77DOqVq2Kk5MT7du3JzIyEoAqVarw559/mpZPSkq6HTzExbEEeDHTOFUxflDe5gUcyfh5SMbzMsDTcXGEjhwJwPfff8/06dNZtWoVBoOBOnXqAMYP4zfeeAN3d3cqVKjA2LFjScuosl26dCmNGzdm2LBhODk5MXHixCzbk9OYkZGRtG/fHicnJ6pWrcpnn32W7fsBEBwcTN26dSlTpgxeXl53rSM706dPx8XFhUqVKrFixQrT6zdv3qRnz564u
i7e3N1KlTTXtkS5cupUmTJvcduygrXbo069evZ+nSpTg6OrJq1SpeeeWVbOc1Nzdn06ZNnD17looVK+Lp6cmqVasA6NChAyNGjOC1116jTJkyPP7442zZssXYBrNrV8h0mPsxYDkwCHABNmU8cmwnY2YG1atnG/vGjRvZsmULLi4uvPXWW3z11VfUqFHjvtsdExPDm2++iaOjI97e3jg7O/POO+/cdzn1CCnsk9glhbe3t9SuXVvCw8MlOjpa/Pz8shSpmJuby3vvvSeJiYkSHx+fpVDk9vL169eXS5cuSXR0tNSoUUMWLFggIiJbtmwRNzc3OX78uNy6dUu6d+8ugJw5cy
WPz9/cXDw0N+++03iYuLk1deeUW6desmIiKnT58WW1tb2bZtmyQnJ8vMmTOlSpUqkpSUZIrjhx9+yHE7d+zYIc7OznL48GFJTEyUgQMHStOmTbNsR5bl4+JELC1FQM6BlM0oqIkEqZhRWHN7mkPGNMkosIkCSQGZA+IGknD9uoiITJgwwbQ9t7300kvyf
3fxIXFyd
231K9fXxYuXCgiIkuWLBFzc3OZP3++pKSkSHx8/F3bld2YzZo1k
85z+SkJAgv/76q7i4uMj27duzfV927twpx44dk7S0NDl69KiUK1dONmzYkOO85ubmMmzYMElMTJRdu3aJra2tqVK3R48e0r59e4mJiZHz589LtWrVTMVLS5YskcaNG5vGutffQYl24oSIjc39iwdzKih89tnC3gL1CNKE/JB4e3ubEqiIs
Sx8dHRIwfwJaWlpKQkGCanl1CXrZsmen5u+++K/369RMRkd69e8vIkSNN086cOXPfhDxixAjT8xMnToilpaWkpqbK5MmTpVOnTqZpaWlp4uHhITt37jTFca+E3KdPH3n33XdNz2NjY8XCwkLOnz+f/fIXLojY2Zk+7DxBDoOsBHkz41KTUyBfgLx4jw9JB5Aj27aJyN3J8/Lly1K6dOksiTYoKEgCAgJExJjEvLy8ctym7MYMDw+XUqVKSUxMjOm1kSNHSq9eve45zm1DhgyRoUOHZjvtdkKOi4szvdapUyeZPHmypKamSunSpeXEiROmaQsXLhR/f3/TtmhCvr+0tDTZ9/TTcis3Ff13PuztRTK+HCmVn/SQ9UPk5eVl+tnb29t0KBfA1dUVa2vrey6fU3Xm7crO7NaT21hSUlKIiooiMjIyS0VrqVKl8PLyylIlei93Lm8wGHB2ds55+cRE4+G/DP7ALmB3xs8BQEjGwz/TYnOBmhibNDgAN4Goy5ezXUVYWBgpKSm4u7ubKm779evHlStXTPPk5j27czudnJywz3Sv3DuraTM7ePAgzZs3x9XVlbJly7Jw4UKioqJyHN/R0RE7O7ssY0dGRhIVFUVycnKW9/he61V3i4+Pp0uXLrxnZYV527aQ6X2+JzMz4+Hu776DR/AKCFX4NCE/RBEREaafw8PD8fDwMD3/N/2W3d3duXjxY
yW0slpaWuLi44OHhYexmlEFEiIiIMFWJ3i/OO5e/desW0dHROVeZOjpCSorp6e2EHJrxsz93J+RQYCawGrgO3MCYmCXjg/XOGL28vLCysiIqKspUbRsTE2Mq9snNdt053cPDg2vXrhEbG2t67V7VtF27dqV9+/ZERERw8+ZN+vfvn6WK+E7Xr1/nVqaq89t/Ly4uLlhaWmZ5j/NSxVvSXb58mYCAAKysrPhhxw6svv0WBg8Ga2uwtc1+ITMzY9L28YH9+6GYn6NXRZcm5Ifok08+4eLFi1y7do3p06fTpUuXfBm3c+fOLFmyhFOnThEfH8/kyZPvu8zy5cs5efIk8fHxjB8/no4dO2Jubk7nzp0JDg5mx44dpKSkMHfuXKysrPDzM9aburm58eeff+Y4bteuXVmyZAlHjhwhKSmJ0aNH07BhQypluiwpCxcXY2vMDP7ATiAB8ASaAt8D0UDdjHliMTZhdwVSgclADEDG3qqbmxsXLlwwFTq5u7vTunVr3n77bWJiYkhPT+fcuXOEhITc93267c4xvby88PPzY9SoUSQmJnLs2DE+
xzunXrlu3ysbGxODk5YW1tzU8
URQUNB91zlhwgSSk5MJDQ1l8+bNdOrUyfQ7GjNmDLGxsYSFhTFv3rxicUlWYTt27BgNGzbkxRdfZNmyZcYjUqVKwfTpcPkyvP8+eHoaL2eyswMbG+PP7dvD1q1w5gw8/nhhb4Z6hGlCfoi6du1K69at8fHxwcfHx3Q7uX
hRdeYPDgwTRv3pyqVaua+jhbWVnluEyPHj0IDAykfPnyJCYmMn/+fAAee+wxli9fzqBBg3BxcWHTpk1s2rTJdPvCUaNGMXXqVBwcHJgzZ85d4z777LNMmTKFV199FXd3d86dO8fXX3+dc/ClShl7VtvYAFAdMGBMxGCsovYBGgO3LwB5DnghY15vwNrSEi9HR9Oh706dOgHg7OxMvYybyX/11VckJyebqtw7duzIX3/9da+3NYvsxly5ciUXLlzAw8ODDh06MGnSJFq1apXt8p9++injx4/H3t6eyZMn07lz52znu618+fI4Ojri4eFBt27dWLhwoalS96OPPsLOzg4fHx+aNGlC165d6dOnT663pSQKDg6mZcuWzJw5k3Hjxt19RKRsWeOecng4XL0KJ07An39CbCx88w00bpzl1IpSBcFM7nXcTBVLp06d4vHHHycpKSnbDkYBAQF0796dvn37FkJ02YiOhgoV4PZlUHllbQ1
ZVlT1spMJ5ymT9/PjNnzmT9+vX4+voWdkhK5Uj3kB8RGzZsIDk5mevXrzNixAhefPHF4tM+0tkZBgzI+RzevdjaGvdsNBmrO6SmpjJgwAA+++wz9u3bp8lYFXmakB8RixYtwtXVlSpVqmBubs6CBQsKO6S8mT0befZZEvPSmcjWFp5/3njuT6lMbt68Sdu2bTl
jz79u3LuYZBqSJED1mrImPGtGnU+PBDXoqLwyw5+a771d6WVqoU5lZWEBgIH30E2l5QZXL+/HnatWtHixYt+O9
1t8jhSpEk/3kFWRsGXLFj769FPq
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
e
+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
fr1ExGR
u
5OhQ4caJ+zdK1K2rAjIZZDSIPGZEm4QSEAuErKYmYlk7AVfv35dNm7cKO+9955ERkZKnTp15Jtvvsk27uwSckREhGl6/fr1ZeXKldku26tXryxtQGNjY6VUqVISHh6e7fwODg5y5MgR03qfffZZ07QTJ06ItbV1tsupgqPnkEuwMWPGkJKSwqxZs/K0XEJCAv/5z3/45Zdf2LdvH1WrVi2gCFVBERE++OADZsyYwRdffEHbtm3zZdyC6kR2v/GvXLnC4MGDCQ0NJTY2lvT0dBwdHbMse2eHrtvLRkRE0KZNG+OETAVsYUAK4J5pjHQgVzcINTMzjmVpycaNG5k3bx4XLlxg0aJFxMXFEZWp6Ot+8tJZLPP7YzAYcHJyIjIyEi8vL+bOncvixYuJjIzEzMyMmJiYLHHcuZ7ExERSU1OzdFBTBUsvWCuhVq9ezapVq1i1alWe/uHCwsJo0qQJiYmJ7N+/X5NxMXTz5k06duxIUFAQBw8ezLdkDAXXiex+448aNQozMzOOHTtGTEwMy5cvz3V3Li8vL86dOwdAgrU1qRkFbF6AFRAF3Mh4xAAnbseczVim10qVAmtrwsLCePPNN/n444+Jjo7mxo0bPP744/+uc9g9ZH5/4uLiuHbtGh4eHoSGhjJz5kxWr17N9evXuXHjBmXLli2wONSD0YRcAh07dowBAwawfv36PDWO2L59Ow0bNqRbt26sXLkSOzu7AoxSFYSjR4/yzDPP4Obmxp49e6hUqVK+jv/JJ59w8eJFrl27lmMnssTExDx3Irtt9uzZXL9+nYiICD788EPT+LGxsRgMBhwcHLh06VKuL91LSkqibt26LFiwgCeeeAI3f3/OJifzO8Y949bA2xgTcTpwDgi5HTNwEchcf+4G/AnQuDEAt27dwszMDFdXVwCWLFnC8ePHcxXbg/juu+/Ys2cPycnJjBs3joYNG+Ll5UVsbCwWFha4urqSmppqurGEKlo0IZcw165do0OHDnz44YfUzWWbPxFh9pvaxOQAACAASURBVOzZ9OjRg5UrVzJ8+HBtTlAMLV26lJYtWzJx4kQ+/fRTrKys8n0dBdWJ7LaXXnqJp59+mqeeeoq2bdvyxhtvAMYbofzyyy+ULVuWtm3b8so
2S7fEpKCvv372f37t3s2LEDFxcXlixZQps2
h16xZibk67MmUIy7j07yuMCbcW4Ah0BP7KGKsFUBvjzTZuf619AzhZqhQOP
Myy+/TK1atXj77bdp1KgRbm5u/P
zTOSNYFoWvXrkyaNAknJycOHz7MihUrAHjuued44YUXqF69Ot7e3lhbW2c5vK2KBu3UVYKkpaXRpk0bnnjiiVzfwSkuLo4+ffpw/vx51q1bR8WKFQs4SpXfEhISGDRoEHv37mXdunUFdo14QXciMzMz48yZM3k6TZKWlsaRI0f48ccf2blzJ3v27KFKlSo0b96cFi1a0LRp07u7Z0VGgo8PJCU9WKDlyhmv3X7ILSyLVHMV9UD0bH0JMnr0aNLS0pgxY0au5j9z5gwdOnSgQYMGhIaGYm1tXcARqvx29uxZOnbsSM2aNTl06BAGg6GwQypQ6enp/D979x1XZfUHcPwDXGQjUxRECBeihpojR+I2QzT3zlFqZWWOX+6ROLK0nEXukbvhNs1tTjT3xhREXKAgQ+Be+P7+uHoFxYExBM/79bov773POs9zr3zvOc8533Pq1Cl27NjBjh072LVrF66urtStW5ePPvqIxYsX4+jo+OyduLrqs439+KM+T3VmWFjot1P5pJWXoALya2LFihWsWrWK4ODgF+rEtX79enr06MGYMWPo3bu3aqLOg1avXk2vXr0YNWoUn376ab78DEWE8+fPs2PHDrZv387OnTuxs7Ojbt26tG/fnqCgoHS9h1/YxIkQFg
1794ULa0hMBAUCljlZekmqxfA8ePH6dBgwZs3boV3+fkGE5NTWXMmDHMmTOHVatWUb169RwqpZJVtFotQ4cOZdWqVaxYsYJq1arldpGyjIhw+fJlQwDesWMHpqamhibounXrZt290dRUGDQIZszQv05MzHg9Kyv9KORZs6BTp6w5tvJaUgE5n4uKiqJKlSqMHz+e9u3bP3Pd6OhounTpwt27d1m1ahVFihR55vrKqyciIoJ27dphY2PzYs2zeUB4eHi6AJyUlJQuAHt5eWVv7f/6dQgKgunTQad71Byt1ervFw8apM/hnc9vByjZTwXkfEyn09GkSRMqVKjw3GEgp06domXLljRu3JjJkydToECBHCqlklW2b99O586d6dOnD0OGDMmz8+LevHmTnTt3GgLwnTt3qFOnjiEAe3t7507zu04H587B3bug0YCTE5Qo8d8molCUNFRAzsf+97
cezYMTZt2vTM+8YrV66kT58+TJ48mQ8++CAHS6hkhdTUVL755htmzJjB4sWLqV+/fm4XKVPu3LnDrl27DAE4PDyc2rVrGwJw+fLl8+yPC0XJDNWpK59atmwZv/322zM7cel0OsO9xs2bN1PpsUnVlVffnTt36NKlCzExMQQHB+eJKfzu3bvHnj17DAE4JCSEmjVrUrduXRYsWEDFihUxMTHJ7WIqSo5TNeR86NixYzRs2PCZnbgiIyNp3749RkZGLFu2LFMZu5RXQ3BwMG3atKF169ZMmDDhpeaxzgnx8fHs3bvXcB/49OnTVKtWzXAfuEqVKq9s2RUlJ6mAnM9ERkZSpUoVJk6cSNu2bTNc58iRI7Rq1Yr27dszbtw4VRvJY0SEn376idGjRxMUFPTUrFS5JTExkQMHDhgC8NGjR6lYsaIhAL/99ttqTLuiZEAF5HxEp9PRuHFjKleuzMSJEzNcZ+HChQwcOJCffvqJ1q1b53AJlf8qLi6O3r17c
0aX799ddXYnIPrVZLcHCwIQAfOnQIHx8f6tatS926dalVq5bKe64oL0DdQ85HBg0ahEajYfz48U8sS05Opn
mzZsoWdO3dStmzZXCih8l+cPXuWVq1aUb16dfbv34+FhUWulCMlJYWjR48aAvDevXspXrw49erVo1+/fhmno1QU5blUQM4nli5dyurVqwkODn6iCfr69eu0adMGBwcHDh06hJ2dXS6VUnlZS5cupW/fvkycOJEePXrk6LEfpqN82Alr9+7duLq6Uq9ePXr27Mkvv/ySL8Y7K0puU03W+cDRo0dp1KgR27dvp3z58umW7du3j7Zt29KrVy+GDx+uho/kMUlJSYaWjV9
fW5mdaywsN0lA8D8MN0lA+HIdWpU+fl0lEqivJMqoacx0VGRtKiRQtmzpyZLhin7fgzf/78LJ2EXskZV65coU2bNhQrVozDhw9nWzPww3SUDwPww3SU9erVIyAggO+
15N1acoOUDVkPMwnU5Ho0aNqFq1aroZnBITE/nkk08IDg7mjz/+oGTJkrlYSuVFPRw3/s0337BhwwZ69OjBoEGD6NevX5Znprp69aoh+G7fvh2tVmvohFWvXj3eeOONfDkZhaK8ylRAzmPCw8O5desWlSpVol+/fpw9e5YNGzYY7huHhYXRsmVLihcvzty5c/P9dHuvtIQEWLtWP2tQQgIULAhvvgl16z4xPZ9Op8Pd3Z07d+7QpEkTjhw5wrJly6hVq1aWFOXmzZvpAnB0dHS6dJSlS5dWAVhRcpkKyHlMv379mDZtGh06dGD
v0cPnwYe3t7QJ/LuGPHjgwcOJABAwaoP7C5JSQEpk6F+fP1gff+fX0e5AIF9A8bGxgwAD78EB50sFu0aBGffvop8fHxGBsbs2vXrv8UjKOiotKlo4yIiEiXjrJcuXKqP4GivGJUQM5jKlSowPHjxwEoW7Ysu3fvxt7ensmTJzNp0iSWLFmS53IZ5yvz50OfPvoArNU+fT1LSzA3h23bSClfniJFinD79m3D4pIlS3LhwoUXPmxMTEy6dJSXLl2iZs2ahgCs0lEqyqtPBeRXjQjExemfW1unm0lGp9NhZWVFcnKy4T0vLy8qV67MpUuX+O233/Dw8MjpEisP/fgj/O9/Lz6hPYC1NSs++4z233yDqakpPj4+VK9enXr16lG/fn0cHBwy3Cw+Pp6
7b0Ax95swZqlatagjAKh2louQ9KiC/ClJTYft2+PZ
9GRvpHairUqQNffQUNGhB85AjVqlXD1NSU1NRUdDodRkZGvPXWW+zevTvXEkXkR56ensyZM4cGDRq82Aa7dkGTJvrm6UwSe3vOrF1LmRo1MDY2JiYmhiZNmhAXF8eJEycAfUe9/fv3G+4BHzt2jEqVKhk6YVWrVk2lo1SUPE4Ne8ptW7dCt24QE/OoZpzWtm1w8CDY2BDx/vvY2NgwcOBAxo4dC+iHrBw9epSjR49So0aNnC278sjw4S8VjAGMkpIoe+AA1KpFWFgYderU4dq1a6SmpjJ8+HD27dvHoUOHKFeuHHXr1mXUqFHUqFHjqekoFyxYwJw5c/j7778N73Xr1o2iRYsavjeKorx6VEDOTYsXQ+/ez/9DHhcHcXE0X7CAmJkzqTB1KsnJyZibm2NsbMy
76ZrhlbyWGXLsHhwy+/fUICfP89m8qUoVWbNtx/8H0wNjbm9OnTDBgwgHfeeQdbW9ssKrCiKK8kUXLHn3+KWFiI6O8av/jDwkJ6Vq0q3t7eEhISIqmpqbl9JrkuLCxMWrRoIU5OTuLg4CB9+vQREZGUlBQJDAyUYsWKibOzs3Tp0kWio6MN261Zs0Z8fHykYMGC4ufnJ2fOnDEs8/DwkL/++ktERM6ePSuenp6ybNmyDI8PyFRjY3kDxBFkIEjKg88rBKQuiMODZR1B7qb5PD1AvgMpb2ws5hqNGBsbi0ajERsbGzEyMpImTZqIr6+v2NjYiJeXl2zatElERKKjo6VHjx5SuHBhcXV1lWHDholOp5MzZ86ImZmZGBsbi5WVlRQsWFB+/vln0Wg0YmpqKlZWVtK0aVMREZkwYYJ4eXmJtbW1lClTRn7
fds+XwURXkxr3VA7tq1qwwbNizHjztqxAjpVKBA5oPxw4eDg0hyco6X+6HLly8LIFqtNtfK8JBOp5M333xTvvzyS4mLi5P79+/Lnj17RERk7ty5Urx4cbl06ZLExsZKixYtpHPnziIicv78ebG0tJQtW7ZIcnKyTJw4UYoXLy5JSUki8iggHzlyRNzd3WXdunVPLQMgdUCiQEJBSoLMfvBZXQTZApIIcgvkHZC+jwXkKiDXNBqJ+vpr8fb2lm+++Ub++OMP6dixo5ibm8uWLVskJSVFwsPD5ezZsyIi0rx5c+nVq5fExcXJzZs3pUqVKhIUFCQiIvPnz5eaNWumK2NG3/WVK1fKtWvXJCUlRZYvXy6WlpYSERGRNR+MoiiZpgYi5oYLF/Qdtl6WVgvr1mVdeXKYTqfLsn0dOnSIiIgIvvvuO6ysrDA3NzeM312yZAn9+/fHy8sLa2trJkyYwPLly9HpdKxYsQJ/f38aNmyIqakpAwcO5P79++zbt8+w7z179tCsWTMWLlxI06ZNn1mOQYADUAz4Elj24P0SQEPADHAG+gO7Htv2C8BVp8MhOZmAgABCQkIwMjJi7969eHl50bBhQ4yNjXFzc8Pb25ubN2+yadMmpkyZgpWVFYUKFaJfv34sX748U9euTZs2uLq6YmxsTLt27ShZsiSHDh3K1D4URck6eT4ge3p6MmHCBHx8fLC3t6d79+4kJiYC+s4tjydXMDIyIiQkhFmzZrFkyRK+/fZ
K2tCQgIyHD/RkZGTJs2DS8vL5ycnPjf
5H6oNgeunSJerVq4ejoyNOTk506tSJ6Ohow7YTJ07Ezc0NGxsbSpcuzbZt2/jzzz8Zv3IlK3Q6rIGHUwXMB8oANoAX8PMzznlBbCy1unZNV8agoCBKliyJvb09ffr0QTLoPJ+YmIiFhQWRkZEAjB07Fo1Gw7179wAYPnw4X375JQAbNmygYsWK2Nra4u7uzujRow37qV27NgB2dnZYW1uzf/9+AObNm0eZMmWwt7encePGhIaGpivjzJkzKVmyZJam8rx69SoeHh5oNE92h4iIiEg3DMzDwwOdTsfNmzefWGZsbIy7uzvXrl0zvBcUFESNGjWoW7fuc8uRNtOzBxDx4PktoD3gBtgCnYHIx7YtDGBiwuVbt1i4cCHz5s2jU6dOhIaGGr5raYWGhqLVailSpAh2dnbY2dnRu3dvbt269dxyprVo0SIqVKhg2MepU6cM3w1FUXJeng/IoK8Jbd68mUuXLnHhwoUX6knaq1cvOnXqxFdffUVcXBzrnlHj/OOPPzh8+DD
PMPa9asYd68eYC+h/OQIUOIiIjg7NmzXL161RC4zp8/z4wZMwgODiY2NpbNmzfj6enJu++8w1CgHRAHHH9wjELAeuAe+uDcD/jnWScQH6/vmf3A+vXrCQ4O5vjx46xcuZLNmzc/sYm5uTlVqlRh1y59HW337t14eHiwd+9ew2s/Pz8ArKysWLRoEdHR0WzYsIGffvqJ1atXG9YDiI6OJi4ujurVq7N69WrGjx/P77
zu3bt3nnnXfo0KFDuuOvXr2agwcPcubMmWedWaa4u7sTFhaWYa3b1dU13Y+CsLAwNBoNLi4uTywTEa5evYqbm5vhvaCgIMLCwujXr99zy3E1zfMwwPXB8yGAEXAC/Wf7C5DhOEMLC+5YWxMZGUlqairx8fEAXL58mebNmzNw4EB+/vlntm3bhpGREWZmZkRGRhIdHU10dDT37t3j9OnTABlmaHv8vdDQUHr27MmMGTOIiooiOjqacuXKZfhDTlGUnJEvAvJnn32Gu7s7Dg4ODBs2jGXLlj1/o0wYNGgQDg4OFCtWjC+
NKw/xIlStCwYUPMzMxwdnamf
+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
3cLgbcuQNvvQX
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
CDvv
+M9d5LYSHixQpImJq+mLBWKMRKVRI5MoVERGJj4+XypUri7W1tTg4OEjTpk3TfR5r164VNzc3KVCggNjY2IiVlZVUrFhRRo0aJYcPH5bUNK0liqIoInl02JOHh0e65zqdLsNMR5s2beLtt9/GwcEBOzs7Nm7cSGRkpGG5o6MjGo3G8NrS0pK4uDhu376NTqd7NFQlNhaPNPsNBQ7yaDiMHbAEuJFmnScmCExOhnv30r31+HAerVZLZGQkKSkpDB48mOLFi2Nra4unpyeAoey
fYbGzduxMPDAz8/P
v3
Ua3XhwgWaNm1K4cKFsbW1ZejQoemuwWvLzU3f+71SJbC0hKd1qjI21i/39dWv/+C7Z2lpSXBwMLGxsURFRbFu3TpsH/TgBggICCA8PJykpCTu3btHdHQ0U6ZMIS4ujg4dOuDu7s4nn3zCxo0b02UeUxTl9ZUnA3JoaKjheVhYGBqNBhcXl3TrJCUl0apVKwYOHMjNmzeJjo7mvffeQ14gB7GzszMajebRUBVLS8LSLHcH/Hg0HCYaiAN+SrPOE8NqTE3ByirdW48P5zE1NcXJyYmlS5eyZs0atm7dSkxMjD4HMxjKXqVKFdasWcOtW7d4
33DbNJZZRa85NPPsHb25uLFy9y7949xo8f/0LX4LXg7Kyfuenvv6FDBzA3B2trsLXV/2tuDu3awe7d+l72hQu/9KE0Gg21a9dm0qRJXLhwgW3btlG8eHG++eYbXFxcaNGiBfPnz+fWrVvP35miKPlSngzIP/zwA5cvXyYuLo6hQ4fSrl27dDVd0OeETkpKMgTXTZs2sWXLlhfav4mJCS1btmT06NEkJCRwxsWFhWmWNwUuAIvRJ4/QAsHA2WftVKOBBzXdh3755RfOnDlDQkICI0eOpHXr1piYmBAbG4uZmRmOjo4kJCQwdOjQdOe1ZMkSYmJiMDU1xdbW1jBkxsXFhaioKGJiYgzrx8bGYmtri7W1NefOneOnn35CeUzFirB4sT6hy5EjsG2bPgDfvg1Ll0I2jBEvXbo0AwcOZPfu3fz777+0bNmSjRs3UqpUKWrUqME333zD6dOn1Y8nRXmN5MmA3KVLF2rXrs0
7yBubk506dPf2IdGxsbpk2bRtu2
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\n",
"text/plain": [
"
"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"ca
onara = DependencyScheduler()\n",
"\n",
"# First, the part about cooking the pancetta.\n",
"ca
onara.add_task('dice onions', [])\n",
"ca
onara.add_task('dice pancetta', [])\n",
"ca
onara.add_task('put oil and butter in pan', [])\n",
"ca
onara.add_task('put pancetta in pan', ['dice pancetta'])\n",
"ca
onara.add_task('put onions in pan', ['dice onions'])\n",
"ca
onara.add_task('cook pancetta', ['put oil and butter in pan',\n",
" 'put pancetta in pan',\n",
" 'put onions in pan'])\n",
"\n",
"# Second, the part about beating the eggs.\n",
"ca
onara.add_task('put eggs in bowl', [])\n",
"ca
onara.add_task('beat eggs', ['put eggs in bowl'])\n",
"\n",
"# Third, cooking the pasta.\n",
"ca
onara.add_task('fill pot with water', [])\n",
"ca
onara.add_task('
ing pot of water to a boil', ['fill pot with water'])\n",
"ca
onara.add_task('add salt to water', ['
ing pot of water to a boil'])\n",
"ca
onara.add_task('put pasta in water', ['
ing pot of water to a boil',\n",
" 'add salt to water'])\n",
"ca
onara.add_task('colander pasta', ['put pasta in water'])\n",
"\n",
"# And finally, we can put everything together.\n",
"ca
onara.add_task('serve', ['beat eggs', 'cook pancetta', 'colander pasta'])\n",
"\n",
"# Let's look at our schedule!\n",
"ca
onara.show()\n"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {
"colab": {
"base_uri": "https:
localhost:8080/"
},
"deletable": false,
"editable": false,
"id": "Ncr1M1LTkacN",
"nbgrader": {
"checksum": "b71b1bfa89a45be334e3eb7
1ffe580",
"grade": false,
"grade_id": "cell-dde3ea491011fe74",
"locked": true,
"schema_version": 1,
"solution": false
},
"outputId": "c2c72843-3ca6-4c6a-98ad-4daf6c5081a1"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Starting by doing: {'dice onions', 'put eggs in bowl', 'dice pancetta', 'put oil and butter in pan', 'fill pot with water'}\n",
"Completed: put eggs in bowl\n",
"Now doing: {'dice onions', 'dice pancetta', 'put oil and butter in pan', 'fill pot with water', 'beat eggs'}\n",
"Completed: put oil and butter in pan\n",
"Now doing: {'dice onions', 'fill pot with water', 'beat eggs', 'dice pancetta'}\n",
"Completed: dice pancetta\n",
"Now doing: {'dice onions', 'fill pot with water', 'beat eggs', 'put pancetta in pan'}\n",
"Completed: beat eggs\n",
"Now doing: {'dice onions', 'fill pot with water', 'put pancetta in pan'}\n",
"Completed: put pancetta in pan\n",
"Now doing: {'dice onions', 'fill pot with water'}\n",
"Completed: dice onions\n",
"Now doing: {'put onions in pan', 'fill pot with water'}\n",
"Completed: fill pot with water\n",
"Now doing: {'put onions in pan', '
ing pot of water to a boil'}\n",
"Completed:
ing pot of water to a boil\n",
"Now doing: {'put onions in pan', 'add salt to water'}\n",
"Completed: put onions in pan\n",
"Now doing: {'add salt to water', 'cook pancetta'}\n",
"Completed: add salt to water\n",
"Now doing: {'cook pancetta', 'put pasta in water'}\n",
"Completed: put pasta in water\n",
"Now doing: {'colander pasta', 'cook pancetta'}\n",
"Completed: cook pancetta\n",
"Now doing: {'colander pasta'}\n",
"Completed: colander pasta\n",
"Now doing: {'serve'}\n",
"Completed: serve\n",
"Now doing: set()\n"
]
}
],
"source": [
"# And let's finally prepare ca
onara!\n",
"execute_schedule(ca
onara)\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"id": "lo45Mr8YkacN",
"nbgrader": {
"checksum": "7bade197fa4e480a09146b22ef8afb25",
"grade": false,
"grade_id": "cell-daa0327fa3f623ef",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"source": [
"This is not necessarily the best order of actions to prepare pasta ca
onara, but it definitely works as a schedule."
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"id": "GtCxMENWkacN",
"nbgrader": {
"checksum": "32d632a86ab53799e90ac07e4bdbec37",
"grade": false,
"grade_id": "cell-62458aa5f6bd6db0",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"source": [
"## Building a Better Execution Engine"
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"id": "z0ujdvV-kacN",
"nbgrader": {
"checksum": "1c62725f1ed690ccb49e8526dec0f1c8",
"grade": false,
"grade_id": "cell-68a98344892ae6e4",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"source": [
"Let us build a better execution engine for our schedules. Right now, we have a function:"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {
"deletable": false,
"editable": false,
"id": "y9mNp7cdkacN",
"nbgrader": {
"checksum": "acea01d4083f8b34a8913c0d277fa2af",
"grade": false,
"grade_id": "cell-ee813cfbdf456ac5",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"outputs": [],
"source": [
"def execute_schedule(s, show=False):\n",
" s.reset()\n",
" in_process = s.available_tasks\n",
" print(\"Starting by doing:\", in_process)\n",
" while len(in_process) > 0:\n",
" # Picks one random task to be the first to be completed.\n",
" t = random.choice(list(in_process))\n",
" print(\"Completed:\", t)\n",
" in_process = in_process - {t} | s.mark_completed(t)\n",
" print(\"Now doing:\", in_process)\n",
" if show:\n",
" s.show()\n",
" # Have we done all?\n",
" if not s.done:\n",
" print(\"E
or, there are tasks that could not be completed:\", s.uncompleted)\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"id": "vzMENNIqkacN",
"nbgrader": {
"checksum": "6c135f48b406d3d04b197904ef911090",
"grade": false,
"grade_id": "cell-3c03e5954721ecbc",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"source": [
"We want to wrap these methods into a class, RunSchedule. This will allow us more flexibility in executing a schedule, as we will be able to specify parameters that guide the execution policy, inte
upt and resume the execution, and so on. \n",
"An object of class RunSchedule is initialized with a DependencyScheduler. It then has the following methods: \n",
"\n",
"* **reset:** mark all tasks as not completed. \n",
"* **step:** perform one step in the schedule, completing a single task.\n",
"* **run:** performs all steps in the schedule, until completion. \n",
"* **done:** indicates that all tasks have been done.\n",
"\n",
"What should these methods return? _step_ will return the task executed, while _run_ will return the whole list of tasks, in the order in which they were done. "
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {
"deletable": false,
"editable": false,
"id": "BQWFGtRKkacN",
"nbgrader": {
"checksum": "baeff
c770c2247d1b401f184c7aaf4",
"grade": false,
"grade_id": "cell-419c455e1fa49a35",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"outputs": [],
"source": [
"class RunSchedule(object):\n",
"\n",
" def __init__(self, scheduler):\n",
" self.scheduler = scheduler\n",
" self.in_process = None # Indicating, we don't know yet.\n",
"\n",
" def reset(self):\n",
" self.scheduler.reset()\n",
" self.in_process = None\n",
"\n",
" def step(self):\n",
" \"\"\"Performs a step, returning the task, if any, or None,\n",
" if there is no step that can be done.\"\"\"\n",
" # If we don't know what steps are in process, we get them.\n",
" if self.in_process is None:\n",
" self.in_process = self.scheduler.available_tasks\n",
" if len(self.in_process) == 0:\n",
" return None\n",
" t = random.choice(list(self.in_process))\n",
" self.in_process = self.in_process - {t} | self.scheduler.mark_completed(t)\n",
" return t\n",
"\n",
" @property\n",
" def done(self):\n",
" return self.scheduler.done\n",
"\n",
" def run(self):\n",
" \"\"\"Runs the scheduler from the cu
ent configuration to completion.\n",
" You must call reset() first, if you want to run the whole schedule.\"\"\"\n",
" tasks = []\n",
" while not self.done:\n",
" t = self.step()\n",
" if t is not None:\n",
" tasks.append(t)\n",
" return tasks\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"id": "wRSN_6JfkacN",
"nbgrader": {
"checksum": "d9a54aa7a503239bf81f2463cb74319f",
"grade": false,
"grade_id": "cell-50337ca62797b2cc",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"source": [
"We can run our pasta ca
onara with this RunSchedule class:"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {
"colab": {
"base_uri": "https:
localhost:8080/"
},
"deletable": false,
"editable": false,
"id": "_9bOnhqpkacN",
"nbgrader": {
"checksum": "7cd3e1103d79f0bd0bac7e4e02f77301",
"grade": false,
"grade_id": "cell-a0b0e7d1e74b4d33",
"locked": true,
"schema_version": 1,
"solution": false
},
"outputId": "3ddaa8df-9d58-44ba-aaed-b8dff5cd5358"
},
"outputs": [
{
"data": {
"text/plain": [
"['dice onions',\n",
" 'put onions in pan',\n",
" 'put eggs in bowl',\n",
" 'beat eggs',\n",
" 'dice pancetta',\n",
" 'fill pot with water',\n",
" 'put oil and butter in pan',\n",
" 'put pancetta in pan',\n",
" 'cook pancetta',\n",
" '
ing pot of water to a boil',\n",
" 'add salt to water',\n",
" 'put pasta in water',\n",
" 'colander pasta',\n",
" 'serve']"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"runner = RunSchedule(ca
onara)\n",
"runner.reset()\n",
"runner.run()\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"id": "gB0_0GlnkacN",
"nbgrader": {
"checksum": "1bc2fd9f9c1b7e56a64
85bc56df26e",
"grade": false,
"grade_id": "cell-d160f03528fef7eb",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"source": [
"Let us pause for a moment and ask: did we really need to create a new class? Could we not have done the above in the scheduler class? \n",
"\n",
"This is debatable. The idea in keeping the two classes separate is clarity of goals: \n",
"\n",
"* The scheduler is concerned with what _can_ be done next. \n",
"* The runner is concerned with any practical constraint to the execution, and with the choice of _what_, among the possible, is actually done. \n",
"\n",
"We will have occasion below to rely on this division of concerns."
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"id": "VmUnjXuCkacN",
"nbgrader": {
"checksum": "4bdadeaf1a6dfab0650df33f9282634c",
"grade": false,
"grade_id": "cell-ab56ae966c12c39d",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"source": [
"### Code changes and rotten eggs"
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"id": "dYaHPtGVkacN",
"nbgrader": {
"checksum": "59bf5e852f155980256b6ef310bee302",
"grade": false,
"grade_id": "cell-10062b48fd612300",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"source": [
"#### Code changes\n",
"\n",
"Imagine that you need to compile three programs, $a$, $c$, and then link together the results into $f.out$. Once this is done, you compile $d$ and $e$, and link into $g.out$. As the last step, you link the two li
aries $g.out$ and $f.out$ together, and produce $h$. You do it once. Great. But now you realize that you need to change $b$. Do you have to start from scratch? \n",
"\n",
"You may think, who cares, it's the CPU doing the work, not me. Fair enough, but there are some large systems that take minutes, dozen of minutes, to compile. If you are compiling the linux kernel on a low power CPU, it might take hours. Surely you don't want to redo everything from scratch! \n",
"\n",
"So imagine you have the tasks in an intermediate state, with some being completed (possibly all of them), and some not. You can now mark one of the tasks as incomplete, to signal you need to do it again. What is the set of tasks that as a consequence should also be marked incomplete? \n",
"If you have two tasks $x$ and $y$, with $y$ being a successor to $x$, if $x$ is marked as \"undone\" as it needs to be redone, then also $y$ will need to be redone, as it might use the results of $x$.\n",
"\n",
"To implement this, we will perform two modifications. First, we will endow our scheduler with a _redo_ method, which marks a task and all its successors to be redone -- that is, it _unmarks_ them as done. We let you implement this; you have already seen how to compute reachability in the graph chapter. \n"
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"id": "4VKN56WzkacN",
"nbgrader": {
"checksum": "f4f62ac8c425709abda425a8ad8b639b",
"grade": false,
"grade_id": "cell-9f80ab8aa77e6100",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"source": [
"## Question 2: redo for code"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {
"deletable": false,
"id": "eMfe4d1nkacN",
"nbgrader": {
"checksum": "dda6cc12b8a5445c115239cfadc9289d",
"grade": false,
"grade_id": "cell-80715adbd3dac83e",
"locked": false,
"schema_version": 1,
"solution": true
}
},
"outputs": [],
"source": [
"### Implementation of `redo`\n",
"\n",
"def dependency_scheduler_redo(self, t):\n",
" \"\"\"Mark the task t, and all its successors, as undone.\n",
" Returns the set of successor tasks of t, with t included.\"\"\"\n",
" # YOUR CODE HERE\n",
" tasks = set()\n",
" tasks.add(t)\n",
" if t in self.completed_tasks:\n",
" self.completed_tasks.remove(t)\n",
" for s in self.successors[t]:\n",
" tasks.add(s)\n",
" for x in dependency_scheduler_redo(self, s):\n",
" tasks.add(x)\n",
" return tasks\n",
"\n",
"DependencyScheduler.redo = dependency_scheduler_redo\n"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {
"deletable": false,
"id": "6CaaXn0HkacN",
"nbgrader": {
"checksum": "5585de9f76f2078b994256defd546daa",
"grade": false,
"grade_id": "cell-ffbf3c1f4fa3bdd2",
"locked": false,
"schema_version": 1,
"solution": true
}
},
"outputs": [],
"source": [
"# Here is a place where you can test your code. \n",
"\n",
"# YOUR CODE HERE"
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"id": "AE0YhFAXkacN",
"nbgrader": {
"checksum": "65022df11bcbd0b2cfaf5c4408754571",
"grade": false,
"grade_id": "cell-5b62e886f0ae12ea",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"source": [
"Let us test the implementation."
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {
"deletable": false,
"editable": false,
"id": "AP8H7FmhkacN",
"nbgrader": {
"checksum": "53c69adb193594c1059c599021d9205b",
"grade": true,
"grade_id": "cell-8357360c4a918edb",
"locked": true,
"points": 10,
"schema_version": 1,
"solution": false
}
},
"outputs": [],
"source": [
"### Tests for `redo` for code. 10 points. \n",
"\n",
"s = DependencyScheduler()\n",
"s.add_task('a', [])\n",
"s.add_task('b', ['a'])\n",
"s.add_task('c', ['a'])\n",
"s.add_task('d', ['b', 'c'])\n",
"s.add_task('e', ['a', 'd'])\n",
"\n",
"s.mark_completed('a')\n",
"s.mark_completed('b')\n",
"s.mark_completed('c')\n",
"assert_equal(s.available_tasks, {'d'})\n",
"s.redo('b')\n",
"assert_equal(s.available_tasks, {'b'})\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"id": "dvAbNHUukacN",
"nbgrader": {
"checksum": "f8f408a0c22b5baae9ebc0394d3e18f7",
"grade": false,
"grade_id": "cell-dc8e08c747c3f414",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"source": [
"Next, we implement a runner that has an additional operation _redo(t)_ for a task t. "
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {
"deletable": false,
"editable": false,
"id": "v8Lqw1mnkacN",
"nbgrader": {
"checksum": "4ed044492ef70632de7970d20b137fb5",
"grade": false,
"grade_id": "cell-ef3550fd3be8ba89",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"outputs": [],
"source": [
"def run_schedule_redo(self, t):\n",
" \"\"\"Marks t as to be redone.\"\"\"\n",
" # We drop everything that was in progress.\n",
" # This also forces us to ask the scheduler for what to redo.\n",
" self.in_process = None\n",
" return self.scheduler.redo(t)\n",
"\n",
"RunSchedule.redo = run_schedule_redo\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"id": "0eQ0DQe9kacN",
"nbgrader": {
"checksum": "3f4ec294c647cca80d50e650f19723d8",
"grade": false,
"grade_id": "cell-649d49e90f721cf7",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"source": [
"We can now play with it. "
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {
"colab": {
"base_uri": "https:
localhost:8080/"
},
"deletable": false,
"editable": false,
"id": "FyhvQByTkacN",
"nbgrader": {
"checksum": "0b03de64cc41e4a31cc5b46ccefd49e4",
"grade": false,
"grade_id": "cell-e75c320e4a31c2d1",
"locked": true,
"schema_version": 1,
"solution": false
},
"outputId": "17d36e43-85a8-4412-eaa5-b97ba6160e09"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"dice onions\n",
"fill pot with water\n",
"
ing pot of water to a boil\n",
"dice pancetta\n",
"add salt to water\n",
"put eggs in bowl\n",
"put oil and butter in pan\n",
"beat eggs\n",
"put onions in pan\n",
"put pasta in water\n",
"---> readd salt\n",
"marking undone: {'colander pasta', 'add salt to water', 'put pasta in water', 'serve'}\n",
"completed: {'put onions in pan', 'dice onions', 'put eggs in bowl', '
ing pot of water to a boil', 'put oil and butter in pan', 'dice pancetta', 'fill pot with water', 'beat eggs'}\n",
"put pancetta in pan\n",
"cook pancetta\n",
"add salt to water\n",
"put pasta in water\n",
"colander pasta\n",
"serve\n",
"None\n",
"None\n",
"None\n",
"None\n",
"---
edo dice pancetta\n",
"marking undone: {'put pancetta in pan', 'serve', 'cook pancetta', 'dice pancetta'}\n",
"completed: {'put onions in pan', 'dice onions', 'put eggs in bowl', '
ing pot of water to a boil', 'put oil and butter in pan', 'colander pasta', 'fill pot with water', 'add salt to water', 'beat eggs', 'put pasta in water'}\n",
"dice pancetta\n",
"put pancetta in pan\n",
"cook pancetta\n",
"serve\n"
]
}
],
"source": [
"runner = RunSchedule(ca
onara)\n",
"runner.reset()\n",
"for _ in range(10):\n",
" print(runner.step())\n",
"print(\"---> readd salt\")\n",
"print(\"marking undone:\", runner.redo(\"add salt to water\"))\n",
"print(\"completed:\", runner.scheduler.completed_tasks)\n",
"for _ in range(10):\n",
" print(runner.step())\n",
"print(\"---
edo dice pancetta\")\n",
"print(\"marking undone:\", runner.redo(\"dice pancetta\"))\n",
"print(\"completed:\", runner.scheduler.completed_tasks)\n",
"for t in runner.run():\n",
" print(t)\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"id": "GvHfXhTrkacN",
"nbgrader": {
"checksum": "fefa652c64562e34
0febc03b8e5c8c",
"grade": false,
"grade_id": "cell-d879d3343e6f13f3",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"source": [
"You have learned to sequence the order in which to do tasks so as to respect their dependencies. In the next chapter, we will learn how to also take into account the time it takes for us to do the tasks. In the meantime, bon appetit, or rather, guten appetit, or rather, buon appetito!"
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"id": "YFAQC0CFkacN",
"nbgrader": {
"checksum": "762427c225bf731e0
90204533754a7",
"grade": false,
"grade_id": "cell-d8ce6c37cba9be0",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"source": [
"#### Redoing in cooking\n",
"\n",
"The act of redoing a cooking step is somewhat different than the act of redoing something in code. Suppose you cook pasta, unite with it the fried bacon and onions, and then -- te
ible mishap -- you unite with it the beaten egg yolks in which one of the eggs is rotten. \n",
"\n",
"In code, when one file changes, you only need to redo the things that _depend_ on that file. In cooking, it is different: even if nothing changed in the bacon, onions, and cooked pasta, once you add to it rotten eggs you have to redo the pasta, bacon, onions, etc, as well, as they have now been contaminated. The root of the problem is that in a makefile, when you combine two files to compute a result, you do not destroy the original files, whereas in cooking, once you combine foods, you don't have the original foods any longer. Cooking is like a makefile in which, once you combine files, you immediately delete them. \n",
"\n",
"So let us come up with a precise definition of what needs to be redone in cooking, when one of the steps goes bad (the eggs are rotten, you burn the food on the stove, and so on). \n",
"\n",
"Initially, we label _redo_ the task that needs redoing. We then propagate the label according to these two rules: \n",
"\n",
"* If a task $v$ is labeled _redo_, if $u$ is a successor of $v$ and $u$ is completed, then $u$ is also labeled _redo_. \n",
"* If a task $v$ is labeled _redo_, and if $u$ is a predecessor of $v$, then $u$ is also labeled _redo_ (note that in this case, we are guaranteed that $u$ is completed). \n",
"\n",
"The first rule co
esponds to a _forward_ pass in the dependency garph; the second rule co
esponds to a _backward_ pass in the dependency relation. \n",
"Once the _redo_ label is propagated, all tasks that are marked _redo_ are changed from completed, to uncompleted. \n",
"\n",
"We ask you to implement this in code."
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"id": "t3763UgKkacN",
"nbgrader": {
"checksum": "bc530f1067c9f06847e1fa513a92990c",
"grade": false,
"grade_id": "cell-6d12164e3e76339b",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"source": [
"## Question 3: redo for recipes"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {
"deletable": false,
"id": "hGpcMDickacN",
"nbgrader": {
"checksum": "6ccca5682cbed48c50d2a9ea4300b62c",
"grade": false,
"grade_id": "cell-a0618093f5920c44",
"locked": false,
"schema_version": 1,
"solution": true
}
},
"outputs": [],
"source": [
"### Implementation of `cooking_redo`\n",
"\n",
"def dependency_scheduler_cooking_redo(self, v):\n",
" \"\"\"Indicates that the task v needs to be redone, as something went bad.\n",
" This is the \"cooking\" version of the redo, in which the redo propagates\n",
" to both successors (as for code) and predecessors.\"\"\"\n",
" # YOUR CODE HERE\n",
" redo_tasks = {t} | self.successors[t]\n",
" self.completed_tasks = self.completed_tasks - redo_tasks\n",
" \n",
" return redo_tasks \n",
"\n",
"DependencyScheduler.cooking_redo = dependency_scheduler_cooking_redo\n"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {
"deletable": false,
"id": "Q-CPnQRjkacN",
"nbgrader": {
"checksum": "fef9951e6a653a4975154941aa5e881a",
"grade": false,
"grade_id": "cell-aa93a1ed6a926cff",
"locked": false,
"schema_version": 1,
"solution": true
}
},
"outputs": [],
"source": [
"# Here is a place where you can test your code. \n",
"\n",
"# YOUR CODE HERE"
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"id": "bGHcfSPikacN",
"nbgrader": {
"checksum": "27d265e4416ecc09
1d88678feb3e3c",
"grade": false,
"grade_id": "cell-9a8d2fd5d7f7954d",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"source": [
"Let us check that the code works. First, a simple example. "
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {
"colab": {
"base_uri": "https:
localhost:8080/",
"height": 408
},
"deletable": false,
"editable": false,
"id": "jqvumL0KkacN",
"nbgrader": {
"checksum": "0ac9dcabcfdf363f540a35363e3c6103",
"grade": true,
"grade_id": "cell-c81c441e91888093",
"locked": true,
"points": 10,
"schema_version": 1,
"solution": false
},
"outputId": "d81d41fa-d5aa-45ee-8b9f-97430299a424"
},
"outputs": [
{
"ename": "AssertionE
or",
"evalue": "Items in the second set but not the first:\n'b'\n'a'",
"output_type": "e
or",
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[1;31mAssertionE
or\u001b[0m Traceback (most recent call last)",
"\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 17\u001b[0m \u001b[0ms\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcooking_redo\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'c'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 18\u001b[0m \u001b[1;31m# When we redo c, both its successor d, and predecessors a, b have to be redone.\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 19\u001b[1;33m \u001b[0massert_equal\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ms\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mavailable_tasks\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m{\u001b[0m\u001b[1;34m'a'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'b'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'e'\u001b[0m\u001b[1;33m}\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 20\u001b[0m \u001b[0massert_equal\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ms\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcompleted_tasks\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mset\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 21\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
"\u001b[1;32m~\\Anaconda3\\lib\\unittest\\case.py\u001b[0m in \u001b[0;36massertEqual\u001b[1;34m(self, first, second, msg)\u001b[0m\n\u001b[0;32m 837\u001b[0m \"\"\"\n\u001b[0;32m 838\u001b[0m \u001b[0massertion_func\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_getAssertEqualityFunc\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mfirst\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0msecond\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 839\u001b[1;33m \u001b[0massertion_func\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mfirst\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0msecond\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mmsg\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mmsg\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 840\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 841\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0massertNotEqual\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mfirst\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0msecond\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mmsg\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mNone\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
"\u001b[1;32m~\\Anaconda3\\lib\\unittest\\case.py\u001b[0m in \u001b[0;36massertSetEqual\u001b[1;34m(self, set1, set2, msg)\u001b[0m\n\u001b[0;32m 1097\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 1098\u001b[0m \u001b[0mstandardMsg\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;34m'\\n'\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mjoin\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mlines\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m-> 1099\u001b[1;33m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mfail\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_formatMessage\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mmsg\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mstandardMsg\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 1100\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 1101\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0massertIn\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mmember\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mcontainer\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mmsg\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mNone\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
"\u001b[1;32m~\\Anaconda3\\lib\\unittest\\case.py\u001b[0m in \u001b[0;36mfail\u001b[1;34m(self, msg)\u001b[0m\n\u001b[0;32m 678\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mfail\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mmsg\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mNone\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 679\u001b[0m \u001b[1;34m\"\"\"Fail immediately, with the given message.\"\"\"\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 680\u001b[1;33m \u001b[1;32mraise\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mfailureException\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mmsg\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 681\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 682\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0massertFalse\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mexpr\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mmsg\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mNone\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
"\u001b[1;31mAssertionE
or\u001b[0m: Items in the second set but not the first:\n'b'\n'a'"
]
}
],
"source": [
"### Basic tests for `cooking_redo`. 10 points. \n",
"\n",
"s = DependencyScheduler()\n",
"s.add_task('a', [])\n",
"s.add_task('b', [])\n",
"s.add_task('c', ['a', 'b'])\n",
"s.add_task('d', ['c', 'a'])\n",
"s.add_task('e', [])\n",
"s.add_task('f', ['e'])\n",
"s.add_task('g', ['f', 'd'])\n",
"\n",
"s.mark_completed('a')\n",
"s.mark_completed('b')\n",
"s.mark_completed('c')\n",
"s.mark_completed('d')\n",
"assert_equal(s.available_tasks, {'e'})\n",
"s.cooking_redo('c')\n",
"# When we redo c, both its successor d, and predecessors a, b have to be redone.\n",
"assert_equal(s.available_tasks, {'a', 'b', 'e'})\n",
"assert_equal(s.completed_tasks, set())\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"id": "wvmDn4kkkacN",
"nbgrader": {
"checksum": "9837d82e5252ea166f9df307ac050674",
"grade": false,
"grade_id": "cell-ca557220e8080773",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"source": [
"And now, some slightly more sophisticated tests."
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {
"deletable": false,
"editable": false,
"id": "7ICulRsskacN",
"nbgrader": {
"checksum": "e9305566644280e83a323332ac42b1f2",
"grade": true,
"grade_id": "cell-4c4d6c54901c7d9",
"locked": true,
"points": 10,
"schema_version": 1,
"solution": false
}
},
"outputs": [
{
"ename": "AssertionE
or",
"evalue": "Items in the second set but not the first:\n'b'\n'a'",
"output_type": "e
or",
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[1;31mAssertionE
or\u001b[0m Traceback (most recent call last)",
"\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 18\u001b[0m \u001b[0ms\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcooking_redo\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'c'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 19\u001b[0m \u001b[1;31m# When we redo c, both its successor d, and predecessors a, b have to be redone.\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 20\u001b[1;33m \u001b[0massert_equal\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ms\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mavailable_tasks\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m{\u001b[0m\u001b[1;34m'a'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'b'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'f'\u001b[0m\u001b[1;33m}\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 21\u001b[0m \u001b[0massert_equal\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ms\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcompleted_tasks\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m{\u001b[0m\u001b[1;34m'e'\u001b[0m\u001b[1;33m}\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 22\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
"\u001b[1;32m~\\Anaconda3\\lib\\unittest\\case.py\u001b[0m in \u001b[0;36massertEqual\u001b[1;34m(self, first, second, msg)\u001b[0m\n\u001b[0;32m 837\u001b[0m \"\"\"\n\u001b[0;32m 838\u001b[0m \u001b[0massertion_func\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_getAssertEqualityFunc\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mfirst\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0msecond\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 839\u001b[1;33m \u001b[0massertion_func\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mfirst\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0msecond\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mmsg\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mmsg\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 840\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 841\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0massertNotEqual\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mfirst\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0msecond\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mmsg\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mNone\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
"\u001b[1;32m~\\Anaconda3\\lib\\unittest\\case.py\u001b[0m in \u001b[0;36massertSetEqual\u001b[1;34m(self, set1, set2, msg)\u001b[0m\n\u001b[0;32m 1097\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 1098\u001b[0m \u001b[0mstandardMsg\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;34m'\\n'\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mjoin\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mlines\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m-> 1099\u001b[1;33m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mfail\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_formatMessage\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mmsg\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mstandardMsg\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 1100\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 1101\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0massertIn\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mmember\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mcontainer\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mmsg\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mNone\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
"\u001b[1;32m~\\Anaconda3\\lib\\unittest\\case.py\u001b[0m in \u001b[0;36mfail\u001b[1;34m(self, msg)\u001b[0m\n\u001b[0;32m 678\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mfail\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mmsg\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mNone\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 679\u001b[0m \u001b[1;34m\"\"\"Fail immediately, with the given message.\"\"\"\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 680\u001b[1;33m \u001b[1;32mraise\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mfailureException\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mmsg\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 681\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 682\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0massertFalse\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mexpr\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mmsg\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mNone\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
"\u001b[1;31mAssertionE
or\u001b[0m: Items in the second set but not the first:\n'b'\n'a'"
]
}
],
"source": [
"### Advanced tests for `cooking_redo`. 10 points. \n",
"\n",
"s = DependencyScheduler()\n",
"s.add_task('a', [])\n",
"s.add_task('b', [])\n",
"s.add_task('c', ['a', 'b'])\n",
"s.add_task('d', ['c', 'a'])\n",
"s.add_task('e', [])\n",
"s.add_task('f', ['e'])\n",
"s.add_task('g', ['f', 'd'])\n",
"\n",
"s.mark_completed('a')\n",
"s.mark_completed('b')\n",
"s.mark_completed('c')\n",
"s.mark_completed('d')\n",
"s.mark_completed('e')\n",
"assert_equal(s.available_tasks, {'f'})\n",
"s.cooking_redo('c')\n",
"# When we redo c, both its successor d, and predecessors a, b have to be redone.\n",
"assert_equal(s.available_tasks, {'a', 'b', 'f'})\n",
"assert_equal(s.completed_tasks, {'e'})\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"id": "k13cqyuJkacO",
"nbgrader": {
"checksum": "8e2d0c5ee7ca1ee6b0228ce1fcf4b129",
"grade": false,
"grade_id": "cell-1354768f9bcb0376",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"source": [
"## Question 4: Implement And-Or Schedules\n",
"\n",
"In the schedules we have seen so far, the dependencies are in _and_ one with the other: if a task $a$ depends on $b, c$, then _both_ $b$ _and $c$ need to be completed before $a$ can be started. \n",
"It is possible to consider also cases where dependencies are in an _or_ relation: if $a$ depends on $b, c$ in an _or_ way, then it suffices to complete one of $b$ _or_ $c$ before starting $a$. \n",
"For instance, in our Ca
onara Pasta example, it is possible (even though not necessarily advisable) to use shallots in place of onions. \n",
"In that case, instead of \n",
"\n",
" ca
onara.add_task('put onions in pan', ['dice onions'])\n",
"\n",
"we could have:\n",
"\n",
" ca
onara.add_or_task('put onions in pan', ['dice onions', 'dice shallots'])\n",
"\n",
"so that before putting the (now generally named) onions in a pan, we could choose to dice either shallots or onions. \n",
"\n",
"Formally, the idea is to endow the Scheduler class with _two_ methods: \n",
"\n",
"* `add_and_task(self, t, dependencies)` adds a task `t` with list of dependencies `dependencies`, so that `t` can be done when _all_ of the dependencies are done. The task `t` is called an AND node in the dependency graph. \n",
"\n",
"* `add_or_task(self, t, dependencies)` adds a task `t` with list of dependencies `dependencies`, so that `t` can be done when _at least one_ of the dependencies is done. The task `t` is called an OR node in the dependency graph. \n",
"\n",
"You need to find a way to remember which dependency graph nodes are AND or OR nodes, and you need to implement the properties `done`, `available_tasks`, `uncompleted`, and the method `mark_completed`, to make this class work. \n",
"Implementing the `show` method is optional; do it if it helps you debug your code. "
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {
"deletable": false,
"id": "MwsOh-7vkacO",
"nbgrader": {
"checksum": "b4902dcc720ffd415db259d5d7d9e70c",
"grade": false,
"grade_id": "cell-51732cbc3481ec67",
"locked": false,
"schema_version": 1,
"solution": true
}
},
"outputs": [
{
"ename": "IndentationE
or",
"evalue": "expected an indented block (, line 9)",
"output_type": "e
or",
"traceback": [
"\u001b[1;36m File \u001b[1;32m\"\"\u001b[1;36m, line \u001b[1;32m9\u001b[0m\n\u001b[1;33m def add_and_task(self, t, dependencies):\u001b[0m\n\u001b[1;37m ^\u001b[0m\n\u001b[1;31mIndentationE
or\u001b[0m\u001b[1;31m:\u001b[0m expected an indented block\n"
]
}
],
"source": [
"### `AND_OR_Scheduler` implementation\n",
"\n",
"class AND_OR_Scheduler(object):\n",
"\n",
" def __init__(self):\n",
" # It is up to you to implement the initialization.\n",
" # YOUR CODE HERE\n",
"\n",
" def add_and_task(self, t, dependencies):\n",
" \"\"\"Adds an AND task t with given dependencies.\"\"\"\n",
" # YOUR CODE HERE\n",
"\n",
" def add_or_task(self, t, dependencies):\n",
" \"\"\"Adds an OR task t with given dependencies.\"\"\"\n",
" # YOUR CODE HERE\n",
"\n",
" @property\n",
" def done(self):\n",
" # YOUR CODE HERE\n",
"\n",
" @property\n",
" def available_tasks(self):\n",
" \"\"\"Returns the set of tasks that can be done in parallel.\n",
" A task can be done if:\n",
" - It is an AND task, and all its predecessors have been completed, or\n",
" - It is an OR task, and at least one of its predecessors has been completed.\n",
" And of course, we don't return any task that has already been\n",
" completed.\"\"\"\n",
" # YOUR CODE HERE\n",
"\n",
" def mark_completed(self, t):\n",
" \"\"\"Marks the task t as completed, and returns the additional\n",
" set of tasks that can be done (and that could not be\n",
" previously done) once t is completed.\"\"\"\n",
" # YOUR CODE HERE\n",
"\n",
" def show(self):\n",
" \"\"\"You can use the nx graph to display the graph. You may want to ensure\n",
" that you display AND and OR nodes differently.\"\"\"\n",
" # YOUR CODE HERE\n"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {
"deletable": false,
"id": "Iol14ZOXkacO",
"nbgrader": {
"checksum": "27af5864ccc43f22993a72d0f647bdc4",
"grade": false,
"grade_id": "cell-038c005b93e6e0f1",
"locked": false,
"schema_version": 1,
"solution": true
}
},
"outputs": [],
"source": [
"# Here is a place where you can test your code. \n",
"\n",
"# YOUR CODE HERE"
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"id": "CPtCKfh4kacO",
"nbgrader": {
"checksum": "a5b1f35544aaaa7231a3bc093db3d5b9",
"grade": false,
"grade_id": "cell-482edb12036108dc",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"source": [
"Let us do some simple tests. First, for good old AND nodes. "
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {
"deletable": false,
"editable": false,
"id": "uwnhgFwekacO",
"nbgrader": {
"checksum": "c873af11920709a2d8333932e617be8b",
"grade": true,
"grade_id": "cell-9a86f02cc5bca274",
"locked": true,
"points": 10,
"schema_version": 1,
"solution": false
}
},
"outputs": [
{
"ename": "NameE
or",
"evalue": "name 'AND_OR_Scheduler' is not defined",
"output_type": "e
or",
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[1;31mNameE
or\u001b[0m Traceback (most recent call last)",
"\u001b[1;32md464bc>\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[1;31m### Simple tests for AND nodes. 10 points.\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 2\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 3\u001b[1;33m \u001b[0ms\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mAND_OR_Scheduler\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 4\u001b[0m \u001b[0ms\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0madd_and_task\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'a'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m[\u001b[0m\u001b[1;34m'b'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'c'\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 5\u001b[0m \u001b[0massert_equal\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ms\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mavailable_tasks\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m{\u001b[0m\u001b[1;34m'b'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'c'\u001b[0m\u001b[1;33m}\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
"\u001b[1;31mNameE
or\u001b[0m: name 'AND_OR_Scheduler' is not defined"
]
}
],
"source": [
"### Simple tests for AND nodes. 10 points. \n",
"\n",
"s = AND_OR_Scheduler()\n",
"s.add_and_task('a', ['b', 'c'])\n",
"assert_equal(s.available_tasks, {'b', 'c'})\n",
"r = s.mark_completed('b')\n",
"assert_equal(r, set())\n",
"assert_equal(s.available_tasks, {'c'})\n",
"r = s.mark_completed('c')\n",
"assert_equal(r, {'a'})\n",
"assert_equal(s.available_tasks, {'a'})\n",
"r = s.mark_completed('a')\n",
"assert_equal(r, set())\n",
"assert_equal(s.available_tasks, set())\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"id": "_7OpH7p-kacO",
"nbgrader": {
"checksum": "451c1a9c2301ae0361c28ad6e69c35da",
"grade": false,
"grade_id": "cell-77803bc9d9342c22",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"source": [
"Then, some simple tests for OR nodes. "
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {
"deletable": false,
"editable": false,
"id": "6J8pACOTkacO",
"nbgrader": {
"checksum": "af51d6d7f9b58c91cc90e5e7c48a7647",
"grade": true,
"grade_id": "cell-19e1d2c726e4be1b",
"locked": true,
"points": 10,
"schema_version": 1,
"solution": false
}
},
"outputs": [
{
"ename": "NameE
or",
"evalue": "name 'AND_OR_Scheduler' is not defined",
"output_type": "e
or",
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[1;31mNameE
or\u001b[0m Traceback (most recent call last)",
"\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[1;31m### Simple tests for OR nodes. 10 points.\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 2\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 3\u001b[1;33m \u001b[0ms\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mAND_OR_Scheduler\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 4\u001b[0m \u001b[0ms\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0madd_or_task\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'a'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m[\u001b[0m\u001b[1;34m'b'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'c'\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 5\u001b[0m \u001b[0massert_equal\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ms\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mavailable_tasks\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m{\u001b[0m\u001b[1;34m'b'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'c'\u001b[0m\u001b[1;33m}\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
"\u001b[1;31mNameE
or\u001b[0m: name 'AND_OR_Scheduler' is not defined"
]
}
],
"source": [
"### Simple tests for OR nodes. 10 points. \n",
"\n",
"s = AND_OR_Scheduler()\n",
"s.add_or_task('a', ['b', 'c'])\n",
"assert_equal(s.available_tasks, {'b', 'c'})\n",
"r = s.mark_completed('b')\n",
"# Now 'a' becomes available.\n",
"assert_equal(r, {'a'})\n",
"# But note that 'c' is also available, even if useless.\n",
"assert_equal(s.available_tasks, {'a', 'c'})\n",
"r = s.mark_completed('a')\n",
"assert_equal(r, set())\n",
"assert_equal(s.available_tasks, {'c'})\n",
"r = s.mark_completed('c')\n",
"assert_equal(r, set())\n",
"assert_equal(s.available_tasks, set())\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": false,
"editable": false,
"id": "wGCCs4GHkacO",
"nbgrader": {
"checksum": "587858ea7715ed0dfc82913fa3a63542",
"grade": false,
"grade_id": "cell-80257a5f8718f673",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"source": [
"Note that a drawback of this simple solution, as illustrated by the above test case, is that we do not distinguish between the tasks that are useful to do the root task, and the tasks that are useless, that is, not part of a minimal solution. We simply call them available, as they can be done, even though there is no advantage in doing them. "
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {
"deletable": false,
"editable": false,
"id": "yqPCp5KWkacO",
"nbgrader": {
"checksum": "2da9553393518e5ca462fd18da9aa002",
"grade": true,
"grade_id": "cell-fa32f16841d80974",
"locked": true,
"points": 10,
"schema_version": 1,
"solution": false
}
},
"outputs": [
{
"ename": "NameE
or",
"evalue": "name 'AND_OR_Scheduler' is not defined",
"output_type": "e
or",
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[1;31mNameE
or\u001b[0m Traceback (most recent call last)",
"\u001b[1;32mdf8cb44472>\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[1;31m### Tests with both AND and OR nodes. 10 points.\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 2\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 3\u001b[1;33m \u001b[0ms\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mAND_OR_Scheduler\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 4\u001b[0m \u001b[0ms\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0madd_and_task\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'a'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m[\u001b[0m\u001b[1;34m'b'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'c'\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 5\u001b[0m \u001b[0ms\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0madd_or_task\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'b'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m[\u001b[0m\u001b[1;34m'b1'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'b2'\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
"\u001b[1;31mNameE
or\u001b[0m: name 'AND_OR_Scheduler' is not defined"
]
}
],
"source": [
"### Tests with both AND and OR nodes. 10 points. \n",
"\n",
"s = AND_OR_Scheduler()\n",
"s.add_and_task('a', ['b', 'c'])\n",
"s.add_or_task('b', ['b1', 'b2'])\n",
"s.add_or_task('c', ['c1', 'c2'])\n",
"r = s.mark_completed('b1')\n",
"assert_equal(s.available_tasks, {'b', 'b2', 'c1', 'c2'})\n",
"r = s.mark_completed('b')\n",
"assert_false('a' in s.available_tasks)\n",
"r = s.mark_completed('c1')\n",
"assert_false('a' in s.available_tasks)\n",
"r = s.mark_completed('c')\n",
"assert_true('a' in s.available_tasks)\n",
"\n",
"s = AND_OR_Scheduler()\n",
"s.add_or_task('a', ['b', 'c'])\n",
"s.add_and_task('b', ['b1', 'b2'])\n",
"s.add_and_task('c', ['c1', 'c2'])\n",
"r = s.mark_completed('b1')\n",
"assert_equal(s.available_tasks, {'b2', 'c1', 'c2'})\n",
"r = s.mark_completed('c1')\n",
"assert_equal(s.available_tasks, {'b2', 'c2'})\n",
"r = s.mark_completed('c2')\n",
"assert_equal(s.available_tasks, {'b2', 'c'})\n",
"r = s.mark_completed('c')\n",
"assert_true('a' in s.available_tasks)\n",
"\n"
]
},
{
"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": []
}
],
"metadata": {
"colab": {
"collapsed_sections": [],
"name": "“Homework_11_Scheduling_with_Dependencies.ipynb”的副本",
"provenance": []
},
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemi
or_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.1"
},
"test_info": {
"id": "4adb3d5055da02e7ae8251ca99f4acfa901ab256"
}
},
"nbformat": 4,
"nbformat_minor": 1
}
Assign/.ipynb_checkpoints/Solution file-checkpoint.ipynb{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Solution File"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Homework 11: Scheduling with Dependencies"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Our first implementation of the class is as follows. We let you complete the available_tasks and mark_completed methods"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"from collections import defaultdict\n",
"import networkx as nx # Li
ary for displaying graphs.\n",
"import matplotlib.pyplot as plt\n",
"\n",
"class DependencyScheduler(object):\n",
"\n",
" def __init__(self):\n",
" self.tasks = set()\n",
" # The successors of a task are the tasks that depend on it, and can\n",
" # only be done once the task is completed.\n",
" self.successors = defaultdict(set)\n",
" # The predecessors of a task have to be done before the task.\n",
" self.predecessors = defaultdict(set)\n",
" self.completed_tasks = set() # completed tasks\n",
"\n",
" def add_task(self, t, dependencies):\n",
" \"\"\"Adds a task t with given dependencies.\"\"\"\n",
" # Makes sure we know about all tasks mentioned.\n",
" assert t not in self.tasks or len(self.predecessors[t]) == 0, \"The task was already present.\"\n",
" self.tasks.add(t)\n",
" self.tasks.update(dependencies)\n",
" # The predecessors are the tasks that need to be done before.\n",
" self.predecessors[t] = set(dependencies)\n",
" # The new task is a successor of its dependencies.\n",
" for u in dependencies:\n",
" self.successors[u].add(t)\n",
"\n",
" def reset(self):\n",
" self.completed_tasks = set()\n",
"\n",
" @property\n",
" def done(self):\n",
" return self.completed_tasks == self.tasks\n",
"\n",
"\n",
" def show(self):\n",
" \"\"\"We use the nx graph to display the graph.\"\"\"\n",
" g = nx.DiGraph()\n",
" g.add_nodes_from(self.tasks)\n",
" g.add_edges_from([(u, v) for u in self.tasks for v in self.successors[u]])\n",
" node_colors = ''.join([('g' if v in self.completed_tasks else 'r')\n",
" for v in self.tasks])\n",
" nx.draw(g, with_labels=True, node_color=node_colors)\n",
" plt.show()\n",
"\n",
" @property\n",
" def uncompleted(self):\n",
" \"\"\"Returns the tasks that have not been completed.\n",
" This is a property, so you can say scheduler.uncompleted rather than\n",
" scheduler.uncompleted()\"\"\"\n",
" return self.tasks - self.completed_tasks\n",
"\n",
" def _check(self):\n",
" \"\"\"We check that if t is a successor of u, then u is a predecessor\n",
" of t.\"\"\"\n",
" for u in self.tasks:\n",
" for t in self.successors[u]:\n",
" assert u in self.predecessors[t]\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Question 1: implement `available_tasks` and `mark_completed`. "
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"### Implementation of `available_tasks` and `mark_completed`.\n",
"\n",
"def scheduler_available_tasks(self):\n",
" \"\"\"Returns the set of tasks that can be done in parallel.\n",
" A task can be done if all its predecessors have been completed.\n",
" And of course, we don't return any task that has already been\n",
" completed.\"\"\"\n",
" # YOUR CODE HERE\n",
" return ({t for t in self.tasks \n",
" if self.predecessors[t].issubset(self.completed_tasks)}\n",
" - self.completed_tasks)\n",
"\n",
"def scheduler_mark_completed(self, t):\n",
" \"\"\"Marks the task t as completed, and returns the additional\n",
" set of tasks that can be done (and that could not be\n",
" previously done) once t is completed.\"\"\"\n",
" # YOUR CODE HERE\n",
" for p in...
SOLUTION.PDF

Answer To This Question Is Available To Download

Related Questions & Answers

More Questions »

Submit New Assignment

Copy and Paste Your Assignment Here