Unit 5
Unit 5
Unit 5
5.1 Prolog
5.2 Abstract Data Types (ADTs) in Prolog
%%%%%%%%%%%%%%%%%%% stack operations %%%%%%%%%%%%%%%
%member(X,[X|T]).
%member(X,[Y|T]):-member(X,T).
empty_stack([]).
% S = [a,b,c,d]
% ?- stack(Top, _, [a,b,c]).
% Top = a
stack(E, S, [E|S]).
empty_queue([]).
% without removing it
empty_set([]).
member_set(E, S) :- member(E, S).
add_to_set(X, S, [X|S]).
remove_from_set(E, [E|T], T) :- !.
remove_from_set(E, T, T_new), !.
/*
union([], S, S).
union([H|T], S, S_new) :-
union(T, S, S2),
intersection([], _, []).
intersection([H|T], S, [H|S_new]) :-
member_set(H, S),
intersection(T, S, S_new),!.
intersection([_|T], S, S_new) :-
intersection(T, S, S_new),!.
*/
set_diff([], _, []).
set_diff([H|T], S, T_new) :-
member_set(H, S),
set_diff(T, S, T_new),!.
set_diff([H|T], S, [H|T_new]) :-
set_diff(T, S, T_new), !.
subset([], _).
subset([H|T], S) :-
member_set(H, S),
subset(T, S).
equal_set(S1, S2) :-
precedes(State, H).
insert_sort_queue(State, T, T_new).
go(Start, Goal) :-
empty_stack(Empty_been_list),
reverse_print_stack(Been_list).
mov(State, Next),
% not(unsafe(Next)),
not(member_stack(Next, Been_list)),
reverse_print_stack(S) :-
empty_stack(S).
reverse_print_stack(S) :-
reverse_print_stack(Rest),
write(E), nl.
go(Start, Goal) :-
empty_queue(Empty_open),
state_record(Start, nil, State),
add_to_queue(State, Empty_open, Open),
empty_set(Closed),
path(Open, Closed, Goal).
path(Open,_,_) :- empty_queue(Open),
write('graph searched, no solution found').
printsolution(State_record, _):-
state_record(State,nil, State_record),
write(State), nl.
printsolution(State_record, Closed) :-
state_record(State, Parent, State_record),
state_record(Parent, Grand_parent, Parent_record),
member(Parent_record, Closed),
printsolution(Parent_record, Closed),
write(State), nl.
go(Start, Goal) :-
empty_set(Closed),
empty_sort_queue(Empty_open),
heuristic(Start, Goal, H),
state_record(Start, nil, 0, H, H, First_record),
insert_sort_queue(First_record, Empty_open, Open),
path(Open,Closed, Goal).
path(Open,_,_) :-
empty_sort_queue(Open),
write("graph searched, no solution found").
% moves generates all children of a state that are not already on open or closed. The only %
wierd thing here is the construction of a state record, test, that has unbound variables in % all
positions except the state. It is used to see if the next state matches something % already on
open or closed, irrespective of that states parent or other attributes Also,I've % commented out
unsafe since the way I've coded the water jugs problem I don't really % need it.
insert_list([], L, L).
printsolution(Next_record, _):-
state_record(State, nil, _, _,_, Next_record),
write(State), nl.
printsolution(Next_record, Closed) :-
state_record(State, Parent, _, _,_, Next_record),
state_record(Parent, Grand_parent, _, _, _, Parent_record),
member_set(Parent_record, Closed),
printsolution(Parent_record, Closed),
write(State), nl.
solve(Goal):-call(Goal).
Note, that vanilla meta-interpreter uses build-in predicate clause(H,B) which finds a
clause in Prolog program with head that unifies with H and body B (if there is no body, then
Body=true). The modified vanilla meta-interpreter can be used to compute "proof" of the
computation:
solve(true, fact).
solve((A,B),(ProofA, ProofB)):-
solve(A, ProofA),solve(B, ProofB).
solve(A, A-ProofB):-
clause(A,B),solve(B, ProofB).
It is also possible to write a meta-interpreter that uses list of goals instead of traditional
conjunction of goals. In some cases, this could be more natural as one does not need to traverse
the structure of goal each time a primitive goal is being found.
solve([]).
solve([A|T]):-
clause(A,B),
add_to_list(B,T,NT),
solve(NT).
A clause such as: gp(X, Y) :- p(X, Z) , p(Z, Y). can be interpreted as data, where :- and ,
are just infix binary constructors. Also
Proof = (gp(bob,sue) :-
(p(bob,mary) :-
(m(bob,mary) :- true)),
(p(mary,sue) :-
(m(mary,sue) :- true)))
?- why(gp(bob,sue)).
gp(bob,sue) is true
because p(bob,mary) is true
because m(bob,mary) is true
because p(mary,sue) is true
because m(mary,sue) is true
yes
A Simple Meta-interpreter
solve(true) :-!.
solve(not A) :- not(solve(A)).
q(X) :- s(X).
r(X) :- t(X).
s(a).
t(b).
t(c).
test1 :- solve(p(a,b)).
test2 :- solve(p(X,Y)).
test3 :- solve(p(f,g)).
solve(not A) :- not(solve(A)).
solve(A) :- askuser(A).
askuser(A):- write(A),
nl, read(true).
q(X) :- s(X).
r(X) :- t(X).
s(a).
t(b).
t(c).
test1 :- solve(p(a,b)).
test2 :- solve(p(X,Y)).
test3 :- solve(p(f,g)).
1. What is matching?
2. What are abstract data types?
3. With an example, explain how facts are represented in prolog?
4. Explain how frames can be represented in prolog?
5. Explain the use of assert and been predicate in prolog?
Answer:
Predicates
Clauses with the same clause name, the same number of arguments and defined in the
same module are combined in the database and form the definition of a predicate. The common
clause name is called the predicate name or functor of the predicate. The number of arguments
is the arity. For example, the predicate fac/2 is defined by the collection of all clauses with the
clause head fac(Arg1,Arg2), where Arg1 and Arg2 may be any terms.
The separate clauses of a predicate are connected by disjunction, i.e. by inclusive OR.
Clauses with the same clause name but a different number of arguments belong to different
predicates. Likewise, clauses which have the same clause name and the same arity but are
associated with different modules belong to different predicates.
Only predicates whose clauses have been included in the database with consult/1, reconsult/1 or
with an assert predicate can be modified, i.e. clauses can be added (assert predicates) or removed
(retract predicates), individual predicates can be deleted (abolish/1) or replaced (reconsult/1).
Assert is used to add a new predicate to the current database. Been predicate is used to record
previously visited states and avoid loops.
The clauses of these predicates can be output with listing/0/1 and analyzed with clause
predicates. Note however that to do so you must call the Prolog system with the -debug option.
Compiled predicates
Whenever references are made in this manual to compiled predicates they should be
taken to mean predicates which cannot be decompiled. These can no longer be modified by
simply adding or removing clauses.
12-mark questions
Answer:
A knight can move two squares either horizontally or vertically followed by one square
in an orthogonal direction as long as it does not move off the board. The attempt is to find a
series of legal moves in which the knight lands on each square of the chessboard exactly
once.
1 2 3
4 5 6
7 8 9
:- dynamic been/1.
path(Z,Z).
path2(Z,Z,Been).
path3(Z,Z,Been).
move(1,6).
move(1,8).
move(2,7).
move(2,9).
move(3,4).
move(3,8).
move(4,3).
move(4,9).
move(6,7).
move(6,1).
move(7,6).
move(7,2).
move(8,3).
move(8,1).
move(9,4).
move(9,2).
7) Write the prolog code for the wolf, goat, and cabbage problem.
Answer:
This is an example of a production system in Prolog. A farmer with his wolf, goat, and
cabbage come to the edge of a river they wish to cross. There is a boat at the river's edge, but,
of course, only the farmer can row. The boat also can carry only two things (including the
rower) at a time. Devise a sequence of crossings of the river so that all four arrive safely on
the other side of the river. Remembering that If the wolf is ever left alone with the goat, the
wolf will eat the goat. Similarly, if the goat is left alone with the cabbage, the goat will eat
the cabbage.
/*
* This is the code for the Farmer, Wolf, Goat and Cabbage Problem
* using the ADT Stack.
*
* Run this code by giving PROLOG a "go" goal.
* For example, to find a path from the west bank to the east bank,
* give PROLOG the query:
*
* go(state(w,w,w,w), state(e,e,e,e)).
*/
go(Start,Goal) :-
empty_stack(Empty_been_stack),
stack(Start,Empty_been_stack,Been_stack),
path(Start,Goal,Been_stack).
/*
* Path predicates
*/
path(Goal,Goal,Been_stack) :-
write('Solution Path Is:' ), nl,
reverse_print_stack(Been_stack).
path(State,Goal,Been_stack) :-
move(State,Next_state),
not(member_stack(Next_state,Been_stack)),
stack(Next_state,Been_stack,New_been_stack),
path(Next_state,Goal,New_been_stack),!.
/*
* Move predicates
*/
move(state(X,X,G,C), state(Y,Y,G,C))
:- opp(X,Y), not(unsafe(state(Y,Y,G,C))),
writelist(['try farmer takes wolf',Y,Y,G,C]).
move(state(X,W,X,C), state(Y,W,Y,C))
:- opp(X,Y), not(unsafe(state(Y,W,Y,C))),
writelist(['try farmer takes goat',Y,W,Y,C]).
move(state(X,W,G,X), state(Y,W,G,Y))
:- opp(X,Y), not(unsafe(state(Y,W,G,Y))),
writelist(['try farmer takes cabbage',Y,W,G,Y]).
move(state(X,W,G,C), state(Y,W,G,C))
:- opp(X,Y), not(unsafe(state(Y,W,G,C))),
writelist(['try farmer takes self',Y,W,G,C]).
move(state(F,W,G,C), state(F,W,G,C))
:- writelist([' BACKTRACK from:',F,W,G,C]), fail.
/*
* Unsafe predicates
*/
unsafe(state(X,Y,Y,C)) :- opp(X,Y).
unsafe(state(X,W,Y,Y)) :- opp(X,Y).
/*
* Definitions of writelist, and opp.
*/
writelist([]) :- nl.
opp(e,w).
opp(w,e).
reverse_print_stack(S) :-
empty_stack(S).
reverse_print_stack(S) :-
stack(E, Rest, S),
reverse_print_stack(Rest),
write(E), nl.
State