在序言中表示线性函数

时间:2019-01-02 10:36:22

标签: prolog

我想写一些复合项,它们表示Y = a + b * X形式的总体中不同变量之间的线性关系(例如,对于由汽车组成的总体,燃料消耗= 2 + 3 *距离)。我在说明该关系是关于人口(组)时遇到问题,同时在说明每个变量的值都在对象内链接时(例如,汽车A的油耗是2 + 3 *汽车A的距离,而不是汽车B的距离) )。


这可能表示该关系是针对总体的,但是没有明确指出每个变量的值都在对象内链接:

causes(
    cause(distance),
    effect(fuelConsumption),
    a(2),
    b(3)
).

相反,这捕获了每个变量的值在对象内链接,但是错过了该化合物是一个关系(一条线)。该化合物的每个实例化都代表两个点,但是我想要的是将每个实例化为一条直线。

car(aCar).
car(anotherCar).
causes(
        cause(Car, distance, D),
        effect(Car, fuelConsumption, F)
):- car(Car), F #= 2 + 3 * D.

这似乎更接近解决方案,但是由于两个原因,我仍然不是很满意:1.关于线性关系的陈述应适用于任何总体,而不仅仅是我恰好在总体项中指定的对象; 2.并未将与燃料消耗的距离相关的函数明确化(例如,如果存在指数关系,该怎么办?)。

population([car1, car2, car3, car4]).
causes(
    cause(P, distance),
    effect(P, fuelConsumption),
    a(2),
    b(3)
):-population(P).

任何帮助将不胜感激。我的目标是声明关系尽可能准确和透明(即应易于阅读)。

谢谢!

/ JC

一些与相关问题有关的链接:
representing-a-system-of-equations-about-classes-of-objects
how-to-encode-causal-relations-in-prolog-as-a-linear-function

1 个答案:

答案 0 :(得分:3)

这只是您遇到的另一个盲目刺伤。这是一个有趣的问题。但是我必须承认,我总是觉得这有点像X-Y的情况,如果我对您的情况有更多了解,那么我会更好地理解您为什么要寻找看起来对我来说如此复杂的东西。

/*

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

因此,我的基本想法是验证对象。 prop/2确实是在这里进行反思,但是我目前不使用它。 propvalue/4对属性是原因还是结果进行了抽象,使您可以统一访问这两个属性。

此处的关键思想是causes/5。这不是表示数据的最美学上令人愉悦的方式,但是我认为它汇集了您拥有的核心思想:在此集合中,此属性是通过此计算得出的。实际上,这里没有表示的是原因的概念;我只是没有看到在这里进行修改的价值。我希望,如果这是我的代码,总的来说,我会将Car传递到此计算中,无论您需要哪种汽车属性,都可以得到。但是我从来没有真正完全理解过你有趣的问题。

如果关闭了,您可以做一些事情来使UI更好。您可以将causes/5的前两个参数替换为car(C),然后使用=../2propvalue/4中汇编该参数。您还可以使用:-将目标与头部分开,并使用current_predicate/3重新获得propvalue/4中的身体目标。结合这些想法,您将获得一个更简单的causes/3,如下所示:

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.

这里的想法是,causes/3规则实际上更像是propvalue/4可以访问的数据结构,而不是直接调用的结构。 propvalue/4会枚举您各种总体中所有实体的所有属性(计算的和非计算的)。您可以通过将propvalue/4更改为propvalue/3并在此处进行=../2解构来进一步提高可读性。但是我认为,要使其正常工作,您将需要一个类似于entity/3的表格,以人口形式表示,其中每个人的属性都未经计算。

我认为将这个建模问题转移到Logtalk可能是一个很好的主意,该问题具有一些与生俱来的对象概念,这可能会使您的设计更简单。在我看来,您可能会厌倦了如此冗长地编写属性获取操作,在这种情况下,您可能会受益于真实对象,或者通过引入自己的语法并将其解析为该语法。

无论如何,这是目前我对所追求的东西的最佳猜测,希望对您有所帮助。