首页 > 解决方案 > 在 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. 将距离与fuelConsumption 关联起来的函数没有明确说明(例如,如果存在指数关系等呢?)。

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

标签: prolog

解决方案


这只是对您的问题的又一次盲目尝试。这是一个有趣的问题。但我必须承认,我总是觉得这有点像 XY 情况,如果我对你的背景有更多了解,我将能够更好地理解你为什么要寻找在我看来如此复杂的东西。

/*

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)并用于=../2将该参数组装到propvalue/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/4propvalue/3进行=../2解构来提高可读性。但我认为要让它发挥作用,您将需要一个类似于 的人口表格表示entity/3,其中每个人口都有非计算属性。

我认为将这个建模问题交给Logtalk可能是一个非常好的主意,它有几个与生俱来的对象概念,可能会使您的设计更直接。在我看来,您可能会厌倦必须如此冗长地编写属性获取,在这种情况下,您可能会从真实对象中受益匪浅,或者通过引入自己的语法并将其解析为该对象。

无论如何,这是我目前对你所追求的最好的猜测,我希望它有所帮助。


推荐阅读