【问题标题】:Prolog ensure a rule's return parameters are unique and in canonical orderProlog 确保规则的返回参数是唯一的并且按照规范顺序
【发布时间】:2017-01-01 06:02:43
【问题描述】:

我在 Prolog 文件中声明了一些数据,如下所示:

gen1(grass).
gen1(poison).
gen1(psychic).
gen1(bug).
gen1(rock).

...

gen1((poison, flying)).
gen1((ghost, poison)).
gen1((water, ice)).

...

weak1(grass, poison).
weak1(grass, bug).
weak1(poison, rock).

strong1(grass, rock).
strong1(poison, grass).
strong1(bug, grass).
strong1(poison, bug).
strong1(psychic, poison).
strong1(bug, poison).
strong1(bug, psychic).
strong1(rock, bug).

请注意,对于复合 gen1(...),数据没有定义 strong1weak1。这些是由对最小工作示例没有贡献的规则确定的。我提到它们是因为知道它们的存在可能会很有用。

我试图找出形成循环的这些术语之间的关系。这是一个示例函数:

triangle1(A, B, C) :-
    setof(A-B-C, (
             gen1(A), gen1(B), gen1(C), A \= B, A \= C, B \= C,
              strong1(A, B), strong1(B, C), strong1(C, A)
             ), Tris),
    member(A-B-C, Tris).

此设置确实删除了 ABC 顺序相同的重复项。但是,它不会删除不同顺序的重复项。例如:

?- triangle1(A, B, C),
   member(A, [bug, grass, rock]),
   member(B, [bug, rock, grass]),
   member(C, [bug, rock, grass]).
A = bug,
B = grass,
C = rock ;
A = grass,
B = rock,
C = bug ;
A = rock,
B = bug,
C = grass ;
false.

该查询应该只返回一组[A, B, C]

我曾考虑过使用sort/2,但在某些情况下,简单的排序会改变答案的含义:

?- triangle1(A, B, C),
   sort([A, B, C], [D, E, F]),
   \+member([D, E, F], [[A, B, C], [B, C, A], [C, A, B]]).
A = D, D = bug,
B = F, F = psychic,
C = E, E = poison .

我也尝试过<>,但显然它们不适用于原子。

有什么想法吗?

(我查看了类似的问题,但不知道我在这里所做的与其他人所做的相比如何)

编辑:根据关于最小工作示例的评论。

【问题讨论】:

  • 您需要阅读How to Ask,然后向我们提供minimal reproducible example
  • @Enigmativity 我之前实际上已经阅读过它,并且我已经尝试在这里遵守它。我承认这个问题可能会更加集中,并且样本数据与问题的内容不是最相关的。我将使用更好的示例数据编辑问题,这应该提供最小的示例,尽管是文学编程风格。

标签: prolog prolog-setof


【解决方案1】:

您可以尝试在setof/3 调用内部进行排序。所以你应该避免以错误的顺序生成三元组。

我的意思是:调用setof/3,而不是

A \= B, A \= C, B \= C,

试试

A @< B, A @< C, B \= C,

通过这种方式,您强制 A 低于 B 并低于 C,您可以避免重复并保持正确的解决方案。

完整的triangle1/3

triangle1(A, B, C) :-
    setof(A-B-C, (
             gen1(A), gen1(B), gen1(C), A @< B, A @< C, B \= C,
              strong1(A, B), strong1(B, C), strong1(C, A)
             ), Tris),
    member(A-B-C, Tris).

【讨论】:

  • 使用setof/3 删除了由于从一个原子到另一个原子的多条路径而导致的重复项。这是基于 stackoverflow.com/questions/16243081/… 的,对于复合类型特别方便。您需要完整的代码才能理解:gist.github.com/proegssilb/4bbc307ffad40e0ee337edc55dc2c4e6
  • @proegssilb - 我已经使用基于setof/3triangle1/3 和我的triangle1/3 简化版本尝试了您的完整代码(重新排序子句或我的gprolog 忽略了很多);调用 triangle(A, B, C) 在这两种情况下,我都会得到完全相同的 854 个结果(并且顺序相同)。
  • 哦,我使用的是 SWI Prolog 6.2.6,而不是 GNU Prolog。在 SWI Prolog 中,strong/2weak/2 的规则会为 strong(X, (dragon, flying)) 这样的情况生成双重结果,因为 strong(ice, dragon)strong(ice, flying) 都已定义(至少,这是我从 GUI Tracer 中了解到的;甚至对 Prolog 的工作原理一无所知)。
  • @proegssilb - 抱歉:你是对的:strong1(A, (B, C)) 和类似规则正在引入重复的解决方案。 bagof/3 很好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-21
  • 1970-01-01
相关资源
最近更新 更多