180 likes | 192 Views
CS 3304 Comparative Languages. Lecture 21: Logic Languages – Perspective 3 April 2012. Extended Example: Tic-Tac-Toe. Ordering allows the programmer to indicate that certain resolutions are preferred and should be considered before other “ fallback ” options.
E N D
CS 3304Comparative Languages • Lecture 21:Logic Languages – Perspective • 3 April 2012
Extended Example: Tic-Tac-Toe • Ordering allows the programmer to indicate that certain resolutions are preferred and should be considered before other “fallback” options. • Tic-tac-toe example - a game played by two players on a 3x3 grid of squares: • Two players, X and O, take turns placing markers in empty squares. • A player wins when placing three markers in a row, horizontally, vertically, or diagonally. • Uses a built-in predicate \+ that succeeds if its argument (a goal) cannot be proven.
Squares in a Row ordered_line(1,2,3). ordered_line(4,5,6). ordered_line(7,8,9). ordered_line(1,4,7). ordered_line(2,5,8). ordered_line(3,6,9). ordered_line(1,5,9). ordered_line(3,5,7). line(A,B,C) :- ordered_line(A,B,C). line(A,B,C) :- ordered_line(A,C,B). line(A,B,C) :- ordered_line(B,A,C). line(A,B,C) :- ordered_line(B,C,A). line(A,B,C) :- ordered_line(C,A,B). line(A,B,C) :- ordered_line(C,B,A).
Moves move(A) :- good(A),empty(A). full(A) :- x(A). full(A) :- o(A). empty(A) :- \+full(A). %strategy: good(A) :- win(A). good(A) :- block_win(A). good(A) :- split(A). good(A) :- strong_build(A). good(A) :- weak_build(A).
Strategies win(A) :- x(B),x(C),line(A,B,C). block_win(A) :- o(B),o(C),line(A,B,C). split(A) :- x(B),x(C),different(B,C), line(A,B,D),line(A,C,E),empty(D),empty(E). same(A,A). different(A,B) :- \+(same(A,B)). strong_build(A) :- x(B),line(A,B,C),empty(C), \+(risky(C)). risky(C) :- o(D),line(C,D,E),empty(E). weak_build(A) :- x(B),line(A,B,C),empty(C), \+(double_risky(C)). double_risky(C) :- o(D),o(E),different(D,E), line(C,D,F),line(C,E,G),empty(F),empty(G).
Default Pick good(5). good(1). good(3). good(7). good(9). good(2). good(4). good(6). good(8).
Imperative Control Flow • Cut - a zero-argument predicate ! (exclamation point): • Always succeeds. • Side effect: commits the interpreter to whatever choices have been made since unifying the parent goal with the left hand side of the current rule. • Example - list membership: • No cut:member(X, [X | _]).member(X, [_ | T]) :- member(X, T). • Cut:member(X, [X | _) :- !.member(X, [_ | T]) :- member(X, T). • Alternative:member(X, [X | _).member(X, [H | T]) :- X \= H, member(X, T). • X \= H means X and H will not unify.
Cut • Implementing \+:\+(P) :- call(P), !, fail.\+(P). • The call predicate takes a term as argument and attempts to satisfy it as a goal. • The fail predicate always fail. • It is possible to replace all !with \+, i.e. confine !within \+: • Often makes it easier to read. • Often makes it less efficient. • Used to create the effect of if...then...else:statement :- condition, !, then_part.statement :- else_part.
Loops • The fail predicate can be used in conjunction with a “generator” to implement a loop. • Example generator:append([], A, A).append([H | T], A, [H | L]) :- append(T, A, L). • Example loop:print_partitions(L) :- append(A, B, L), write(A), write(' '), write(B), nl, fail.print_partitions(_). • Output:[] [a, b, c][a] [b, c][a, b] [c][a, b, c] []Yes
Generate-and-Test • The programming idiom - an unbounded generator with a test-cut terminator: • Example generator:natural(1).natural(N) :- natural(M, N is M+1. • Example test-cut:my_loop(N) :- natural(I), write(I), nl, I = N, !. • Generally used in conjunction with side effects: • Modification of the program database. • I/O: • Output: write, nl, put. • Input: read, get, consult, reconsult:get(X) :- repeat, get0(X), X >=32, !.
Database Manipulation • Prolog is homoiconic: it can represent itself. • It can also modify itself. • Add clause with the built-in predicate assert. • Remove clause with the built-in predicates retract and retractall. • clause predicate attempts to match its two arguments against the head and body of some existing clause in the database. • Individual terms can be created, or their contents extracted, using the built-in predicates functor, arg, and =.. . • functor(T, F, N)succeeds if and only if T is a term with functor F and arity N. • arg(N, T, A)succeeds if and only if its first two arguments are instantiated, N is a natural number, T is a term, and A is the Nth argument of T. • Infix predicate =..“equates” a term with a list.
Theoretical Foundations • In mathematical logic, a predicate is a function that maps constants (atoms) or variables to the values true and false. • Predicate calculus provides a notation and inference rules for constructing and reasoning about propositions (statements) composed of predicate applications, operators, and the quantifiers ∀ and ∃. • Operators include and (∧), or (∨), not (¬), implication (→), and equivalence (↔). • Quantifiers are used to introduce bound variables in an appended proposition, much as λ introduces variables in the lambda calculus. • The universal quantifier, ∀, indicates that the proposition is true for all values of the variable. • The existential quantifier, ∃, indicates that the proposition is true for at least one value of the variable. • Clausal form provides a unique expression for every preposition.
Execution Order • While logic is inherently declarative, most logic languages explore the tree of possible resolutions in deterministic order. • Prolog provides a variety of predicate to control the execution order and to manipulate database explicitly during execution. • An example for declarative way:declarative_sort(L1, L2) :- permutation(L1, L2), sorted(L2).permutation([], []).permutation(L, [H | T]) :- append(P, [H | S], L), append(P, S, W), permutation(W, T). • An example for imperative way:quicksort([], []).quicksort([A | L1], L2) :- partition(A, L1, P1, S1), quicksort(P1, P2), quicksort(S1, S2), append(P2, [A | S2], L2).partition(A, [], [], []).partition(A, [H | T], [H | P], S) :- A >= H, partition(A, T, P, S).partition(A, [H | T], P, [H | S]) :- A =< H, partition(A, T, P, S). • Distinguish between the specification of a program and its implementation.
“Closed World” Assumption • Closed world assumption: the database is assumed to contain everything that is true. • When the database doe not have information to prove the query, the query is assumed to be false. • Prolog can prove that a goal is true but it cannot prove that the goal is false. • Assumption: if a goal cannot be proven true, it is false. • Prolog is a true/fail system, not true/false system. • The problem of the closed-world assumption is related to the negation problem.
Negation • A collection of Horn clauses does not include any things assumed to be false: purely “positive” logic. • \+ predicate is different from logical negation – it can succeed simply because our current knowledge is insufficient to prove it. • Negation in Prolog occurs outside any implicit existential quantifiers on the right-hand side of the rule: • \+(takes(X, his201)). where X is uninstantiated means:¬∃X[takes(X, his201)] rather than ∃X[¬takes(X, his201)] • A complete characterization of the values of X for which ¬takes(X, his201) is true would require a complete exploration of the resolution tree something that Prolog does only when all goals fails or when repeatedly prompted with semicolons.
Trace • Built-in structure that displays instantiations at each step • Tracing model of execution - four events: • Call (beginning of attempt to satisfy goal) • Exit (when a goal has been satisfied) • Redo (when backtrack occurs) • Fail (when goal fails) • Example: trace. distance(chevy, Chevy_Distance). (1) 1 Call: distanc(chevy, _0)? (2) 2 Call: speed(chevy, _5)? (2) 2 Exit: speed(chevy, 105) (3) 2 Call: time(chevy, _6)? (3) 2 Exit: time(chevy, 21) (4) 2 Call: _0 is 105*21? (4) 2 Exit: 2205 is 105*21 (1) 1 Exit: distance(chevy, 2205) Chevy_Distance = 2205
Trace Example likes(jake,chocolate). likes(jake,apricots). likes(darcie,licorice). likes(darcie,apricots). trace. likes(jake,X), likes(darcie,X). (1) 1 Call: likes(jake, _0)? (1) 1 Exit: likes(jake, chocolate) (2) 1 Call: likes(darcie, chocolate)? (2) 1 Fail: likes(darcie, chocolate) (1) 1 Redo: likes(jake, _0)? (1) 1 Exit: likes(jake, apricots) (3) 1 Call: likes(darcie, apricots)? (3) 1 Exit: Likes(darcie, apricots) X = apricots
Summary • A logic program is a set of axioms from which the computer attempts to construct a proof. • Unlike imperative (Turing machine) and functional (lambda calculus) languages, Prolog provides limited generality of resolution theorem proving: space/time efficiency tradeoff. • Prolog is homoiconic: programs look like ordinary data structures, and can be created, modified, and executed on the fly. • Imperative features tend to be responsible for more than their share of program bugs but some tasks (e.g., graphical I/O) are almost impossible to accomplish without side effects.