Laborator 3
Problema 1
Cod:
abs(X, X) :- X>=0,!.
abs(X, Y) :- Y is -X.
Metoda alternativa:
abs2(X, Y) :- (X>=0, Y is X, !) ;
Y is -X.
Apel:
abs(2, Y).
abs(-2, Y).
Rezultatul obtinut:
Y = 2.
Y = 2.
Explicatii:
Daca prima conditie nu a fost valida, stim cu siguranta ca X este mai mic ca 0. In caz ca prima conditie este indeplinita, punem operatorul "cut" pentru a nu cauta si alta solutie in mod inutil.
Problema 2
Cod:
fibonacci(0, 0):-!.
fibonacci(1, 1):-!.
fibonacci(N, F) :- N>1,
Nnew is N-1,
Nnew2 is N-2,
fibonacci(Nnew, Fnew),
fibonacci(Nnew2, Fnew2),
F is Fnew+Fnew2.
Apel:
fibonacci(5, F).
Rezultatul obtinut:
F = 5.
Explicatii:
Trebuie sa punem "Nnew" si "Nnew2" din motivele precizate in lucrarea de laborator.
Problema 3
Cod:
divisor(X, Y, D) :- (Y=:=0, D is X, !) ;
Rest is X mod Y,
divisor(Y, Rest, D).
variante:
cmmdc(A, 0, D) :- D is A,!.
cmmdc(A, B, D) :- Rest is A mod B, cmmdc(B, Rest, D).
cmmdc2(A, B, D) :- (B=:=0, D is A, !);
Rest is A mod B, cmmdc2(B, Rest, D).
cmmdc3(A, A, D) :- D is A, !.
cmmdc3(A, B, D) :- A > B, Dif is A-B, cmmdc(Dif, B, D).
cmmdc3(A, B, D) :- A < B, Dif is B-A, cmmdc(A, Dif, D).
cmmdc4(A, B, D) :- (A=:=B, D is A,!);
(A > B, Dif is A-B, cmmdc(Dif, B, D));
(A < B, Dif is B-A, cmmdc(A, Dif, D)).
Apel:
divisor(15, 3, D).
Rezultatul obtinut:
D = 3.
Explicatii:
Algoritmul lui Euclid... punem operatorul "cut" pentru a stopa procesul de backtracking.
Problema 4
Cod:
evaluating(Expression, Value) :- Exp is Expression, plus(Exp, 0, Value).
eval(X, X) :- number(X).
eval(A+B, Value) :- eval(A, Anew), plus(Anew, B, Value).
eval(A-B, Value) :- eval(A, Anew), plus(B, Value, Anew).
Apel:
evaluating(1+2+3+4+5, R).
eval(1+2+3+4+5, R).
Rezultatul obtinut:
R = 15.
R = 15.
Explicatii:
Instantiez expresia si dupa o verific folosind metoda predefinita.
Sol 2:
A+B=1+2+3. =>A=1+2 si B=3.
A+B=V
Problema 5
Consider the following rules for symbolic differentiation (U, V are mathematical expressions, x is a variable):
dx/dx = 1
d(-U)/dx = -(dU/dx)
d(U+V)/dx = dU/dx + dV/dx
d(U-V)/dx = dU/dx - dV/dx
d(U*V)/dx = U*(dV/dx) + V*(dU/dx)
These rules can easily be translated into Prolog, for instance, the third rule can be defined as
diff(plus(U,V),x,plus(RU,RV)) :-
diff(U,x,RU),
diff(V,x,RV).
Write the remaining rules. Here is a test query:
?- diff(plus(times(x,x),x),x,Result).
Result = plus(plus(times(x, 1), times(x, 1)), 1) ;
No
Note: Prolog has built-in functors such as +, - and * that can be used in infix or prefix notation, so the given Prolog clause can also be written as diff(U+V,x,RU+RV):-diff(U,x,RU),diff(V,x,RV).
Keep in mind, though, that terms such as U+V are still trees with the functor at the root, and that evaluation of such terms requires additional processing (see the next question).
Write a predicate that simplifies mathematical expressions as follows:
U*1 = U
U+0 = U
U+U = 2*U
U-U = 0
Hint: most of your clauses will need to be recursive. Also add a base case that leaves the expression untouched (in case none of the cases applies), and recursive clauses that take expressions of the form U+V and return X+Y, where X is the simplification of U and Y is the simplification of V.
Here is a test query:
?- simp(plus(plus(times(x,1),times(x,1)),1),Result).
Result = plus(times(2, x), 1) ;
No
Cod:
Apel:
Rezultatul obtinut:
Explicatii: