Somebody could help me with this little program in prolog? - prolog

When I run my program with this sentence:
| ?- constraints(C).
and the result is:
C = [espacio(chuck,brenda,lewis,cafe,treintayuno),
espacio(bill,mary,tread,rojo,veinteynueve),
espacio(steve,cindy,branch,negra,cuarentaytres),
espacio(tom,laura,forrest,azul,treintaycinco)|_A] ?
The result is fine but at the end is there an "|A" and I don't know what is wrong???
It is my code:
/*
Cuatro parejas deciden ir a acampar a la selva del estado un fin de semana.
Cada pareja viajo en una van diferente y cada una eligio un espacio de
campo separado. Todos los sitios para acampar estan etiquetados con un
numero y mientras estan en la misma area los sitios no se juntan entre si.
Determina el nombre completo de cada pareja, color de van y numero de su
espacio de campo.
TRADUCCION
1.- BIll quie no esta casado con Laura, no manejo una Van Negra
2.- Chuck y su esposa Brenda no acamparon en el espacio #35. El apellido de
Breanda no es Forrest
3.- La pareja Lewis quien manejo una van Cafe, acamparon en el espacio 31
4.- Tom acampo en un espacio mas bajo del que acampo Cindy pero mas alto
que la pareja que manejo una Van Roja.
5.- Tom no esta casado con Mary Tread. Steve Branch no maneja una van azul.
6.- La pareja que maneja la van negra acampo en el espacio #43
ORIGINAL
1. Bill, who is not married to Laura, didn't drive a black van.
2. Chuck and his wife Brenda were not camped in space #35. Brenda's last
name is not
Forrest.
3. The Lewis couple, who drove a tan van, camped in space #31.
4. Tom camped in a space numbered lower than the one Cindy camped in but
higher than the
couple who drove in the red van did.
5. Tom isn't married to Mary Tread. Steve Branch didn't drive a blue van.
6. The couple driving the black van camped in space #43.
*/
use_module( library(basics)).
use_module(library(lists)).
% UN CAMPAMENTO ES UNA LISTA DE 5 ESPACIOS; CADA ESPACIO TIENE UNA PAREJA
(HOMBRE Y MUJER Y APELLIDO) UNA VAN Y UN NUMERO DE ESPACIO.
campamento([espacio(_,_,_,_,_),
espacio(_,_,_,_,_),
espacio(_,_,_,_,_),
espacio(_,_,_,_,_)]).
% De acuerdo a las sentencias previas podemos establecer lo siguiente:
constraints( Campamento ):-
member(espacio(chuck,brenda,_,_,_), Campamento), % 2)
member(espacio(_,_,lewis,cafe,treintayuno), Campamento), % 3)
member(espacio(_,mary,tread,_,_), Campamento), % 5)
member(espacio(_,_,_,rojo,veinteynueve), Campamento), % implicito
)
member(espacio(_,_,_,negra,cuarentaytres), Campamento), % 6)
member(espacio(_,_,_,azul,treintaycinco), Campamento), % implicito
)
member(espacio(bill,_,_,_,veinteynueve), Campamento), % implicito
)
member(espacio(steve,cindy,branch,_,_), Campamento), % implicito )
member(espacio(_,cindy,_,_,cuarentaytres), Campamento), %
implicito )
member(espacio(tom,laura,forrest,_,_), Campamento). % implicito )
% member(espacio(tom,_,_,blue,_), Campamento). % implicito )
% member(espacio(_,mary,_,red,_), Campamento). % implicito )
append([X|Y],Z,[X|W]) :- append(Y,Z,W).
append([],X,X).
member(X,[X|_]).
member(X,[_|T]) :- member(X,T).
% perm2(X,Y, X,Y).
% perm2(X,Y, Y,X).
/*member(X,[X|T]).
member(X,[H|T]) :- member(X,T).*/

(Your program has several errors: In particular use_module(xx) must be prefixed with :-)
constraints/1 essentially looks like this:
constraints(L) :-
member(a, L),
member(b, L),
member(c, L),
member(d, L).
So you demand that a, b, c, and d are elements of L. But nowhere do you state how long the list should be. You can observe this by looking at alternate answers pressing ;Return.
?- constraints(L).
L = [a, b, c, d|_A]
; L = [a, b, c, _A, d|_B]
; L = [a, b, c, _A, _B, d|_C]
; false.
To fix this, add length(L, 4) at the beginning, before any goal member/2.

OK, it is my Friend!!!
Thanks very much for all you help!!! it is the code like how i tell you:
/*
ORIGINAL
1. Bill, who is not married to Laura, didn't drive a black van.
2. Chuck and his wife Brenda were not camped in space #35. Brenda's last name is not
Forrest.
3. The Lewis couple, who drove a tan van, camped in space #31.
4. Tom camped in a space numbered lower than the one Cindy camped in but higher than the
couple who drove in the red van did.
5. Tom isn't married to Mary Tread. Steve Branch didn't drive a blue van.
6. The couple driving the black van camped in space #43.
*/
%:- use_module( library(basics)).
:- use_module(library(lists)).
campamento([espacio(_,_,_,_,_),
espacio(_,_,_,_,_),
espacio(_,_,_,_,_),
espacio(_,_,_,_,_)]).
constraints( Campamento ):-
length(Campamento, 4),
% campamento(Campamento),
member(espacio(chuck,brenda,_,_,_), Campamento), % 2)
member(espacio(_,_,lewis,cafe,treintayuno), Campamento), % 3)
member(espacio(_,mary,tread,_,_), Campamento), % 5)
member(espacio(_,_,_,rojo,veinteynueve), Campamento), % implicito
member(espacio(_,_,_,negra,cuarentaytres), Campamento), % 6)
member(espacio(_,_,_,azul,treintaycinco), Campamento), % implicito
member(espacio(bill,_,_,_,veinteynueve), Campamento), % Implicito
member(espacio(steve,cindy,branch,_,_), Campamento), % implicito
member(espacio(_,cindy,_,_,cuarentaytres), Campamento), % implicito
member(espacio(tom,laura,forrest,_,_), Campamento). % implicito
append([],X,X).
append([X|Y],Z,[X|W]) :- append(Y,Z,W).
member(X,[X|T]).
member(X,[H|T]) :- member(X,T).
perm2(X,Y, X,Y).
perm2(X,Y, Y,X).

Related

Convert FOPL expression to prolog

Given premises and corresponding FOPL. Goal: Prove that Marcus hated Caesar.
Marcus was a Pompeian
pompeian(Marcus)
All Pompeians were Romans.
Vx: pompeian(x) --> roman(x)
All Romans were either loyal to Caesar or hated him.
Vx: roman(x) --> loyalto(x, Caesar) v hate(x, Caesar)
Everyone is loyal to someone.
Vx Ey: loyalto(x, y)
People only try to assassinate rulers they aren't loyal to.
Vx Vy: ~loyalto(x, y) --> trytoassassinate(x, y)
Marcus tried to assassinate Caesar.
trytoassassinate(Marcus, Caesar)
How can I implement each of the premises one by one using SWI Prolog?
I tried to write prolog and code and attached my implementation below, I am having difficulty implementing rule number 4.
roman(X):-
pompeians(X).
hates(X, caesar):-
roman(X), not_loyal(X, caesar).
not_loyal(X,Y):-
not(loyal(X,Y)).
% How to implement "Everyone is loyal to someone."?
not_loyal(X,Y):-
assassinate(X,Y).
assassinate(marcus, caesar).
pompeians(marcus).
How about:
% 1
pompeian(marcus).
% 2
roman(P) :-
pompeian(P).
% 3
roman_loyalty_ceasar_feeling(caesar, loyal).
roman_loyalty_ceasar_feeling(notcaesar, hatred).
roman_loyalty_feeling(P, LoyalTo, CaesarFeel) :-
roman(P),
roman_loyalty_ceasar_feeling(LoyalTo, CaesarFeel). % 3
person(P, LoyalTo, CaesarFeel) :-
roman_loyalty_feeling(P, LoyalTo, CaesarFeel), % 4
\+ try_assassinate(P, LoyalTo). % 5
% 6
try_assassinate(marcus, caesar).
Result in swi-prolog:
?- person(Person, LoyalTo, CaesarFeel).
Person = marcus,
LoyalTo = notcaesar,
CaesarFeel = hatred.

Problem in generating verses of a poem in prolog

Given a problem in Prolog,
In a lost-world language, a poem can have any number of verses, each of which takes the following form:
A B B C
D E E C
F F G
H I I C
where the same letter represents rhymed words. For example,
anun kura tama su
unuri bimo co kuru
sonen ariten sicom
kana te shime xanadu.
We have to generate a poem for a given no of verses.
My code
norhyme(X):- X="anun";X="unuri";X="sicom";X="kana".
pairrhyme(X,Y):-X="kura",Y="tama";
X="tama",Y="Kura";
X="bimo",Y="co";
X="co",Y="bimo";
X="sonen",Y="ariten";
X="ariten",Y="sonen";
X="te",Y="shime";
X="shime",Y="te";
X="su",Y="kuru";
X="kuru",Y="su";
X="kuru",Y="shanadu";
X="shanadu",Y="kuru";
X="su",Y="xanadu",
X="xanadu",Y="su".
triplerhyme(X,Y,Z):-X="su",Y="kuru",Z="xanadu".
generatepoem(0).
generatepoem(Y):- norhyme(A),pairrhyme(B,C),triplerhyme(D,E,F),
write(A),write(' '),write(B),write(' '),write(C),write(' '),write(D),nl,
norhyme(G),pairrhyme(H,I),
write(G),write(' '),write(H),write(' '),write(I),write(' '),write(E),nl,
pairrhyme(J,K),norhyme(L),
write(J),write(' '),write(K),write(' '),write(L),nl,
norhyme(M),pairrhyme(N,O),
write(M),write(' '),write(N),write(' '),write(O),write(' '),write(F), nl,
Y1 is Y-1,generatepoem(Y1).
Ideally the output should be
anun kura tama su
anun kura tama kuru
kura tama anun
anun kura tama xanadu
//as well as
anun kura tama su
anun tama kura kuru
bimo co anun
anun kuru su xanadu
//and all other possible combinations
However I don't get all the combinations and my program enters an infinite loop. What is the problem??
For more information,drop a comment below.
Here is a more stylish-correct version:
norhyme(anun).
norhyme(unuri).
norhyme(sicom).
norhyme(kana).
pairrhyme_one_way(kura,tama).
pairrhyme_one_way(bimo,co).
pairrhyme_one_way(sonen,ariten).
pairrhyme_one_way(te,shime).
pairrhyme_one_way(su,kuru).
pairrhyme_one_way(kuru,shanadu).
pairrhyme_one_way(su,xanadu).
pairrhyme(X,Y) :- pairrhyme_one_way(X,Y).
pairrhyme(X,Y) :- pairrhyme_one_way(Y,X).
triplerhyme(su,kuru,xanadu).
generatepoem(0).
generatepoem(Y):-
Y > 0,
norhyme(A),
pairrhyme(B,C),
triplerhyme(D,E,F),
format("~a ~a ~a ~a~n",[A,B,C,D]),
norhyme(G),
pairrhyme(H,I),
format("~a ~a ~a ~a~n",[G,H,I,E]),
pairrhyme(J,K),
norhyme(L),
format("~a ~a ~a~n",[J,K,L]),
norhyme(M),
pairrhyme(N,O),
format("~a ~a ~a ~a~n",[M,N,O,F]),
Y1 is Y-1,
% If we "cut" here, we will always choose the same solution...
generatepoem(Y1).
Even better would be to build a list of lines via generatepoem and output it once instead of performing side-effects "during the proof search".
Note the following:
For generatepoem/1 we succeed with no further side-effects if the argument is 0, and we perform further side-effects otherwise. However, the "otherwise" case is guarded by Y > 0. If we don't do that, the proof search succeeds on the base case 0 and there is another solution where generatepoem(0) performs side-effects, then calls itself with -1, -2, -3 ... ad infinitum.
The solution does not commit to the choices made in a passage through generatepoem/1 because we don't "cut" at the place where I put the comment. SO through backtracking, we will eventually generate all possible poems, but that is not really interesting. Better to select a poem at random...
Change the code to construct a solution and then output once
Solving the uglyness of a spray of format/2 calls first:
generatepoem([],0).
generatepoem([[A,B,C,D],[G,H,I,E],[J,K,L],[M,N,O,F]|More],Y):-
Y > 0,
norhyme(A),
pairrhyme(B,C),
triplerhyme(D,E,F),
norhyme(G),
pairrhyme(H,I),
pairrhyme(J,K),
norhyme(L),
norhyme(M),
pairrhyme(N,O),
Y1 is Y-1,
generatepoem(More,Y1).
dump([]) :- !.
dump([[A,B,C,D]|More]) :-
!,
format("~a ~a ~a ~a~n",[A,B,C,D]),
dump(More).
dump([[A,B,C]|More]) :-
format("~a ~a ~a~n",[A,B,C]),
dump(More).
Note the cuts in the bodies of dump/2 to tell Prolog there are no alternative solutions (SWI-Prolog doesn't see that by itself).
The stream of poems can now be generated through:
?- generatepoem(L,2),dump(L).
Change the code to construct a solution randomly (although we can't backtrack)
This is done by harnessing the power of bagof/3 and random_between/3 (the latter eminently a non-logic predicate):
When all is said and done:
norhyme(anun).
norhyme(unuri).
norhyme(sicom).
norhyme(kana).
pairrhyme_one_way(kura,tama).
pairrhyme_one_way(bimo,co).
pairrhyme_one_way(sonen,ariten).
pairrhyme_one_way(te,shime).
pairrhyme_one_way(su,kuru).
pairrhyme_one_way(kuru,shanadu).
pairrhyme_one_way(su,xanadu).
pairrhyme(X,Y) :- pairrhyme_one_way(X,Y).
pairrhyme(X,Y) :- pairrhyme_one_way(Y,X).
triplerhyme(su,kuru,xanadu).
% we need a 1-arg equivalent to pairrhyme/2
pairrhyme_tuple([X,Y]) :- pairrhyme_one_way(X,Y).
pairrhyme_tuple([X,Y]) :- pairrhyme_one_way(Y,X).
% non-backtrackably select a random element from a list
randomly_select(List,Element) :-
length(List,Length),
MaxIndex is Length-1,
random_between(0,MaxIndex,Index), % fails if MaxIndex < 0, i.e. if List is empty
nth0(Index,List,Element).
% non-backtrackably select a random solution of Goal
% this works because our Goals do not generate all that many solutions
random_solution(Goal,Element) :-
bagof(X,call(Goal,X),Bag), % fails if there is no solution
randomly_select(Bag,Element).
% an equivalent of nohryme/1 which non-backtrackably selects a random solution
norhyme_randomly(X) :- random_solution(norhyme,X).
% an equivalent of pairrhyme/2 which non-backtrackably selects a random solution
pairrhyme_randomly(X,Y) :- random_solution(pairrhyme_tuple,[X,Y]).
% an equivalent of generatepoen/2 which non-backtrackably selects a random solution
generatepoem_randomly([],0).
generatepoem_randomly([[A,B,C,D],[G,H,I,E],[J,K,L],[M,N,O,F]|More],Y):-
Y > 0,
norhyme_randomly(A),
pairrhyme_randomly(B,C),
triplerhyme(D,E,F),
norhyme_randomly(G),
pairrhyme_randomly(H,I),
pairrhyme_randomly(J,K),
norhyme_randomly(L),
norhyme_randomly(M),
pairrhyme_randomly(N,O),
Y1 is Y-1,
generatepoem_randomly(More,Y1).
dump([]) :- !.
dump([[A,B,C,D]|More]) :-
!,
format("~a ~a ~a ~a~n",[A,B,C,D]),
dump(More).
dump([[A,B,C]|More]) :-
format("~a ~a ~a~n",[A,B,C]),
dump(More).
And so:
?- generatepoem_random(L,2),dump(L).
unuri shime te su
sicom sonen ariten kuru
ariten sonen unuri
anun kura tama xanadu
kana shime te su
unuri su xanadu kuru
te shime sicom
kana su xanadu xanadu

Square placing in Prolog

I have a nxn area. And I want to list all of the positions of possible kxk m squares (k < n) which don't touch each other in that area. I want to list the coordinates of the upper-leftmost squares of those kxk squares. Can you give me some hint about implementing this with Prolog? I'm very new to this language. I just read a small tutorial but now I don't know what to do.
They are also touching if their corners touch.
The input and output should be like this :(k : size of small square,n : size of big square, m: number of small squares)
>func(k,n,m,O).
>func(1,3,2,O).
O =[1-1,1-3];
O =[1-1,2-3];
O =[1-1,3-1];
O =[1-1,3-2];
O =[1-1,3-3];
O =[1-2,3-1];
O =[1-2,3-2];
O =[1-2,3-3];
O =[1-3,2-1];
O =[1-3,3-1];
O =[1-3,3-2];
O =[1-3,3-3];
O =[2-1,2-3];
O =[2-1,3-3];
O =[2-3,3-1];
O =[3-1,3-3];
No.
I post a solution showing a possible Prolog coding, in style generate and test. There is some slot where you'll place appropriate arithmetic, just to complete your assignment.
%% placing
place_squares(Big, Small, Squares) :-
place_not_overlapping(Big, Small, [], Squares).
place_not_overlapping(Big, Small, SoFar, Squares) :-
available_position(Big, Small, Position),
\+ overlapping(Small, Position, SoFar),
place_not_overlapping(Big, Small, [Position|SoFar], Squares).
place_not_overlapping(_Big, _Small, Squares, Sorted) :-
sort(Squares, Sorted).
overlapping(Size, R*C, Squares) :-
member(X*Y, Squares),
... % write conditions here
available_position(Big, Small, Row*Col) :-
Range is Big - Small + 1,
between(1, Range, Row),
between(1, Range, Col).
after placing, it's easy to display
%% drawing
draw_squares(Big, Small, Squares) :-
forall(between(1, Big, Row),
(forall(between(1, Big, Col),
draw_point(Row*Col, Small, Squares)),
nl
)).
draw_point(Point, Small, Squares) :-
( nth1(I, Squares, Square),
contained(Point, Square, Small)
) -> write(I) ; write('-').
contained(R*C, A*B, Size) :-
... % place arithmetic here
the result with requested dimensions, and drawing
?- place_squares(5,2,Q),draw_squares(5,2,Q).
1122-
1122-
3344-
3344-
-----
Q = [1*1, 1*3, 3*1, 3*3] ;
1122-
1122-
33-44
33-44
-----
Q = [1*1, 1*3, 3*1, 3*4] ;
1122-
1122-
33---
3344-
--44-
Q = [1*1, 1*3, 3*1, 4*3] .
...
the place_squares/3 output is sorted, to ease displaying, and could as well be used to get rid of symmetry, and get a count of all solutions:
9 ?- setof(Q, place_squares(5,2,Q), L), length(L, N).
L = [[], [1*1], [1*1, 1*3], [1*1, 1*3, 3*1], [1*1, 1*3, 3*1, ... * ...], [1*1, 1*3, ... * ...|...], [1*1, ... * ...|...], [... * ...|...], [...|...]|...],
N = 314.
You can note that this accepts boards with 'spare' space. You could filter out such incomplete solutions, to complete your task.

From 8-Queens solution to more generic n-Queens solution in Prolog

I am studying Prolog for an universitary exame and I have some problem with the following exercise.
I have the following classic solution of 8-Queens problem (and this is not a problem for me), Modifying this solution I have to create a new solution for the more generic n-Queens problem that handle a variable number of queens.
solution([]).
solution([X/Y|Others]) :- solution(Others),
member(Y,[1,2,3,4,5,6,7,8]),
noattack(X/Y, Others).
noattack(_,[]).
noattack(X/Y, [X1/Y1 | Others]) :-
Y =\= Y1, % Q e Q1 sono su righe diverse
% Q e Q1 sono su diagonali diverse:
Y1-Y =\= X1-X,
Y1-Y =\= X-X1,
% Q non attacca regine nella sottolista Others:
noattack( X/Y, Others).
% TEMPLATE DELLE SOLUZIONI: c'è una regina su ogni colonna:
template([1/Y1,2/Y2,3/Y3,4/Y4,5/Y5,6/Y6,7/Y7,8/Y8]).
Ok, this program look pretty simple: I have a list of queen that have that they must not attack each other.
If the list of queen is empty there is not the possibility that a queen attack another queen in the list, so the empty list is a solution of the problem (it is the base case of the solution)
*If the list of queen is not empty I can divide it into [X/Y|Others] where X/Y rappresent position on the board of the first queen in the list *(the position is rappresentend by the couple (X,Y) where X is the column and Y the line)
So, it is TRUE that the list [X/Y|Others] is a SOLUTION of the problem if the following relations are true:
The sublist Others is itself a solution (Others don't contain queen that attack some other queen in the list)
Y belongs belongs to an integer value between 1 and 8 (because I have 8 line)
The first queen of the list don't attacck the others queens in the sublist Others
Then it is defined the noattack relation that specify when I can say that it is true that a queen don't attack another queen (this is pretty simple: they can't stay on the same line, on the same column, on the same diagonal)
Finally I have a solution template that simplify my life constraining the X value with value from 1 to 8 (because I know that 2 queens can't stay on the same columns...so every queen in the solution stay on a different column from all others queens)
So I think that the biggest problem it is on the line in which I specify the number of columns:
member(Y,[1,2,3,4,5,6,7,8])
and on the line in which I define the solution template:
template([1/Y1,2/Y2,3/Y3,4/Y4,5/Y5,6/Y6,7/Y7,8/Y8]).
I have no idea about how to extend the previous solution to handle a variable number of queens.
seems easy, passing around the size:
solution(_, []).
solution(N, [X/Y|Others]) :-
solution(N, Others),
between(1, N, Y),
noattack(X/Y, Others).
noattack(_,[]).
noattack(X/Y, [X1/Y1 | Others]) :-
Y =\= Y1, % Q e Q1 sono su righe diverse
Y1-Y =\= X1-X, % Q e Q1 sono su diagonali diverse
Y1-Y =\= X-X1,
noattack( X/Y, Others). % Q non attacca regine nella sottolista Others
% TEMPLATE DELLE SOLUZIONI: c'è una regina su ogni colonna:
template(N, L) :-
findall(I/_, between(1,N,I), L).
test:
?- N=6, template(N, L), solution(N, L).
N = 6,
L = [1/5, 2/3, 3/1, 4/6, 5/4, 6/2] ;
N = 6,
L = [1/4, 2/1, 3/5, 4/2, 5/6, 6/3] ;
N = 6,
L = [1/3, 2/6, 3/2, 4/5, 5/1, 6/4] ;
N = 6,
L = [1/2, 2/4, 3/6, 4/1, 5/3, 6/5] ;
false.
(I should draw it to say if it's ok...)

Implementing a relation on a data structure [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I have the following simple Prolog program that, through the use of data structure, represents a family composed of husband, wife and children list:
family(
person(bob, smith, date(7,may,1968), 30000),
person(ann, smith, date(18,july,1970), 32000),
[person(dave, smith, date(1,june,1984), 0),
person(edna, smith, date(25,may,1990), 0)]
).
family(
person(mario, rossi, date(7,may,1968), 30000),
person(lucia, verdi, date(18,july,1970), 32000),
[person(luca, rossi, date(1,june,1984), 5000),
person(maria, rossi, date(25,may,1990), 0),
person(paolo, rossi, data(16, april, 1980), 10000)]
).
family(
person(carlo, bianchi, date(7,may,1968), 30000),
person(flavia, blabla, date(18,july,1970), 32000),
[person(figlio1, bianchi, date(1,june,1984), 0),
person(figlio2, bianchi, date(25,may,2001), 0),
person(figlio3, bianchi, data(16, april, 1980), 10000),
person(figlio4, bianchi, data(10, april, 1978), 20000)]
).
family(
person(no, no, date(7,may,1968), 30000),
person(no, no, date(18,july,1970), 32000),
[]
).
/* Regola che mostra i mariti: */
husband(X) :- family(X,_,_).
/* Regola che mostra l mogli: */
wife(X) :- family(_,X,_).
/* Regola che mostra i figli:
X è figlio se in una famiglia c'è una lista di figli e se X appartiene
alla lista dei figli: */
child(X) :- family(_,_,Children),
member(X,Children).
This is very simple. By some facts I represent some family and I have some rule to perform some query (to obtain the husbands, the wifes, if X is a child in a family, if a person exist in a family, the salary of a person and the date of birth of a person)
OK, until now I have no problem.
Then I have the following exercise related to the previous program: Write a rule that calculates the total salary of all the children in each family
So I have to calculate a value that I have call ChildrenIncoming that represents the sum of the salary (the last value in the person data structure representing a child in a family data structure) of all the children belonging to a specific family
I am finding many problems to implement this functionality.
I am started from easier task (for example retrieve the salary of an husband) like this:
husbandIncoming(HSurname, HIncoming) :- husband(HSurname), % Seleziona un cognome
salary(HSurname, HIncoming).
I have try to calculate the ChildrenIncoming value trying to do something like it (that it is incomplete and don't work):
childrenList(Husband,ChildrenList) :- family(Husband,_,ChildrenList).
/* If ChildrenList is empty: ChildrenIncomung value 0 */
childrenIncoming(Husband,[],0).
childrenIncoming(Husband,ChildrenList,ChildrenIncoming) :-
childrenList(Husband,ChildrenList),
ChildrenList = [Head|Tail],
childrenIncoming(Husband,Tail,TailIncoming),
salary(Head, ChildrenIncoming).
first thing is that I identify a family by the husband so I can retrieve the ChildrenList using the childrenList rule (this rule works well).
Then I would calculate the sum of all the salary of all person that are inside this ChildreList and to do that I introduced the relation childrenIncoming that have to calculate it.
This relation start by the fact that simply say:
childrenIncoming(Husband,[],0).
If a family (having Husband as paterfamilias) have empty children list, then the total incoming of the children is 0.
Then I have introduce a rule (wrong) that should calculate this value in the case of non-empty children list.
The reasoning behind this rule is that:
1) A not empty children list contains person.
2) a non-empty list can be divided into an Head of the list (that is a person) and a Tail sublist (a list of person)
3) the head is a person and have a salary
4) the tail contains persons and each one have a salary
But I don't know how mix these ideas in the right way to obtain the desired result (the value of the total incoming of all person in the children list)
I don't know if this kind or reasoning is good or if I am wrong from the beginning.
If you add these predicates to family/3 facts
husband(family(H, W, C), P) :- family(H, W, C), H = person(P,_,_,_).
children(family(_, _, C), C).
income(P, I) :- P = person(_,_,_,I).
childrenIncoming(Family, ChildrenIncoming) :-
children(Family, Children),
sum_income(Children, 0, ChildrenIncoming).
sum_income([], Sum, Sum).
sum_income([C|Children], SoFar, Sum) :-
income(C, I),
Updated is I + SoFar,
sum_income(Children, Updated, Sum).
with this query you get
?- husband(F, mario), childrenIncoming(F,I).
F = family(person(mario, rossi, date(7, may, 1968), 30000), person(lucia, verdi, date(18, july, 1970), 32000), [person(luca, rossi, date(1, june, 1984), 5000), person(maria, rossi, date(25, may, 1990), 0), person(paolo, rossi, data(16, april, 1980), 10000)]),
I = 15000 .
I also create this one that calculate the total incoming of all components of a specific family:
/* FATTO (CASO BASE): Se la lista dei figli è una lista vuota, non ci
sono figli quindi la somma dei redditi dei figli è 0
*/
somma([],0).
/* REGOLA (CASO GENERALE): La lista dei figli non è vuota quindi può essere
decomposta in un'HEAD (person(_,_,_,E) ed in una sottolista L.
SE è VERO che: il valore della somma di tutti gli elementi nella
sottolista L è S1 ed è VERO che il valore di S è S1+E allora è VERO
che la somma dei redditi nella lista [H|L] è S
*/
somma([person(_,_,_,E)|L],S):- somma(L,S1),
S is S1+E.
/* Una famiglia è identificata dal COGNOME DEL MARITO.
Il REDDITO TOTALE di una famiglia è la somma del reddito del marito +
reddito moglie + la somma dei redditi di tutti i figli nella lista
dei figli.
*/
reddito(C,R):- family(person(_,C,_,RP), person(_,_,_,RM), FIGLI),
somma(FIGLI,RF),
R is RF+RP+RM.
The comments are in italian but I think that looking the code is pretty simple understand what it means :-)

Resources