Logic Programming Part 3: Control Flow James Cheney CS 411
Declarative Programming Ideal: Write down logical formulas that define programs clearly & concisely In logic, clause order doesn’t matter Control flow, efficiency invisible Reality: Must know how programs are run Efficiency (backtracking, clause order) Correctness (determinism, termination)
Clause order matters p(X) :- p(X). p(a). Has answer X p(a) But depth-first search doesn’t terminate.
Clause order matters p(a). p(X) :- p(X). Terminates with X p(a) .
Backtracking Consider a :- b,c,d,e,f. a :- b,c,d,e,g. b. c. d. e. g. First we solve b,c,d,e, then fail on f. Then we solve b,c,d,e again and then g. Duplicate effort!
Order and Backtracking If instead we do (logically equivalent) a :- f,b,c,d,e. a :- g,b,c,d,e. b. c. d. e. g. then the failure occurs earlier, and there is less wasted effort.
Nondeterminism Consider mem(A,A::L). mem(A,B::L) :- mem(A,L). Then ?- member (1,[1,2,3,1]). can succeed in two different ways.
“Cut” PROLOG includes a goal called “cut”, written !, for pruning the search space Removes current backtracking state. Allows more control over search, efficiency However, “cut” damages correspondence to logic
“Cut” Example mem(A,A::L) :- !. mem(A,B::L) :- mem(A,L). ?- mem([1,X],[[1,2],[1,3]]). yes X 2; no Only the first solution is found.
“Cut” Example But, the definition of mem is no longer “complete”: ?- mem(X,[1,2,3,4]). yes X 1; no “cut” may exclude desirable solutions
More Reality In PROLOG, I/O primitives are “impure” predicates Example: main :- write(“What is your name?”), read(X), write(“Hello, ”), write(“X”). Now duplication can also change program.
Other LP systems lProlog: (l X. F X) a == f a ? PROLOG uses FOL, lProlog uses higher-order logic Typed “Functional programming” (map, fold) Powerful, but complex, higher-order unification (l X. F X) a == f a ?
Sorting sorted([]). sorted([A]). sorted([A,B|M]) :- A < B, sorted(B,M). sort(L,M) :- perm(L,M), sorted (L,M). Complexity?
Mergesort msort([],[]). msort(L,L’) :- split(L,L1,L2), msort(L1,L1’), merge(L1’,L2’,L’). split([],[]). split([A|L],[A|M],N) :- split(L,N,M).
Mergesort (Cont’d) merge([],L,L). merge(L,[],L). merge([A|L],[B|M],[A|N]) :- A <= B, merge(L,[B|M],N). merge([A|L],[B|M],[B|N]) :- A > B, merge([A|L],M,N).
Other LP systems: Mercury Mercury: typed, “pure” ML-style polymorphism, datatypes Modes & determinism checking I/O primitives take “world argument” main(W0,W4) :- read(X,W1,W2), write(“Hello World”,W2,W3), write(X,W3,W4).
Other LP systems: lProlog Idea: Mix functional and logic paradigms Term language is higher-order typed l-calculus Requires solving hard (undecidable!) unification problems (lx. F x) a = f a F f, F (lx. a) Can encode variable binding syntax using l’s
Applications Artificial intelligence Constraint solving/optimization Natural language processing Expert systems Constraint solving/optimization Logic programs + constraints describe solutions to complex problems Query languages (eg SQL, XQuery) declarative in flavor
Summary Logic programming a powerful paradigm “Algorithm = logic + control” Unfortunately, for efficiency reasons, LP programs diverge from this ideal Mathematical clarity != programming efficiency “cut”, imperative features lead to opaque programs Lesson: TANSTAAFL.