360 likes | 488 Views
COMP 3715 Spring 05. Problem solving as search. The story so far Search as a way for artificial intelligence Various search techniques Depth/Breadth first search Heuristic search Hill climbing Best-first search A* search However: how to formulate a AI problem as search?.
E N D
Problem solving as search • The story so far • Search as a way for artificial intelligence • Various search techniques • Depth/Breadth first search • Heuristic search • Hill climbing • Best-first search • A* search • However: how to formulate a AI problem as search?
Problem solving as search • Transforming a problem to a search • Recall that search involves searching a graph • Graph contains • Nodes • Edges • Starting node • Finishing nodes
Problem solving as search • General procedures • Nodes -> State of the problem • Edges -> How to transit from one state to another • Starting node -> initial state • Finishing nodes -> final state • Weights on nodes -> How close is that state to the final state • Weights on edges -> The cost of moving from one state to the other
Mapping problem to graph search • Example 1: (textbook, p82) • You are given • One 4-galloon jug, no markers • One 3-galloon jug, no markers • Unlimited water supply • You goal • Fill up two gallons of water in the 4-gallon jug
Mapping problem to graph search • Step 1: figure out the states • For this example • Amount of water in each jug • Can be expressed by a tuple (X, Y) • X = amount of water in the 4-gallon jug • 0 X 4 • Y = amount of water in the 3-gallon jug • 0 Y 3
Mapping problem to graph search • Step 2: figure out the initial and final states • For this example • Initially both jugs are empty: (0, 0) • Finally I want 2 galloon in the 4-galloon jug: (2, 0), (2, 1), (2, 2), (2, 3) • Notice that for many problems there can be multiple final states
Mapping problem to graph search • Step 3: figuring out the transitions • i.e. how do I get from one state to another • This is based on the possible actions one can take • These are viewed as edges to the graph • For this example: • Filling a jug • Emptying a jug • Pouring water from one jug to another
Mapping problem to graph search • Step 3: figuring out the transitions (ctd.) • Need to map each possible move to figure out the transitions. • Examples: • Fill the 4-gallon jug: (X, Y) -> (4, Y) • Fill the 3-gallon jug: (X, Y) -> (X, 3) • Empty the 4-gallon jug to the 3-galloon jug: (X, Y) -> (0, X+Y) [if X+Y 3] • Fill the 3-gallon jug from water in 4 galloon jug (X, Y) -> (X+Y-3, 3) [if X+Y > 3] • Empty the 3-gallon jug to the 4-galloon jug: (X, Y) -> (X+Y, 0) [if X+Y 4] • Fill the 4-gallon jug from water in 3 galloon jug (X, Y) -> (4, X+Y-4) [if X+Y > 4] • Empty the 3-galloon jug: (X, Y) -> (X, 0) • Empty the 4-galloon jug: (X, Y) -> (0, Y)
Mapping problem to graph search • Step 4: Apply algorithm • Example: Breadth First Search • Initial queue: {(0,0)/0} • Store the state, and which transition lead to that state • Visited state:{}
Queue: {(0,0)}, Visited State: {} • Pop Top of the queue: (0,0) • Fill the 4-gallon jug: (0, 0) -> (4, 0) • Fill the 3-gallon jug: (0, 0) -> (0, 3) • Empty the 4-gallon jug to the 3-galloon jug: (0, 0) -> (0, 0+0 = 0) [if X+Y 3] • Fill the 3-gallon jug from water in 4 galloon jug (0, 0) -> (X+Y-3, 3) [if X+Y > 3] (not applicable) • Empty the 3-gallon jug to the 4-galloon jug: (0, 0) -> (0+0 = 0, 0) [if X+Y 4] • Fill the 4-gallon jug from water in 3 galloon jug (X, Y) -> (4, X+Y-4) [if X+Y > 4] (not applicable) • Empty the 3-galloon jug: (0, 0) -> (0, 0) • Empty the 4-galloon jug: (0, 0) -> (0, 0) • States to add: (4, 0)/1, (0, 3)/2
Queue: {(4,0)/1, (0, 3)/2}, Visited State: {(0, 0)} • Pop Top of the queue: (4,0) • Fill the 4-gallon jug: (4, 0) -> (4, 0) • Fill the 3-gallon jug: (4, 0) -> (4, 3) • Empty the 4-gallon jug to the 3-galloon jug: (X, Y) -> (X, X+Y) [if X+Y 3] (not applicable) • Fill the 3-gallon jug from water in 4 galloon jug (4, 0) -> (4+0-3 =1, 3) [if X+Y > 3] • Empty the 3-gallon jug to the 4-galloon jug: (4, 0) -> (4+0 = 4, 0) [if X+Y 4] • Fill the 4-gallon jug from water in 3 galloon jug (4, Y) -> (4, X+Y-4) [if X+Y > 4] (not applicable) • Empty the 3-galloon jug: (4, 0) -> (4, 0) • Empty the 4-galloon jug: (4, 0) -> (0, 0) • States to add: (4, 3)/2, (1, 3)/4
Queue: {(0, 3)/2}, (4,3)/2, (1,3)/4}, Visited State: {(0, 0), (4,0)/1} • Pop Top of the queue: (0, 3) • Fill the 4-gallon jug: (0, 3) -> (4, 3) • Fill the 3-gallon jug: (0, 3) -> (0, 3) • Empty the 4-gallon jug to the 3-galloon jug: (0, 3) -> (0, 0+3 = 3) [if X+Y 3] (not applicable) • Fill the 3-gallon jug from water in 4 galloon jug (0, 3) -> (0+3-3 = 0, 3) [if X+Y > 3] • Empty the 3-gallon jug to the 4-galloon jug: (0, 3) -> (3+0 = 3, 0) [if X+Y 4] • Fill the 4-gallon jug from water in 3 galloon jug (4, Y) -> (4, X+Y-4) [if X+Y > 4] (not applicable) • Empty the 3-galloon jug: (0, 3) -> (0, 0) • Empty the 4-galloon jug: (0, 3) -> (0, 3) • States to add: (3, 0)/5
Coding the search algorithm • To code the search algorithm, need to code • State – as a class • Transition – as a function of state, returning the next state • The search algorithm itself – as a function
Coding the search algorithm -- state class State { State() { x=0; y=0;} // Initialize; boolean IsError() { return (x == -1);} // check if the state is an error state; boolean IsFinal() {return (x==2);} // check if state is final state void ErrorState() {x=-1;} // return an error state int x = 0; // amount of water in 4-gallon jug int y = 0; // amount of water in 3-gallon jug };
Coding the search algorithm -- transition State transition (State curstate, int transnum){ State result; if (transnum == 1) {result.x = 4; result.y = curstate.y;} // fill the 4-galloon jug else if (transnum == 2) {result.x = curstate.x; result.y = 3;} // fill the 3-galloon jug else if (transnum == 3) { if ((curstate.x + curstate.y) <= 3) // check if transition legal then (result.x = 0; result.y = curstate.x + curstate.y;} // empty the 4-gallon jug to the 3-galloon jug else ( result.ErrorState();) // transition not legal, return error-state } else if ….. …… return result; };
Coding the search algorithm -- algorithm State curstate; Queue<state> queue; Set<state> visited; visited.add(curstate); While (!curstate.IsFinish()) { for (int i = 1 to 8) { State newState = transition(curstate, i); if (!newState.IsError() and (newstate not in visited) and (newstate not in queue) {queue.add(newstate);} } curstate = queue.poptop(); visited.add(curstate); }
Coding the search algorithm -- notes • Too many transitions • Need to use a class to represent transitions • Need a separate function to generate all possible transitions • Different search algorithms • Change the data structure that use to store the info • For depth-first search: stack • For best-first search: priority queue • For some data structure, need to associate value (weight) to each state • Define a value() method in the state class
Generalization: Planning • Previous techniques can be generalized to a more complicated context • State can be more complicated. • Transition can be more elaborated • E.g. represented using first-order logic • Algorithms can search in a more varied way. • Example: action planning -- STRIPS
Generalization: Planning -- STRIPS • Overall picture • Clauses (predicate) representing the states of the world • Transitions are represented as actions to add/delete clauses • Transitions have elaborate conditions to check whether it can execute
Generalization: Planning -- STRIPS • States • Clauses representing reality • at(robot, living_room) • door_open(kitchen, living_room) • carry(kitchen, living_room, beer) • Each state has a set of clauses associated with it
Generalization: Planning -- STRIPS • Transitions • Have four parts • Operator • Name of the transition • Variables use to define who is applying the operation. E.g. open_door(R1, R2) : the door between room R1 and room R2 is opened • Preconditions • Clauses that must be true in the current state for the transitions to be applicable • Once again, variables are used
Generalization: Planning -- STRIPS • Transitions • Once the transition is chosen: • Add • Clauses to be added to the current state • Delete • Clauses to be deleted from the current state • The add and delete operations are applied to form the new current state
Generalization: Planning -- STRIPS • Transitions • Example • Open the door between room R1 and room R2 while the robot is at R1 • Operator: open(R1, R2) • Pre-condition: at(robot, R1), door_closed(R1, R2) • Add: door_open(R1, R2) • Delete: door_closed(R1, R2)
Generalization: Planning -- STRIPS • Algorithm: means-end analysis • Set up initial state and final (target) state • Example • Initial state: Fred and his robot is in the living room with the door closed. While there is a bottle of beer at the kitchen • At(robot, living_room), at(beer, kitchen), at(Fred, living_room), door_closed(kitchen, living_room)
Generalization: Planning -- STRIPS • Algorithm: means-end analysis • Set up initial state and final (target) state • Example • Target state: Fred want to get the beer to his hand, with the kitchen door still closed • At(robot, living_room), at(beer, living_room), at(Fred, living_room), door_closed(kitchen, living_room)
Generalization: Planning -- STRIPS • Algorithm: means-end analysis • At each step, compare the initial state and the final state • Consider which clause is in the final state but not in the initial state • Example • Initial state: At(robot, living_room), at(beer, kitchen), at(Fred, living_room), door_closed(kitchen, living_room) • Target state: At(robot, living_room), at(beer, living_room), at(Fred, living_room), door_closed(kitchen, living_room) • At(beer, living_room) in target state but not in initial state • Try to find a way to create the those clause
Generalization: Planning -- STRIPS • Algorithm: means-end analysis • Target clause to add: at(beer, living room) • Consider this transition • Operator: Carry(R1, R2, O) • Precondition: door_open(R1, R2), at(robot, R1), at(O, R1) • Add: at(robot, R2), at(O, R2) • Delete: at(robot, R1), at(O, R1)
Generalization: Planning -- STRIPS • Algorithm: means-end analysis • Substitute living_room for R2, and beer for O, kitchen for R1 • Operator: Carry(living_room, living_room, beer) • Precondition: door_open(R1, living_room), at(robot, living_room), at(beer, living_room) • Add: at(robot, living_room), at(beer, living_room) • Delete: at(robot, kitchen), at(beer, kitchen) • If we can apply this operation from the initial state, it would lead to the final state
Generalization: Planning -- STRIPS • Algorithm: means-end analysis • Problem: pre-condition of the transition is not valid in the initial state! • Operator: Carry(living_room, living_room, beer) • Precondition: door_open(R1, living_room), at(robot, living_room), at(beer, living_room) • Add: at(robot, living_room), at(beer, living_room) • Delete: at(robot, kitchen), at(beer, kitchen) • Thus we need to plan to go from the initial state to a state where the red-colored clauses are true • Recursion!
Search techniques in games • Similar formulation • State: the situation of the game • The current score • The position of the chess pieces on the board • Final state: a situation where you wins! • My final score > opponent’s final score • The position of the chess pieces signals checkmate • Transition: legal move allowed
Search techniques in games • Problem • Typically too many states • Thus, heuristic search • Each state is assigned a value • Some function of the chessboard • Your current score – opponent’s current score • The search use techniques to go to a position with the highest possible value
Search techniques in games • Problem • You can search what you like, but you have to make a move • Moreover, your opponent will make moves too! • That means, the path you take may not be the path your opponent wants to take.
Solution: MiniMax procedure • Consider your search as building a tree • Alternative level denotes move by alternative player • When you move, you want to maximize the value • When your opponent moves, he wants to minimize the value • So at each node, pick the moves that make most sense for each player • Then based on that, find the optimal value
Algorithm outline • Need a state class to capture the current state of the game • Need to keep track of game status • Game board • What each player holds • Current score • Need a way to generate next moves • Either a function that return all the states
Algorithm outline Int MiniMax(State curstate, boolean ismymove) { int curoptimal; int count = 0; int bestmove; for (move = each possible moves) { int thismovescore = Score(curstate, move) State newstate = NextState(curstate, move); thismovescore += MinMax(newstate, ~ ismymove); if (count == 0) {curoptimal = thismovescore; bestmove = move;} else if (ismymove && thismovescore > curoptimal) {curoptimal = thismovescore; bestmove = move;} else if (~ ismymove && thismovescore < curoptimal) {curoptimal = thismovescore; bestmove = move;} } return curoptimal; }