Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
CS 2104
Functional Programming (Continued)
Lecturer : Dr. Abhik Roychoudhury
School of Computing
Discussion on Innermost Eval
Last question of last year’s final
Searching over infinite sorted lists
Discussion in class
Hamming Number
List, in ascending order with no
repetition, all positive integers with no
prime factors other than 2, 3, or 5.
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15,...
n as a prime factor
fun scale n []
= []
|
scale n (x::xs) = (n*x) :: (scale n xs)
scale 2 [1,2,3,4,5] = [2,4,6,8,10]
scale 3 [1,2,3,4,5] = [3,6,9,12,15]
scale 3 (scale 2 [1,2,3,4,5])
= [6,12,18,24,30]
Merging two Streams
fun merge []
[]
= []
|
merge (x::xs) (y::ys) =
if x < y then x :: merge xs (y::ys)
else if x > y then y :: merge (x::xs) ys
else x :: merge xs ys
merge [2,4,6] [3,6,9]
= [2,3,4,6,9]
Hamming numbers
1
scale 2
merge
::
merge
scale 3
scale 5
val hamming = 1 ::
merge (scale 2 hamming)
(merge (scale 3 hamming)
(scale 5 hamming))
Outline
More about Higher-order Function
Type inference and Polymorphism
Evaluation Strategies
Exception Handling
Exception Handling
• Handle special cases or failure (the exceptions)
occurred during program execution.
hd [];
uncaught exception hd
• Exception can be raised and handled in the program.
exception Nomatch;
exception Nomatch : exn
fun member(a,x) =
if null(x) then raise Nomatch
else if a = hd(x) then x
else member(a,tl(x))
fun member(a,x) =
if null(x) then raise Nomatch
else if a = hd(x) then x
else member(a,tl(x))
member(3,[1,2,3,1,2,3]) ;
val it = [3,1,2,3] : int list
member(4,[]) ;
uncaught exception Nomatch
member(5,[1,2,3]) handle Nomatch=>[];
val it = [] : int list
CS 2104 – Prog. Lang. Concepts
Logic Programming – I
Dr. Abhik Roychoudhury
School of Computing
Prolog
The only popular logic programming language.
Short for “Programming in Logic”.
Programs are first order logic formulae.
Clean formal semantics.
Procedural language.
Procedures are called predicates.
Prolog
Rather unusual compared to imperative languages.
How to start studying it ?
Logic - Usual approach.
Programming - Our approach
[Draft Book: Programming in Tabled Prolog]
Refer : Chapter 2 of this online book
[by Prof. David S. Warren, SUNY Stony Brook]
http://www.cs.sunysb.edu/~warren
Procedural nature
Prolog is a procedural language like PASCAL.
Write procedure/subprograms to carry out specific
tasks.
Features of Prolog procedures (predicates)
Assign once variables
Only one value ever gets assigned to a variable.
Nondeterminism
Multiple definitions of the same procedure.
Assign Once variables
At any point of program exec, any Prolog variable V
Cannot have
For (I = 1 ; I < = 10; I++) Sum := Sum + I
Instead, how about
Has a value, which will never be changed
Or, does not have a value yet.
Sum(0) = 0
Sum(I) = Sum(I – 1) + I
if I > 0
Sum(0), Sum(1), Sum(2), …. are all distinct vars.
Summing of 1..N
add(N, Sum) : If N = 0
then Sum := 0
else add(N – 1, Sum1)
Sum := Sum1 + N
The above is not Prolog syntax, but shows its
procedural nature with assign once variables.
Recursion and iteration
add is a recursive procedure.
Instead of iterating over I, add issues recursive
invocation.
Each recursive invocation of add results in a new
Sum var.
Recursion and iteration
Instead of one Sum var. getting many values
Multiple sum variables.
Each gets one value.
This is only the programming style, do not worry
about efficiency of implementation.
General technique of modeling iteration via
recursion
new variable for each recursive invocation
Symmetric Assignment
Variables are assign once.
LHS and RHS of assignment – no difference
X := 0
X := Y
0 := X
Y := X
If X,Y are assign-once there can be only one
reasonable semantics for both sequences.
Symmetric Assignment
X
0
0
Y
0
X := 0
X := Y
A var. is , if no value has been assigned yet.
0 := X
Y := X
X
0
0
Y
0
Even re-orderings of such symmetric assignments will
give the same result – Why ?
Test and Assignment
X := Y
Before this “assignment” executes:
Case 1: X = , Y =
Future assignments of X and Y must match
Case 2: X = , Y = v (some value)
X is assigned the value v
Test and Assignment
Case 3: Y = , X = v (some value)
Case 4:
Y is assigned the value v
X = v1, Y = v2
Test whether the values v1 and v2 are “same”
With assign once variables, just one operator
for both test and assignment. Call it =
Sum of 1..N - Revisited
add(N, Sum) : ( N = 0
-> Sum = 0
; N1 is N –1,
add(N1, Sum1),
Sum is Sum1 + N
).
->, ;
is :
denotes if-then-else
special case of = for arith. expr.
So far…
Prolog is procedural.
Variables are assign once.
Assignment is symmetric.
Same operator for test and assignment
Call this unification – more later
Now…
Data Structures in Prolog
Unification
Lists, Trees, Terms
Pattern Matching
Test and Assignment
Non-determinism in Prolog
Data Structures in Prolog
No data types. Every data is a term.
Terms are trees constituted from
Integers – 1, -1, 2,
Float - 3.14159, 2.0,…
Other constants- a,b,c (small letters)
Other terms
A term represents itself.
Examples of terms
1
3.14159
f(a) where no meaning has been assigned to f
f(g(a, b), c)
F(g(a,b), 1, h(d))
Prolog variables written in capital letters: X, Y, Z,…
Variables get “assigned” to terms via program Exec.
Prolog Lists
[]
[1,2,3]
[or, not, [b, 1], 3.1415]
[H|T]
list with head H, tail T
[a,H2|T] –
list with a, H2, followed by T
Sum of an array of integers
add(List, Sum) : ( List = []
-> Sum = 0
; List = [Head|Tail],
add(Tail, TailSum),
Sum is TailSum + Head
).
Unification
List = [ Head | Tail]
If Head, Tail assigned already, constructs List
(assignment of List).
If List assigned already, assigns head of List to
Head, tail of List to Tail
List could even be partially instantiated
[a, b, c | X]
More powerful than X = Y
Unification
Combines the power of
Pattern matching (discussed for FP)
Symmetric assignment
Test
Sum is TailSum + Head
Evaluate the expression TailSum + Head
Assign this value to Sum
This is not unification.
Appending two lists
append(L1, L2, L3) : ( L1 = []
-> L3 = L2
; L1 = [X|L1Tail], % Consume L1
append(L1Tail, L2, L3Tail),
L3 = [X|L3Tail]
% Produce L3
).
Other correct variations follow – Look closely !!
Append – Version 2
append(L1, L2, L3) : ( L1 = []
-> L3 = L2
; L3 = [X|L3Tail], % Produce L3
L1 = [X|L1Tail], % Consume L1
append(L1Tail, L2, L3Tail)
).
Constructing L3, even when L3Tail =
Non-determinism
A prog. lang is deterministic if
For any point in program execution always
exactly one next step (command)
A Prolog procedure (predicate) may have
multiple definitions (clauses).
The applicability of these definitions is not
mutually exclusive.
Example
friend(X, Y) :- X = mary, Y = cindy.
friend(X, Y) :- X = mary, Y = emily.
To find the friends of mary
User asks the question friend(mary, Z)
Underlying execution has two choices
Choose first rule, return Z = cindy
Choose second rule, return Z = emily.
How would this be programmed in FP ?
Append program - Revisited
append(L1, L2, L3) :L1 = [], L3 = L2.
append(L1, L2, L3) :L1 = [X|L1t],
append(L1t,L2,L3t), L3=[X|L3t].
The two clauses are mutually exclusive, or are they
?? If not, then non-determinism in execution !!
One program – many tasks
Depends on how we use this program.
Prolog program execution triggered by asking
a question (query).
Query 1: ?- append([a,b],[c,d,e,f],X)
Append two given lists, and return this list in X.
Execution is deterministic.
Similar to the way append function works in FP.
One program – many tasks
Query 2: ?- append([a,b],[c],[a,b,c])
Verifies that the result of appending the first two
arguments is indeed the third argument.
Execution is deterministic.
Query 3: ?- append([a,b],X,[a,b,c])
Which list when appended with [a,b] gives [a,b,c]
Execution is deterministic.
One program – many tasks
Query 4: ?- append(X,Y,[a,b,c])
Execution is non-deterministic.
Returns all possible X, Y such that by appending
them the list [a,b,c] is obtained
X
X
X
X
=
=
=
=
[], Y =
[a], Y =
[a,b], Y
[a,b,c],
[a,b,c]
[b,c]
= [c]
Y = []
Membership in a list
member(X, [X|L]).
member(X, [Y|L]) :- member(X, L).
Clauses of the form (Head :- Body).
Unifications can be moved to Head.
Can ask the queries
member(1, [1,2,3]).
member(X, [1,2,3]).
Non-deterministic computation
member(X, [1,2])
X=1
member(X, [2])
X=2
member(X, [])
fail
Query Evaluation
Prolog computation proceeds by query evaluation.
Query evaluation is non-deterministic
Each clause of the form (Head :- Body.)
There can be > 1 clause whose head unifies with the query
Example : The query member(X, [1,2,3])
Evaluation of a query Q in a Prolog program P
Checks which clause heads of P unify with Q
Let these clauses be {c1,c2,…,cn}
Evaluate the bodies of {c1,c2,…,cn} in program P.
Query Evaluation of member
Query : member(X, [1,2])
Program: member(X, [X|L]).
member(X, [Y|L]) :- member(X, L).
Step 1: Unifies with both clauses.
First clause: Unify X = 1, L = [2].
Body = null
Second clause: Unify Y = 1, L = [2].
Body = member(X, [2])
Query Evaluation of member
Step 2: Need to evaluate member(X, [2])
Unifies with both clauses of program.
First clause: Unify X = 2, L = []
Body = null
Second clause: Unify Y = 2, L = []
Body = member(X, [])
Step 3: Need to evaluate member(X, [])
Unifies with no program clause.
Computation fails.
Failure and Non-determinism
Evaluating query Q in program P
Q unifies with no clause head of P - failure
Q unifies with exactly one clause head – deterministic step.
Q unifies with > 1 clause head
Non-determinism.
Multiple “answers” for query Q in program P.
Example: member(X, []) fails
member(X, [1,2])
produces > 1 assignments for X (“answers”)
Summary: Prolog execution
Evaluating member(X, [1,2])
Invoking the member subprogram with parameters
Since 2 unifying clauses 2 execution paths
X, [1,2]
Think of these 2 definitions (clauses) running on 2 different
Machines : M1 , M2
M1 terminates and produces the assignment X = 1.
M2 goes on to evaluate member(X, [2]).
Summary: Prolog execution
Evaluating member(X, [2])
Invoking the member subprogram with parameters
Since 2 unifying clauses 2 execution paths
X, [2]
Think of these 2 definitions (clauses) running on 2 different
Machines: M3, M4
M3 terminates and produces the assignment X = 2.
M4 goes on to evaluate member(X, []).
Evaluating member(X, [])
No unifying clauses, M4 aborts after reporting failure
Exercises
Write Prolog predicates for
Reversing a list
Insertion sorting a list
Merging two sorted lists
In what unusual ways can you use
them (which is not possible in C) ?
Implement BST operations in Prolog.