Representing linear functions in prolog

Multi tool use
I want to write compound terms that represent linear relations between different variables in a population of the form Y = a + b*X (e.g. fuelConsumption = 2 + 3 * distance, for a population consisting of cars). I have problems with stating that the relation is about a population (group) while at the same stating that values for each variable are linked within objects (i.e. that car A’s fuel consumption is 2 + 3 * car A’s distance, and not car B’s distance).
This could represent that the relation is for a population but misses to explicitly state that values of each variable are linked within objects:
causes(
cause(distance),
effect(fuelConsumption),
a(2),
b(3)
).
Conversely, this captures that values of each variable are linked within objects but misses that the compound is a relation (a line). Each instantiation of this compound represents two points, but what i wanted was each instantiation to be a line.
car(aCar).
car(anotherCar).
causes(
cause(Car, distance, D),
effect(Car, fuelConsumption, F)
):- car(Car), F #= 2 + 3 * D.
This seems closer to a solution but i am still not really satisfied for two reasons: 1. The statement about the linear relation should hold for any population and not just the objects that i happen to specify in the population term; 2. The function that relates distance to fuelConsumption is not made explicit (e.g. what about if there is an exponential relation, etc?).
population([car1, car2, car3, car4]).
causes(
cause(P, distance),
effect(P, fuelConsumption),
a(2),
b(3)
):-population(P).
Any help would be greatly appreciated. My goal is to declare relations are precisely and transparently as possible (i.e. should be human-readable).
Thanks!
/JC
Some links to related questions:
representing-a-system-of-equations-about-classes-of-objects,
how-to-encode-causal-relations-in-prolog-as-a-linear-function
prolog
|
show 2 more comments
I want to write compound terms that represent linear relations between different variables in a population of the form Y = a + b*X (e.g. fuelConsumption = 2 + 3 * distance, for a population consisting of cars). I have problems with stating that the relation is about a population (group) while at the same stating that values for each variable are linked within objects (i.e. that car A’s fuel consumption is 2 + 3 * car A’s distance, and not car B’s distance).
This could represent that the relation is for a population but misses to explicitly state that values of each variable are linked within objects:
causes(
cause(distance),
effect(fuelConsumption),
a(2),
b(3)
).
Conversely, this captures that values of each variable are linked within objects but misses that the compound is a relation (a line). Each instantiation of this compound represents two points, but what i wanted was each instantiation to be a line.
car(aCar).
car(anotherCar).
causes(
cause(Car, distance, D),
effect(Car, fuelConsumption, F)
):- car(Car), F #= 2 + 3 * D.
This seems closer to a solution but i am still not really satisfied for two reasons: 1. The statement about the linear relation should hold for any population and not just the objects that i happen to specify in the population term; 2. The function that relates distance to fuelConsumption is not made explicit (e.g. what about if there is an exponential relation, etc?).
population([car1, car2, car3, car4]).
causes(
cause(P, distance),
effect(P, fuelConsumption),
a(2),
b(3)
):-population(P).
Any help would be greatly appreciated. My goal is to declare relations are precisely and transparently as possible (i.e. should be human-readable).
Thanks!
/JC
Some links to related questions:
representing-a-system-of-equations-about-classes-of-objects,
how-to-encode-causal-relations-in-prolog-as-a-linear-function
prolog
1
You should include links to previous related questions in with your current question.
– Guy Coder
Jan 2 at 11:56
Are you open to swipl 7 dicts ? Or should the solution be portable to generic plain Prolog ?
– CapelliC
Jan 2 at 19:14
1
Thank you @CapelliC but, as you mentioned, I am looking for a standard Prolog solution.
– JCR
Jan 2 at 23:00
What is the most concise free-form statement that conveys this relationship? Would it be something likefor cars, distance causes fuelConsumption = 2 + 3 * distance
? I think you're getting bogged down in the actual syntax of Prolog here and I'm trying to understand your problem generally.
– Daniel Lyons
Jan 3 at 17:28
I see what you mean @DanielLyons. It would be "For all cars in a set, distance causes fuelConsumption; and for any car in this set, that car’s fuel consumption can be obtained as 2 + 3 * distance for that car.
– JCR
Jan 3 at 23:05
|
show 2 more comments
I want to write compound terms that represent linear relations between different variables in a population of the form Y = a + b*X (e.g. fuelConsumption = 2 + 3 * distance, for a population consisting of cars). I have problems with stating that the relation is about a population (group) while at the same stating that values for each variable are linked within objects (i.e. that car A’s fuel consumption is 2 + 3 * car A’s distance, and not car B’s distance).
This could represent that the relation is for a population but misses to explicitly state that values of each variable are linked within objects:
causes(
cause(distance),
effect(fuelConsumption),
a(2),
b(3)
).
Conversely, this captures that values of each variable are linked within objects but misses that the compound is a relation (a line). Each instantiation of this compound represents two points, but what i wanted was each instantiation to be a line.
car(aCar).
car(anotherCar).
causes(
cause(Car, distance, D),
effect(Car, fuelConsumption, F)
):- car(Car), F #= 2 + 3 * D.
This seems closer to a solution but i am still not really satisfied for two reasons: 1. The statement about the linear relation should hold for any population and not just the objects that i happen to specify in the population term; 2. The function that relates distance to fuelConsumption is not made explicit (e.g. what about if there is an exponential relation, etc?).
population([car1, car2, car3, car4]).
causes(
cause(P, distance),
effect(P, fuelConsumption),
a(2),
b(3)
):-population(P).
Any help would be greatly appreciated. My goal is to declare relations are precisely and transparently as possible (i.e. should be human-readable).
Thanks!
/JC
Some links to related questions:
representing-a-system-of-equations-about-classes-of-objects,
how-to-encode-causal-relations-in-prolog-as-a-linear-function
prolog
I want to write compound terms that represent linear relations between different variables in a population of the form Y = a + b*X (e.g. fuelConsumption = 2 + 3 * distance, for a population consisting of cars). I have problems with stating that the relation is about a population (group) while at the same stating that values for each variable are linked within objects (i.e. that car A’s fuel consumption is 2 + 3 * car A’s distance, and not car B’s distance).
This could represent that the relation is for a population but misses to explicitly state that values of each variable are linked within objects:
causes(
cause(distance),
effect(fuelConsumption),
a(2),
b(3)
).
Conversely, this captures that values of each variable are linked within objects but misses that the compound is a relation (a line). Each instantiation of this compound represents two points, but what i wanted was each instantiation to be a line.
car(aCar).
car(anotherCar).
causes(
cause(Car, distance, D),
effect(Car, fuelConsumption, F)
):- car(Car), F #= 2 + 3 * D.
This seems closer to a solution but i am still not really satisfied for two reasons: 1. The statement about the linear relation should hold for any population and not just the objects that i happen to specify in the population term; 2. The function that relates distance to fuelConsumption is not made explicit (e.g. what about if there is an exponential relation, etc?).
population([car1, car2, car3, car4]).
causes(
cause(P, distance),
effect(P, fuelConsumption),
a(2),
b(3)
):-population(P).
Any help would be greatly appreciated. My goal is to declare relations are precisely and transparently as possible (i.e. should be human-readable).
Thanks!
/JC
Some links to related questions:
representing-a-system-of-equations-about-classes-of-objects,
how-to-encode-causal-relations-in-prolog-as-a-linear-function
prolog
prolog
edited Jan 2 at 15:02
Guy Coder
16k44187
16k44187
asked Jan 2 at 10:36


JCRJCR
320311
320311
1
You should include links to previous related questions in with your current question.
– Guy Coder
Jan 2 at 11:56
Are you open to swipl 7 dicts ? Or should the solution be portable to generic plain Prolog ?
– CapelliC
Jan 2 at 19:14
1
Thank you @CapelliC but, as you mentioned, I am looking for a standard Prolog solution.
– JCR
Jan 2 at 23:00
What is the most concise free-form statement that conveys this relationship? Would it be something likefor cars, distance causes fuelConsumption = 2 + 3 * distance
? I think you're getting bogged down in the actual syntax of Prolog here and I'm trying to understand your problem generally.
– Daniel Lyons
Jan 3 at 17:28
I see what you mean @DanielLyons. It would be "For all cars in a set, distance causes fuelConsumption; and for any car in this set, that car’s fuel consumption can be obtained as 2 + 3 * distance for that car.
– JCR
Jan 3 at 23:05
|
show 2 more comments
1
You should include links to previous related questions in with your current question.
– Guy Coder
Jan 2 at 11:56
Are you open to swipl 7 dicts ? Or should the solution be portable to generic plain Prolog ?
– CapelliC
Jan 2 at 19:14
1
Thank you @CapelliC but, as you mentioned, I am looking for a standard Prolog solution.
– JCR
Jan 2 at 23:00
What is the most concise free-form statement that conveys this relationship? Would it be something likefor cars, distance causes fuelConsumption = 2 + 3 * distance
? I think you're getting bogged down in the actual syntax of Prolog here and I'm trying to understand your problem generally.
– Daniel Lyons
Jan 3 at 17:28
I see what you mean @DanielLyons. It would be "For all cars in a set, distance causes fuelConsumption; and for any car in this set, that car’s fuel consumption can be obtained as 2 + 3 * distance for that car.
– JCR
Jan 3 at 23:05
1
1
You should include links to previous related questions in with your current question.
– Guy Coder
Jan 2 at 11:56
You should include links to previous related questions in with your current question.
– Guy Coder
Jan 2 at 11:56
Are you open to swipl 7 dicts ? Or should the solution be portable to generic plain Prolog ?
– CapelliC
Jan 2 at 19:14
Are you open to swipl 7 dicts ? Or should the solution be portable to generic plain Prolog ?
– CapelliC
Jan 2 at 19:14
1
1
Thank you @CapelliC but, as you mentioned, I am looking for a standard Prolog solution.
– JCR
Jan 2 at 23:00
Thank you @CapelliC but, as you mentioned, I am looking for a standard Prolog solution.
– JCR
Jan 2 at 23:00
What is the most concise free-form statement that conveys this relationship? Would it be something like
for cars, distance causes fuelConsumption = 2 + 3 * distance
? I think you're getting bogged down in the actual syntax of Prolog here and I'm trying to understand your problem generally.– Daniel Lyons
Jan 3 at 17:28
What is the most concise free-form statement that conveys this relationship? Would it be something like
for cars, distance causes fuelConsumption = 2 + 3 * distance
? I think you're getting bogged down in the actual syntax of Prolog here and I'm trying to understand your problem generally.– Daniel Lyons
Jan 3 at 17:28
I see what you mean @DanielLyons. It would be "For all cars in a set, distance causes fuelConsumption; and for any car in this set, that car’s fuel consumption can be obtained as 2 + 3 * distance for that car.
– JCR
Jan 3 at 23:05
I see what you mean @DanielLyons. It would be "For all cars in a set, distance causes fuelConsumption; and for any car in this set, that car’s fuel consumption can be obtained as 2 + 3 * distance for that car.
– JCR
Jan 3 at 23:05
|
show 2 more comments
1 Answer
1
active
oldest
votes
This is just another blind stab at your problem. It's an interesting problem. But I must confess I always feel like it's a bit of an X-Y situation, where if I knew more about your context I would be better able to understand why you're seeking something that looks, to me, so complex.
/*
For all cars in a set, distance causes fuelConsumption; and for any
car in this set, that car’s fuel consumption can be obtained as
2 + 3 * distance for that car.
*/
% prop(Set, PropertyName)
prop(car, distance).
prop(car, fuelConsumption).
% entity(Set, Individual, Properties)
entity(car, car1, [distance=23]).
entity(car, car2, [distance=0]).
%% There are two ways to find a property value:
%%
%% 1. Look for the property in the individual's properties
propvalue(Set, Individual, Property, Value) :-
entity(Set, Individual, Properties),
memberchk(Property=Value, Properties).
%% 2. Compute the property using other aspects of the individual
propvalue(Set, Individual, Property, Value) :-
causes(Set, Individual, Property, Value, Query),
call(Query).
%% causes(Set, Individual, Property, Value, Goal)
causes(car, C, fuelConsumption, V,
(propvalue(car, C, distance, D), V is 2 + 3 * D)).
So my basic idea here is to reify your objects. prop/2
is really here for reflection, but I'm not using it presently. propvalue/4
abstracts over whether the properties are causes or effects, giving you uniform access to either.
The key idea here is causes/5
. This is not the most aesthetically pleasing way to represent the data, but I think it brings together the core ideas you have: that, across this set, this property is derived by this calculation. What is not represented here, really, is the idea of the cause; I just didn't see the value in reifying that here. I would expect, if this were my code, that in general I'd be passing a Car into this calculation and whatever properties of the car you need, you just get. But I have never really fully understood your interesting problem.
If this is close, there are things you can do to make the UI nicer. You could replace the first two arguments of causes/5
with something like car(C)
and use =../2
to assemble that parameter in propvalue/4
. You could also use :-
to separate the goal from the head and use current_predicate/3
to re-obtain the body goal in propvalue/4
. Combining these ideas, you would get a simpler causes/3
that would look like this:
propvalue(Set, Individual, Property, Value) :-
SetIndividual =.. [Set, Individual],
call(causes, SetIndividual, Property, Value).
causes(car(C), fuelConsumption, V) :-
propvalue(car, C, distance, D),
V is 2 + 3 * D.
The idea here is that causes/3
rules are really acting more like a data structure to be accessed by propvalue/4
than something you're going to call directly. propvalue/4
will enumerate all the properties (computed and not) of all the entities in your various populations. You could probably improve the readability more by changing propvalue/4
into propvalue/3
and doing the =../2
destructuring here instead. But I think for it to work, you're going to want a tabular representation of your populations akin to entity/3
, with the non-computed properties for each one there.
I think it would probably be a very good idea to take this modeling problem over to Logtalk, which has several innate notions of object that would probably make your design more straightforward. It seems likely to me that you'd tire of having to write your property-getting so verbosely, in which case you would probably benefit greatly from real objects, or else from introducing your own syntax and parsing it into this.
Anyway, this is currently my best guess as to what you're after, I hope it helps.
thank you very much for providing such a detailed response! I think you captured my problem nicely with the causes/5 predicate containing both the set and individuals within the set! Really appreciate your effort!
– JCR
Jan 5 at 19:33
@JCR I am so pleased I was able to help you! Such an interesting problem, I hope you continue to enjoy using Prolog to attack it and others!
– Daniel Lyons
Jan 6 at 7:07
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%2f54004796%2frepresenting-linear-functions-in-prolog%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
This is just another blind stab at your problem. It's an interesting problem. But I must confess I always feel like it's a bit of an X-Y situation, where if I knew more about your context I would be better able to understand why you're seeking something that looks, to me, so complex.
/*
For all cars in a set, distance causes fuelConsumption; and for any
car in this set, that car’s fuel consumption can be obtained as
2 + 3 * distance for that car.
*/
% prop(Set, PropertyName)
prop(car, distance).
prop(car, fuelConsumption).
% entity(Set, Individual, Properties)
entity(car, car1, [distance=23]).
entity(car, car2, [distance=0]).
%% There are two ways to find a property value:
%%
%% 1. Look for the property in the individual's properties
propvalue(Set, Individual, Property, Value) :-
entity(Set, Individual, Properties),
memberchk(Property=Value, Properties).
%% 2. Compute the property using other aspects of the individual
propvalue(Set, Individual, Property, Value) :-
causes(Set, Individual, Property, Value, Query),
call(Query).
%% causes(Set, Individual, Property, Value, Goal)
causes(car, C, fuelConsumption, V,
(propvalue(car, C, distance, D), V is 2 + 3 * D)).
So my basic idea here is to reify your objects. prop/2
is really here for reflection, but I'm not using it presently. propvalue/4
abstracts over whether the properties are causes or effects, giving you uniform access to either.
The key idea here is causes/5
. This is not the most aesthetically pleasing way to represent the data, but I think it brings together the core ideas you have: that, across this set, this property is derived by this calculation. What is not represented here, really, is the idea of the cause; I just didn't see the value in reifying that here. I would expect, if this were my code, that in general I'd be passing a Car into this calculation and whatever properties of the car you need, you just get. But I have never really fully understood your interesting problem.
If this is close, there are things you can do to make the UI nicer. You could replace the first two arguments of causes/5
with something like car(C)
and use =../2
to assemble that parameter in propvalue/4
. You could also use :-
to separate the goal from the head and use current_predicate/3
to re-obtain the body goal in propvalue/4
. Combining these ideas, you would get a simpler causes/3
that would look like this:
propvalue(Set, Individual, Property, Value) :-
SetIndividual =.. [Set, Individual],
call(causes, SetIndividual, Property, Value).
causes(car(C), fuelConsumption, V) :-
propvalue(car, C, distance, D),
V is 2 + 3 * D.
The idea here is that causes/3
rules are really acting more like a data structure to be accessed by propvalue/4
than something you're going to call directly. propvalue/4
will enumerate all the properties (computed and not) of all the entities in your various populations. You could probably improve the readability more by changing propvalue/4
into propvalue/3
and doing the =../2
destructuring here instead. But I think for it to work, you're going to want a tabular representation of your populations akin to entity/3
, with the non-computed properties for each one there.
I think it would probably be a very good idea to take this modeling problem over to Logtalk, which has several innate notions of object that would probably make your design more straightforward. It seems likely to me that you'd tire of having to write your property-getting so verbosely, in which case you would probably benefit greatly from real objects, or else from introducing your own syntax and parsing it into this.
Anyway, this is currently my best guess as to what you're after, I hope it helps.
thank you very much for providing such a detailed response! I think you captured my problem nicely with the causes/5 predicate containing both the set and individuals within the set! Really appreciate your effort!
– JCR
Jan 5 at 19:33
@JCR I am so pleased I was able to help you! Such an interesting problem, I hope you continue to enjoy using Prolog to attack it and others!
– Daniel Lyons
Jan 6 at 7:07
add a comment |
This is just another blind stab at your problem. It's an interesting problem. But I must confess I always feel like it's a bit of an X-Y situation, where if I knew more about your context I would be better able to understand why you're seeking something that looks, to me, so complex.
/*
For all cars in a set, distance causes fuelConsumption; and for any
car in this set, that car’s fuel consumption can be obtained as
2 + 3 * distance for that car.
*/
% prop(Set, PropertyName)
prop(car, distance).
prop(car, fuelConsumption).
% entity(Set, Individual, Properties)
entity(car, car1, [distance=23]).
entity(car, car2, [distance=0]).
%% There are two ways to find a property value:
%%
%% 1. Look for the property in the individual's properties
propvalue(Set, Individual, Property, Value) :-
entity(Set, Individual, Properties),
memberchk(Property=Value, Properties).
%% 2. Compute the property using other aspects of the individual
propvalue(Set, Individual, Property, Value) :-
causes(Set, Individual, Property, Value, Query),
call(Query).
%% causes(Set, Individual, Property, Value, Goal)
causes(car, C, fuelConsumption, V,
(propvalue(car, C, distance, D), V is 2 + 3 * D)).
So my basic idea here is to reify your objects. prop/2
is really here for reflection, but I'm not using it presently. propvalue/4
abstracts over whether the properties are causes or effects, giving you uniform access to either.
The key idea here is causes/5
. This is not the most aesthetically pleasing way to represent the data, but I think it brings together the core ideas you have: that, across this set, this property is derived by this calculation. What is not represented here, really, is the idea of the cause; I just didn't see the value in reifying that here. I would expect, if this were my code, that in general I'd be passing a Car into this calculation and whatever properties of the car you need, you just get. But I have never really fully understood your interesting problem.
If this is close, there are things you can do to make the UI nicer. You could replace the first two arguments of causes/5
with something like car(C)
and use =../2
to assemble that parameter in propvalue/4
. You could also use :-
to separate the goal from the head and use current_predicate/3
to re-obtain the body goal in propvalue/4
. Combining these ideas, you would get a simpler causes/3
that would look like this:
propvalue(Set, Individual, Property, Value) :-
SetIndividual =.. [Set, Individual],
call(causes, SetIndividual, Property, Value).
causes(car(C), fuelConsumption, V) :-
propvalue(car, C, distance, D),
V is 2 + 3 * D.
The idea here is that causes/3
rules are really acting more like a data structure to be accessed by propvalue/4
than something you're going to call directly. propvalue/4
will enumerate all the properties (computed and not) of all the entities in your various populations. You could probably improve the readability more by changing propvalue/4
into propvalue/3
and doing the =../2
destructuring here instead. But I think for it to work, you're going to want a tabular representation of your populations akin to entity/3
, with the non-computed properties for each one there.
I think it would probably be a very good idea to take this modeling problem over to Logtalk, which has several innate notions of object that would probably make your design more straightforward. It seems likely to me that you'd tire of having to write your property-getting so verbosely, in which case you would probably benefit greatly from real objects, or else from introducing your own syntax and parsing it into this.
Anyway, this is currently my best guess as to what you're after, I hope it helps.
thank you very much for providing such a detailed response! I think you captured my problem nicely with the causes/5 predicate containing both the set and individuals within the set! Really appreciate your effort!
– JCR
Jan 5 at 19:33
@JCR I am so pleased I was able to help you! Such an interesting problem, I hope you continue to enjoy using Prolog to attack it and others!
– Daniel Lyons
Jan 6 at 7:07
add a comment |
This is just another blind stab at your problem. It's an interesting problem. But I must confess I always feel like it's a bit of an X-Y situation, where if I knew more about your context I would be better able to understand why you're seeking something that looks, to me, so complex.
/*
For all cars in a set, distance causes fuelConsumption; and for any
car in this set, that car’s fuel consumption can be obtained as
2 + 3 * distance for that car.
*/
% prop(Set, PropertyName)
prop(car, distance).
prop(car, fuelConsumption).
% entity(Set, Individual, Properties)
entity(car, car1, [distance=23]).
entity(car, car2, [distance=0]).
%% There are two ways to find a property value:
%%
%% 1. Look for the property in the individual's properties
propvalue(Set, Individual, Property, Value) :-
entity(Set, Individual, Properties),
memberchk(Property=Value, Properties).
%% 2. Compute the property using other aspects of the individual
propvalue(Set, Individual, Property, Value) :-
causes(Set, Individual, Property, Value, Query),
call(Query).
%% causes(Set, Individual, Property, Value, Goal)
causes(car, C, fuelConsumption, V,
(propvalue(car, C, distance, D), V is 2 + 3 * D)).
So my basic idea here is to reify your objects. prop/2
is really here for reflection, but I'm not using it presently. propvalue/4
abstracts over whether the properties are causes or effects, giving you uniform access to either.
The key idea here is causes/5
. This is not the most aesthetically pleasing way to represent the data, but I think it brings together the core ideas you have: that, across this set, this property is derived by this calculation. What is not represented here, really, is the idea of the cause; I just didn't see the value in reifying that here. I would expect, if this were my code, that in general I'd be passing a Car into this calculation and whatever properties of the car you need, you just get. But I have never really fully understood your interesting problem.
If this is close, there are things you can do to make the UI nicer. You could replace the first two arguments of causes/5
with something like car(C)
and use =../2
to assemble that parameter in propvalue/4
. You could also use :-
to separate the goal from the head and use current_predicate/3
to re-obtain the body goal in propvalue/4
. Combining these ideas, you would get a simpler causes/3
that would look like this:
propvalue(Set, Individual, Property, Value) :-
SetIndividual =.. [Set, Individual],
call(causes, SetIndividual, Property, Value).
causes(car(C), fuelConsumption, V) :-
propvalue(car, C, distance, D),
V is 2 + 3 * D.
The idea here is that causes/3
rules are really acting more like a data structure to be accessed by propvalue/4
than something you're going to call directly. propvalue/4
will enumerate all the properties (computed and not) of all the entities in your various populations. You could probably improve the readability more by changing propvalue/4
into propvalue/3
and doing the =../2
destructuring here instead. But I think for it to work, you're going to want a tabular representation of your populations akin to entity/3
, with the non-computed properties for each one there.
I think it would probably be a very good idea to take this modeling problem over to Logtalk, which has several innate notions of object that would probably make your design more straightforward. It seems likely to me that you'd tire of having to write your property-getting so verbosely, in which case you would probably benefit greatly from real objects, or else from introducing your own syntax and parsing it into this.
Anyway, this is currently my best guess as to what you're after, I hope it helps.
This is just another blind stab at your problem. It's an interesting problem. But I must confess I always feel like it's a bit of an X-Y situation, where if I knew more about your context I would be better able to understand why you're seeking something that looks, to me, so complex.
/*
For all cars in a set, distance causes fuelConsumption; and for any
car in this set, that car’s fuel consumption can be obtained as
2 + 3 * distance for that car.
*/
% prop(Set, PropertyName)
prop(car, distance).
prop(car, fuelConsumption).
% entity(Set, Individual, Properties)
entity(car, car1, [distance=23]).
entity(car, car2, [distance=0]).
%% There are two ways to find a property value:
%%
%% 1. Look for the property in the individual's properties
propvalue(Set, Individual, Property, Value) :-
entity(Set, Individual, Properties),
memberchk(Property=Value, Properties).
%% 2. Compute the property using other aspects of the individual
propvalue(Set, Individual, Property, Value) :-
causes(Set, Individual, Property, Value, Query),
call(Query).
%% causes(Set, Individual, Property, Value, Goal)
causes(car, C, fuelConsumption, V,
(propvalue(car, C, distance, D), V is 2 + 3 * D)).
So my basic idea here is to reify your objects. prop/2
is really here for reflection, but I'm not using it presently. propvalue/4
abstracts over whether the properties are causes or effects, giving you uniform access to either.
The key idea here is causes/5
. This is not the most aesthetically pleasing way to represent the data, but I think it brings together the core ideas you have: that, across this set, this property is derived by this calculation. What is not represented here, really, is the idea of the cause; I just didn't see the value in reifying that here. I would expect, if this were my code, that in general I'd be passing a Car into this calculation and whatever properties of the car you need, you just get. But I have never really fully understood your interesting problem.
If this is close, there are things you can do to make the UI nicer. You could replace the first two arguments of causes/5
with something like car(C)
and use =../2
to assemble that parameter in propvalue/4
. You could also use :-
to separate the goal from the head and use current_predicate/3
to re-obtain the body goal in propvalue/4
. Combining these ideas, you would get a simpler causes/3
that would look like this:
propvalue(Set, Individual, Property, Value) :-
SetIndividual =.. [Set, Individual],
call(causes, SetIndividual, Property, Value).
causes(car(C), fuelConsumption, V) :-
propvalue(car, C, distance, D),
V is 2 + 3 * D.
The idea here is that causes/3
rules are really acting more like a data structure to be accessed by propvalue/4
than something you're going to call directly. propvalue/4
will enumerate all the properties (computed and not) of all the entities in your various populations. You could probably improve the readability more by changing propvalue/4
into propvalue/3
and doing the =../2
destructuring here instead. But I think for it to work, you're going to want a tabular representation of your populations akin to entity/3
, with the non-computed properties for each one there.
I think it would probably be a very good idea to take this modeling problem over to Logtalk, which has several innate notions of object that would probably make your design more straightforward. It seems likely to me that you'd tire of having to write your property-getting so verbosely, in which case you would probably benefit greatly from real objects, or else from introducing your own syntax and parsing it into this.
Anyway, this is currently my best guess as to what you're after, I hope it helps.
answered Jan 4 at 20:29
Daniel LyonsDaniel Lyons
17.7k23863
17.7k23863
thank you very much for providing such a detailed response! I think you captured my problem nicely with the causes/5 predicate containing both the set and individuals within the set! Really appreciate your effort!
– JCR
Jan 5 at 19:33
@JCR I am so pleased I was able to help you! Such an interesting problem, I hope you continue to enjoy using Prolog to attack it and others!
– Daniel Lyons
Jan 6 at 7:07
add a comment |
thank you very much for providing such a detailed response! I think you captured my problem nicely with the causes/5 predicate containing both the set and individuals within the set! Really appreciate your effort!
– JCR
Jan 5 at 19:33
@JCR I am so pleased I was able to help you! Such an interesting problem, I hope you continue to enjoy using Prolog to attack it and others!
– Daniel Lyons
Jan 6 at 7:07
thank you very much for providing such a detailed response! I think you captured my problem nicely with the causes/5 predicate containing both the set and individuals within the set! Really appreciate your effort!
– JCR
Jan 5 at 19:33
thank you very much for providing such a detailed response! I think you captured my problem nicely with the causes/5 predicate containing both the set and individuals within the set! Really appreciate your effort!
– JCR
Jan 5 at 19:33
@JCR I am so pleased I was able to help you! Such an interesting problem, I hope you continue to enjoy using Prolog to attack it and others!
– Daniel Lyons
Jan 6 at 7:07
@JCR I am so pleased I was able to help you! Such an interesting problem, I hope you continue to enjoy using Prolog to attack it and others!
– Daniel Lyons
Jan 6 at 7:07
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%2f54004796%2frepresenting-linear-functions-in-prolog%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
oxHIzOC4uOS,faO 2te KO
1
You should include links to previous related questions in with your current question.
– Guy Coder
Jan 2 at 11:56
Are you open to swipl 7 dicts ? Or should the solution be portable to generic plain Prolog ?
– CapelliC
Jan 2 at 19:14
1
Thank you @CapelliC but, as you mentioned, I am looking for a standard Prolog solution.
– JCR
Jan 2 at 23:00
What is the most concise free-form statement that conveys this relationship? Would it be something like
for cars, distance causes fuelConsumption = 2 + 3 * distance
? I think you're getting bogged down in the actual syntax of Prolog here and I'm trying to understand your problem generally.– Daniel Lyons
Jan 3 at 17:28
I see what you mean @DanielLyons. It would be "For all cars in a set, distance causes fuelConsumption; and for any car in this set, that car’s fuel consumption can be obtained as 2 + 3 * distance for that car.
– JCR
Jan 3 at 23:05