Week # 10 Lecture # 19 & 20 General Problem Solver: Learning Objectives

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 10

Week # 10 Lecture # 19 & 20

GENERAL PROBLEM SOLVER


RELATED VIDEOS ON YOUTUBE

Sr. Channel Video Name URL

1 Dr Umair Abdullah Assignment 6 solution https://youtu.be/8TqfwxEOHtA

2 Dr Umair Abdullah GPS Introduction https://youtu.be/PJmhdvr2TsE

https://youtu.be/EkJUHSzI_Aw
3 Dr Umair Abdullah GPS Moving Block Example
https://youtu.be/cTjo9jSToJQ

4 Dr Umair Abdullah GPS: Drive son to school example https://youtu.be/1ljVgtDEMwo

https://youtu.be/ran8kLIPWzM
https://youtu.be/tgM9BU6PnCQ
5 Dr Umair Abdullah GPS in class videos (2019) https://youtu.be/9FGxOsWXmhE
https://youtu.be/92eyE4Mf9Uc
https://youtu.be/DCqiGghEkDw

Learning Objectives
1. Solution of assignment # 6
2. General Problem Solver Introduction
3. Arranging Block example in GPS
4. Drive son to school example
5. GPS Code overview
PRE-REQUISITS

1. You have learned basics of Python programming


2. You have learned recursive programming in Python
SOLUTION (Assignment # 6)

QUESTION: Define a recursive function in Python named sub_er (i.e. substitute


embedded-recursive) . It should take three arguments; old-value, new-value, and a list
which could be nested. The function should replace old-value with the new-value from the
given list. Also TRACE the sample function call given below;

>>> sub_er (10, 5, [10, 8, [10, 12], 10)


[ 5 , 8 , [5 , 12], 5]

SOLUTION:

def sub_er(o, n, x, ans=[]):


print('sub_er(',o,',',n,', ',x,', ',ans,')')
if x == []:
return ans
elif o == x[0]:
return sub_er(o, n, x[1:], ans)
elif type(x[0]) is list:
ans1 = sub_er(o, n, x[0], [])
ans.append(ans1)
return sub_er(o, n, x[1:], ans)
else:
ans.append(x[0])
return sub_er(o, n, x[1:], ans)

TRACING

print(sub_er(10, 5, [10, 8, [10, 12],10,14]))


sub_er( 10 , 5 , [10, 8, [10, 12], 10, 14] , [] )
sub_er( 10 , 5 , [8, [10, 12], 10, 14] , [] )
sub_er( 10 , 5 , [[10, 12], 10, 14] , [8] )
sub_er( 10 , 5 , [10, 12] , [] )
sub_er( 10 , 5 , [12] , [] )
sub_er( 10 , 5 , [] , [12] )
sub_er( 10 , 5 , [10, 14] , [8, [12]] )
sub_er( 10 , 5 , [14] , [8, [12]] )
sub_er( 10 , 5 , [] , [8, [12], 14] )
[8, [12], 14]
GENERAL PROBLEM SOLVER

Introduction

Given this description of a theory of problem solving, how should we go about writing a
program? The main idea is to solve a problem using a process called means-ends analysis,
where the problem is stated in terms of what we want to achieve at the end. In Newell and
Simon’s example, the problem is to get the kid to school, but in general we would like the
program to be able to solve a broad class of problems. We can solve a problem if we can find
some way to eliminate “the difference between what I have (current state) and what I want
(goal state).” For example, if what I have is a child at home and what I want is a child as
school, then driving may be a solution, because we know that driving leads to a change in
location. We should be aware that using means-ends analysis is a choice: it is also possible to
start from the current situation and search forward to the goal, or to employ a mixture of
different search strategies.

Some actions require the solving of preconditions as sub-problems. Before we can


drive the car, we need to solve the sub-problem of getting the car in working condition. It may
be that the car is already working, in which case we need do nothing to solve the sub-problem.
So a problem is solved either by taking appropriate action directly, or by first solving for the
preconditions of an appropriate action and then taking the action. It is clear we will need some
description of allowable actions, along with their preconditions and effects. We will also need
to develop a definition of appropriateness. However, if we can define these notions better, it
seems we won’t need any new notions. Thus, we will arbitrarily decide that the problem
description is complete and move on to the problem specification.
Specification

At this point we have an idea-admittedly vague-of what it means to solve a


problem in GPS. We can refine these notions into representations that are closer to Python as
follows:

 We can represent the current state of the world —“what I have”— or the goal state –
“what I want” – as sets of conditions. Common Python doesn’t have a data type for sets,
but it does have lists, which can be used to implement sets. Each condition can be
represented by a symbol. Thus, a typical goal might be the list of two conditions (rich
famous) and a typical current state might be (unknown poor).

 We need a list of allowable operators. This list well be constant over the course of a
problem, or even a series of problems, but we want to be able to change it and tackle a
new problem domain.

 An operator can be represented as a structure composed of an action, a list of


preconditions and a list of effects. We can place limits on the kinds of possible effects by
saying that an effect either adds or deletes a condition from the current state. Thus, the
list of effects can be split into an add-list and a delete-list. The original GPS allowed
more flexibility in the specification of effects, but flexibility leads to inefficiency.

 A complete problem is described to GPS in terms of a starting state, a goal state, and a set
of known operators. Thus, GPS will be a function of three arguments. For example, a
sample call might be:
(GPS ` (unknown poor) ‘ (rich famous) list-of-ops)

 In other words, starting from the state of being poor and unknown, achieve the
state of being rich and famous, using any combination of the known operators. GPS
should return a true value only if it solves the problem and it should print a record of the
actions taken. The simplest approach is to go through the conditions in the goal state one
at a time and try to achieve each one. If they can all be achieved, then the problem is
solved.

 A single goal condition can be achieved in two ways. If it is already in the current state,
the goal is trivially achieved with no effort. Otherwise, we have to find some appropriate
operator and try to apply it.

 An operator is appropriate if one of the effects of the operator is to add the goal in
question to the current state; in other words, if the goal is in the operator’s add-list.

We can apply an operator if we can achieve all the preconditions. But this is easy, because we
just defined the notion of achieving a goal in the previous paragraph. Once the preconditions
have been achieved, applying an operator’s add-list and delete-list. Since our program is just a
simulation – it won’t be actually driving a car or dialing a telephone – we must be content
simply to print out the action, rather than taking any real action.

 1st Characteristic of Humans: General Problem Solving Ability:


Humans, Computer, (in Software is the purpose of AI)
 2nd Characteristic of Humans: Functionality not at the time of manufacturing
 Separating functionality from code therefore have two components
1. Code/processor/ inference engine
2. Knowledge of actions as part of data
 Functionality is part of data (not code contrary to conventional programming)
 3rd Characteristic of Humans: Means-ends analysis
1. What actions are required to achieve goal
2. What are requirements (sub-goals) to be true in order to perform the intended goal
3. What change will occur in current state
 Format of operator
1. action
2. preconds
3. add
4. delete
Example 1: Write GPS operators to achieve final state by moving blocks present in the
sequence as shown in initial state. Note that at one time only one block can be picked (only
from top).

A C

B A

C B

Final State Initial State

block_ops = [
{"action":"Move block C on table",
"preconds":["Block C on A", "C-free"],
"add":["Block C on table", "A-free"],
"delete":["Block C on A"]},
{"action":"Move block A on table",
"preconds":["Block A on B","A-free"],
"add":["Block A on table", "B-free"],
"delete":["Block A on B"]},
{"action":"Move block B on C",
"preconds":["Block B on table", "B-free", "C-free"],
"add":["Block B on C"],
"delete":["Block B on table","C-free"]},
{"action":"Move block A on B",
"preconds":["Block A on table", "A-free","B-free"],
"add":["Block A on B"],
"delete":["Block A on table", "B-free"]}
]

gps(["Block B on table", "Block A on B", "Block C on A", "C-free"],


["Block C on table", "Block B on C", "Block A on B", "A-free"]
,block_ops )
TRACING:

0 Achieving: BLOCK C ON TABLE


0 Consider: MOVE BLOCK C ON TABLE
1 Achieving: BLOCK C ON A
1 Achieved: BLOCK C ON A
1 Achieving: C-FREE
1 Achieved: C-FREE
0 Action: MOVE BLOCK C ON TABLE Achieved: BLOCK C ON TABLE
0 Achieving: BLOCK B ON C
0 Consider: MOVE BLOCK B ON C
1 Achieving: BLOCK B ON TABLE
1 Achieved: BLOCK B ON TABLE
1 Achieving: B-FREE
1 Consider: MOVE BLOCK A ON TABLE
2 Achieving: BLOCK A ON B
2 Achieved: BLOCK A ON B
2 Achieving: A-FREE
2 Achieved: A-FREE
1 Action: MOVE BLOCK A ON TABLE Achieved: B-FREE
1 Achieving: C-FREE
1 Achieved: C-FREE
0 Action: MOVE BLOCK B ON C Achieved: BLOCK B ON C
0 Achieving: BLOCK A ON B
0 Consider: MOVE BLOCK A ON B
1 Achieving: BLOCK A ON TABLE
1 Achieved: BLOCK A ON TABLE
1 Achieving: A-FREE
1 Achieved: A-FREE
1 Achieving: B-FREE
1 Achieved: B-FREE
0 Action: MOVE BLOCK A ON B Achieved: BLOCK A ON B
0 Achieving: A-FREE
0 Achieved: A-FREE

EXECUTING MOVE BLOCK C ON TABLE


EXECUTING MOVE BLOCK A ON TABLE
EXECUTING MOVE BLOCK B ON C
EXECUTING MOVE BLOCK A ON B
EXAMPLE 2: DRIVING SON TO SCHOOL

sch_ops = [ {
"action": "drive son to school",
"preconds": ["son at home", "car works"],
"add": ["son at school"],
"delete": ["son at home"]
},
{ "action": "shop installs battery",
"preconds": ["car needs battery", "shop knows problem", "shop
has money"],
"add": ["car works"],
"delete": []
},
{ "action": "tell shop problem",
"preconds": ["in communication with shop"],
"add": ["shop knows problem"],
"delete": []
},
{ "action": "telephone shop",
"preconds": ["know phone number"],
"add": ["in communication with shop"],
"delete": []
},
{ "action": "look up number",
"preconds": ["have phone book"],
"add": ["know phone number"],
"delete": []
},
{ "action": "give shop money",
"preconds": ["have money"],
"add": ["shop has money"],
"delete": ["have money"]
}
]

gps(["son at home", "have money", "have phone book", "car needs


battery"], ["son at school"],sch_ops )

0 Achieving: SON AT SCHOOL


0 Consider: DRIVE SON TO SCHOOL
1 Achieving: SON AT HOME
1 Achieved: SON AT HOME
1 Achieving: CAR WORKS
1 Consider: SHOP INSTALLS BATTERY
2 Achieving: CAR NEEDS BATTERY
2 Achieved: CAR NEEDS BATTERY
2 Achieving: SHOP KNOWS PROBLEM
2 Consider: TELL SHOP PROBLEM
3 Achieving: IN COMMUNICATION WITH SHOP
3 Consider: TELEPHONE SHOP
4 Achieving: KNOW PHONE NUMBER
4 Consider: LOOK UP NUMBER
5 Achieving: HAVE PHONE BOOK
5 Achieved: HAVE PHONE BOOK
4 Action: LOOK UP NUMBER Achieved: KNOW PHONE NUMBER
3 Action: TELEPHONE SHOP Achieved: IN COMMUNICATION WITH SHOP
2 Action: TELL SHOP PROBLEM Achieved: SHOP KNOWS PROBLEM
2 Achieving: SHOP HAS MONEY
2 Consider: GIVE SHOP MONEY
3 Achieving: HAVE MONEY
3 Achieved: HAVE MONEY
2 Action: GIVE SHOP MONEY Achieved: SHOP HAS MONEY
1 Action: SHOP INSTALLS BATTERY Achieved: CAR WORKS
0 Action: DRIVE SON TO SCHOOL Achieved: SON AT SCHOOL
EXECUTING LOOK UP NUMBER
EXECUTING TELEPHONE SHOP
EXECUTING TELL SHOP PROBLEM
EXECUTING GIVE SHOP MONEY
EXECUTING SHOP INSTALLS BATTERY
EXECUTING DRIVE SON TO SCHOOL
GPS CODE

def gps(initial_states, goal_states, operators):


prefix = 'EXECUTING '
for operator in operators:
operator['action'] = operator['action'].upper()
operator['add'].append(prefix + operator['action'])
operator['preconds'] = [pre.upper() for pre in operator['preconds']]
operator['delete'] = [dlst.upper() for dlst in operator['delete']]
operator['add'] = [add.upper() for add in operator['add']]
initial_states = [state.upper() for state in initial_states]
goal_states = [goal.upper() for goal in goal_states]
final_states = achieve_all(initial_states, operators, goal_states, [])
if not final_states:
return None
actions = [state for state in final_states if state.startswith(prefix)]
for a in actions:
print(a)
return actions

def achieve_all(states, ops, goals, goal_stack):


for goal in goals:
states = achieve(states, ops, goal, goal_stack)
if not states:
return None
for goal in goals:
if goal not in states:
return None
return states

def achieve(states, operators, goal, goal_stack):


print(len(goal_stack), 'Achieving: %s' % goal)
if goal in states:
print(len(goal_stack), 'Achieved: %s' % goal)
return states
if goal in goal_stack:
return None
for op in operators:
if goal not in op['add']:
continue
result = apply_operator(op, states, operators, goal, goal_stack)
if result:
return result

def apply_operator(operator, states, ops, goal, goal_stack):


print(len(goal_stack), 'Consider: %s' % operator['action'])
result = achieve_all(states, ops, operator['preconds'], [goal] +
goal_stack)
if not result:
return None
print(len(goal_stack), 'Action: %s' % operator['action'], ' Achieved:
%s' % goal)
add_list, delete_list = operator['add'], operator['delete']
return [state for state in result if state not in delete_list] + add_list

----------------------- END -------------------

You might also like