Prolog Backtracking findall for two variables

Multi tool use
I want to write a function residents(Housenumber,N) which
(1) gives me the amount of residents per house given the housenumber
AND
(2) when Housenumber is a variable, one is able to backtrack all resident counts for each house number.
Given are the following facts in the form of resident(Forename, Surname, Housenumber).
resident('Tim','Cook',1).
resident('Elisabeth','Cook',1).
resident('Thomas','Cook',1).
resident('George','Cook',1).
resident('Steve','Jobs',2).
resident('Lisa','Jobs',2).
resident('Karen','Jobs',2).
resident('Mark','Zuckerberg',3).
resident('Priscilla','Zuckerberg',3).
The second condition should work like:
residents(X,N).
X = 1,
N = 4,
X = 2,
N = 3,
X = 3,
N = 2.
I tried the following attempt.
residents(X,N):-
findall(X,resident(_,_,X),L),
length(L,N).
The first condition is satiesfied, however, the second condition gives me the total amount of all residents, not clustered for each house. I also tried the bagof and setof predicates but it did not help. Thanks a lot for any help.
prolog
add a comment |
I want to write a function residents(Housenumber,N) which
(1) gives me the amount of residents per house given the housenumber
AND
(2) when Housenumber is a variable, one is able to backtrack all resident counts for each house number.
Given are the following facts in the form of resident(Forename, Surname, Housenumber).
resident('Tim','Cook',1).
resident('Elisabeth','Cook',1).
resident('Thomas','Cook',1).
resident('George','Cook',1).
resident('Steve','Jobs',2).
resident('Lisa','Jobs',2).
resident('Karen','Jobs',2).
resident('Mark','Zuckerberg',3).
resident('Priscilla','Zuckerberg',3).
The second condition should work like:
residents(X,N).
X = 1,
N = 4,
X = 2,
N = 3,
X = 3,
N = 2.
I tried the following attempt.
residents(X,N):-
findall(X,resident(_,_,X),L),
length(L,N).
The first condition is satiesfied, however, the second condition gives me the total amount of all residents, not clustered for each house. I also tried the bagof and setof predicates but it did not help. Thanks a lot for any help.
prolog
add a comment |
I want to write a function residents(Housenumber,N) which
(1) gives me the amount of residents per house given the housenumber
AND
(2) when Housenumber is a variable, one is able to backtrack all resident counts for each house number.
Given are the following facts in the form of resident(Forename, Surname, Housenumber).
resident('Tim','Cook',1).
resident('Elisabeth','Cook',1).
resident('Thomas','Cook',1).
resident('George','Cook',1).
resident('Steve','Jobs',2).
resident('Lisa','Jobs',2).
resident('Karen','Jobs',2).
resident('Mark','Zuckerberg',3).
resident('Priscilla','Zuckerberg',3).
The second condition should work like:
residents(X,N).
X = 1,
N = 4,
X = 2,
N = 3,
X = 3,
N = 2.
I tried the following attempt.
residents(X,N):-
findall(X,resident(_,_,X),L),
length(L,N).
The first condition is satiesfied, however, the second condition gives me the total amount of all residents, not clustered for each house. I also tried the bagof and setof predicates but it did not help. Thanks a lot for any help.
prolog
I want to write a function residents(Housenumber,N) which
(1) gives me the amount of residents per house given the housenumber
AND
(2) when Housenumber is a variable, one is able to backtrack all resident counts for each house number.
Given are the following facts in the form of resident(Forename, Surname, Housenumber).
resident('Tim','Cook',1).
resident('Elisabeth','Cook',1).
resident('Thomas','Cook',1).
resident('George','Cook',1).
resident('Steve','Jobs',2).
resident('Lisa','Jobs',2).
resident('Karen','Jobs',2).
resident('Mark','Zuckerberg',3).
resident('Priscilla','Zuckerberg',3).
The second condition should work like:
residents(X,N).
X = 1,
N = 4,
X = 2,
N = 3,
X = 3,
N = 2.
I tried the following attempt.
residents(X,N):-
findall(X,resident(_,_,X),L),
length(L,N).
The first condition is satiesfied, however, the second condition gives me the total amount of all residents, not clustered for each house. I also tried the bagof and setof predicates but it did not help. Thanks a lot for any help.
prolog
prolog
edited Dec 30 '18 at 0:56
canadair
asked Dec 30 '18 at 0:39
canadaircanadair
162
162
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
The issue is that findall/3
automatically quantifies over the free variables (first and last name here) such that all solutions for the same adress get merged. Have a look at bagof/3
(see e.g. the SWI Documentation), it allows you to manually quantify (which is not necessary here). To find the number of people living at the address, the list L
also needs to collect the names of the residents per number, not the number itself:
?- bagof(X-Y, resident(X,Y,Z), Zs), length(Zs, N).
Z = 1,
Zs = ['Tim'-'Cook', 'Elisabeth'-'Cook', 'Thomas'-'Cook', 'George'-'Cook'],
N = 4 ;
Z = 2,
Zs = ['Steve'-'Jobs', 'Lisa'-'Jobs', 'Karen'-'Jobs'],
N = 3 ;
Z = 3,
Zs = ['Mark'-'Zuckerberg', 'Priscilla'-'Zuckerberg'],
N = 2.
2
Can't upvote due to too less reputation but thank you!
– canadair
Dec 30 '18 at 11:55
add a comment |
Often complicated machinations with bagof
and setof
are indications that the data model needs work .
When a prolog predicate represents a data term it is good to think of it like a database table .
The name of the predicate is correspondent to the name of the database table .
The argument of the predicate are correspondent to the field within the database table .
For example : if designing and normalizing a database table then certainly a "resident" would not store a value of a house number ; instead the "resident" has a reference to a "house" and a "house" is an entity unto itself .
:- [library('lists')] .
:- source .
:- initialization demo .
(
demo
)
:-
(
?- residents(HOUSEi,COUNTi)
)
.
(
residents(_houseI_,_countI_)
)
:-
(
house(_houseI_)
,
house_residents(house(_houseI_),_residentS_)
,
length(_residentS_,_countI_)
)
.
(
house_residents(_houseO_,_residentS_)
)
:-
(
_houseO_
,
_queryO_ = resident(_,_houseO_)
,
setof(_queryO_,_queryO_,_residentS_)
)
.
house(1) .
house(2) .
house(3) .
resident(name(first('Tim'),last('Cook')),house(1)).
resident(name(first('Elisabeth'),last('Cook')),house(1)).
resident(name(first('Thomas'),last('Cook')),house(1)).
resident(name(first('George'),last('Cook')),house(1)).
resident(name(first('Steve'),last('Jobs')),house(2)).
resident(name(first('Lisa'),last('Jobs')),house(2)).
resident(name(first('Karen'),last('Jobs')),house(2)).
resident(name(first('Mark'),last('Zuckerberg')),house(3)).
resident(name(first('Priscilla'),last('Zuckerberg')),house(3)).
1
I tried to run your code on GNU Prolog, SWI and Yap but it only works with the latter. Perhaps you could change your code that it works for more implementations? It should not be too hard because e.g.library(lists)
is not used. If you reformat dropping the unneccessary parenthesis, the code becomes also much more readable.
– lambda.xy.x
Dec 31 '18 at 13:07
with swipl an irrelevant error message because of the (apparently) unusual:- source
but the code still works with correct answers from the top-level .
– Kintalken
Dec 31 '18 at 20:49
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53974437%2fprolog-backtracking-findall-for-two-variables%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
The issue is that findall/3
automatically quantifies over the free variables (first and last name here) such that all solutions for the same adress get merged. Have a look at bagof/3
(see e.g. the SWI Documentation), it allows you to manually quantify (which is not necessary here). To find the number of people living at the address, the list L
also needs to collect the names of the residents per number, not the number itself:
?- bagof(X-Y, resident(X,Y,Z), Zs), length(Zs, N).
Z = 1,
Zs = ['Tim'-'Cook', 'Elisabeth'-'Cook', 'Thomas'-'Cook', 'George'-'Cook'],
N = 4 ;
Z = 2,
Zs = ['Steve'-'Jobs', 'Lisa'-'Jobs', 'Karen'-'Jobs'],
N = 3 ;
Z = 3,
Zs = ['Mark'-'Zuckerberg', 'Priscilla'-'Zuckerberg'],
N = 2.
2
Can't upvote due to too less reputation but thank you!
– canadair
Dec 30 '18 at 11:55
add a comment |
The issue is that findall/3
automatically quantifies over the free variables (first and last name here) such that all solutions for the same adress get merged. Have a look at bagof/3
(see e.g. the SWI Documentation), it allows you to manually quantify (which is not necessary here). To find the number of people living at the address, the list L
also needs to collect the names of the residents per number, not the number itself:
?- bagof(X-Y, resident(X,Y,Z), Zs), length(Zs, N).
Z = 1,
Zs = ['Tim'-'Cook', 'Elisabeth'-'Cook', 'Thomas'-'Cook', 'George'-'Cook'],
N = 4 ;
Z = 2,
Zs = ['Steve'-'Jobs', 'Lisa'-'Jobs', 'Karen'-'Jobs'],
N = 3 ;
Z = 3,
Zs = ['Mark'-'Zuckerberg', 'Priscilla'-'Zuckerberg'],
N = 2.
2
Can't upvote due to too less reputation but thank you!
– canadair
Dec 30 '18 at 11:55
add a comment |
The issue is that findall/3
automatically quantifies over the free variables (first and last name here) such that all solutions for the same adress get merged. Have a look at bagof/3
(see e.g. the SWI Documentation), it allows you to manually quantify (which is not necessary here). To find the number of people living at the address, the list L
also needs to collect the names of the residents per number, not the number itself:
?- bagof(X-Y, resident(X,Y,Z), Zs), length(Zs, N).
Z = 1,
Zs = ['Tim'-'Cook', 'Elisabeth'-'Cook', 'Thomas'-'Cook', 'George'-'Cook'],
N = 4 ;
Z = 2,
Zs = ['Steve'-'Jobs', 'Lisa'-'Jobs', 'Karen'-'Jobs'],
N = 3 ;
Z = 3,
Zs = ['Mark'-'Zuckerberg', 'Priscilla'-'Zuckerberg'],
N = 2.
The issue is that findall/3
automatically quantifies over the free variables (first and last name here) such that all solutions for the same adress get merged. Have a look at bagof/3
(see e.g. the SWI Documentation), it allows you to manually quantify (which is not necessary here). To find the number of people living at the address, the list L
also needs to collect the names of the residents per number, not the number itself:
?- bagof(X-Y, resident(X,Y,Z), Zs), length(Zs, N).
Z = 1,
Zs = ['Tim'-'Cook', 'Elisabeth'-'Cook', 'Thomas'-'Cook', 'George'-'Cook'],
N = 4 ;
Z = 2,
Zs = ['Steve'-'Jobs', 'Lisa'-'Jobs', 'Karen'-'Jobs'],
N = 3 ;
Z = 3,
Zs = ['Mark'-'Zuckerberg', 'Priscilla'-'Zuckerberg'],
N = 2.
answered Dec 30 '18 at 1:30
lambda.xy.xlambda.xy.x
3,1441426
3,1441426
2
Can't upvote due to too less reputation but thank you!
– canadair
Dec 30 '18 at 11:55
add a comment |
2
Can't upvote due to too less reputation but thank you!
– canadair
Dec 30 '18 at 11:55
2
2
Can't upvote due to too less reputation but thank you!
– canadair
Dec 30 '18 at 11:55
Can't upvote due to too less reputation but thank you!
– canadair
Dec 30 '18 at 11:55
add a comment |
Often complicated machinations with bagof
and setof
are indications that the data model needs work .
When a prolog predicate represents a data term it is good to think of it like a database table .
The name of the predicate is correspondent to the name of the database table .
The argument of the predicate are correspondent to the field within the database table .
For example : if designing and normalizing a database table then certainly a "resident" would not store a value of a house number ; instead the "resident" has a reference to a "house" and a "house" is an entity unto itself .
:- [library('lists')] .
:- source .
:- initialization demo .
(
demo
)
:-
(
?- residents(HOUSEi,COUNTi)
)
.
(
residents(_houseI_,_countI_)
)
:-
(
house(_houseI_)
,
house_residents(house(_houseI_),_residentS_)
,
length(_residentS_,_countI_)
)
.
(
house_residents(_houseO_,_residentS_)
)
:-
(
_houseO_
,
_queryO_ = resident(_,_houseO_)
,
setof(_queryO_,_queryO_,_residentS_)
)
.
house(1) .
house(2) .
house(3) .
resident(name(first('Tim'),last('Cook')),house(1)).
resident(name(first('Elisabeth'),last('Cook')),house(1)).
resident(name(first('Thomas'),last('Cook')),house(1)).
resident(name(first('George'),last('Cook')),house(1)).
resident(name(first('Steve'),last('Jobs')),house(2)).
resident(name(first('Lisa'),last('Jobs')),house(2)).
resident(name(first('Karen'),last('Jobs')),house(2)).
resident(name(first('Mark'),last('Zuckerberg')),house(3)).
resident(name(first('Priscilla'),last('Zuckerberg')),house(3)).
1
I tried to run your code on GNU Prolog, SWI and Yap but it only works with the latter. Perhaps you could change your code that it works for more implementations? It should not be too hard because e.g.library(lists)
is not used. If you reformat dropping the unneccessary parenthesis, the code becomes also much more readable.
– lambda.xy.x
Dec 31 '18 at 13:07
with swipl an irrelevant error message because of the (apparently) unusual:- source
but the code still works with correct answers from the top-level .
– Kintalken
Dec 31 '18 at 20:49
add a comment |
Often complicated machinations with bagof
and setof
are indications that the data model needs work .
When a prolog predicate represents a data term it is good to think of it like a database table .
The name of the predicate is correspondent to the name of the database table .
The argument of the predicate are correspondent to the field within the database table .
For example : if designing and normalizing a database table then certainly a "resident" would not store a value of a house number ; instead the "resident" has a reference to a "house" and a "house" is an entity unto itself .
:- [library('lists')] .
:- source .
:- initialization demo .
(
demo
)
:-
(
?- residents(HOUSEi,COUNTi)
)
.
(
residents(_houseI_,_countI_)
)
:-
(
house(_houseI_)
,
house_residents(house(_houseI_),_residentS_)
,
length(_residentS_,_countI_)
)
.
(
house_residents(_houseO_,_residentS_)
)
:-
(
_houseO_
,
_queryO_ = resident(_,_houseO_)
,
setof(_queryO_,_queryO_,_residentS_)
)
.
house(1) .
house(2) .
house(3) .
resident(name(first('Tim'),last('Cook')),house(1)).
resident(name(first('Elisabeth'),last('Cook')),house(1)).
resident(name(first('Thomas'),last('Cook')),house(1)).
resident(name(first('George'),last('Cook')),house(1)).
resident(name(first('Steve'),last('Jobs')),house(2)).
resident(name(first('Lisa'),last('Jobs')),house(2)).
resident(name(first('Karen'),last('Jobs')),house(2)).
resident(name(first('Mark'),last('Zuckerberg')),house(3)).
resident(name(first('Priscilla'),last('Zuckerberg')),house(3)).
1
I tried to run your code on GNU Prolog, SWI and Yap but it only works with the latter. Perhaps you could change your code that it works for more implementations? It should not be too hard because e.g.library(lists)
is not used. If you reformat dropping the unneccessary parenthesis, the code becomes also much more readable.
– lambda.xy.x
Dec 31 '18 at 13:07
with swipl an irrelevant error message because of the (apparently) unusual:- source
but the code still works with correct answers from the top-level .
– Kintalken
Dec 31 '18 at 20:49
add a comment |
Often complicated machinations with bagof
and setof
are indications that the data model needs work .
When a prolog predicate represents a data term it is good to think of it like a database table .
The name of the predicate is correspondent to the name of the database table .
The argument of the predicate are correspondent to the field within the database table .
For example : if designing and normalizing a database table then certainly a "resident" would not store a value of a house number ; instead the "resident" has a reference to a "house" and a "house" is an entity unto itself .
:- [library('lists')] .
:- source .
:- initialization demo .
(
demo
)
:-
(
?- residents(HOUSEi,COUNTi)
)
.
(
residents(_houseI_,_countI_)
)
:-
(
house(_houseI_)
,
house_residents(house(_houseI_),_residentS_)
,
length(_residentS_,_countI_)
)
.
(
house_residents(_houseO_,_residentS_)
)
:-
(
_houseO_
,
_queryO_ = resident(_,_houseO_)
,
setof(_queryO_,_queryO_,_residentS_)
)
.
house(1) .
house(2) .
house(3) .
resident(name(first('Tim'),last('Cook')),house(1)).
resident(name(first('Elisabeth'),last('Cook')),house(1)).
resident(name(first('Thomas'),last('Cook')),house(1)).
resident(name(first('George'),last('Cook')),house(1)).
resident(name(first('Steve'),last('Jobs')),house(2)).
resident(name(first('Lisa'),last('Jobs')),house(2)).
resident(name(first('Karen'),last('Jobs')),house(2)).
resident(name(first('Mark'),last('Zuckerberg')),house(3)).
resident(name(first('Priscilla'),last('Zuckerberg')),house(3)).
Often complicated machinations with bagof
and setof
are indications that the data model needs work .
When a prolog predicate represents a data term it is good to think of it like a database table .
The name of the predicate is correspondent to the name of the database table .
The argument of the predicate are correspondent to the field within the database table .
For example : if designing and normalizing a database table then certainly a "resident" would not store a value of a house number ; instead the "resident" has a reference to a "house" and a "house" is an entity unto itself .
:- [library('lists')] .
:- source .
:- initialization demo .
(
demo
)
:-
(
?- residents(HOUSEi,COUNTi)
)
.
(
residents(_houseI_,_countI_)
)
:-
(
house(_houseI_)
,
house_residents(house(_houseI_),_residentS_)
,
length(_residentS_,_countI_)
)
.
(
house_residents(_houseO_,_residentS_)
)
:-
(
_houseO_
,
_queryO_ = resident(_,_houseO_)
,
setof(_queryO_,_queryO_,_residentS_)
)
.
house(1) .
house(2) .
house(3) .
resident(name(first('Tim'),last('Cook')),house(1)).
resident(name(first('Elisabeth'),last('Cook')),house(1)).
resident(name(first('Thomas'),last('Cook')),house(1)).
resident(name(first('George'),last('Cook')),house(1)).
resident(name(first('Steve'),last('Jobs')),house(2)).
resident(name(first('Lisa'),last('Jobs')),house(2)).
resident(name(first('Karen'),last('Jobs')),house(2)).
resident(name(first('Mark'),last('Zuckerberg')),house(3)).
resident(name(first('Priscilla'),last('Zuckerberg')),house(3)).
answered Dec 30 '18 at 16:58


KintalkenKintalken
1408
1408
1
I tried to run your code on GNU Prolog, SWI and Yap but it only works with the latter. Perhaps you could change your code that it works for more implementations? It should not be too hard because e.g.library(lists)
is not used. If you reformat dropping the unneccessary parenthesis, the code becomes also much more readable.
– lambda.xy.x
Dec 31 '18 at 13:07
with swipl an irrelevant error message because of the (apparently) unusual:- source
but the code still works with correct answers from the top-level .
– Kintalken
Dec 31 '18 at 20:49
add a comment |
1
I tried to run your code on GNU Prolog, SWI and Yap but it only works with the latter. Perhaps you could change your code that it works for more implementations? It should not be too hard because e.g.library(lists)
is not used. If you reformat dropping the unneccessary parenthesis, the code becomes also much more readable.
– lambda.xy.x
Dec 31 '18 at 13:07
with swipl an irrelevant error message because of the (apparently) unusual:- source
but the code still works with correct answers from the top-level .
– Kintalken
Dec 31 '18 at 20:49
1
1
I tried to run your code on GNU Prolog, SWI and Yap but it only works with the latter. Perhaps you could change your code that it works for more implementations? It should not be too hard because e.g.
library(lists)
is not used. If you reformat dropping the unneccessary parenthesis, the code becomes also much more readable.– lambda.xy.x
Dec 31 '18 at 13:07
I tried to run your code on GNU Prolog, SWI and Yap but it only works with the latter. Perhaps you could change your code that it works for more implementations? It should not be too hard because e.g.
library(lists)
is not used. If you reformat dropping the unneccessary parenthesis, the code becomes also much more readable.– lambda.xy.x
Dec 31 '18 at 13:07
with swipl an irrelevant error message because of the (apparently) unusual
:- source
but the code still works with correct answers from the top-level .– Kintalken
Dec 31 '18 at 20:49
with swipl an irrelevant error message because of the (apparently) unusual
:- source
but the code still works with correct answers from the top-level .– Kintalken
Dec 31 '18 at 20:49
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53974437%2fprolog-backtracking-findall-for-two-variables%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Du,0xQLdrVSuwIL