1 / 39

Prolog for Linguists Symbolic Systems 139P/239P

Prolog for Linguists Symbolic Systems 139P/239P. John Dowding Week 10, December 3, 2001 jdowding@stanford.edu. Iterative Deepening. Addresses depth-first run-away Or exploring an infinite part of the search tree first If the program has a solution, ID will help you find it

diamond
Download Presentation

Prolog for Linguists Symbolic Systems 139P/239P

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Prolog for Linguists Symbolic Systems 139P/239P John Dowding Week 10, December 3, 2001 jdowding@stanford.edu

  2. Iterative Deepening • Addresses depth-first run-away • Or exploring an infinite part of the search tree first • If the program has a solution, ID will help you find it • Puts a depth bound on the computation • Increases depth bound when no solutions are found

  3. Iterative Deepening Pure Prolog Interpreter • We can solve this in a general way by writing a specialized Prolog interpreter in Prolog. • Using a new Prolog built-in clause/2: • clause(Goal, Body) When (Goal :- Body) is in the Prolog database, and is declared dynamic. • The Body for a fact is defined to be true. • For now, we will only worry about interpreting pure Prolog, no Prolog built-ins or cut.

  4. id_call/[1,3] id_call(Goal):- start(Start), increment(Increment), id_call(Goal, Start, Increment). id_call(Goal, Bound, Increment):- retractall(more_search), id_interpret(Goal, Bound, Remaining), Remaining < Increment. id_call(Goal, Bound, Increment):- more_search, NextBound is Bound + Increment, id_call(Goal, NextBound, Increment).

  5. id_interpret/3 id_interpret(_Goal, 0, _Remaining):- !, assert_once(more_search), fail. id_interpret(true, Bound, Remaining):- !, Remaining is Bound - 1. id_interpret((Goal1,Goal2), Bound, Remaining):- !, Bound1 is Bound - 1, id_interpret(Goal1, Bound1, Bound2), id_interpret(Goal2, Bound2, Remaining). id_interpret(Goal, Bound, Remaining):- NextBound is Bound - 1, clause(Goal, Body), id_interpret(Body, NextBound, Remaining).

  6. Iterative Deepening Translator • Turn something like this: • Into something like this:

  7. Turn something like this: is_number(0). is_number(s(Number)):- is_number(Number). Into something like this: is_number(_, 0, _):- !, assert_once(more_search), fail. is_number(0, Bound, RestBound):- RestBound is Bound – 1. is_number(s(Number), Bound, RestBound):- NextBound is Bound – 1, is_number(Number, NextBound, RestBound). Iterative Deepening Translator

  8. Iterative Deepening Translator (cont) id_consult_term((NT --> Rule)):- !, grammar_rule_body(Rule, Body, Start, End), make_nonterminal(NT, Start, End, Goal), id_consult_term((Goal :- Body)). id_consult_term((:- Goal)):- !, call(Goal). id_consult_term((Goal :- Body)):- !, id_add_base_clause(Goal), make_id_goal(Goal, NewGoal, Bound, RemainingBound), id_consult_body(Body, NewBody, NextBound, RemainingBound), assertz((NewGoal :- (NextBound is Bound - 1, NewBody))). id_consult_term(Fact):- id_add_base_clause(Fact), make_id_goal(Fact, NewGoal, Bound, RemainingBound), assertz((NewGoal :- (RemainingBound is Bound - 1))).

  9. Iterative Deepening Translator (cont) id_consult_body((Body1, Body2), (NewBody1,NewBody2), Bound, RemainingBound):- !, id_consult_body(Body1, NewBody1, Bound, NextBound), id_consult_body(Body2, NewBody2, NextBound, RemainingBound). id_consult_body(Goal, NewGoal, Bound, Remaining):- make_id_goal(Goal, NewGoal, Bound, Remaining).

  10. id_add_base_clause/1 id_add_base_clause(Goal):- functor(Goal, Functor, Arity), NewArity is Arity + 2, functor(BaseGoal, Functor, NewArity), BoundArg is Arity + 1, arg(BoundArg, BaseGoal, 0), BaseBody = (!, assert_once(more_search), fail), \+ clause(BaseGoal, BaseBody), !, asserta((BaseGoal :- BaseBody)). id_add_base_clause(_Goal).

  11. make_id_goal/4 make_id_goal(Goal, NewGoal, Bound, Remaining):- functor(Goal, Functor, Arity), NewArity is Arity + 2, functor(NewGoal, Functor, NewArity), BoundArg is Arity + 1, arg(BoundArg, NewGoal, Bound), arg(NewArity , NewGoal, Remaining), copy_n_args(Arity, Goal, NewGoal). copy_n_args(0, _Goal, _NewGoal):- !. copy_n_args(Index, Goal, NewGoal):- arg(Index, Goal, Arg), arg(Index, NewGoal, Arg), NextIndex is Index - 1, copy_n_args(NextIndex, Goal, NewGoal).

  12. Could have just used make_nonterminal/4 • Missed opportunity for generalization… % this is the lazy way to do this using univ. make_nonterminal(NT, Start, End, Goal):- NT =.. List, append(List, [Start,End], FullList), Goal =.. FullList.

  13. id_call/1 id_call(Goal):- start(Start), increment(Increment), make_id_goal(Goal, NewGoal, Bound, Remaining), id_call(NewGoal, Start, Bound, Remaining, Increment). id_call(Goal, Bound, Bound, Remaining, Increment):- retractall(more_search), call(Goal), Remaining < Increment. id_call(Goal, CurrentBound, Bound, Remaining, Increment):- more_search, NextBound is CurrentBound + Increment, id_call(Goal, NextBound, Bound, Remaining, Increment).

  14. Logic and Prolog • Review Propositional and Predicate Logic • Introduce Clausal Form • Resolution Rule and Theorem Proving • This material is from Ch. 10 in Clocksin and Mellish

  15. Clausal Form and Prolog (A1  A2  … An) :- (B1  B2  … Bm) • Prolog is restricted to clauses where N <= 1. • That is, Prolog cannot prove disjunctions • When M=0, we call this a fact. • When N=0, we call this a goal. • If M=0 and N=0, we have an empty clause, which is false. • The restriction to definite clauses means Prolog cannot represent all first order theories. • But, definite clauses are still powerful enough to prove theorems about all computable functions.

  16. Prolog and Theorem Proving • Suppose that we want to prove that a formula B is a logical consequence of a consistent set of clauses S: S = {A1 … AN} • Then, adding B to S should make it inconsistent S’= {A1 … AN, :- B} • This is how Prolog proves theorems, it adds the negation of the Goal to the set of clauses, and proves that it is inconsistent.

  17. Resolution Rule for Predicate Logic If Ai unifies with Ai’, yielding the substitution function  A1 …Ai AN  A B1 … BN  Ai’ (A1 … B1 … BN … AN  A)

  18. Prolog Theorem Proving • Prolog uses a restricted form of the Resolution Rule as it’s only inference rule • Starting with a Goal (a disjunction of negative literals) :- B1 … BN • One application of the resolution rule to the left-most negative literal, and a rule of the form B1’ :- C1 … CM, where B1 unifies with B1’, with substitution  • Yields :-  (C1 … CM B2 … BN) • This continues until the the empty clause (false) is derived • The history of substitution functions is used to produce an “answer”, effectively a counter-example to the claim that B1 … BN is inconsistent.

  19. DCG with yes/no and wh- questions • Yes/no questions feature AUX-inversion Does John like Molly? • The AUX (do, be, can, have, will, etc.) moves before the subject, but still has to agree in number and person: Does he like Molly? Do you like Molly? Do they like Molly? Does the woman like Molly? Do the women like Molly? • We will add a force marker (decl, ynq, whq) to our QLFs.

  20. Yes/no Questions s_base(GapsIn, GapsOut, [decl, QLF]) --> declarative_sentence(GapsIn, GapsOut, QLF). s_base(GapsIn, GapsOut, [ynq, QLF]) --> yes_no_question(GapsIn, GapsOut, QLF). yes_no_question(GapsIn, GapsOut, QLF) --> aux(Person, Number, _Tense), np(nom, Person, Number, GapsIn, GapsNext, NP, NPVar), vp(_, _, GapsNext, GapsOut, NPVar, VP), {conjoin(NP, VP, QLF)}.

  21. Wh-question • One way to analyse wh-questions is as a wh-noun phrase followed by a sentence containing a gap: Who likes Molly? Who does Molly like? • English requires the AUX to be inserted for non-subject gaps: Who likes Molly? Who does Molly like? *Who Molly likes?

  22. Wh-questions wh_question(GapsIn, GapsOut, QLF) --> wh_np(Person, Number, NP, NPVar), yes_no_question([np_gap(_Case, Person, Number, NPVar)|GapsIn], GapsOut, YNQQLF), {conjoin(NP, YNQQLF, QLF)}. wh_question(GapsIn, GapsOut, QLF) --> wh_np(Person, Number, NP, NPVar), declarative_sentence([np_gap(nom, Person, Number, NPVar)|GapsIn], GapsOut, DeclQLF), {conjoin(NP, DeclQLF, QLF)}.

  23. Wh-NPs (cont) • I got lazy on the different forms of wh- NPs wh_np(third, singular, qterm(wh, NPVar, who), NPVar) --> [who]. wh_np(third, singular, qterm(wh, NPVar, what), NPVar) --> [what].

  24. Other things to talk about? • Any other questions? • Prolog compilation • 1st argument indexing • Prolog Modules • Prolog Libraries • Or, if-then, if-then-else • statistics[0,2], and how to time things

  25. Prolog compilation • Modern Prolog implementions use the Warren Abstract Machine (WAM) • Invented by David Warren, one of the founders of Quintus • Combines to a portable byte-code, which is then interpreted • Some implementations (like sometimes SICStus) compile down to native code. • All modern Prolog implementations support first-argument indexing.

  26. 1st Argument indexing • Prolog treats the 1st argument to a predicate specially • Uses the functor, and arity of the 1st argument term to index the predicate • If you are expecting a particular argument position to be an input position, • And that argument differentiates the clauses of the predicates, • Then make that the 1st argument

  27. 1st Argument Indexing • Consider: list_length([], 0). list_length([_Head|Tail], N):- list_length(Tail, PartialN), N is N + 1. • And, member(Element, [Element|_List]). member(Element, [_Head|List]):- member(Element, List).

  28. 1st Argument Indexing (cont) n(bed, singular, bed(X), X). n(beds, plural, bed(X), X). n(book, singular, book(X), X). n(books, plural, book(X), X). n(cat, singular, cat(X), X). n(cats, plural, cat(X), X). n(desk, singular, desk(X), X). n(desks, plural, desk(X), X). n(dog, singular, dog(X), X). n(dogs, plural, dog(X), X).

  29. Prolog Modules • Keeps Prolog predicates in separate name spaces • File based • Optional • By default, predicates are in the module user. • Directives to define a module: :- module(ModuleName, PredicateList). defines a Module with a set of Public predicates • Directives to access predicates from another module: :- use_module(ModuleName). :- use_module(ModuleName, [Pred1/Arity1, …, PredN/ArityN]).

  30. Modularized Tokenizer • Add to the top of tokenizer.pl (before any predicates): :- module(tokenizer, [tokenize_file/2, tokenize/2]). • To use it in grammar.pl: :- use_module(tokenizer, [tokenize/2]).

  31. Prolog Libraries • Prolog has a large set of library predictes • All are defined using the Module system • The libraries are not defined in the Prolog library, and will vary significantly between Prolog versions • So, using libraries will make your Program less portable • Access a library with use_module :- use_module(library(ModuleName)). :- use_module(library(ModuleName), PredicateList).

  32. Using library(lists) At the top of assignment.pl: :- use_module(library(lists),[append/3]).

  33. Special Syntax: or • Or uses the syntax (Goal1 ; Goal2)and creates a new choice point. • Defined as though: (Goal1 ; _Goal2) :- call(Goal1). (_Goal1 ; Goal2):- call(Goal2). • Except that cuts in Goal1or Goal2are transparent through the ;/2. • Use these carefully because they can make your programs hard to read and understand.

  34. Special Syntax: if-then • If-then uses the special syntax (Condition -> Goal) • Defined as though: (Condition -> Goal) :- call(Condition), !, call(Goal). • Except that any cuts in Condition or Goal are transparent through ->/2. • This is sometimes used for it’s little cut of any choice points in the Condition (called a snip). • This is not logical if-then, since if Condition fails, then (Condition ->Goal) fails.

  35. Special Syntax: if-then-else • If-then-else uses the special syntax: (Condition -> Goal1; Goal2) • Defined as though: (Condition ->Goal1; _Goal2) :- call(Condition), !, call(Goal1). (_Condition ->_Goal1; Goal2) :- call(Goal2). • Except that cuts in Condition, Goal1, and Goal2 are transparent through ->/2 and ;/2.

  36. Programming Tips on or, if-then, if-then-else • You never really need them, but they’re handy when your lazy. • They can make your program harder to read and understand. • Use white-space to make the special syntax stand out. ( goal1(…) ; goal2(…)) (condition(…) -> result(…) ; otherwise(…)) • Never nest or combine them. • If the Condition contains only built-in predicates, then the compiler can often be clever when compiling them.

  37. Timing and Statistics • Built-in statistics/1 gives lots of information about time and memory use. • statistics/2 gives you information about specific values. statistics(runtime, [BaseTime, TimeSinceLastCall]). • Times are measured in milliseconds

  38. Timing Predicates % time(+Goal, +Iterations, -RunTime). time(Goal, Iterations, RunTime):- statistics(runtime, [StartTime, _]), iterate(Iterations, Goal), statistics(runtime, [EndTime, _]), RunTime is (EndTime - StartTime) / Iterations. iterate(0, _):- !. iterate(Counter, Goal):- call(Goal), !, NextCounter is Counter - 1, iterate(NextCounter, Goal).

  39. Final Projects • Any questions on final projects? • Due date: Dec. ??

More Related