[SOLVED] flex database AI data structure Haskell algorithm interpreter prolog UOB Open

$25

File Name: flex_database_AI_data_structure_Haskell_algorithm_interpreter_prolog_UOB_Open.zip
File Size: 725.34 KB

5/5 - (1 vote)

UOB Open
Artificial Intelligence: Logic Programming III
Oliver Ray

base case
Translation From Haskell: Example
recursive case
length([],X) :- X =0 .
UOB Open
%length[] =0
% length (_:l) = 1 + length l
length([_|L], X) :- X is 1 + Y , length(L, Y) .
length([], 0).
length([_|L], X) :- length(L, Y) , X is 1 + Y .
Note: we must place the recursive length call before the is call since the latter requires its right argument to be ground at call time

Computing Answers: Intuition
Prologs execution mechanism returns computed answer substitutions by repeatedly resolving query literals with (user-defined) database clauses until there are no literals left to prove:
A query literal is chosen by a selection rule (which, in standard Prolog returns the left-most call)
A database clause is chosen by a search rule (which, in standard Prolog , returns clauses top-to-bottom)
In fact, a fresh variant of the database clause is created by renaming all of the variables to ones not yet in play and alternative clauses are considered, in order (known as backtracking and visualized in an SLD or search tree)
A most general unifier (mgu) is computed for the selected literal and the head of the chosen clause
The resolvent of the query and the clause (on that literal under that mgu) is formed by applying the mgu and
replacing the selected literal by the body of clause in order to leave a new query
This is repeated until we derive a query with no literals, known as the empty clause and written
At that point the composition of all the mgus is taken and applied to the original query to yield an answer
If there are no resolvents, the branch is a failed dead end denoted by # or an underlined goal UOB Open

Substitutions and MGUs: Formalised
A substitution is a set of bindings of (distinct) variables to terms (distinct from themselves): ={X1/t1, Xn/tn} where is used to denote the empty substitution ={}
The application of a substitution to an expression E is denoted E and obtained by replacing any (free) variable Xi in E by the corresponding term ti from , if one exists
The composition of two substitutions 1 and 2 denoted 12 is defined as follows:
12 = {X/(t2) | X/t1 ^ Xt2 } {Y/s2 | YX for all X/t1} so E(12)=(E1)2
A substitution 1 is (as or) more general than a 2 iff there exists some 3 such that 13 =2
A substitution is a unifier of two expressions E1 and E2 iff E1=E2
A substitution is a most general unifier (mgu) of two expressions E1 and E2 iff is a unifier of E1 and E2 that is more general than all other unifiers of E1 and E2 (and is unique up to renaming)
Given two expressions E1,E2 and an (initially empty) substitution , we can compute an mgu as follows: mgu(E1,E2,)=mgu(E1{X/t}, E2 {X/t}, {X/t}) where X is a variable from one expression at the first syntactic position where the two expressions differ and t is corresponding term in the other (nb. if neither is a variable then there is no mgu; if both are variables then we can bind either to the other; strictly we should fail if t mentions X but this occurs check is usually omitted in Prolog)
UOB Open

Example: substitutions
given and and and and and
t1 = p( W, f(W , X)) t2 = p(Y,f(a,Z))
1 = { W/X , X/W}
2 = { W/a, Y/a, Z/X }
3 = {W/a,Y/a,X/Z}
4 = { W/a, Y/a, Z/V, X/V }
t11 = p(W, f(W,X)) {W/X, X/W} = p(X, f(X,W))
t21 = p(Y, f(a,Z)) {W/X, X/W} = p(Y, f(a,Z))
Thus 1 is NOT a unifier of t1and t2
But 2 and 3and 4 all ARE unifiers of t1and t2 (EASY EXERCISE!)
2 is more general than 3 as { W/a, Y/a, Z/X} {X/Z} = {W/a, Y/a, X/Z} since Z/Z is excluded from composition 3 is more general than 4 as { W/a, Y/a, X/Z} {Z/V} = {W/a, Y/a, X/V, Z/V}
4 is NOT more general than 3 as { W/a, Y/a, Z/V, X/V} = {W/a, Y/a, X/Z} implies V/Z in order to exclude Z/. from the composition, but then V/Z would be in the composition, which is a contradiction
UOB Open

Example: MGU (and common errors!)
given and
naively trying
plus( X plus( s(V)
X/s(V)
, Y , , W ,
Y/W or W/Y
s(Y) ) s(s(V)) )
Y/s(V)
gives { X/s(V), Y/W, Y/s(V) } or { X/s(V), W/Y, Y/s(V) } either
But these are both incorrect as the first is not even a substitution (as it contains two different bindings for Y) and the second is not a unifier (as the instantiated terms disagree on the second argument)!
Thus, correctly applying the mgu algorithm means applying the computed binding to the two expressions as we proceed and composing it with the other bindings computed thus far. For example
UOB Open
mgu(plus(X,Y,s(Y)), plus(s(V),W,s(s(V))), )
= mgu(plus(s(V),Y,s(Y)), plus(s(V),W,s(s(V))), {X/s(V)} )
= mgu(plus(s(V),W,s(W)), plus(s(V),W,s(s(V))), {X/s(V),Y/W} )
= mgu(plus(s(V),W,s(s(V))), plus(s(V),W,s(s(V))), {X/s(V),Y/s(V), W/s(V)} )
Giving a correct answer {X/s(V),Y/s(V), W/s(V)}
% you can also use W/Y

Example: MGU (and common confusion!)
these slides
https://cs.stackexchang e.com/questions/10967 3/how-can-i-compute- the-most-general- unifier-for-these-two- expressions
(After translating this into Prolog notation) How would you answer this query?
UOB Open

Translation: MGU (and common confusion!)
Given these two expressions
t1 = f(g(a,h(b)) , g(X,Y))
t2 = f(g(Z,Y), g(Y,Y))
a student computes their mgu as
= { Z/a, Y/h(b), X/h(b) }
but then suggests the following would be more general = { Z/a, Y/h(b), X/Y }
and finds this is actually what Prolog returns
https://cs.stackexchang e.com/questions/10967 3/how-can-i-compute- the-most-general- unifier-for-these-two- expressions
Which of these substitutions is a unifier and which is more general than the other? What mgu(s) are computed by our algorithm and what mistakes has the student made?
UOB Open

Solution: MGU (and common confusion!)
Given these two expressions
t1 = f(g(a,h(b)) , g(X,Y))
t2 = f(g(Z,Y), g(Y,Y))
a student computes their mgu as
= { Z/a, Y/h(b), X/h(b) }
but then suggests the following would be more general = { Z/a, Y/h(b), X/Y }
and finds this is actually what Prolog returns
is indeed an mgu (and is also returned by our alg.!)
is indeed more general than (strictly) as {Y/h(b)} =
but is not returned by our alg. (if you do not forget to compose subs.!) and is not a unifier as f(g(a,h(b)),g(Y,h(b))) f(g(a,h(b)),g(h(b),h(b)))
this actually means Prolog binds both X and Y to h(b) and Z to a!
UOB Open

Unification & Resolution: Example
for convenience: use . for [|]
length( .(a, .(b, .(c, []))) , N) length( .(H1, T1) , N1)
length( .(a, .(b, .(c, []))) , N) length( .(a, T1) , N1)
length( .(a, .(b, .(c, []))) , N) length( .(a, .(b, .(c, []))) , N1)
H1/a
H1/a, T1/[b,c]
H1/a, T1/[b,c], N1/N
Selected query literal
Selected clause variant
?- length([a,b,c], N).
length([H1|T1], N1) :- length(T1, M1), N1 is 1+M1.
?- length([a,b,c],N).
length([a,b,c], N) :- length([b,c],M1), N is 1+M1.
knowledge base
most general unifier (mgu)
{H1/a, T1/[b,c], N1/N}
UOB Open
resolvent
?- length([b,c], M1), N is 1+M1.
length([], 0).
length([_|T], N) :- length(T, M), N is 1+M.

Proof Tree: Example
?- length([a,b,c],N).
{H1/a, T1/[b,c], N1/N}
{H2/b, T2/[c], N2/M1}
{H3/c, T3/[], N3/M2}
{M3/0}
{M2/1}
{M1/2}
?- length([b,c],M1), N is 1+M1.
length([H1|T1],N1) :- length(T1,M1), N1 is 1+M1.
length([H2|T2],N2) :- length(T2,M2), N2 is 1+M2.
?- length([c],M2), M1 is 1+M2, N is 1+M1.
length([H3|T3],N3) :- length(T3,M3), N3 is 1+M3.
?- length([],M3), M2 is 1+M3, M1 is 1+M2, N is 1+M1.
?- M2 is 1+0, M1 is 1+M2, N is 1+M1.
?- M1 is 1+1, N is 1+M1.
?- N is 1+2.
length([],0).
UOB Open
{N/3} computed answer substitution empty clause
length([], 0).
length([_|T], N) :- length(T, M), N is 1+M.

Accumulators and Tail Recursion
You may have noticed the definition of length/2 on the previous slide results in an unnecessarily inefficient memory footprint (which is linear with respect to the length of the list) by gradually collecting together all of the is literals before actually starting to evaluate them (at least under Prologs default left-most selection strategy)
A deterministic tail recursive definition (like the original Haskell) will often be more memory efficient but that possibility was ruled out here due to the use of a moded arithmetic operator (which requires all its input arguments to be ground at the time of a call)
But, it is often relatively easy to obtain an efficient tail recursive Prolog definition using an auxiliary argument called an accumulator (which stores the intermediate result of the computation up until this point, starting from some initial given value)
% length(+List, -Len)
% Len is length of List
length([], 0).
length([_|T], N) :- length(T, M), N is 1+M.
% length(+List, +Acc, -Len)
% length(List, 0, Len) length(List, Len) length([], A, A).
length([_|T], A, N) :- M is 1+A, length(T, M, N).
UOB Open

?- length([a,b,c],0,N).
?- M1 is 1+0, length([b,c],M1,N).
Proof Tree: Revisited
{H1/a, T1/[b,c], A1/0, N1/N}
{M1/1}
{H2/b, T2/[c], A2/1, N2/N}
{M2/2}
{H3/c, T3/[], A3/2, N3/N}
{M3/3}
?- length([b,c],1,N).
length([H2|T2], A2, N2) :- M2 is 1+A2, length(T2, M2, N2).
M2 is 1+1, length([c],M2,N).
?- length([c],2,N).
M3 is 1+2, length([],M3,N).
?- length([],3,N).
length([H3|T3], A3, N3) :- M3 is 1+A3, length(T3, M3, N3).
length([], A4, A4).
UOB Open
{A4/3, N/3}
length([H1|T1], A1, N1) :- M1 is 1+A1, length(T1, M1, N1).
length([], A, A).
length([_|T], A, N) :- M is 1+A, length(T, M, N).

Memory Usage: Implications
UOB Open

library implementation: length (?List,?Len)
case handling
type checking
accumulator
fast list access (swiss army knife)
error handling
UOB Open

Shows search space reachable through backtracking
Nodes are queries: the root is the initial query and children are the resolvents of the parent on its first literal Leaves represent success branches (empty clause []) or failure branches with no resolvents (underlined )
A proof tree can be obtained for each success branch by reconstructing the resolved clauses and mgus
?-student_of(S,peter)
Search (SLD) Tree
student_of(X,T):-
follows(X,C),teaches(T,C).
follows(paul,computer_science).
follows(paul,expert_systems).
follows(maria,ai_techniques).
teaches(adrian,expert_systems).
teaches(peter,ai_techniques).
teaches(peter,computer_science).
:-follows(S,C),teaches(peter,C)
:-teaches(peter,computer_science) :-teaches(peter,ai_techniques) :-teaches(peter,ai_techniques)
:-teaches(peter,expert_systems)
UOB Open
[]
[]

Infinite Search Trees
brother_of(X,Y) :- brother_of(Y,X).
brother_of(paul,peter).
?-brother(peter,B)
:-brother(B,peter)
:-brother(peter,B) [] :-brother(B,peter)
brother_of(paul,peter).
brother_of(X,Y):-
brother_of(Y,X).
?-brother(peter,B)
:-brother(B,peter)
[] :-brother(peter,B) :-brother(B,peter)
brother(X,Y):- brother(X,Z),
brother(Z,Y).
:-brother(peter,B)
:-brother(paul,Z1),brother(Z1,Z),brother(Z,
[]
?-brother(paul,B)
[]
brother(paul,peter).
brother(peter,adrian).
[]
:-brother(paul,Z),brother(Z,B)

[]
:-brother(peter,Z),brother(Z,B)

UOB Open
B

Pruning the search with cut (!)
Sometimes we want to control which part of the SLD-tree is searched efficiency: to avoid searching a particular region
correctness: to avoid unwanted answers
Prolog offers a pruning mechanism called cut and written !
should primarily be used for efficiency reasons
for correctness, higher-level constructs such as not/1 and if-then-else are available (defined in terms of cut)
Cut and derived constructs are non-declarative, make programs harder to understand, and should be used judiciously!
UOB Open

The effect of cut
?- Q
?- p, S
?- L, !, R, S
?- !, R, S ?- R, S

p :- L, !, R
UOB Open
pruned by cut !

ASCII notation for SLD trees (in online exams)
?- precedes each goal, + is a choice point, X marks a subtree pruned by cut, # is a failure branch, : is an infinite branch, [] is a success branch, and {..} represents any computed answer):
?- goal.
|
?- resolvent.
|
++-X-. |||
?- branch_1 ?- branch_2 ?- branch_n |||
.!. |||
?- success ?- failure ?- infinite ||:
[] # :
{..}
UOB Open

[] {Z=5}
Example: max(+Int, +Int, ?Int)
?- max(3,5,Z).
|
+X. ||
?- 3=<5,!. ?- 3>5. ||
!# |
?- max(3,5,5).
|
+X. ||
?- 3=<5,!. ?- 3>5. ||
!# |
[]
?- max(3,5,3). ?- max(3,5,4). ||
?- 3>5. |
#
#
max(X,Y,Y) :- X= Y.
http://www.learnprolognow.org /lpnpage.php?pagetype=html& pageid=lpn-htmlse44
The cut can prune away some redundant failure branches, to give better computational efficiency
?- max(5,3,3). ||
+-. +-. ||||
?- 5=<3,!. ?- 5>3. ?- 5=<3,!. ?- 5>3. | | | |
# [] # [] {Z=5}
?- max(5,3,Z).
UOB Open

The cut-fail definition of negation
Negation-as-Failure can be defined in terms of cut as shown by the following definitions of the operators \+ and \+ which are both equivalent to Prologs built-in + operator:
:- op(900, fy, \+).
\+ X :- X, !, fail. \+ _.
:- op(900, fy, \+).
\+ X :- X, !, fail ; true.
UOB Open

UOB Open
P :- +q, r.
P :- q.
q.
r.
Example: negation as failure
?- p.
|
+. ||
?- +q, r. ?- q. ||
+X. [] ||
?- q, !, fail, r. ?- r. ||
?- !, fail, r. [] |
?- fail, r.
|
#

Vanilla meta-interpreter (using cut)
UOB Open
Implied by cuts !

Depth-bounded meta-interpreter
UOB Open

Interactive User Shell
UOB Open

Graph search
Many AI problems reduce to searching for goals in a graph structure
Search space is a graph, with partial solutions or states as nodes and possible transitions as arcs
search space may contain cycles
often approximated by a tree: easier algorithm, requires less memory, but is less efficient
because of repetitions
or can add loop detection by keeping a list of visited nodes
transitions may have costs associated with them
Blind search methods look for goals in a systematic way, but do not take the quality of partial solutions into account (e.g. using heuristics)
Backtracking search can be modelled with the notion of an agenda (which is simply a list of the nodes we plan to search next)
UOB Open

Agenda-based search
UOB Open
search(Agenda,Goal):-
next(Agenda,Goal,Rest),
goal(Goal).
search(Agenda,Goal):- next(Agenda,Current,Rest), children(Current,Children), add(Children,Rest,NewAgenda), search(NewAgenda,Goal).
This code makes an abstraction of the order in which search nodes are added and removed from the agenda
Given an Agenda, which is a set of nodes representing the frontier of the search process (initially set to start node), it will returns a Goal node accessible from those on the agenda

Depth-first vs Breadth-first
search_df([Goal|Rest],Goal):-
goal(Goal).
search_df([Current|Rest],Goal):-
children(Current,Children),
append(Children,Rest,NewAgenda),
search_df(NewAgenda,Goal).
search_bf([Goal|Rest],Goal):-
goal(Goal).
search_bf([Current|Rest],Goal):-
children(Current,Children),
append(Rest,Children,NewAgenda),
search_bf(NewAgenda,Goal).
children(Node,Children):- findall(C,arc(Node,C),Children).
in depth-first, children are added to front of agenda
in breadth-first, children are added to back of agenda
Note that next has been implicitly implemented here by simply taking the first goal from head of a list representing the agenda to leave rest in the tail
Note that in case of cyclic graphs, we may want to only take children weve not previously visited!
UOB Open

Depth-firstsearch
Memory Requirements
n=0
n=1 n=2
agenda = stack (last-in first-out)
incomplete: may get trapped in infinite branch n=3
no shortest-path property
requires O(Bn) memory
Breadth-firstsearch
agenda = queue (first-in first-out)
complete: will find all solutions
first solution found along shortest path
requires O(Bn) memory
n=0
B is branching factor (av. number of children) n is the depth
1+(B-1)n
n=1 n=2
n=3
UOB Open
Bn

Best-First Search
When adding children into the agenda, we want to order them with respect to some metric eval that tries to evaluate the quality of each node (in terms of how easily it might to lead to goal state). This is extra information known as a heuristic (function). If the heuristic estimates the distance to a goal, we put nodes with low scores fat the front of the agenda (a.k.a priority queue)
],Goal):
Current|Rest
Current,Children
add_bstf
search_bstf
Best-firstsearch
agenda = priority queue (preferentially ordered )
Behaviour depends on heuristic employed
Guarantee can be obtained if the heuristic satisfies certain properties
E.g. A* search always finds least cost paths using a monotonic heuristic
search_bstf
goal(Goal).
([
Goal|Rest

search_bstf
children(
([
],Goal):
),
(
Children,Rest,NewAgenda
(
), ).
NewAgenda,Goal
n=0
n=1 n=2
n=3
UOB Open

A Search
An A algorithm is a best-first search algorithm that aims at minimising the total cost along a path from start to goal.
estimate of total cost along path through n
f(n) = g(n) + h(n)
actual cost to reach n
from start
estimate of cost to reach goal from n
UOB Open

Global and local optimism
A heuristic
reaching a goal
estimate of cost to reach goal from n
is (
globally
the estimated cost of :
)
is always less than the actual
optimistic
or
cost
admissible
if
(from any node n)
h(n) h*(n)
actual (unknown) cost to reach goal from n
A heuristic is
decreases
h(n
(or
by more than the cost c of an edge from a node n
monotonic
locally optimistic
or
consistent
) 1
if
to a child n
it
never
: 2
e.g.
or Euclidean distance in grid world!
1
)

h(n
2
)c
Manhattan Distance
UOB Open

A* Algorithm
heuristic
first time a node is put on the agenda it is reached along the cheapest path

A* (A
star): an A algorithm with an

always reaches a goal along the cheapest path first
admissible out
assumes ties are ordered first

breadth

in first first is a special case
Monotonicity makes search more efficient

called monotonicity because f

in the absence of monotonicity, agenda may contain multiple copies of the same node reached along different paths
values are never decreasing along a path
UOB Open

Non-monotonic transition
A Non-Monotonic (but admissible) Heuristic
search graph (node-hScore) where all transitions have cost=1
A* agenda (node-fScore) [start-3]
[p-2, r-3] [q-2, r-3] [r-3, s-4] [s-3, s-4] [goal-3, s-4]
start:3 p:1
r:2
q-0
s:1
Non-optimal initial path to node s
UOB Open
goal:0

Path Finding (in grid world)
Breadth

First
Best

First
A* (Manhattan)
https://cs.stanford.edu/people/abisee/tutorial/astar.html
UOB Open

Path Finding (in grid world)
UOB Open
Example of path finding in a grid with walls (green Xs) from start in top left to goal in 4th row of last column where moves can be made immediately S, E, N, W (with any ties broken in that order). Numbers show the order in which cells are added to the agenda, computed path is shown in red

The Prolog and Search part of the exam will comprise
10 of 30 multiple choice questions (answer all)
1 of 3 long questions (answer 2) The exam will assume
a working knowledge of logic programs obtained by studying Chapters 1-6 & 10-11 of the recommended Learn Prolog Now! tutorial.
a familiarity with the relevant content in the slides and videos for the Prolog I-III lectures (including material in the relevant lab intros and Q&A sessions)
The multiple choice and long answer questions in the mock unit paper are all highly representative of the type and style of question in the real exam
A topic-by-topic breakdown of the examinable Prolog and Search material is now given
Examination Hints
UOB Open

Examinable Prolog Content
Lecture 1 Syntax of basic Prolog variables, atoms, compound terms, facts, rules and queries Lab/Q&A: Practice writing simple facts rules and queries involving simple terms and arithmetic operators NOTE: You should know that in the standard order of terms: VARs @< ATOMICs @< COMPOUNDs Lecture 2 – Semantics of basic Prolog – standard translation to FOL – but being aware of the non-classicality of negation as failure), list notation and the built-in predicates length, member, append, findall, bagof and setof – but you only need to know how to use them, not how they are implementedLab/Q&A: Practice writing more complex facts, rules and queries involving recursion and structured terms NOTE: You should understand reflexivity, irreflexivity, symmetry, transitivity and transitive closure Lecture 3 Proof theory of basic Prolog – bindings, substitutions, application, composition, unifiers, mgus, resolution, proof-trees, sld-trees, selection-rule, search-rule, computed-answer, cut, the “cut-fail” definition of negation as failure (you need to know the definitions be able to apply them, including computing mgus and drawing sld-trees with cuts and negationLab/Q&A: Practice writing programs with cuts and higher-order predicatesNOTE: You should be familiar with the basic argument modes indicators: +, – and ? UOB Open (Non-)Examinable Prolog Concepts EXAMINABLE OPERATORS: ( ) [ ] | [|] :- , ; . is + – * / = < @= @< ! + ^ PREDICATES: true, false, fail, length, member, append, findall bagof setof MODE IDICATORS: + – ? CONCEPTS: bindings, substitutions, application, composition, unifiers, mgus, resolution, proof-trees, sld- trees, selection-rule, search-rule, computer answer, cut, the “cut-fail” definition of negation as failureNON-EXAMINABLE OPERATORS: == =:= =@= #= ->
PREDICATES: forall, foreach, maplist, include, exclude, between, format, write, writeln, read, repeat
MODE IDICATORS: ++ @ : ! (https://www.swi-prolog.org/pldoc/man?section=preddesc)
CONCEPTS: accumulators, tail-recursion, failure-driven-loops, meta-interpreters, interactive-shells, user- defined-operators, debugger-commands
UOB Open

Examinable Search Content
Part 1 Blind Search agendas, depth-first-search, depth-bounded-search, breadth- first-search (you need to know their general properties, abstract data structures and be able to simulate their operation at a high-level, but you wont be asked to code them)
Part 2 Heuristic Search admissable heuristics, monotonic heuristics, Euclidean & Manhattan distance metrics in GridWorld-style problems, best-first-search, A*-search (you need to know their definitions and how to apply them within A* search)
UOB Open

UOB Open
Thank you

Reviews

There are no reviews yet.

Only logged in customers who have purchased this product may leave a review.

Shopping Cart
[SOLVED] flex database AI data structure Haskell algorithm interpreter prolog UOB Open
$25