SMAG* A memory-bounded graph search Aisha Walcott
Intro A* can take space exponential in the depth of the search Linear space searches: IDA*, IE Memory-bounded searches, MA*, SMA*
SMA* Russell 1992 2 sets OPEN and CLOSED Makes use of all available memory Propagates f-cost backwards By retaining backed up values then the algorithm still knows how worthwhile it is to go anywhere from n Adds and prunes only one node at a time
SMA* Example Search Space g + h = f Goal node
SMA* Example G is chosen for expansion Search Space g + h = f Goal node SMA* Example G is chosen for expansion Delete the shallowest highest f-cost leaf A remembers the cost of its best forgotten successor Add H, but not solution through H so set its f-cost = inf 2. Deepest lowest f-cost node, A, adds successor G Update f-cost of A to min of its children f(A) = 13 Memory is full B is the best and generates C C is not a goal and its at maximum depth, set its f-cost = inf A is best node and generates its forgotten successor B 4. G is expanded Delete H and Add I G is completed its f-cost = 24 F cost of A becomes min(15,24) = 15 Deepest lowest f-cost node, A, adds successor B Delete C add D then f-cost of D is backed up to B and A 8. Deepest lowest F-cost node, D, is selected D is the goal Solution Found! [Russel, Norvig]
SMA* Summary Utilizes all memory available to it Partially expanded nodes, one successor at a time Complete if the memory is sufficient enough to store the shallowest solution Optimal if the memory is sufficient enough to store the shallowest optimal solution Russell & Norvig- “Most complicated search we have seen yet”
Memory-bounded A* graph searches Heuristic search in graphs is more complex than in trees because there can be more than one path to a node When a shorter path to a node is found its g-value can change If the node has already been expanded then the g-values of all its descendents may need to be revised
Memory-bounded A* graph searches (cont.) SMAG*, Kaindl and Khorsand 1994 SMAG*-Reopen, Zhou and Hansen 2002 SMAG*-Propagate, Zhou and Hansen 2002
SMAG* Bugs in pseudo code of Russell and Norvig Extends to directed acyclic graphs Prunes when there is a better path to a node Better path to n n Prune
SMAG* (cont.) Blocking/Cutting: Consistency: h(n) ≤ h(n’) + c(n, n’) Prune a node from the CLOSED list if it does not occur on the best to any fringe node If not pruned then “memory leak” Consistency: h(n) ≤ h(n’) + c(n, n’) Changing of g-value can be avoided if A* uses a consistent (monotone) heuristic Does not extend to memory-bounded A* because the heuristic estimates are modifies during search
SMAG*-2 Analyze the problem of consistency Provide an improved version of SMAG* reopen nodes propagate costs
Heuristic estimates are backed-up, increasing h and f values Original SMAG* Heuristic estimates are backed-up, increasing h and f values When nodes are pruned from OPEN set to free memory, their parent nodes are restored from CLOSED to OPEN set The new estimates may be admissible but not consistent h’(A) = h’(C) + c(A, C) What is the best path to node C? h’(C) = h(d) + c(C, D) Node C is expanded for the first time 1 1 1 Through A Why? Because g(A) = 1 and the g(B)= 2 then the best path is through A Dashed lines are parts of the graph not expanded [Zhou and Hansen, 2002] 1 1 1
Which node A or B will be expanded first? (ii) Nodes C & D are pruned 1 1 1 Which node A or B will be expanded first? (ii) Nodes C & D are pruned Node B is expanded before node A, although best path to C is through A. Why does this occur? 1 1 1 **The backed-up heuristic for node A is not consistent with the heuristic for node C Node C is expanded before the best path to it is found 1 1 1 [Zhou and Hansen, 2002]
Consistency Pathmax: used to restore consistency When a node n is expanded the h-value of each child n’ is checked. If h(n’)< h(n) – c(n, n’) then h(n’) = h(n) Pathmax only works for the explicit graph (the graph in memory) Figure (iii) shows nodes in OPEN that do no have all their arcs generated; thus, a node may be expanded before the best path to it is found
SMAG* A* propagates revised g-values to its descendents Original SMAG* prunes the nodes descendents Strategy is as many nodes in memory (to avoid re-expansions) and prune least promising nodes SMAG*-2 adapts the propagation strategy by A* to memory- bounded graph search
SMAG*-2 Example Counter to Iteration # 1 Used Counter to keep track of current number of nodes in memory Best Least-cost deepest node in Open succ Next unexamined successor of Best Max = 6 Max nodes in memory A h=90 B h=5 C h=80 D h=15 E 100 40 10 90 30 G 5 20 Start Open Nodes in memory with children being examined SMAG*-2 Example Closed Nodes in memory with all their children in memory Descriptions of Methods: BACKUP(n): if F(n)< min {F of its children} then F(n) = min{F of children} Recursively update parents Completed(n): all the succ’s of n examined CUT(n): carefully delete sub-optimal nodes on path to n GRAPH-CONTROL: multiple paths to a common node keep nest path to common node MEMORY-CONTROL: delete worst node in memory Iteration 1 Best Path-current known least cost path to any node Goal
Iteration # 1 Used 1 2 Best A succ B Max = 6 A h=90 B h=5 C h=80 D h=15 E 100 40 10 90 30 G 5 20 Open Start S(A) = {B} (A) = { } B g = 100, d=1 F = 105 A g = 0, d=0 F = 90 Select the least cost nodes in OPEN = { A } Select deepest node from best = A Closed Set B values: g(B) = g(best) + c(A, B) depth(B)= depth(A)+1 F(B) = max( F(A), g(B) + h(B) )//pathmax Iteration 1 Best Path-current known least cost path to any node S(n): successors of node n with known least-cost path via n (n): Forgotten successors of node n Goal
Open 100 10 Closed 90 40 20 5 30 Start the best path to B is through A Iteration # 2 Used 1,2 3 Best A succ B C Max = 6 A h=90 B h=5 C h=80 D h=15 E 100 40 10 90 30 G 5 20 Open Start S(A) = {B,C} (A) = { } A g = 0, d=0 F = 90 C g = 10, d=1 F = 90 B g = 100, d=1 F = 105 the best path to B is through A the best path to C is through A All successors of A in memory Set C values: g(C) = g(A) + c(A, C) depth(C)= depth(A)+1 F(C) = max( F(A), g(C) + h(C) )//pathmax Closed -There are multiple paths to N8 -The node with the least cost path to N8 stores N8 in it’s S set Iteration 2 N2 N1 N3 Goal N8 If Completed(A) Then BACKUP(A) BACKUP(n): if F(n)< min {F of its children} update Completed(n): all the succ’s of n examined
Open 100 10 C is completed BACKUP C Closed 90 40 20 5 30 Iteration # 3 Used 1,2 2,3 3 4 Best A C succ B C D Max = 6 A h=90 B h=5 C h=80 D h=15 E 100 40 10 90 30 G 5 20 Open Start S(A) = {B,C} (A) = { } C g = 10, d=1 F = 90115 B g = 100, d=1 F = 105 D g = 100, d=2 F = 115 S(C) = {D} (C) = { } C is completed BACKUP C Closed //Reorder OPEN BACKUP A A g = 0, d=0 F = 90105 Iteration 3 When backing up C do nothing because it contains no successors along the best path Set D values: g(D) = g(best) + c(C, D) depth(D)= depth(C)+1 F(D) = max( F(C), g(D) + h(D) )//pathmax Goal
Open 100 10 Closed 90 40 20 5 30 Start All successors of C in memory Iteration # 3 (cont) Used 1,2 2,3 3 4 Best A C succ B C D Max = 6 A h=90 B h=5 C h=80 D h=15 E 100 40 10 90 30 G 5 20 Open Start S(A) = {B,C} (A) = { } B g = 100, d=1 F = 105 D g = 100, d=2 F = 115 C g = 10, d=1 F = 115 S(C) = {D} (C) = { } Closed A g = 0, d=0 F = 105 All successors of C in memory Iteration 3 Goal
Open 100 10 B is completed BACKUP B Closed 90 40 20 5 30 BACKUP A Iteration # 4 Used 1,2 2,3 3,4 4 5 Best A C B succ B C D G Max = 6 A h=90 B h=5 C h=80 D h=15 E 100 40 10 90 30 G 5 20 Open Start S(A) = {B,C} (A) = { } B g = 100, d=1 F=105145 D g = 100, d=2 F = 115 G g = 140, d=2 F = 145 S(B) = {G} (B) = { } S(C) = {D} (C) = { } B is completed BACKUP B BACKUP A Closed A g = 0, d=0 F=105115 C g = 10, d=1 F = 115 All successors of B in memory Iteration 4 Goal
Open 100 10 Closed 90 40 20 5 30 Delete parent(G): Iteration # 5 Used 1,2 2,3 3,4 4,5 4 Best A C B D succ B C D G Max = 6 p(G)=B A h=90 B h=5 C h=80 D h=15 E 100 40 10 90 30 G 5 20 Open Start S(A) = {B,C} (A) = { } succ-hat D g = 100, d=2 F = 115 G g = 140, d=2 F = 145 parent bad path S(B) = {G} (B) = { } S(C) = {D} (C) = { } succ G g = 120, d=3 F = 125 Closed GRAPH-CONTROL(best:D,succ:G) A g = 0, d=0 F=115 C g = 10, d=1 F = 115 B g = 100, d=1 F =145 CUT (succ-hat) Take succ-hat out of its parent S(B) If parent(succ-hat), B, in CLOSED and parent(parent(succ-hat)), A, ≠ NULL Then CUT(B) Deleting nodes along the bad path to G CUT (B) //recursion Iteration 5 GRAPH-CONTROL g(succ) <= g(succ-hat) so since a cheaper path to G is through succ then get rid of the current path to G (ie. cut succ-hat) B is not on the best path then it’d not necessary to have B anymore. S(D) = { } (C) = { } Take B out of its parent S(A) A is completed BACKUP A // does nothing b/c the F-cost of its children //are not greater than it’s F-cost Goal //At level of recursion after CUT(B) from CUT(succ-hat) Delete parent(G): Delete B 2 paths to node G found! Select best path to G
Open 100 10 Closed 90 40 20 5 30 Start Goal Iteration # 5 (cont) Used 1,2 2,3 3,4 4,5 4 Best A C B D succ B C D G Max = 6 Open p(G)= D A h=90 B h=5 C h=80 D h=15 E 100 40 10 90 30 G 5 20 Start S(A) = {C} (A) = { } succ-hat D g = 100, d=2 F = 115 G g = 120, d=3 F = 125 parent S(C) = {D} (C) = { } succ G g = 120, d=3 F = 125 Closed A g = 0, d=0 F = 115 C g = 10, d=1 F = 115 GRAPH-CONTROL(D,G) CUT (succ-hat) Update values of succ-hat Iteration 5(cont.) Propagating succ-hat’s next successor index is already at it’s initial state and S(G) is empty (there are no successors of G that are in memory) S(D) = {G} (C) = { } PROPAGATE (succ-hat) //because we may have zero cost edges Goal
Open 100 10 Closed 90 40 20 5 30 Start Goal Iteration # 5 (cont) Used 1,2 2,3 3,4 4,5 4 Best A C B D succ B C D G Max = 6 p(G)= D A h=90 B h=5 C h=80 D h=15 E 100 40 10 90 30 G 5 20 Open Start S(A) = {C} (A) = { } succ-hat D g = 100, d=2 F = 115 G g = 120, d=3 F = 125 parent S(C) = {D} (C) = { } succ G g = 120, d=3 F = 125 Closed A g = 0, d=0 F = 115 C g = 10, d=1 F = 115 GRAPH-CONTROL(D,G) CUT (succ-hat) Update values of succ-hat Iteration 5(cont.) Since succ-hat is in OPEN then Reorder OPEN. Delete successor (succ). S(D) = {G} (C) = { } PROPAGATE (succ-hat) //because we may have zero cost edges Reorder OPEN //because G is in open Delete succ Goal
Continuing same iteration after GRAPH-CONTROL Closed Iteration # 5 (cont) Used 1,2 2,3 3,4 4,5 4 Best A C B D succ B C D G Max = 6 A h=90 B h=5 C h=80 D h=15 E 100 40 10 90 30 G 5 20 Open Start S(A) = {C} (A) = { } D g = 100, d=2 F=115 G g = 120, d=3 F = 125 S(C) = {D} (C) = { } Continuing same iteration after GRAPH-CONTROL Closed A g = 0, d=0 F = 115 C g = 10, d=1 F = 115 Iteration 5(cont.) The best path to both G and E is through D S(D) = {G} (C) = { } D is NOT completed All the successors of D are NOT in memory Go to next iteration Goal
Open 100 10 Next Iteration Closed 90 40 20 5 30 Start Goal Used 1,2 2,3 3,4 4,5 4 5 Best A C B D succ B C D G E Max = 6 A h=90 B h=5 C h=80 D h=15 E 100 40 10 90 30 G 5 20 Open Start S(A) = {C} (A) = { } D g = 100, d=2 F=115 G g = 120, d=3 F = 125 S(C) = {D} (C) = { } Next Iteration E g = 130, d=3 F = 130 Closed A g = 0, d=0 F = 115 C g = 10, d=1 F = 115 Iteration 6: The best path to both G and E is through D S(D) = {G,E} (C) = { } Goal
What happens with B when backing up A? Nothing. It no longer exists. Iteration # 6 (cont) Used 1,2 2,3 3,4 4,5 4 5 Best A C B D succ B C D G E Max = 6 A h=90 B h=5 C h=80 D h=15 E 100 40 10 90 30 G 5 20 Open Start S(A) = {C} (A) = { } D g = 100, d=2 F=115125 G g = 120, d=3 F = 125 E g = 130, d=3 F = 130 S(C) = {D} (C) = { } Closed D is completed BACKUP D C completed BACKUP C //recursion A completed BACKUP A //recursion A g = 0, d=0 F=115125 C g = 10, d=1 F=115125 Iteration 6 (cont) The best path to D is through C. The best path to B and C is through A. Assume A is completed even though B has been deleted from memory. S(D) = {G,E} (C) = { } Goal B was Deleted by CUT What happens with B when backing up A? Nothing. It no longer exists.
Open 100 10 Closed 90 40 20 5 30 Start All successors of D in memory Iteration # 6 (cont) Used 1,2 2,3 3,4 4,5 4 5 Best A C B D succ B C D G E Max = 6 A h=90 B h=5 C h=80 D h=15 E 100 40 10 90 30 G 5 20 Open Start S(A) = {C} (A) = { } D g = 100, d=2 F=125 G g = 120, d=3 F = 125 E g = 130, d=3 F = 130 S(C) = {D} (C) = { } Closed A g = 0, d=0 F = 125 C g = 10, d=1 F = 125 All successors of D in memory Iteration 6 (cont) All successors of D are in memory S(D) = {G,E} (C) = { } Goal
Open 100 10 Next Iteration Closed 90 40 20 5 30 GRAPH-CONTROL(G,E) Used 1,2 2,3 3,4 4,5 4 5 Best A C B D G succ B C D G E Max = 6 A h=90 B h=5 C h=80 D h=15 E 100 40 10 90 30 G 5 20 Open p(E)=D Start S(A) = {C} (A) = { } succ-hat G g = 120, d=3 F = 125 E g = 130, d=3 F = 130 parent S(C) = {D} (C) = { } Next Iteration succ E g = 125, d=4 F = 125 Closed A g = 0, d=0 F=125125 C g = 10, d=1 F=125125 D g = 100, d=2 F=125125 GRAPH-CONTROL(G,E) CUT (succ-hat) D is completed BACKUP D C completed BACKUP C //recursion A completed BACKUP A //recursion Iteration 7 GRAPH-CONTROL S(D) = {G,E} (C) = { } Goal
Open 100 10 Closed 90 40 20 5 30 GRAPH-CONTROL(G,E) CUT (succ-hat) Iteration # 7 (cont) Used 1,2 2,3 3,4 4,5 4 5 Best A C B D G succ B C D G E Max = 6 A h=90 B h=5 C h=80 D h=15 E 100 40 10 90 30 G 5 20 Open p(E)=G Start S(A) = {C} (A) = { } succ-hat G g = 120, d=3 F = 125 E g = 125, d=4 F = 125 parent S(C) = {D} (C) = { } succ E g = 125, d=4 F = 125 Closed A g = 0, d=0 F = 125 C g = 10, d=1 F = 125 D g = 100, d=2 F=125 S(G) = {E} (G) = { } GRAPH-CONTROL(G,E) CUT (succ-hat) Update Values of succ Iteration 7(cont.) GRAPH-CONTROL Propagate E does nothing because E has no successors. Reorder OPEN according to new F-cost S(D) = {G} (D) = { } PROPAGATE (succ-hat) Reorder Open Delete succ Goal
Open 100 10 G is completed BACKUP G Closed 90 40 20 5 30 Start Iteration # 7 (cont) Used 1,2 2,3 3,4 4,5 4 5 Best A C B D G succ B C D G E Max = 6 A h=90 B h=5 C h=80 D h=15 E 100 40 10 90 30 G 5 20 Open Start S(A) = {C} (A) = { } G g = 120, d=3 F=125 E g = 125, d=4 F = 125 S(C) = {D} (C) = { } G is completed BACKUP G Closed A g = 0, d=0 F=125 C g = 10, d=1 F=125 D g = 100, d=2 F=125 S(G) = {E} (G) = { } Iteration 7(cont.) GRAPH-CONTROL Propagate E does nothing because E has no successors. Reorder OPEN according to new F-cost S(D) = {G} (D) = { } All successors of G in memory Goal
Goal Reached! Cost of solution = 125 Iteration # 8 Used 1,2 2,3 3,4 4,5 4 5 Best A C B D G E succ B C D G E Max = 6 A h=90 B h=5 C h=80 D h=15 E 100 40 10 90 30 G 5 20 Open p(E)=G Start S(A) = {C} (A) = { } E g = 125, d=4 F = 125 S(C) = {D} (C) = { } Next Iteration Closed p(C)=A p(D)=C Select the least cost nodes in OPEN = {E } Select deepest node from best = E A g = 0, d=0 F = 125 C g = 10, d=1 F = 125 D g = 100, d=2 F=125 S(G) = {E} (G) = { } Test if best = goal return F( best ) p(G)=D Iteration 8 S(D) = {G} (C) = { } G g = 120, d=3 F = 125 Goal Goal Reached! Cost of solution = 125 Traverse the backpointers( ptrs to parent) from goal to start
Memory Control What happens when there is not enough memory to store the solution? 2 cases there is a solution at depth 4 but it’s not the optimal solution no solution paths with depth <= 4 In both cases what does the algorithm return? When does it terminate?
Open 100 10 Closed 90 Used = Max Memory 40 20 Delete worst 5 30 Iteration # 4 Used 1,2 3 4 Best A C B succ B C D G Max = 4 A h=90 B h=5 C h=80 D h=15 E 100 40 10 90 30 G 5 20 S(A) = {B,C} (A) = { } Open Start worst B g = 100, d=1 F=105 D g = 100, d=2 F = 115 G g = 140, d=2 F = 145 S(B) = {G} (B) = { } S(C) = {D} (C) = { } Closed Used = Max Memory A g = 0, d=0 F=105 C g = 10, d=1 F = 115 Select worst: the highest cost leaf in OPEN, D Delete worst Goal Memory Control
Open 100 10 B is completed BACKUP B Closed 90 40 20 5 30 Iteration # 4 (cont) Used 1,2 3 4 3,4 Best A C B succ B C D G Max = 4 A h=90 B h=5 C h=80 D h=15 E 100 40 10 90 30 G 5 20 S(A) = {B,C} (A) = { } Open Start C g = 10, d=1 F = 115 B g = 100, d=1 F =105145 G g = 140, d=2 F = 145 B is completed BACKUP B BACKUP A //recursion S(B) = {G} (B) = { } S(C) = {} (C) = {D } Closed A g = 0, d=0 F=105115 All successors of B in memory Goal Memory Control
Open 100 10 Closed 90 40 Used = Max Memory 20 worst = G Delete G 5 30 Iteration # 5 Used 1,2 3 4 3,4 4, 3 Best A C B succ B C D G Max = 4 A h=90 B h=5 C h=80 D h=15 E 100 40 10 90 30 G 5 20 S(A) = {B,C} (A) = { } Open Start worst G g = 140, d=2 F = 145 C g = 10, d=1 F = 115 S(B) = { } (B) = {G} D g = 100, d=2 F = 115 S(C) = {D} (C) = { } Closed A g = 0, d=0 F=115 B g = 100, d=1 F =145 Used = Max Memory worst = G Delete G Goal Memory Control
Open 100 10 C is completed BACKUP C Closed 90 40 20 5 30 Iteration # 5 (cont) Used 1,2 3 4 3,4 4,3 Best A C B succ B C D G Max = 4 A h=90 B h=5 C h=80 D h=15 E 100 40 10 90 30 G 5 20 S(A) = {B,C} (A) = { } Open Start C g = 10, d=1 F = 115 D g = 100, d=2 F = 115 B g = 100, d=1 F =145 C is completed BACKUP C S(B) = { } (B) = {G} S(C) = {D} (C) = { } Closed A g = 0, d=0 F=115 All successors of C are in memory Goal Memory Control
Open 100 10 Closed 90 40 20 5 30 Memory Control If succ != goal AND Iteration # 6 Used 1,2 3 4 4,3,4 Best A C B D succ B C D G Max = 4 A h=90 B h=5 C h=80 D h=15 E 100 40 10 90 30 G 5 20 S(A) = {B,C} (A) = { } Open Start D g = 100, d=2 F = 115 B g = 100, d=1 F =145 If succ != goal AND depth of succ = max-1 Then goto next iteration S(B) = { } (B) = {G} S(C) = {D} (C) = { } Closed A g = 0, d=0 F=115 C g = 10, d=1 F = 115 Iteration 5 GRAPH-CONTROL g(succ) <= g(succ-hat) so since a cheaper path to G is through succ then get rid of the current path to G (ie. cut succ-hat) S(D) = { } (D) = { } Goal Memory Control
Open 100 10 Closed 90 40 20 Used = Max Memory worst = B 5 30 Delete B Iteration # 7 Used 1,2 3 4 4,3,4 4, Best A C B D succ B C D G E Max = 4 A h=90 B h=5 C h=80 D h=15 E 100 40 10 90 30 G 5 20 S(A) = {C} (A) = {B } Open Start worst D g = 100, d=2 F = 115 B g = 100, d=1 F =145 S(B) = { } (B) = {G} S(C) = {D} (C) = { } Closed E g = 130, d=3 F=130 A g = 0, d=0 F=115 C g = 10, d=1 F = 115 Used = Max Memory Iteration 5 GRAPH-CONTROL g(succ) <= g(succ-hat) so since a cheaper path to G is through succ then get rid of the current path to G (ie. cut succ-hat) worst = B S(D) = {E} (D) = { } Delete B Goal Memory Control
Open 100 10 D is completed BACKUP D Closed 90 40 20 5 30 Iteration # 7 (cont) Used 1,2 3 4 4,3,4 4, Best A C B D succ B C D G E Max = 4 A h=90 B h=5 C h=80 D h=15 E 100 40 10 90 30 G 5 20 S(A) = {C} (A) = {B } Open Start D g = 100, d=2 F=115130 A g = 0, d=0 F=115130 E g = 130, d=3 F=130 D is completed BACKUP D BACKUP C //recursion BACKUP A //recursion S(B) = { } (B) = {G} S(C) = {D} (C) = { } Closed C g = 10, d=1 F=115130 Iteration 5 GRAPH-CONTROL g(succ) <= g(succ-hat) so since a cheaper path to G is through succ then get rid of the current path to G (ie. cut succ-hat) S(D) = {E} (D) = { } All successors of D in memory Goal Memory Control
Goal Reached! Cost of solution = 130 With Max Memory = 4 Iteration # 8 Used 1,2 3 4 4,3,4 4, Best A C B D E succ B C D G E Max = 4 A h=90 B h=5 C h=80 D h=15 E 100 40 10 90 30 G 5 20 S(A) = {C} (A) = {B } Open Start A g = 0, d=0 F=130 E g = 130, d=3 F=130 S(B) = { } (B) = {G} S(C) = {D} (C) = { } Closed Select the least cost nodes in OPEN = {A, E } Select deepest node from best = E C g = 10, d=1 F=130 D g = 100, d=2 F=130 Test if best = goal return F( best ) Iteration 5 GRAPH-CONTROL g(succ) <= g(succ-hat) so since a cheaper path to G is through succ then get rid of the current path to G (ie. cut succ-hat) S(D) = {E} (D) = { } Goal Goal Reached! Cost of solution = 130 With Max Memory = 4 Memory Control
Memory Control What happens when there is not enough memory to store the solution? 2 cases there is a solution at depth 4 but it’s not the optimal solution no solution paths with depth <= 4 In both cases what does the algorithm return? When does it terminate? Left as an exercise.
Discussion Comparisons from 2002 paper
References SMA 1992, Russell AI, Russell and Norvig SMAG* 1994, Chakrabarti et al. SMAG*-2 2002, Zhou and Hansen