Prolog Programming (Volume 5) Dr W.F. Clocksin. List cells + Unification = Great Idea Normally we use ‘proper lists’, which are defined according to the.

Slides:



Advertisements
Similar presentations
Artificial Intelligence: Natural Language and Prolog
Advertisements

Prolog Programming (Volume 2) Dr W.F. Clocksin. Lists Lists are the same as other languages (such as ML) in that a list of terms of any length is composed.
C. Varela; Adapted w/permission from S. Haridi and P. Van Roy1 Declarative Programming Techniques Accumulators, Difference Lists (VRH ) Carlos Varela.
Declarative Programming Lists in PROLOG Autumn 2014.
© Patrick Blackburn, Johan Bos & Kristina Striegnitz Lecture 6: More Lists Theory –Define append/3, a predicate for concatenating two lists, and illustrate.
© Patrick Blackburn, Johan Bos & Kristina Striegnitz Lecture 6: More Lists Theory –Define append/3, a predicate for concatenating two lists, and illustrate.
11/10/04 AIPP Lecture 6: Built-in Predicates1 Combining Lists & Built-in Predicates Artificial Intelligence Programming in Prolog Lecturer: Tim Smith Lecture.
Lists in Lisp and Scheme a. Lists are Lisp’s fundamental data structures, but there are others – Arrays, characters, strings, etc. – Common Lisp has moved.
Prolog: List © Patrick Blackburn, Johan Bos & Kristina Striegnitz.
Prolog Programming (Volume 3) Dr W.F. Clocksin. Mapping: The Full Map sqlist(, ) sqlist([], []). sqlist([X|T], [Y|L]) :- Y is X * X, sqlist(T, L). List.
1 Introduction to Prolog References: – – Bratko, I., Prolog Programming.
CSE 3341/655; Part 4 55 A functional program: Collection of functions A function just computes and returns a value No side-effects In fact: No program.
Tail Recursion. Problems with Recursion Recursion is generally favored over iteration in Scheme and many other languages – It’s elegant, minimal, can.
Getting started with ML ML is a functional programming language. ML is statically typed: The types of literals, values, expressions and functions in a.
Chapter 11 Proof by Induction. Induction and Recursion Two sides of the same coin.  Induction usually starts with small things, and then generalizes.
Logic Programming Lecture 3: Recursion, lists, and data structures.
Lambda Calculus and Lisp PZ03J. Lambda Calculus The lambda calculus is a model for functional programming like Turing machines are models for imperative.
ML: a quasi-functional language with strong typing Conventional syntax: - val x = 5; (*user input *) val x = 5: int (*system response*) - fun len lis =
CS 330 Programming Languages 12 / 02 / 2008 Instructor: Michael Eckmann.
Constraint Logic Programming Ryan Kinworthy. Overview Introduction Logic Programming LP as a constraint programming language Constraint Logic Programming.
Lisp. Versions of LISP Lisp is an old language with many variants –LISP is an acronym for List Processing language Lisp is alive and well today Most modern.
ML: a quasi-functional language with strong typing Conventional syntax: - val x = 5; (*user input *) val x = 5: int (*system response*) - fun len lis =
© Patrick Blackburn, Johan Bos & Kristina Striegnitz Lecture 5: Arithmetic Theory –Introduce Prolog`s built-in abilities for performing arithmetic –Apply.
© Patrick Blackburn, Johan Bos & Kristina Striegnitz Lecture 9: A closer look at terms Theory –Introduce the == predicate –Take a closer look at term structure.
© Patrick Blackburn, Johan Bos & Kristina Striegnitz Lecture 5: Arithmetic Theory –Introduce Prolog`s built-in abilities for performing arithmetic –Apply.
Tail Recursion. Problems with Recursion Recursion is generally favored over iteration in Scheme and many other languages – It’s elegant, minimal, can.
CPSC 335 BTrees Dr. Marina Gavrilova Computer Science University of Calgary Canada.
Comp 249 Programming Methodology Chapter 15 Linked Data Structure - Part B Dr. Aiman Hanna Department of Computer Science & Software Engineering Concordia.
CMSC 2021 Recursion Recursive Definition – one that defines something in terms of itself Recursion – A technique that allows us to break down a problem.
CS 321 Programming Languages and Compilers Prolog part 2.
DATA STRUCTURE & ALGORITHMS CHAPTER 3: STACKS. 2 Objectives In this chapter, you will: Learn about stacks Examine various stack operations Discover stack.
CS 403: Programming Languages Lecture 19 Fall 2003 Department of Computer Science University of Alabama Joel Jones.
Data Structures : Project 5 Data Structures Project 5 – Expression Trees and Code Generation.
Stephen P. Carl - CS 2421 Recursion Reading : Chapter 4.
Computer Science Department Data Structure & Algorithms Lecture 8 Recursion.
30/09/04 AIPP Lecture 3: Recursion, Structures, and Lists1 Recursion, Structures, and Lists Artificial Intelligence Programming in Prolog Lecturer: Tim.
Chapter 9: Functional Programming in a Typed Language.
Functional Programming in Scheme and Lisp.
CSC 221: Recursion. Recursion: Definition Function that solves a problem by relying on itself to compute the correct solution for a smaller version of.
Prolog Program Style (ch. 8) Many style issues are applicable to any program in any language. Many style issues are applicable to any program in any language.
CS535 Programming Languages Chapter - 10 Functional Programming With Lists.
© Kenneth C. Louden, Chapter 12 - Logic Programming Programming Languages: Principles and Practice, 2nd Ed. Kenneth C. Louden.
CHP-3 STACKS.
8.1 8 Algorithms Foundations of Computer Science  Cengage Learning.
November 12, 2009Theory of Computation Lecture 17: Calculations on Strings II 1 Numerical Representation of Strings First, we define two primitive recursive.
07/10/04 AIPP Lecture 5: List Processing1 List Processing Artificial Intelligence Programming in Prolog Lecturer: Tim Smith Lecture 5 07/10/04.
Probabilistic Approaches to Phylogenies BMI/CS 576 Sushmita Roy Oct 2 nd, 2014.
M1G Introduction to Programming 2 2. Creating Classes: Game and Player.
Recursion ITI 1121 N. El Kadri. Reminders about recursion In your 1 st CS course (or its equivalent), you have seen how to use recursion to solve numerical.
Given a node v of a doubly linked list, we can easily insert a new node z immediately after v. Specifically, let w the be node following v. We execute.
Logic Programming Lecture 2: Unification and proof search.
CSC 143 P 1 CSC 143 Recursion [Chapter 5]. CSC 143 P 2 Recursion  A recursive definition is one which is defined in terms of itself  Example:  Compound.
Tail Recursion.
CS 550 Programming Languages Jeremy Johnson
ML: a quasi-functional language with strong typing
CS 326 Programming Languages, Concepts and Implementation
Lists in Lisp and Scheme
CS 270 Math Foundations of CS Jeremy Johnson
Algorithm design and Analysis
Prolog Programming (Volume 2)
Chapter 11 Data Compression
CSCE 314: Programming Languages Dr. Dylan Shell
Programming Paradigms and Languages
Programming Techniques
Department of Computer Science
HIGHER ORDER FUNCTIONS
CSE 3302 Programming Languages
Announcements Quiz 5 HW6 due October 23
Text Categorization Berlin Chen 2003 Reference:
Presentation transcript:

Prolog Programming (Volume 5) Dr W.F. Clocksin

List cells + Unification = Great Idea Normally we use ‘proper lists’, which are defined according to the theory of lists: A list of length 0 is [] A list of length N is [H|T] where T is a list of length N-1 This is good when we only want to cons elements onto the from of the list. But, Prolog variables make it possible to do something else:

List cells + Unification = Great Idea zap([a, b, c, Z], Z, R) zap(X, d, X) so, R = [a, b, c, d] More generally, zap([a, b, c | Z], Z, R) zap(X, [d, e, f], X)

Difference Structures Probably one of the most ingenious programming techniques ever invented (by Sten-Åke Tärnlund, 1975) yet neglected by mainstream computer science. A way of using variables as ‘holes’ in data structures that are filled in by unification as the computation proceeds. Most examples here will be with difference lists. Will introduce by showing the usual (non difference list) algorithm for concatenating lists.

Concatenating two lists (WS 25) ?- append([a, b, c], [d, e, f], X). X = [a, b, c, d, e, f] append([], L, L). append([X|Y], T, [X|Z]) :- append(Y, T, Z). Notice this is tail recursive. This definition is possible because of logical variables. Definitions in other languages cannot be tail recursive because the last call is cons, not append.

Concatenating two lists (WS 25) What do these goals do? ?- append([a, b, c], X, [a, b, c, d, e, f]). ?- append([a, b, c], [d, e, f], X). ?- append(X, Y, [a, b, c, d, e, f]). X = []Y = [a, b, c, d, e, f]; X = [a]Y = [b, c, d, e, f]; X = [a, b]Y = [c, d, e, f];.. X = [a, b, c, d, e, f]Y = []

Linearising (flattening) a list (WS 25) Flattening a list is a way of listing the leaf nodes (finding the fringe) of tree-structured data. For example, [ a, b], [c, d, [e, f], g], h, [i, [k] ] ] flattens to [a, b, c, d, e, f, g, h, i, k] Here is the usual program: flatten([], []). flatten([H|T], L3) :- flatten(H, L1), flatten(T, L2), append(L1, L2, L3). flatten(X, [X]). This is very inefficient: how many calls to append?

Instead, Difference Lists The idea is to represent a list segment as a pair of terms, the front and the back. For example, the list segment L1-L2 has the elements a,b: L1 refers to the front of the list, and L2 refers to the back, often a variable. This variable can be used as a ‘hole’ into which another term may be instantiated. If the other term has a hole too, this can be useful. L1L2 a b L1 [a, b | L2]

Example: Append L1-L2 to L3-L4 L1L2 a b L3L4 d e c Call the result X-Y. The following are true about X-Y: X should co-refer with L1 (to be the front of the list) Y should co-refer with L4 (to be the back of the list) L2 should co-refer with L3 (to join the lists together)

Make it so: L1L2 a b L3L4 d e c X Y In Prolog we can use this idea to implement constant-time appending of two lists. As suggested above, doing this is simply a matter of re- arranging variables.

Definition of app The goal app(L1,L2,L3,L4,X,Y) succeeds when the difference lists made from L1 and L2 and concatenated with the difference lists made from L3 and L4 to give the resulting difference list made from X and Y. app(L1, L2, L2, L4, L1, L4). Example execution: ?- app([a, b, c | Z1], Z1, [d, e, | Z2), Z2, X, Y). X = [a, b, c, d, e | Y]. A better way to see the arrangement of variables is like this: app(A, B, B, C, A, C).

Usual notation of difference lists Denote difference list with front L1 and back L2 as L1-L2, where - is an infix binary operator. This represents difference lists as a single term, so cuts down on the arity of procedures. Programs are clearer, as in this definition of app:. app(A-B, B-C, A-C). Example execution: ?- app([a, b, c | Z1]-Z1, [d, e, | Z2)-Z2, X-Y). X-Y = [a, b, c, d, e | Y]-Y. The extra space taken by the ‘-’ functor is not a serious problem in practice. But then, why use app when you can do the rearrangement of variables in-place where it is needed in a program!

Summary L-L is the null difference list [a | Z]-Z is the difference list containing ‘a’. Similarly, [a, b, c | Z]-Z is the difference list containing a, b, c. Unifying the difference list X with Y-[] will rectify the list, that is, turn it into a proper list. For example. unifying [a, b, c | Z]-Z with Y-[] instantiates Y to [a, b, c].

Linearising (flattening) a list (WS 28) flatten(X, Y) :- flatpair(X, Y-[]). flatpair([], L-L). flatpair([H|T], L1-L3) :- flatpair(H, L1-L2), flatpair(T, L2-L3). flatpair(X, [X|Z]-Z). Notice the pattern of ‘stitching’ elements together.

Linearising (flattening) Trees (WS 29) First, how to represent a binary tree. Leaves are any terms. Nodes are constructed from the term n(t 1, t2) where terms t 1 and t 2 are trees called the left branch and the right branch. For example, the term n(n(a,b),n(c,n(d,e))) names the tree: n n n a b c n d e

Linearising (flattening) Trees (WS 29) Linearising a tree. This example will add interest by doing a partial map: only the integers will be linearised. The naive method (using append): lintree(n(A,B), L1) :- lintree(A, LA), lintree(B, LB), append(LA, LB, L1). lintree(I, [I]) :- integer(I). lintree(X, []).

Linearising (flattening) Trees (WS 29) The difference list method: lintree(n(A,B), L1) :- lintree(A, LA), lintree(B, LB), append(LA, LB, L1). lintree(I, [I]) :- integer(I). lintree(X, []).

Worked exercise for WS 29 /* picktree(tree, list of apples, list of pears) */ picktree(apple, [apple | L]-L, P-P). picktree(pear, A-A, [pear | L]-L). picktree(n(L,R), A1-A3, P1-P3) :- picktree(L, A1-A2, P1-P2), picktree(R, A2-A3, P2-P3). picktree(Other, A-A, P-P).

Normalising Sum Expressions (WS 30) The sums (a+b)+(c+d) and (a+(b+(c+d))) may be normalised into a standard form that associates on the left: a+b+c+d, or equivalently, ((a+b)+c)+d. This is only possible because they are sums a b c d a b c d a b c d

Define a predicate normsum The goal normsum(X,Y) succeeds when sum expression X normalises to Y. One method is to first flatten the sum, and then build up the normalised version in another pass. Here is flat(A,B,C), which flattens the sum into the difference list B-C: flat(X+Y), R1-R3) :- !, flat(X, R1-R2), flat(Y, R2-R3). flat(X, [X|Z] - Z). The difference ‘thread’ is R1  R2  R3, and note the ‘!’ to commit to the first clause when a sum node is encountered.

Building up the normalised sum This is not obvious. One way is to accumulate the ‘tree so far’, giving it a new parent node each time an element is found. This ‘stacks up’ nodes instead of inserting them. A ‘base case’ for nil is not needed because the flattened list will have at least two elements. build([X], T, T+X) :- !. build([H | L], T, Z) :- build(L, T+H, Z).

Putting them together Now normalise by flattening then building. The ‘tree so far’ in the second argument of build needs to be initialised with the first element of the flattened list: normalise(A, C) :- flat(A, B-[]), B = [T | L], build(L, T, C).

Do it in one pass instead! Here is a better program: normalise(X, Y) :- norm(X, []-Y). norm(X+Y, A-C) :- !, norm(X, A-B), norm(Y, B-C). norm(X, []-X) :- !. norm(X, A-(A+X)). Here the accumulator is used not only for differencing the elements, but also for building the tree so far. The constant [] is used to represent the null accumulator, but there is no list processing as such.

Find maximum element of a tree A valued (weighted, coloured) binary tree can be defined using compound terms. A node is represented by n(V,L,R ), where V is the value (say a number), and L and R are the left and right branches of the tree. A terminal node will have L and R instantiated to []. For example the term: n(3, n(1, n(4, [], []), n(1, [], [])), n(5, n(9, n(2, [], []), []), n(6, [], n(5, [], [])))) represents the following tree:

Notice no terminals coming from here and here.

Find maximum element of a tree Just like finding the maximum element of a list, use an accumulator to represent the ‘biggest value so far’. /* findmax(Tree, Value so far, Final value) */ findmax([], A, A). findmax(n(V, L, R), A, Z) :- V >= A, !, findmax(L, V, A1), findmax(R, A1, Z). findmax(n(V, L, R), A, Z) :- V < A, !, findmax(L, A, A1), findmax(R, A1, Z).

Copy a tree Make a tree of the same shape as the input. /* copyTree(InputTree, OutputTree) */ copyTree([], []). copyTree(n(V, L, R), n(V, L1, R1) :- copyTree(L, L1), copyTree(R, R1).

Worksheet 32: Max Tree Given an input tree T, write a program that constructs a tree of the same shape as T, but in which the value of each node has been set to the value of the greatest node in T. This can be by finding the greatest element, and then making a copy inserting the greatest element as the value of each node in the copy. However, it can be done in one pass (!) as follows:

Worked Exercise /* mt(InTree, OutTree, Hole, AccumHighest, Highest) */ maxtree(A, B) :- mt(A, B, H, 0, H). mt(n(W, A, B), n(H, A1, B1), H, AC, N) :- W < AC, mt(A, A1, H, AC, ACA), mt(B, B1, H, ACA, N). mt([], [], H, A, A).

Difference Lists are... Very efficient. Popular -- in widespread use in Prolog. Expressive of new methods of computation. Sometimes misleading: difference-list append is not free of side-effects (but is backtrackable) Often hidden. Programmers encapsulate the front and back in a structure p(L1, L2). Most common for this purpose is the infix ‘-’.