From 18f3181204ed78e49950dd50ad83df1c1cccf83c Mon Sep 17 00:00:00 2001 From: Kacper Sokol Date: Thu, 9 Feb 2017 14:01:07 +0000 Subject: [PATCH] Lab files --- .gitignore | 2 ++ labs/README.md | 3 +++ labs/biglist.pl | 15 +++++++++++++++ labs/fib.pl | 18 ++++++++++++++++++ labs/fibn.pl | 19 +++++++++++++++++++ labs/fibt.pl | 18 ++++++++++++++++++ labs/nqueens.pl | 34 ++++++++++++++++++++++++++++++++++ labs/powerset.pl | 36 ++++++++++++++++++++++++++++++++++++ labs/prove.pl | 25 +++++++++++++++++++++++++ labs/prove_p.pl | 41 +++++++++++++++++++++++++++++++++++++++++ labs/prove_r.pl | 32 ++++++++++++++++++++++++++++++++ labs/psort.pl | 32 ++++++++++++++++++++++++++++++++ labs/secondorder.pl | 29 +++++++++++++++++++++++++++++ labs/setof_sort.pl | 10 ++++++++++ 14 files changed, 314 insertions(+) create mode 100644 .gitignore create mode 100644 labs/README.md create mode 100644 labs/biglist.pl create mode 100644 labs/fib.pl create mode 100644 labs/fibn.pl create mode 100644 labs/fibt.pl create mode 100644 labs/nqueens.pl create mode 100644 labs/powerset.pl create mode 100644 labs/prove.pl create mode 100644 labs/prove_p.pl create mode 100644 labs/prove_r.pl create mode 100644 labs/psort.pl create mode 100644 labs/secondorder.pl create mode 100644 labs/setof_sort.pl diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..96c02b3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +# Mac OS files +*.DS_Store diff --git a/labs/README.md b/labs/README.md new file mode 100644 index 0000000..f9c07e2 --- /dev/null +++ b/labs/README.md @@ -0,0 +1,3 @@ +## Prolog files for labs ## +This folder contains Prolog files for lab exercises. +Interactive online version of these is available [here](http://labs.simply-logical.space). diff --git a/labs/biglist.pl b/labs/biglist.pl new file mode 100644 index 0000000..319eb75 --- /dev/null +++ b/labs/biglist.pl @@ -0,0 +1,15 @@ +biglist(Low,High,L):- + bagof(X,between(Low,High,X),L). + +% between/3 is built-in but could have been defined as follows: +% between(Low,_High,Low). +% between(Low,High,Number):- +% Low < High, +% NewLow is Low+1, +% between(NewLow,High,Number). + +/** <examples> + +?- biglist(1,25,L). + +*/ diff --git a/labs/fib.pl b/labs/fib.pl new file mode 100644 index 0000000..b500992 --- /dev/null +++ b/labs/fib.pl @@ -0,0 +1,18 @@ +% fib(N,F) <- F is the N-th Fibonacci number +% inefficient doubly-recursive version +fib(1,1). +fib(2,1). +fib(N,F):- + N>2,N1 is N-1,N2 is N-2, + fib(N1,F1),fib(N2,F2), + F is F1+F2. + +/** <examples> + +?- fib(5,F). +?- fib(10,F). +?- fib(20,F). +?- fib(25,F). +?- fib(30,F). + +*/ diff --git a/labs/fibn.pl b/labs/fibn.pl new file mode 100644 index 0000000..1eb588a --- /dev/null +++ b/labs/fibn.pl @@ -0,0 +1,19 @@ +% fibn(N,Na,Nb,F) <- F is the N-th Fibonacci number +% in the sequence starting with Na, Nb +fibn(1,Na,_,Na). +fibn(2,_,Nb,Nb). +fibn(N,Na,Nb,F):- + N>2, N1 is N-1, + Nc is Na+Nb, + fibn(N1,Nb,Nc,F). + +% the original Fibonacci sequence starts with 1, 1 +fibn(N,F):- + fibn(N,1,1,F). + +/** <examples> + +?- member(N,[10,20,50,100,200]), fibn(N,F). +?- maplist(fibn, [10,20,50,100,200], L). + +*/ diff --git a/labs/fibt.pl b/labs/fibt.pl new file mode 100644 index 0000000..aedfbb3 --- /dev/null +++ b/labs/fibt.pl @@ -0,0 +1,18 @@ +% :-use_rendering(svgtree). % uncomment this line to see visualisations + +% fibt(N,E) <- E is an arithmetic expression +% representing the N-th Fibonacci number +% that can be rendered as a tree +% and evaluated with is/2. +fibt(1,1). +fibt(2,1). +fibt(N,(F1+F2)):- + N>2,N1 is N-1,N2 is N-2, + fibt(N1,F1),fibt(N2,F2). + +/** <examples> + +?- fibt(5,E), F is E. +?- fibt(10,E), F is E. + +*/ diff --git a/labs/nqueens.pl b/labs/nqueens.pl new file mode 100644 index 0000000..e375ffb --- /dev/null +++ b/labs/nqueens.pl @@ -0,0 +1,34 @@ +% :-use_rendering(chess). % Uncomment this line for chess renderer + +nqueens(N,Columns) :- + setof(X,between(1,N,X),Rows), + perm(Rows,Columns), % generator + safe(Columns). % tester + +%%% tester +safe([]). +safe([Column|Columns]) :- + noattack(Column,Columns,1), + safe(Columns). + +noattack(_,[],_). +noattack(Y,[Y1|Ylist],Xdist) :- + abs(Y-Y1) =\= Xdist, + Xdist1 is Xdist+1, + noattack(Y,Ylist,Xdist1). + +%%% generator +perm([],[]). +perm(L,[X|PR]):- + remove_one(X,L,R), + perm(R,PR). + +remove_one(X,[X|Ys],Ys). +remove_one(X,[Y|Ys],[Y|Zs]):- + remove_one(X,Ys,Zs). + +/** <examples> + +?- nqueens(8,Columns). + +*/ diff --git a/labs/powerset.pl b/labs/powerset.pl new file mode 100644 index 0000000..a4577f3 --- /dev/null +++ b/labs/powerset.pl @@ -0,0 +1,36 @@ +% powerset(S,PS) <- PS is the list of all sublists of S +% First try +powerset1([],[[]]). +powerset1([H|T],PowerSet):- + powerset1(T,PowerSetOfT), + extend_pset(H,PowerSetOfT,PowerSet). % not tail-recursive + +% extend_pset(X,S,ES) <- ES contains two copies of each list in S, +% one with X and one without +extend_pset(_,[],[]). +extend_pset(H,[List|MoreLists],[List,[H|List]|More]):- + extend_pset(H,MoreLists,More). + +% Second try: swap calls in recursive clause +powerset2([],[[]]). +powerset2([H|T],PowerSet):- + extend_pset(H,PowerSetOfT,PowerSet), % generator (bad! why?) + powerset2(T,PowerSetOfT). % tail-recursive + +% Third try: use accumulator +powerset([],PowerSet,PowerSet). +powerset([H|T],Acc,PowerSet):- + extend_pset(H,Acc,Acc1), % efficient generator + powerset(T,Acc1,PowerSet). % tail-recursive + +powerset(Set,PowerSet):-powerset(Set,[[]],PowerSet). + +/** <examples> + +?- powerset1([a,b,c,d,e,f],PS). +?- powerset2([a,b,c,d,e,f],PS). +?- powerset([a,b,c,d,e,f],PS). +?- extend_pset(1,[[],[2],[3],[2,3]],ES). +?- extend_pset(1,S,ES). + +*/ diff --git a/labs/prove.pl b/labs/prove.pl new file mode 100644 index 0000000..487edf8 --- /dev/null +++ b/labs/prove.pl @@ -0,0 +1,25 @@ +prove(A):- + ( A=true -> true % we're done + ; A=not(B) -> not(prove(B)) % negation as failure + ; A=(B,C) -> prove(B),prove(C) % conjunctive query + ; otherwise -> cl(A,B),prove(B) % resolve against clause + ). + +% cl(H,B) <- (H:-B) is object-level clause +cl(rectangle,(polygon(4),angles(90))). +cl(square,(rectangle,regular)). +cl(triangle,polygon(3)). +cl(equilateral_triangle,(triangle,regular)). +%%% facts +cl(polygon(4),true). +cl(regular,true). +cl(angles(90),true). + +/** <examples> + +?- prove(rectangle). +?- prove(square). +?- prove(not(triangle)). +?- prove(not((rectangle,triangle))). + +*/ diff --git a/labs/prove_p.pl b/labs/prove_p.pl new file mode 100644 index 0000000..d46e347 --- /dev/null +++ b/labs/prove_p.pl @@ -0,0 +1,41 @@ +% display a proof tree +prove_p(A):-prove_p(A,P),write_proof(P). + +prove_p(A,P):- + ( A=true -> P=[] + ; A=(B,C) -> cl(B,D),conj_append(D,C,E), + prove_p(E,PE),P=[p(A,(B:-D))|PE] + ; otherwise -> cl(A,B),prove_p(B,PB), + P=[p(A,(A:-B))|PB] + ). + +write_proof([]):- + write('...............[]'),nl. +write_proof([p(A,B)|Proof]):- + write((:-A)),nl, + write('.....|'),write('..........'),write(B),nl, + write('.....|'),write('..................../'),nl, + write_proof(Proof). + +conj_append(A,B,C):- + ( A=true -> B=C + ; A=(A1,A2) -> C=(A1,C2),conj_append(A2,B,C2) + ; otherwise -> C=(A,B) + ). + +% cl(H,B) <- (H:-B) is object-level clause +cl(rectangle,(polygon(4),angles(90))). +cl(square,(rectangle,regular)). +cl(triangle,polygon(3)). +cl(equilateral_triangle,(triangle,regular)). +%%% facts +cl(polygon(4),true). +cl(regular,true). +cl(angles(90),true). + +/** <examples> + +?- prove_p(rectangle). +?- prove_p(square). + +*/ diff --git a/labs/prove_r.pl b/labs/prove_r.pl new file mode 100644 index 0000000..718fcb8 --- /dev/null +++ b/labs/prove_r.pl @@ -0,0 +1,32 @@ +prove_r(A):- + writeln(A), % show current query + ( A=true -> true + ; A=not(B) -> not(prove_r(B)) + ; A=(B,C) -> cl(B,D),conj_append(D,C,E),prove_r(E) + ; otherwise -> cl(A,B),prove_r(B) + ). + +conj_append(A,B,C):- + ( A=true -> B=C + ; A=(A1,A2) -> C=(A1,C2),conj_append(A2,B,C2) + ; otherwise -> C=(A,B) + ). + +% cl(H,B) <- (H:-B) is object-level clause +cl(rectangle,(polygon(4),angles(90))). +cl(square,(rectangle,regular)). +cl(triangle,polygon(3)). +cl(equilateral_triangle,(triangle,regular)). +%%% facts +cl(polygon(4),true). +cl(regular,true). +cl(angles(90),true). + +/** <examples> + +?- prove_r(rectangle). +?- prove_r(square). +?- prove_r(not(triangle)). +?- prove_r(not((rectangle,triangle))). + +*/ diff --git a/labs/psort.pl b/labs/psort.pl new file mode 100644 index 0000000..f3e9bd7 --- /dev/null +++ b/labs/psort.pl @@ -0,0 +1,32 @@ +:-use_module(library(random)). % for randseq/3 to generate random lists + +% psort(L,SL) <- L and SL contain the same elements, SL is sorted +psort(L,SL):- + perm(L,SL), % generator + write('. '), % demonstrate inefficiency of generator + sorted(SL). % tester + +% perm(L,PL) <- L and PL are permutations of each other +perm([],[]). +perm(L,[X|PR]):- + remove_one(X,L,R), + perm(R,PR). + +% remove_one(X,Ys,Zs) <- Zs is Ys minus one occurence of X +remove_one(X,[X|Ys],Ys). +remove_one(X,[Y|Ys],[Y|Zs]):- + remove_one(X,Ys,Zs). + +% sorted(L) <- L is a sorted list +sorted([]). +sorted([_X]). +sorted([X,Y|L]):- + ( compare('=', X, Y) + ; compare('<', X, Y) + ), sorted([Y|L]). + +/** <examples> + +?- randseq(5,100,In), psort(In,Out). + +*/ diff --git a/labs/secondorder.pl b/labs/secondorder.pl new file mode 100644 index 0000000..507dcc2 --- /dev/null +++ b/labs/secondorder.pl @@ -0,0 +1,29 @@ +% list of pairs +p1(L,X,Y):- + bagof((X,Y),(between(1,3,X),between(X,3,Y)),L). + +% one list for each X +p2(L,X,Y):- + bagof(Y,(between(1,3,X),between(X,3,Y)),L). + +% lists for each X combined +p3(L,X,Y):- + bagof(Y,X^(between(1,3,X),between(X,3,Y)),L). + +% one list for each Y +p4(L,X,Y):- + bagof(X,(between(1,3,X),between(X,3,Y)),L). + +% lists for each Y combined +p5(L,X,Y):- + bagof(X,Y^(between(1,3,X),between(X,3,Y)),L). + +/** <examples> + +?- p1(L,X,Y). +?- p2(L,X,Y). +?- p3(L,X,Y). +?- p4(L,X,Y). +?- p5(L,X,Y). + +*/ diff --git a/labs/setof_sort.pl b/labs/setof_sort.pl new file mode 100644 index 0000000..8fa1183 --- /dev/null +++ b/labs/setof_sort.pl @@ -0,0 +1,10 @@ +:-use_module(library(random)). % for randseq/3 to generate random lists + +setof_sort(In,Out):- + setof(X,member(X,In),Out). + +/** <examples> + +?- randseq(20,100,In), setof_sort(In,Out). + +*/