@@ -305,6 +305,85 @@ def iterative_deepening_search(problem):
305305 if result != 'cutoff' :
306306 return result
307307
308+ # ______________________________________________________________________________
309+ # Bidirectional Search
310+ # Pseudocode from https://webdocs.cs.ualberta.ca/%7Eholte/Publications/MM-AAAI2016.pdf
311+
312+ def bidirectional_search (problem ):
313+ e = problem .find_min_edge ()
314+ gF , gB = {problem .initial : 0 }, {problem .goal : 0 }
315+ openF , openB = [problem .initial ], [problem .goal ]
316+ closedF , closedB = [], []
317+ U = infinity
318+
319+
320+ def extend (U , open_dir , open_other , g_dir , g_other , closed_dir ):
321+ """Extend search in given direction"""
322+ n = find_key (C , open_dir , g_dir )
323+
324+ open_dir .remove (n )
325+ closed_dir .append (n )
326+
327+ for c in problem .actions (n ):
328+ if c in open_dir or c in closed_dir :
329+ if g_dir [c ] <= problem .path_cost (g_dir [n ], n , None , c ):
330+ continue
331+
332+ open_dir .remove (c )
333+
334+ g_dir [c ] = problem .path_cost (g_dir [n ], n , None , c )
335+ open_dir .append (c )
336+
337+ if c in open_other :
338+ U = min (U , g_dir [c ] + g_other [c ])
339+
340+ return U , open_dir , closed_dir , g_dir
341+
342+
343+ def find_min (open_dir , g ):
344+ """Finds minimum priority, g and f values in open_dir"""
345+ m , m_f = infinity , infinity
346+ for n in open_dir :
347+ f = g [n ] + problem .h (n )
348+ pr = max (f , 2 * g [n ])
349+ m = min (m , pr )
350+ m_f = min (m_f , f )
351+
352+ return m , m_f , min (g .values ())
353+
354+
355+ def find_key (pr_min , open_dir , g ):
356+ """Finds key in open_dir with value equal to pr_min
357+ and minimum g value."""
358+ m = infinity
359+ state = - 1
360+ for n in open_dir :
361+ pr = max (g [n ] + problem .h (n ), 2 * g [n ])
362+ if pr == pr_min :
363+ if g [n ] < m :
364+ m = g [n ]
365+ state = n
366+
367+ return state
368+
369+
370+ while openF and openB :
371+ pr_min_f , f_min_f , g_min_f = find_min (openF , gF )
372+ pr_min_b , f_min_b , g_min_b = find_min (openB , gB )
373+ C = min (pr_min_f , pr_min_b )
374+
375+ if U <= max (C , f_min_f , f_min_b , g_min_f + g_min_b + e ):
376+ return U
377+
378+ if C == pr_min_f :
379+ # Extend forward
380+ U , openF , closedF , gF = extend (U , openF , openB , gF , gB , closedF )
381+ else :
382+ # Extend backward
383+ U , openB , closedB , gB = extend (U , openB , openF , gB , gF , closedB )
384+
385+ return infinity
386+
308387# ______________________________________________________________________________
309388# Informed (Heuristic) Search
310389
@@ -848,6 +927,9 @@ def h(self, node):
848927 """h function is straight-line distance from a node's state to goal."""
849928 locs = getattr (self .graph , 'locations' , None )
850929 if locs :
930+ if type (node ) is str :
931+ return int (distance (locs [node ], locs [self .goal ]))
932+
851933 return int (distance (locs [node .state ], locs [self .goal ]))
852934 else :
853935 return infinity
0 commit comments