Representing linear functions in prolog

Multi tool use
Multi tool use












3















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










share|improve this question




















  • 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
















3















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










share|improve this question




















  • 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














3












3








3








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










share|improve this question
















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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 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














  • 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








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












1 Answer
1






active

oldest

votes


















3














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.






share|improve this answer
























  • 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











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
});


}
});














draft saved

draft discarded


















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









3














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.






share|improve this answer
























  • 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
















3














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.






share|improve this answer
























  • 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














3












3








3







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.






share|improve this answer













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.







share|improve this answer












share|improve this answer



share|improve this answer










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



















  • 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




















draft saved

draft discarded




















































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.




draft saved


draft discarded














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





















































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
DAV AeSdsW4UEPJHI,wSshj0MRrS7bH,EF LlAwSn8GHbq6NnPrtHsVN MU82gdDc6hBgUYC

Popular posts from this blog

Monofisismo

Angular Downloading a file using contenturl with Basic Authentication

Olmecas