diff --git a/Frederik/README.md b/Frederik/README.md new file mode 100644 index 0000000000000000000000000000000000000000..48759441295640017d9a4fd9733b2ee0baf1c6e2 --- /dev/null +++ b/Frederik/README.md @@ -0,0 +1,10 @@ +Readme +=== + +AI 1 - 2019/2020 +--- + +* 2019-10-28: `prolog/2019-10-28-tutorial.pl` (simple prolog exercises) +* 2019-10-31 (substition for Katja): `prolog/2019-10-31-tutorial.pl` (simple prolog exercises) +* 2019-11-04: `prolog/2019-11-04-trees.pl` (some simple tree exercises) +* 2019-11-11: `2019-11-11-nary-trees.pl` (tree exercise in preparation for tree-search homework) diff --git a/Frederik/prolog/2019-10-28-tutorial.pl b/Frederik/prolog/2019-10-28-tutorial.pl new file mode 100644 index 0000000000000000000000000000000000000000..3ceaa148063645fa55d026340ec660c6828e808e --- /dev/null +++ b/Frederik/prolog/2019-10-28-tutorial.pl @@ -0,0 +1,64 @@ +% This is the prolog file we created during the tutorial. +% +% Remark: inspired by this problem list: http://www.ic.unicamp.br/~meidanis/courses/mc336/2009s2/prolog/problemas/ + + +% INTRODUCTION + +country(germany). + +geolocation(X) :- country(X). + + +bigger(russia, germany). +bigger(germany, belgium). +bigger(A, B) :- + bigger(A, C), bigger(C, B). + + +% LIST EXERCISES + +firstelement([A|_], A). + + +lastelement([A], A). +lastelement([_|A], B) :- + lastelement(A, B). + + +secondlast([H,_], H). +secondlast([_|A], B) :- + secondlast(A, B). + + +second([], []). +second([A], [A]). +second([A,_|B], [A|Restlist]) :- + second(B, Restlist). + + +prepend(A, B, [A|B]). + + +duplicate([], []). +duplicate([A], [A,A]). +duplicate([H|T], [H,H|T2]) :- + duplicate(T, T2). + + +% INSERTION SORT + +insert(Element, [], [Element]). + +insert(Element, [Hs|Ts], [Element,Hs|Ts]):- + Element =< Hs. + +insert(Element, [Hs|Ts], [Hs|Tl]) :- + Element >= Hs, + insert(Element, Ts, Tl). + +inssort([], []). +inssort([H|T], Result) :- + inssort(T, X), + insert(H, X, Result). + diff --git a/Frederik/prolog/2019-10-31-tutorial.pl b/Frederik/prolog/2019-10-31-tutorial.pl new file mode 100644 index 0000000000000000000000000000000000000000..11c4f282d0e9b46ca512e11a24b09a47aefa63d4 --- /dev/null +++ b/Frederik/prolog/2019-10-31-tutorial.pl @@ -0,0 +1,65 @@ +% INTRODUCTION + +animal(elephant). + +bigger(elephant, bird). +bigger(elephant, cow). +bigger(cow, mouse). + +bigger(X, Y) :- + bigger(X, A), bigger(A, Y). + +% Note: The above definition for a transitive relation +% results in loop, which wasn't resolved during the tutorial. +% If you want to know more about it, take a look at this answer: +% https://stackoverflow.com/a/28615704 + + +% SIMPLE LIST TASKS +% inspired from http://www.ic.unicamp.br/~meidanis/courses/mc336/2009s2/prolog/problemas/ + +getfirst([X|_], X). + +getlast([X], X). +getlast([_|R], X) :- + getlast(R, X). + +getsecondlast([X,_], X). +getsecondlast([_|R], X) :- + getsecondlast(R, X). + +getlength([], 0). +getlength([X|R], L) :- + getlength(R, N), L is N+1. + +second([], []). +second([X], [X]). +second([X,Y|R], [X|S]) :- + second(R, S). + +fourth(X, Y) :- + second(X, Z), second(Z, Y). + +prepend(X,SomeList,[X|SomeList]). + +duplicate([], []). +duplicate([X|R], [X,X|S]) :- + duplicate(R, S). + + +% INSERTION SORT + +insert(X, [], [X]). +insert(X, [H|R], [H|S]) :- + X >= H, insert(X, R, S). +insert(X, [H|R], [X,H|R]) :- + X =< H. + +inssort([], []). +inssort([H|T], L) :- + inssort(T, TSorted), + write('inserting '), + write(H), + write('\n'), + insert(H, TSorted, L). + diff --git a/Frederik/prolog/2019-11-04-trees.pl b/Frederik/prolog/2019-11-04-trees.pl new file mode 100644 index 0000000000000000000000000000000000000000..2c22b600fd268224e27ed66b88642b8219579136 --- /dev/null +++ b/Frederik/prolog/2019-11-04-trees.pl @@ -0,0 +1,61 @@ +% Check that a tree is indeed a binary tree +% (as specified in the homework) +isbinary(nil). +isbinary(tree(N, X, Y)) :- + integer(N), + isbinary(X), + isbinary(Y). + +% Helper predicate: get the maximum of two integers +% e.g max(2,7,X) results in X=7. +% +% ! is the cut operator. +% It tells prolog not to backtrack anymore. +% In this case, we want to ignore the second case, +% if the first case is applicable. +max(X,Y,X) :- X >= Y, !. +max(_,Y,Y). + +% Get the largest node in a tree +% (assuming it only contains natural numbers) +treemax(nil, 0). +treemax(tree(N, X, Y), Result) :- + treemax(X, XRes), + treemax(Y, YRes), + max(XRes, YRes, XYRes), + max(XYRes, N, Result). + +% Get the depth of a tree +treedepth(nil, 0). +treedepth(tree(_, X, Y), Depth) :- + treedepth(X, XDepth), + treedepth(Y, YDepth), + max(XDepth, YDepth, D), + Depth is D + 1. + +% helper predicate: concatenate two lists +concatenate([], L, L). +concatenate([H|T], L, [H|TL]) :- + concatenate(T, L, TL). + +% get the leaves of a binary tree +leaves(nil, []). +leaves(tree(N, nil, nil), [N]) :- !. +leaves(tree(N, X, Y), Result) :- + leaves(X, XL), + leaves(Y, YL), + concatenate(XL, YL, Result). + +% compute the result of a formula (which you can think of as a tree). +% Example tree: plus(times(2,6), 7) +compute(SomeInt, SomeInt) :- + integer(SomeInt). +compute(times(X, Y), R) :- + compute(X, XRes), + compute(Y, YRes), + R is XRes * YRes. +compute(plus(X, Y), R) :- + compute(X, XRes), + compute(Y, YRes), + R is XRes + YRes. + diff --git a/Frederik/prolog/2019-11-11-nary-trees.pl b/Frederik/prolog/2019-11-11-nary-trees.pl new file mode 100644 index 0000000000000000000000000000000000000000..33fc2225fac427a33d705dda77d0560e23508956 --- /dev/null +++ b/Frederik/prolog/2019-11-11-nary-trees.pl @@ -0,0 +1,35 @@ +% The tree definition from the homework assignment. +istree(tree(Value,Children)) :- + string(Value),subtrees(Children). +subtrees([]). +subtrees([(Cost,T)|Rest]) :- + number(Cost),istree(T), subtrees(Rest). + + +% An example tree. +% If you want to call e.g. addweights with this tree, you can do it with the following trick: +% tree1(X), addweights(X, Sum). +tree1(tree("A", [(2, tree("B", [(1, tree("E", [])), (2, tree("F", []))])), + (5, tree("C", [(2, tree("G", []))])), + (2, tree("D", [(1, tree("X", [(1, tree("Y", []))]))]))])). + +% Add up all the weights of the edges in the tree. +% (we called it cw in the tutorial) +addweights(tree(_, []), 0). +addweights(tree(_, [(X, T)|Rest]), S) :- + addweights(T, S1), + addweights(tree("asdf", Rest), S2), + S is X + S1 + S2. + +% Also adds up all the weights, but in a different way: +% In the previous attempt, we always expected a tree as argument and constructed trees on demand. +% In this approach we'll take a list of (Cost, Tree) pairs instead. +% This is not as pretty, but a useful approach for some tree search algorithms. +addweights2([], 0). +addweights2([(X, tree(_, Children))|Rest], S) :- + addweights2(Rest, S1), + addweights2(Children, S2), + S is S1 + S2 + X. +addweights2(T, S) :- + istree(T), + addweights2([(0, T)], S). diff --git a/Leon/tut1/examples.pl b/Leon/tut1/examples.pl new file mode 100644 index 0000000000000000000000000000000000000000..0f98fbbbe5f32836d60009a1eaf2419976bed68e --- /dev/null +++ b/Leon/tut1/examples.pl @@ -0,0 +1,96 @@ +peter. + +%?- peter. + +likes(peter, mary). +likes(peter, sophie). +cool(X) :- likes(peter,X). + +%?- trace, cool(sophie). + +%?- trace, cool(X). + +has_wheels(mybike, 2). +has_wheels(mytricycle, 3). +has_wheels(mytoycar, 4). +has_wheels(mycar, 4). +has_motor(mybike). +has_motor(mycar). +car(X) :- has_wheels(X, 4), has_motor(X). + +%?- trace, car(Y). + + +% Cool cool cool, but how can we code with this? +% The answers is for the most part...RECURSION! + +nat(zero). +nat(s(X)) :- nat(X). + +% add(X, Y, Z) -> X + Y = Z +add(X, zero, X). +add(X, s(Y), s(Z)) :- add(X, Y, Z). + +% We see, there is no "return" in Prolog, only predicates. +% For every predicate please state in a comment which parameters +% are input and which are output. + + +%% List comprehension: +% list e.g. [1,2,3] or [jamie,cersei], empty list = [] +% pattern matching with lists: +% [Head|Tail], where Head is an element and Tail is a List! +% Also works with first 2 elements [X1, X2 | T] + +append([],L2,L2). +append([H|T],L2,[H|Res]):- + append(T,L2,Res). + + + + + +% A practical example + +% Signature for our problem: +% countN(N : int, L : List[int]) -> int +% counts the occurrences of N in L and returns the result. +% With Prolog-like lists: countN(N, [H | T]) -> int + +% L = [2, 3, 5, 2, 7, 1, 2, 2, 5, 9] +% countN(3, L) -> 1 +% countN(2, L) -> 4 +% countN(8, L) -> 0 +% countN(5, L) -> 2 + +% Delcarative Approach +% countN(N, L) -> res +% res = 0 +% for e in L: +% if e == N: +% res += 1 +% return res + +% Functional / Recursive Approach +% Base Cases: +% countN(N, []) -> return 0 +% Recursive Case: +% countN(N, [H | T]) -> +% if N == H +% return countN(N, [T]) + 1 +% else +% return countN(N, [T]) + + +% ... in prolog we can't "return", so we need another variable in the predicate +% countN(N, L, RES) the number of occurrences of N in list L +% will be "returned/safed" in RES (Will be in relation with RES) + +% Base Cases: +countN(_, [], 0). +%?- trace, countN(2, [], X). +% Recursive Case: +countN(N, [N | T], RES) :- countN(N, T, OLDRES), RES is OLDRES + 1. +countN(N, [M | T], RES) :- not(N=M), countN(N, T, RES). +% Point out: "N" in first line list compr. "is" can be very useful +%?- trace, countN(2, [2], X). diff --git a/Leon/tut1/presentation-handout.pdf b/Leon/tut1/presentation-handout.pdf new file mode 100644 index 0000000000000000000000000000000000000000..c9a7c727c478742718ef5c43b739b7aff9ed231b Binary files /dev/null and b/Leon/tut1/presentation-handout.pdf differ diff --git a/Leon/tut2/presentation-handout.pdf b/Leon/tut2/presentation-handout.pdf new file mode 100644 index 0000000000000000000000000000000000000000..a20969cdb25c26437a1c92aa85cc0c3d9fb92c42 Binary files /dev/null and b/Leon/tut2/presentation-handout.pdf differ