prolog for linguists symbolic systems 139p/239p john dowding week 3, october 22, 2001

Post on 06-Jan-2018

216 Views

Category:

Documents

2 Downloads

Preview:

Click to see full reader

DESCRIPTION

Office Hours We have reserved 4 workstations in the Unix Cluster in Meyer library, fables 1-4 Skipping 4:30-5:30 on Thursday this week Friday 3:30-4:30, after NLP Reading Group this week If not, contact me and we can make other arrangements

TRANSCRIPT

Prolog for LinguistsSymbolic Systems 139P/239P

John DowdingWeek 3, October 22, 2001

jdowding@stanford.edu

Course web page

http://www.stanford.edu/class/symbsys139p

programs used in class power point slides homework assignments, solutions

This gets updated by Tuesday night after Monday’s class.

Office Hours

We have reserved 4 workstations in the Unix Cluster in Meyer library, fables 1-4Skipping 4:30-5:30 on Thursday this week

Friday 3:30-4:30, after NLP Reading Group this week If not, contact me and we can make other arrangements

Course Schedule

1. Oct. 82. Oct. 153. Oct. 224. Oct. 29 (double up)5. Nov. 56. Nov. 127. Nov. 26 (double up)8. Dec. 3

No class on Nov. 19

Prolog Execution Model/Prolog Debugger

CALL EXIT

FAIL REDO

Linked Lists

Prolog allows a special syntax for lists: [a,b,c] is a list of 3 elements [] is a special atom indicating a list with 0 elements

Internally, Prolog lists are regular Prolog terms with the functor ‘.’ (so called “dotted pairs”)[a,b,c] = ‘.’(a, ‘.’(b, ‘.’(c, []))).The symbol | in a list indicates “rest of list”, or the term that is the 2nd argument of a dotted pair.[a,b,c] = [a|[bc]].[Head|Tail] is a common expression for dividing a list into its first element (Head) and the rest of the list (Tail).

Homework

Read section in Sicstus Prolog manual on debugger.Use debugger to trace through today’s example programs and understand how the work.Implement: delete_all(+Element, +List, -NewList) that removes all

occurrences of Element from List to find NewList. replace_all(+Element, +List, +NewElement, -NewList) replaces

every occurrence of Element with NewElement in List to give NewList.

Homework: delete_all/3

%delete_all(+Element, +List, -NewList)delete_all(_Element, [], []).delete_all(Element, [Element|List], NewList) :- !, delete_all(Element, List, NewList).delete_all(Element, [Head|List], [Head|NewList]) :- delete_all(Element, List, NewList).

Homework: replace_all/4

%replace_all(+Element, +List, +NewElement, -NewList)replace_all(_Element, [], _NewElement, []).replace_all(Element, [Element|List], NewElement, [NewElement|

NewList]) :- !, replace_all(Element, List, NewElement, NewList).replace_all(Element, [Head|List], NewElement, [Head|NewList]) :- replace_all(Element, List, NewElement, NewList).

“Pure Prolog” and non-logical built-ins

All the examples so far have been “pure Prolog” Contain no built-ins with non-logical side-effects

Prolog has many built-in predicates that have such side-effects: Type checking of terms Arithmetic Control execution Input and output Modify the program during execution Perform aggregation operations

Use of non-logical built-in predicates usually effects the reversability of your program.

Type-checking Built-in Predicates

var(X) – is true when X is an uninstantiated variable.nonvar(X) – is true when X is not a variable.atom(X) – is true when X is a symbolic constant.number(X) – is true when X is a numberatomic(X) – is true when atom(X) or number(X).compound(X) – is true when X is a compound term.

Term constructor/selectors: functor/3, arg/3

functor(+Term, ?Functor, ?Arity) Find the Functor and Arity of Term

functor(?Term, +Functor, +Arity) Constructs a new Term with Functor and Arity

arg(+N, +Term, ?SubTerm) Unifies SubTerm with the Nth argument of Term

Arithmetic: Built-In is/2

Arithmetic expressions are not normally evaluated in Prolog.Built-In infix operator is/2 evaluates it’s 2nd argument, and unifies the result with it’s 1st argument.| ?- X = 5 + 2.X = 5+2?yes| ?- X is 5 + 2.X = 7 ?yes

Any variables in the right-hand side of is/2 must be instantiated when it is evaluated.

Revisit operator and arithmetic at a later time

Cut (!)

The ! Symbol (pronounced “cut”) modifies the execution of your program by committing to certain choices. That is, it removes choice points.

Removes any choice points that have been created since the predicate was invoked.Easy to describe what it does, more difficult to get used to using it properly.

Cut (cont.)

Head1 :- Goal1, Goal2, …, GoalN, !, …Head2 :- …Head3 :- ……HeadN :- …

Removes the choice point that allows Head2 …HeadNRemoves any choice points that may have been introduced in Goal1 … GoalN.We will discuss Cut in more detail later on.

Example: is_term/1

is_term(Atomic) :- atomic(Atomic).is_term(Variable):- var(Variable).is_term(CompoundTerm):-

compound(CompoundTerm), functor(CompoundTerm, _Functor, Arity).

is_term_helper(Arity, CompoundTerm).

is_term_helper(0, _CompoundTerm) :- !

is_term_helper(Index, CompoundTerm):-arg(Index, CompoundTerm, SubTerm),is_term(SubTerm),NextIndex is Index – 1,is_term_helper(NextIndex, CompoundTerm).

Built-Ins: Term Comparison Operators

Unifies with Term1 = Term2 iff unifies Term1 and Term2 if they are unifiable

Does not unify with Term1 \= Term2, Term1 and Term2 are unchanged

Identical Term1 == Term2 iff are the same terms

Not identical Term1 \== Term2

Example: unify/2 (without occurs check)

unify(Var1, Term2):- var(Var1), !, Var1 = Term2.unify(Term1, Var2):- var(Var2), !, Var2 = Term1.unify(Atomic1,Atomic2):-

atomic(Atomic1), atomic(Atomic2),!,Atomic1 == Atomic2.

unify(Term1, Term2):-compound(Term1),compound(Term2),functor(Term1, Functor, Arity),functor(Term2, Functor, Arity),unify_helper(Arity, Term1, Term2).

Example: unifiable/2 (continued)

unify_helper(0, _Term1, _Term2):-!.

unify_helper(Index, Term1, Term2):-arg(Index, Term1, Arg1),arg(Index, Term2, Arg2),unify(Arg1, Arg2),NextIndex is Index – 1,

unify_helper(NextIndex, Term1, Term2).

Example: identical/2

identical(Var1, Var2):- var(Var1), var(Var2),!, Var1 == Var2.

identical(Atomic1,Atomic2):- atomic(Atomic1), atomic(Atomic2),!, Atomic == Atomic2.

identical(Term1, Term2):-compound(Term1),compound(Term2),functor(Term1, Functor, Arity),functor(Term2, Functor, Arity),identical_helper(Arity, Term1, Term2).

Example: identical/2 (continued)

identical_helper(0, _Term1, _Term2):-!.

identical_helper(Index, Term1, Term2):-arg(Index, Term1, Arg1),arg(Index, Term2, Arg2),identical(Arg1, Arg2),NextIndex is Index – 1,

identical_helper(NextIndex, Term1, Term2).

Unification

Two terms unify iff there is a set of substitutions of variables with terms that makes the terms identicalTrue unification disallows cyclic terms: X=f(X) ought to fail because there is no finite term that can substitute for

X to make those terms identical. This is called the occurs check.

Prolog unification does not enforce the occurs check, and may create cyclic termsOccurs check is expensive O(n) – n is the size of the smaller of the two terms O(n+m) – n and m are the sizes of the two terms In Prolog, it is quite typical to unify a variable with a larger term

Built-ins: true/0 and fail/0.

true. Always succeeds.

fail. Always fails.

Meta-Predicates: call/1, \+/1

Meta-predicates take a Goal as an argument, and execute it.call/1 executes it’s one argument.\+(Goal) succeeds if call(Goal) fails.\+/1 could also be defined using cut and fail.

\+(Goal) :- call(Goal), !, fail.\+(_Goal).

Example: select/3

% select(+List, +Condition, -Element)

select(List, Condition, Element):-member(Element, List),call(Condition).

This might be called with something like: select([a, 5, c, 7], integer(Element), Element) select([1,2,3,4,5,6,7], Element < 5, Element). select([1,2,3,4,5,6,7], (0 is Element mod 2), Element)

More on non-logical predicates

\+ Goal is true if Goal fails. \=, \==, and \+ introduce negation-as-failure Not true negation, but failure-to-prove

A little bit of ‘non logical’ takes you a long way

Another way to write delete_all/3

delete_all(_Element, [], []).delete_all(Element, [Element|List], NewList) :- delete_all(Element, List, NewList).delete_all(Element, [Head|List], [Head|NewList]) :- Element \== Head, delete_all(Element, List, NewList).

Accumulators

Build up partial results to return at the end

list_length([], 0).list_length([_Head|Tail], Result):-

list_length(Tail, N),Result is N +1.

list_length(List, Result) :- list_length_helper(List, 0, Result).

list_length_helper([], Result, Result).list_length_helper([_Head|Tail], Partial, Result):-

NextPartial is Partial + 1,list_length_helper(Tail, NextPartial, Result).

Acccumulators: efficient reverse/3

% reverse(+List, -ReversedList)reverse(List, ReversedList):- reverse_helper(List, [], ReversedList).

reverse_helper([], ReversedList, ReversedList).reverse_helper([Head|Tail], PartialList, ReversedList):- reverse_helper(Tail, [Head|PartialList], ReversedList).

Difference Lists

Use two logical variables that point to different portions of the same list.

Compare stacks with queues:

Stacks

% empty_stack(?Stack) – true if Stack is emptyempty_stack([])

% push(+Item, +Stack, -NewStack) push(Item, Stack, [Item|Stack]).

%pop(+Stack, -Item, -NewStack)pop([Item|NewStack], Item, Stack).

Queues

Queue represented as a pair of lists (Front-Back)Back is always a variable

%empty_queue(?Queue) – true if the queue is emptyempty_queue(Queue-Queue).

%add_to_queue(+Element, +Queue, -NewQueue)add_to_queue(Element, (Front-[Element| Back]), (Front-Back)).

%remove_from_queue(+Queue, -Element, -NewQueue)remove_from_queue(([Element|Front]-Back), Element, (Front-Back)).

Appending Difference Lists

Appending difference lists is very efficientappend_dl((Front-Next), (Next-Back), (Front-Back)).

These uses of difference lists are incomplete data structures Differenced lists are also useful as complete data structures

Considering using difference lists is situations where you might otherwise be doing a lot of appends.

Generate-and-Test

Popular (and sometimes efficient) way to write a program.

Goal :-Generator, - generates candidate solutionsTester. - verifies correct answers

Example: select/3

% select(+List, +Condition, -Element)

select(List, Condition, Element):-member(Element, List), - generates potential solutionscall(Condition). - verifies that the meet the condition

•Example: slow_sort/2

% slow_sort(+List, -SortedList)slow_sort(List, PermutedList):-

permute(List, PermutedList),is_sorted(PermutedList).

%permute(+List, -Permutation)permute([], []).permute([Head|Tail], Permutation):-

permute(Tail, PermutedTail),insert(Head, PermutedTail, Permutation).

Example: slow_sort/2 (cont.)

% insert(+Element, +List, -BiggerList)insert(Element, List, [Element|List]).insert(Element, [Head|List], [Head|BiggerList]):-

insert(Element, List, BiggerList).

% is_sorted(+List)is_sorted([]).is_sorted([_OneElement]).is_sorted([FirstElement, SecondElement|Tail]):-

FirstElement =< SecondElement,is_sorted([SecondElement|Tail]).

Example: NPR Puzzle

Sunday morning’s weekly puzzle on KQED this weekUsing a grid with 4 columns and 3 rows, find 3 four-letter words (along the rows) and 4 three-letter words (along the columns) that Are all common words of English Use each letter only once Include all 6 vowels (a, e, i, o, u, y)

Assume two predicates: three_letter_word(+First, +Second, +Third). four_letter_word(+First, +Second, +Third, +Fourth).

NPR Puzzle (cont)

npr_puzzle:- choose_four_letter_words([A,B,C,D,

E,F,G,H, I,J,K,L]),

test([A,B,C,D, E,F,G,H, I,J,K,L]).

write(A),write(B),write(C),write(D),nl, write(E),write(F),write(G),write(H),nl, write(I),write(J),write(K),write(L),nl, nl, fail.

NPR Puzzle (cont)

choose_four_letter_words([A,B,C,D, E,F,G,H, I,J,K,L]):-

four_letter_word(A,B,C,D), four_letter_word(E,F,G,H), unique_letters([E,F,G,H], [A,B,C,D]), four_letter_word(I,J,K,L), unique_letters([I,J,K,L], [A,B,C,D,E,F,G,H]).

unique_letters([], _).unique_letters([A|Rest], Letters):- \+ member(A, Letters), unique_letters(Rest,Letters).

NPR Puzzle (cont)

test([A,B,C,D, E,F,G,H, I,J,K,L]):- three_letter_word(A,E,I), three_letter_word(B,F,J), three_letter_word(C,G,K), three_letter_word(D,H,L), uses_all_vowels([A,B,C,D,

E,F,G,H, I,J,K,L]),

NPR Puzzle (cont)

uses_all_vowels(Letters):- member(a, Letters), member(e, Letters), member(i, Letters), member(o, Letters), member(u, Letters), member(y, Letters).

NPR Puzzle Results

After some futzing to get good lists of 3 and 4 letter words,and about 4 CPU hours, we get one solution:

peasomitduly

Homework

By now, we have covered most of Chapters 3 and 4 of Clocksin and Mellish. Read them and let me know if you have any questions.Homework to be handed in by noon on the 29th.

top related