Writing a math function in Prolog - prolog

I need to write a function in Prolog, but I don't understand how to return the value of R and put it in the final function. I get that Prolog doesn't return values, but I still can't figure it out.
This is what I have now:
run:- write('Input X, Z:'), nl,
read(X), number(X),
read(Z), number(Z),
func(X,Y),
write('Y='), write(Y), nl.
countR(X,Z,R):- X^2>=Z, R is Z*X.
countR(X,Z,R):- X^2<Z, R is Z*e^-X.
func(X,Y):- X>R, Y is 1-X^R.
func(X,Y):- X=<R, Y is 1-X^-R.

It would be like:
run:- write('Input X, Z:'), nl,
read(X), number(X),
read(Z), number(Z),
func(X,Z,Y),
write('Y='), write(Y), nl.
countR(X,Z,R) :-
Xsq is X^2,
Xsq >= Z,
R is Z*X.
func(X,Z,Y) :-
countR(X, Z, R),
X > R,
Y is 1-X^R.
"func holds for X, Z and Y if countR holds for X, Z, R and X is greater than R and Y is 1-X^R"
and same pattern for the other cases.

Related

Get unique results with Prolog

I have this Prolog code that returns: [[vincent,vincent],[vincent,marcellus],[marcellus,vincent],[marcellus,marcellus],[pumpkin,pumpkin],[honey_bunny,honey_bunny]].
:- initialization main.
loves(vincent, mia).
loves(marcellus, mia).
loves(pumpkin, honey_bunny).
loves(honey_bunny, pumpkin).
jealous(X, Y) :-
loves(X, Z),
loves(Y, Z).
main :-
findall([X, Y], jealous(X, Y), L),
write(L),
halt.
How to get the only results when X != Y?
I tried the following code to get the same results as before.
jealous(X, Y) :-
X \== Y,
loves(X, Z),
loves(Y, Z).
With \=, I got [].
How to get only [vincent,marcellus] as a result?
The order of the goals in your attempted solution is wrong. When called with two distinct variables, the (\==)/2 standard predicate always succeed. The solution is to call the predicate only when its arguments are instantiated:
jealous(X, Y) :-
loves(X, Z),
loves(Y, Z),
X \== Y.
With this fix, your query now returns:
?- findall([X, Y], jealous(X, Y), L).
L = [[vincent, marcellus], [marcellus, vincent]].
So, no one is jealous of himself anymore. But you still get a redundant solution. We can modify the jealous/2 predicate to sort the names in the returned solutions. For example:
jealous(X, Y) :-
loves(X0, Z),
loves(Y0, Z),
X0 \== Y0,
( X0 #< Y0 ->
X = X0, Y = Y0
; X = Y0, Y = X0
).
Now, by using setof/3 instead of findall/3, we get:
?- setof([X, Y], jealous(X, Y), L).
L = [[marcellus, vincent]].
One final observation. A list is a poor solution for representing a pair. The traditional way is to use either X-Y or (X, Y).
Whenever possible, use dif/2 instead of (\==)/2.
dif/2 will help you write logically sound programs.
For details, look at prolog-dif!

Prolog: Unification or Backtracking errors in program

I have a simple knowledge base that encodes a family tree. Some important rules in this representation are as follows:
% fathers
father(michael,cathy).
father(michael,sharon).
father(charles_gordon,michael).
father(charles_gordon,julie).
father(charles,charles_gordon).
father(jim,melody).
father(jim,crystal).
father(elmo,jim).
father(greg,stephanie).
father(greg,danielle).
% mothers
mother(melody,cathy).
mother(melody,sharon).
mother(hazel,michael).
mother(hazel,julie).
mother(eleanor,melody).
mother(eleanor,crystal).
mother(crystal,stephanie).
mother(crystal,danielle).
% parents
parent(X,Y) :- father(X,Y).
parent(X,Y) :- mother(X,Y).
% men
male(michael).
male(charles_gordon).
male(charles).
male(jim).
male(elmo).
male(greg).
% women
female(cathy).
female(sharon).
female(julie).
female(hazel).
female(eleanor).
female(melody).
female(crystal).
female(stephanie).
female(danielle).
person(X) :- male(X) ; female(X).
parent(X,Y) :- father(X,Y) ; mother(X,Y). % X is parent of Y
child(X,Y) :- parent(Y,X).
elder(X,Y) :- parent(X,Y). % X is an elder of Y, meaning X is a parent or an ancestor of Y
elder(X,Y) :- parent(X,Z), elder(Z,Y).
junior(X,Y) :- child(X,Y). % X is a junior of Y, meaning X is a child or some descendant of Y
junior(X,Y) :- child(X,Z), junior(Z,Y).
I am attempting to find the nearest elder between two individuals(predicate ne(X,Y,Z)). This individual Z is the elder of both X and Y, and no junior of Z is also an elder of BOTH X and Y.
My attempt looks like this:
ne(X,Y,Z) :- person(X),
person(Y),
X \= Y,
elder(Z,X),
elder(Z,Y),
junior(A,Z),
not(elder(A,X)),
not(elder(A,Y)).
but this is somehow incorrect, because whenever I run ?- ne(stephanie,cathy,Z). i get
Z = jim ;
Z = jim ;
Z = jim ;
Z = jim ;
Z = elmo ;
Z = elmo ;
Z = elmo ;
Z = elmo ;
Z = eleanor ;
Z = eleanor ;
Z = eleanor ;
Z = eleanor ;
but i'm only supposed to get one answer, and I can't figure out what's wrong. Thanks!
from this graph
seems this answer is correct
?- ne(stephanie,cathy,A).
A = eleanor ;
A = jim.
here is my attempt to ne/3
ne(X,Y,Z) :-
setof(A, (
elder(A, X),
elder(A, Y),
X \= Y,
\+ (elder(A, T), elder(T, X) , elder(T, Y) ))
, As), member(Z, As).
not sure it's the better way...
Setof/3 (joined with member/2) is used to eliminate duplicate answers, since we get
?- aggregate(count,A^ne(stephanie,cathy,A),N).
N = 32.
with this core logic
ne(X,Y,A) :-
elder(A, X),
elder(A, Y),
X \= Y,
\+ (elder(A, T), elder(T, X) , elder(T, Y)).
note variable A replaces locally the original Z
edit
I didn't took in account the savvy comment by #Boris, but after removing the duplicate parent/2 definition, the setof/3+member/2 trick become useless.

Prolog: how can i count number in prolog?

if the goal can (5,3) the out put could be 5,4,3 this my code found big error
predicates
count(integer, integer)
clauses
count(X, Y) :- X > Y, write(3), !.
count(X < Y) :- X > Y, write(X), nl, X1 = X-1, count(X1, Y).
count(X,X):-write(X),nl.
count(X,Y):-X<Y,write(X),nl,X1 is X+1,count(X1,Y).

Implement a predicate subtraction

So far, my program can add two numbers together.
s(0) represents 1, s(s(0)) represents 2 and so on
p(0) represents -1, p(p(0)) is -2 etc.
I want to be able to call a program such that
add2(s(s(0)), p(0), Z).
returns
Z = s(0).
My code is as follows:
numeral(0).
numeral(s(X)) :- numeral(X).
add(0,X,X).
add(s(X),Y,s(Z)) :- add(X,Y,Z).
numeral(X+Y) :- numeral(X), numeral(Y).
add2(X,Y,Z):-add(X,Y,Z).
add2(X+Y, Z,A) :-add(X,Y,R),add2(R,Z,A).
add2(Z,X+Y,A) :-add(X,Y,R),add2(Z,R,A).
numeral(p(X)) :- numeral(X).
add2(p(X),Y,p(Z)) :- add2(X,Y,Z).
p(s(X)) =:= 0.
s(p(X)) =:= 0.
My logic was that if p(s(0)) was in the list, it would just equate it to 0.. I was wrong, however. Does anybody know where to go with this?
Each numeral could be represented only in one of these 3 ways:
0 - null;
s(X) - next, where X is numeral;
p(X) - previous, where X is numeral;
add2/3 should take 2 numerals and return sum of them. It could be defined manually for each possible arguments:
add2(0, 0, 0).
add2(0, s(X), Y) :- Y = s(X).
add2(0, p(X), Y) :- Y = p(X).
add2(s(X), 0, Y) :- Y = s(X).
add2(s(X), s(Y), Z) :- add2(X, Y, s(s(Z))).
add2(s(X), p(Y), Z) :- add2(X, Y, Z).
add2(p(X), 0, Y) :- Y = p(X).
add2(p(X), s(Y), Z) :- add2(X, Y, Z).
add2(p(X), p(Y), Z) :- add2(X, Y, p(p(Z))).
Works well:
?- add2(s(s(0)), p(0), Z).
Z = s(0) .
It is notable that many cases of add2/3 rule is actually overlapped and could be eliminated:
add2(0, X, X).
add2(X, 0, X).
add2(s(X), s(Y), Z) :- add2(X, Y, s(s(Z))).
add2(s(X), p(Y), Z) :- add2(X, Y, Z).
add2(p(X), s(Y), Z) :- add2(X, Y, Z).
add2(p(X), p(Y), Z) :- add2(X, Y, p(p(Z))).

What do results like Z = [_G305] mean in prolog?

I've got these definitions:
memberx(X, [X|_]).
memberx(X, [_|T]) :- memberx(X, T).
intersectionx([], _, []).
intersectionx([H|T], Y, [_|Z]) :- memberx(H, Y), !, intersectionx(T, Y, Z).
intersectionx([_|T], Y, Z) :- intersectionx(T, Y, Z).
I get the following result:
?- intersectionx([1], [1], Z).
Z = [_G305].
Why doesn't it result in Z = [1]??
Z = [_G305].
means that this answer is true for all terms. That is, it is not
only true for Z = [1] - as you expect, but it is also true for Z = [2].
Clearly, that is not what you expected.
So where is the error? A simple way to detect it is to watch out for anonymous
variables denoted _.
Consider:
intersectionx([H|T], Y, [_|Z]) :- memberx(H, Y), !, intersectionx(T, Y, Z).
^^^
What you have written means that the intersection of a list starting with
H and another list will be (provided the goals on the right hand side
are all true) a list starting with anything... Replace anything by that H!

Resources