Prolog规则可以条件在日期之前,但不能在日期之后,为什么?

Prolog rule can condition to be before a date, but not after a date, why?

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

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.

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

我也试过颠倒逻辑:

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

这也不行。

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

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

这行得通。但是在我的 after 规则中用 isafter(D,After) 替换 D @> After 不起作用。

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

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

preceding works just fine:

是吗?您可以使用不受查询约束的变量 IDCategory 来调用它。这已经表明它并不完全符合您的想法。让我们看看里面。

使用这个数据库:

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 对“未绑定变量”的表示法。所以 Dsetof 调用之后的一个变量。您是否希望它绑定到 Preceding 列表中的日期之一?哪一个?

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

?- SomeVariable @< some_atom.
true.

?- SomeVariable @> some_atom.
false.

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