0

我有以下规则在具有特定日期的数据库中查找事实:

preceding(ID,Date,Category,Preceding) :-
    setof([ID,D,Category,Amount], row(ID,D,Category,Amount), Preceding),
    D @< Date.

after(ID,After,Category,Rows) :-
    setof([ID,D,Category,Amount], row(ID,D,Category,Amount), Rows),
    D @> After.

preceding工作得很好:

?- preceding(ID,'2020-01-01',Category,Preceding).
Preceding = [[100002, '2018-11-05', 'CEM', 500.0], [100007, '2018-11-01', 'Consulting Package', 100000.0], [100011, '2017-10-25', 'CEM', 500.0], [100012, '2017-10-15', 'CEM', 500.0], [100012, '2017-10-25', 'Tuition Package', 5543.37], [100013, '2017-10-15', 'CEM'|...], [100013, '2017-11-08'|...], [100014|...], [...|...]|...].

after不起作用:

?- after(ID,'2000-01-01',Category,Rows).
false.

请注意,这两个规则之间的唯一区别@<是vs.@>运算符。我试过改变操作数的顺序,改变规则中语句的顺序,但它不起作用。

我也尝试过颠倒逻辑:

after(ID,After,Category,Rows) :-
    setof([ID,D,Category,Amount], row(ID,D,Category,Amount), Rows),
    After @< D.

这也不起作用。

我什至写了一个单独的规则来检查我是否可以让操作员工作:

isafter(A,B) :- A @> B.

这行得通。但是用D @> Afterisafter(D,After)after规则替换是行不通的。

为什么制作“之前”条件有效,但“之后”条件无效?你能让我的after规则起作用吗?:)

(我实际上想编写一个between同时使用“之前”和“之后”条件的函数,但我意识到我的between函数的确切问题是@>。)

4

1 回答 1

3

preceding工作得很好:

可以?您使用变量调用它ID并且Category不受查询约束。这已经表明它并没有完全按照您的想法进行。让我们看看里面。

使用这个数据库:

row(100002, '2018-11-05', 'CEM', 500.0).
row(100007, '2018-11-01', 'Consulting Package', 100000.0).

让我们看看setof定义中的目标:

?- setof([ID,D,Category,Amount], row(ID,D,Category,Amount), Preceding).
Preceding = [[100002, '2018-11-05', 'CEM', 500.0], [100007, '2018-11-01', 'Consulting Package', 100000.0]].

Preceding列表是按照我们的预期计算的,但是D其他变量呢?他们不受约束。我们可以使这一点更加明确:

?- setof([ID,D,Category,Amount], row(ID,D,Category,Amount), Preceding), write('D: '), writeln(D).
D: _5070
Preceding = [[100002, '2018-11-05', 'CEM', 500.0], [100007, '2018-11-01', 'Consulting Package', 100000.0]].

某种形式_5070是 SWI-Prolog 对“未绑定变量”的表示法。调用D后的变量也是如此。setof您是否期望它绑定到Preceding列表中的日期之一?哪一个?

所以现在我们可以更接近于@>vs.的问题了@<。您正在做的是将原子与'2020-01-01'变量进行比较。@>@<实施所谓的“标准术语顺序”。按照这个顺序,变量总是被认为小于原子:

?- SomeVariable @< some_atom.
true.

?- SomeVariable @> some_atom.
false.

这就是为什么你@<总是成功而你@>总是失败的原因。要解决此问题,您需要回过头来重新考虑您希望setof呼叫做什么。

于 2020-08-25T08:16:05.540 回答