Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 7bb9bf1

Browse files
committed
removes unnecessary definitions/examples from search notebook
1 parent 671dea6 commit 7bb9bf1

File tree

1 file changed

+58
-193
lines changed

1 file changed

+58
-193
lines changed

search.ipynb

Lines changed: 58 additions & 193 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
},
1414
{
1515
"cell_type": "code",
16-
"execution_count": 2,
16+
"execution_count": 1,
1717
"metadata": {
1818
"collapsed": true
1919
},
@@ -45,7 +45,7 @@
4545
" 3. A\\* Search\n",
4646
" 4. Recursive Best First Search\n",
4747
"\n",
48-
"*In the end of this notebook, you can see how different searching algorithms solves the route finding problem defined on romania map.*"
48+
"*Don't miss the visualisations of these algorithms solving route-finding problem defined on romania map at the end of this notebook.*"
4949
]
5050
},
5151
{
@@ -72,243 +72,116 @@
7272
"cell_type": "markdown",
7373
"metadata": {},
7474
"source": [
75-
"sdc"
76-
]
77-
},
78-
{
79-
"cell_type": "markdown",
80-
"metadata": {},
81-
"source": [
82-
"## Uninformed Search Strategies"
83-
]
84-
},
85-
{
86-
"cell_type": "markdown",
87-
"metadata": {},
88-
"source": [
89-
"\n",
90-
" \n",
91-
"The `Problem` class is an abstract class on which we define our problems(*duh*).\n",
92-
"Again, if you are confused about what `abstract class` means have a look at the `Intro` notebook.\n",
9375
"The `Problem` class has six methods.\n",
94-
"* `__init__(self, initial, goal)` : This is what is called a `constructor` and is the first method called when you create an instance of class. In this and all of the below methods `self` refers to the object itself--the object whose method is called. `initial` specifies the initial state of our search problem. It represents the start state from where our agent begins his task of exploration to find the goal state(s) which is given in the `goal` parameter.\n",
95-
"* `actions(self, state)` : This method returns all the possible actions our agent can make in state `state`.\n",
76+
"\n",
77+
"* `__init__(self, initial, goal)` : This is what is called a `constructor` and is the first method called when you create an instance of class. `initial` specifies the initial state of our search problem. It represents the start state from where our agent begins its task of exploration to find the goal state(s) which is given in the `goal` parameter.\n",
78+
"\n",
79+
"\n",
80+
"* `actions(self, state)` : This method returns all the possible actions agent can execute in the given state `state`.\n",
81+
"\n",
82+
"\n",
9683
"* `result(self, state, action)` : This returns the resulting state if action `action` is taken in the state `state`. This `Problem` class only deals with deterministic outcomes. So we know for sure what every action in a state would result to.\n",
84+
"\n",
85+
"\n",
9786
"* `goal_test(self, state)` : Given a graph state, it checks if it is a terminal state. If the state is indeed a goal state, value of `True` is returned. Else, of course, `False` is returned.\n",
87+
"\n",
88+
"\n",
9889
"* `path_cost(self, c, state1, action, state2)` : Return the cost of the path that arrives at `state2` as a result of taking `action` from `state1`, assuming total cost of `c` to get up to `state1`.\n",
90+
"\n",
91+
"\n",
9992
"* `value(self, state)` : This acts as a bit of extra information in problems where we try to optimize a value when we cannot do a goal test."
10093
]
10194
},
10295
{
10396
"cell_type": "markdown",
10497
"metadata": {},
10598
"source": [
106-
"Now the above abstract class acts as a parent class, and there is another named called `GraphProblem` in our module. It creates a graph problem from an instance of the `Graph` class. To create a graph, simply type `graph = Graph(dict(...))`. The dictionary must contain nodes of the graph as keys, so make sure they are `hashable`. If you don't know what that means just use strings or numbers. Each node contains the adjacent nodes as keys and the edge length as its value. Each dictionary then should correspond to another dictionary in the graph. The `Graph` class creates a directed(edges allow only one way traffic) by default. If you want to make an undirected graph, use `UndirectedGraph` instead, but make sure to mention any edge in only one of its nodes."
107-
]
108-
},
109-
{
110-
"cell_type": "markdown",
111-
"metadata": {},
112-
"source": [
113-
"If you didn't understand the above paragraph, `Fret not!`. Just think of the below code as a magicical method to create a simple undirected graph. I'll explain what it is about later."
99+
"We will use the abstract class `Problem` to define out real **problem** named `GraphProblem`. You can see how we defing `GraphProblem` by running the next cell."
114100
]
115101
},
116102
{
117103
"cell_type": "code",
118-
"execution_count": 2,
104+
"execution_count": 6,
119105
"metadata": {
120106
"collapsed": true
121107
},
122108
"outputs": [],
123109
"source": [
124-
"museum_graph = UndirectedGraph(dict(\n",
125-
" Start = dict(Dog = 3, Cat = 9, Mouse = 4),\n",
126-
" Dog = dict(Bear = 7),\n",
127-
" Cat = dict(Monkey = 9, Fish = 8, Penguin = 3),\n",
128-
" Mouse = dict(Penguin = 2),\n",
129-
" Bear = dict(Monkey = 7),\n",
130-
" Monkey = dict(Giraffe = 11, Fish = 6),\n",
131-
" Fish = dict(Giraffe = 8),\n",
132-
" Penguin = dict(Parrot = 4, Elephant = 6),\n",
133-
" Giraffe = dict(Hen = 5),\n",
134-
" Parrot = dict(Hen = 10),\n",
135-
" Elephant = dict(Hen = 9)))"
136-
]
137-
},
138-
{
139-
"cell_type": "markdown",
140-
"metadata": {},
141-
"source": [
142-
"Imagine we are in a museum showcasing statues of various animals. To navigate through the museum there are paths between some statues and the entrance. We define the entrance and the statues as nodes in our graph with the path connecting them as edges. The cost/weight of an edge specifies is its length. So `Start = dict(Dog = 3, Cat = 9, Mouse = 4)` means that there are paths from `Start` to `Dog`, `Cat` and `Mouse` with path costs 3, 9 and 4 respectively. \n",
143-
"\n",
144-
"Here's an image below to better understand our graph."
145-
]
146-
},
147-
{
148-
"cell_type": "markdown",
149-
"metadata": {},
150-
"source": [
151-
"<img src=\"images/search_animal.svg\" width=\"80%\">\n",
152-
"<!-- Theses lovely animal icons were reproduced courtesy of Creative Tail https://www.creativetail.com/40-free-flat-animal-icons/ -->\n"
153-
]
154-
},
155-
{
156-
"cell_type": "markdown",
157-
"metadata": {},
158-
"source": [
159-
"### Breadth First Search"
110+
"%psource GraphProblem"
160111
]
161112
},
162113
{
163114
"cell_type": "markdown",
164115
"metadata": {},
165116
"source": [
166-
"In Breadth First Search, the `shallowest` unexpanded node is chosen for expansion. That means that all nodes of a given depth must be expanded before any node of the next depth level. This search strategy accomplishes this by using a `FIFO` meaning 'First In First Out' queue. Anything that gets in the queue first also gets out first just like the checkout queue in a supermarket. To use the algorithm, first we need to define our problem. Say we want to find the statue of `Monkey` and we start from the entrance which is the `Start` state. We'll define our problem using the `GraphProblem` class."
117+
"Now it's time to define our problem. We will define it by passing `initial`, `goal`, `graph` to `GraphProblem`. So, our problem is to find the goal state starting from the given initial state on the provided graph. Have a look at our romania_map, which is an Undirected Graph containing a dict of nodes as keys and neighbours as values."
167118
]
168119
},
169120
{
170121
"cell_type": "code",
171-
"execution_count": 3,
122+
"execution_count": 16,
172123
"metadata": {
173124
"collapsed": false
174125
},
175126
"outputs": [],
176127
"source": [
177-
"monkey_problem = GraphProblem('Start', 'Monkey', museum_graph)"
128+
"romania_map = UndirectedGraph(dict(\n",
129+
" Arad=dict(Zerind=75, Sibiu=140, Timisoara=118),\n",
130+
" Bucharest=dict(Urziceni=85, Pitesti=101, Giurgiu=90, Fagaras=211),\n",
131+
" Craiova=dict(Drobeta=120, Rimnicu=146, Pitesti=138),\n",
132+
" Drobeta=dict(Mehadia=75),\n",
133+
" Eforie=dict(Hirsova=86),\n",
134+
" Fagaras=dict(Sibiu=99),\n",
135+
" Hirsova=dict(Urziceni=98),\n",
136+
" Iasi=dict(Vaslui=92, Neamt=87),\n",
137+
" Lugoj=dict(Timisoara=111, Mehadia=70),\n",
138+
" Oradea=dict(Zerind=71, Sibiu=151),\n",
139+
" Pitesti=dict(Rimnicu=97),\n",
140+
" Rimnicu=dict(Sibiu=80),\n",
141+
" Urziceni=dict(Vaslui=142)))\n",
142+
"\n",
143+
"romania_map.locations = dict(\n",
144+
" Arad=(91, 492), Bucharest=(400, 327), Craiova=(253, 288),\n",
145+
" Drobeta=(165, 299), Eforie=(562, 293), Fagaras=(305, 449),\n",
146+
" Giurgiu=(375, 270), Hirsova=(534, 350), Iasi=(473, 506),\n",
147+
" Lugoj=(165, 379), Mehadia=(168, 339), Neamt=(406, 537),\n",
148+
" Oradea=(131, 571), Pitesti=(320, 368), Rimnicu=(233, 410),\n",
149+
" Sibiu=(207, 457), Timisoara=(94, 410), Urziceni=(456, 350),\n",
150+
" Vaslui=(509, 444), Zerind=(108, 531))"
178151
]
179152
},
180153
{
181154
"cell_type": "markdown",
182-
"metadata": {},
183-
"source": [
184-
"Now let's find the solution for our problem using the `breadth_first_search` method. Note that it returns a `Node` from which we can find the solution by looking at the path that was taken to reach there."
185-
]
186-
},
187-
{
188-
"cell_type": "code",
189-
"execution_count": 4,
190155
"metadata": {
191-
"collapsed": false
192-
},
193-
"outputs": [
194-
{
195-
"data": {
196-
"text/plain": [
197-
"['Cat', 'Monkey']"
198-
]
199-
},
200-
"execution_count": 4,
201-
"metadata": {},
202-
"output_type": "execute_result"
203-
}
204-
],
205-
"source": [
206-
"bfs_node = breadth_first_search(monkey_problem)\n",
207-
"bfs_node.solution()"
208-
]
209-
},
210-
{
211-
"cell_type": "markdown",
212-
"metadata": {},
213-
"source": [
214-
"We get the output as `['Cat', 'Monkey']`. That is because first the nodes `Dog`, `Cat` and `Mouse` are added to the `FIFO` queue in `some` order when we are expanding the `Start` node. Now when we start expanding nodes in the next level, only the `Cat` node gets us to `Monkey`. Note that during a breadth first search, the goal test is done when the node is being added to the queue."
215-
]
216-
},
217-
{
218-
"cell_type": "markdown",
219-
"metadata": {},
220-
"source": [
221-
"### Uniform-cost Search"
222-
]
223-
},
224-
{
225-
"cell_type": "markdown",
226-
"metadata": {},
227-
"source": [
228-
"In Uniform-cost Search, we expand the node with the lowest path cost (the cost to reach that node from the start) instead of expanding the shallowest node. Rather than a `FIFO` queue, we use something called a `priority queue` which selects the element with the highest `priority` of all elements in the queue. For our problem, the shortest path between animals has the higher priority; the shortest path has the lowest path cost. Whenever we need to enqueue a node already in the queue, we will update its path cost if the newer path is better. This is a very important step, and it means that the path cost to a node may keep getting better until it is selected for expansion. This is the reason that we do a goal check only when a node is selected for expanion."
229-
]
230-
},
231-
{
232-
"cell_type": "code",
233-
"execution_count": 5,
234-
"metadata": {
235-
"collapsed": false
156+
"collapsed": true
236157
},
237-
"outputs": [
238-
{
239-
"data": {
240-
"text/plain": [
241-
"['Dog', 'Bear', 'Monkey']"
242-
]
243-
},
244-
"execution_count": 5,
245-
"metadata": {},
246-
"output_type": "execute_result"
247-
}
248-
],
249158
"source": [
250-
"ucs_node = uniform_cost_search(monkey_problem)\n",
251-
"ucs_node.solution()"
252-
]
253-
},
254-
{
255-
"cell_type": "markdown",
256-
"metadata": {},
257-
"source": [
258-
"We got the path`['Dog', 'Bear', 'Monkey']` instead of `['Cat', 'Monkey']`. Why? The path cost is lower! We can also see the path cost with the path_cost attribute. Let's compare the path cost of the Breadth first search solution and Uniform cost search solution"
159+
"It is pretty straight forward to understand this `romania_map`. The first node **Arad** has three neighbours named **Zerind**, **Sibiu**, **Timisoara**. Each of these nodes are 75, 140, 118 units apart from **Arad** respectively. And the same goes with other nodes.\n",
160+
"\n",
161+
"And `romania_map.locations` contains the positions of each of the nodes. We will use the straight line distance (which is different from the one provided in `romania_map`) between two cities in algorithms like A\\*-search and Recursive Best First Search.\n",
162+
"\n",
163+
"**Define a problem:**\n",
164+
"Hmm... say we want to start exploring from **Arad** and try to find **Bucharest** in our romania_map. So, this is how we do it."
259165
]
260166
},
261167
{
262168
"cell_type": "code",
263-
"execution_count": 6,
169+
"execution_count": null,
264170
"metadata": {
265-
"collapsed": false
171+
"collapsed": true
266172
},
267-
"outputs": [
268-
{
269-
"data": {
270-
"text/plain": [
271-
"(18, 17)"
272-
]
273-
},
274-
"execution_count": 6,
275-
"metadata": {},
276-
"output_type": "execute_result"
277-
}
278-
],
173+
"outputs": [],
279174
"source": [
280-
"bfs_node.path_cost, ucs_node.path_cost"
175+
"romania_problem = GraphProblem('Arad', 'Bucharest', romania_map)"
281176
]
282177
},
283178
{
284179
"cell_type": "markdown",
285180
"metadata": {},
286-
"source": [
287-
"We were right! \n",
288-
"\n",
289-
"The path cost through the `Cat` statue is indeed more than the path cost through `Dog` even though the former passes through two roads compared to the three roads in the `ucs_node` solution."
290-
]
291-
},
292-
{
293-
"cell_type": "markdown",
294-
"metadata": {
295-
"collapsed": true
296-
},
297181
"source": [
298182
"# Romania map visualisations\n",
299183
"\n",
300-
"Let's have a visualisation of Romania map [Figure 3.2] from the book and see how different searching algorithms perform / how frontier expands in each search algorithm for a simple problem to reach 'Bucharest' starting from 'Arad'. This is how the problem is defined:"
301-
]
302-
},
303-
{
304-
"cell_type": "code",
305-
"execution_count": 7,
306-
"metadata": {
307-
"collapsed": false
308-
},
309-
"outputs": [],
310-
"source": [
311-
"romania_problem = GraphProblem('Arad', 'Bucharest', romania_map)"
184+
"Let's have a visualisation of Romania map [Figure 3.2] from the book and see how different searching algorithms perform / how frontier expands in each search algorithm for a simple problem named `romania_problem`."
312185
]
313186
},
314187
{
@@ -320,19 +193,11 @@
320193
},
321194
{
322195
"cell_type": "code",
323-
"execution_count": 8,
196+
"execution_count": null,
324197
"metadata": {
325-
"collapsed": false
198+
"collapsed": true
326199
},
327-
"outputs": [
328-
{
329-
"name": "stdout",
330-
"output_type": "stream",
331-
"text": [
332-
"{'Rimnicu': (233, 410), 'Hirsova': (534, 350), 'Arad': (91, 492), 'Vaslui': (509, 444), 'Oradea': (131, 571), 'Giurgiu': (375, 270), 'Neamt': (406, 537), 'Fagaras': (305, 449), 'Bucharest': (400, 327), 'Sibiu': (207, 457), 'Urziceni': (456, 350), 'Lugoj': (165, 379), 'Craiova': (253, 288), 'Zerind': (108, 531), 'Iasi': (473, 506), 'Mehadia': (168, 339), 'Pitesti': (320, 368), 'Timisoara': (94, 410), 'Drobeta': (165, 299), 'Eforie': (562, 293)}\n"
333-
]
334-
}
335-
],
200+
"outputs": [],
336201
"source": [
337202
"romania_locations = romania_map.locations\n",
338203
"print(romania_locations)"

0 commit comments

Comments
 (0)