逻辑任务中的互斥

  • 本文关键字:任务 prolog gnu-prolog
  • 更新时间 :
  • 英文 :


有三个朋友 - 米莎,彼佳,沃瓦。 姓氏:伊万诺夫、谢苗诺夫、格拉西莫夫。

name(misha).
name(vova).
name(petya).
surname(ivanov).
surname(semyonov).
surname(gerasimov).

米沙不是格拉西莫夫。

full_name(misha,X) :- 
surname(X),
X = gerasimov.  

沃瓦在六年级学习。 格拉西莫夫在五年级。 如何定义 vova 的姓氏(几个(?

沃瓦的父亲是工程师,伊万诺夫的父亲是锁匠。

father(vova,ingeneer).
father(ivanov,locksmith).

如何定义沃瓦的姓氏(一个(?

首先,我们需要捕捉每个名字都有一个给定姓氏的事实。

is_one_of(Name, [ivanov, semyonov, gerasimov]) :-
member(Name, [misha, vova, petya]).

我们还被赋予了关于名字和姓氏的特征(学习,父亲(,每个都有不同的价值观。这由以下谓词捕获。

name_characteristic(vova, studying, sixth_grade).
name_characteristic(vova, father, ingeneer).
surname_characteristic(gerasimov, studying, fifth_grade).
surname_characteristic(ivanov, father, locksmith).

我们也得到了gerasimovis_not姓氏misha.

is_not(misha, gerasimov).

规则 1:Name不能Surname某些共同特征的值是否不同。

is_not(Name, Surname) :-
name_characteristic(Name, Characteristic, Value1),
surname_characteristic(Surname, Characteristic, Value2),
Value1 = Value2.

规则2:如果其他可能的姓氏都不是Name姓氏,则必须NameSurname

is_(Name, Surname) :-
is_one_of(Name, Surnames),
select(Surname, Surnames, RemainingSurnames),
is_none_of(Name, RemainingSurnames).
is_none_of(_, []).
is_none_of(Name, [Surname | RemainingSurnames]) :-
is_not(Name, Surname),
is_none_of(Name, RemainingSurnames).

查询is(vova, Surname)收益:

Surname = semyonov

查询is_not(Name, Surname)收益:

Name = misha,
Surname = gerasimov
Name = vova,
Surname = gerasimov
Name = vova,
Surname = ivanov

这个解决方案使用chr库,它实际上是一种与Prolog略有不同的语言。我现在自己正在学习CHR,这实际上是我用它编写的第二个程序。它可能与我在邮件列表中获得的改进版本过于相似。所以用一粒盐来服用。

在我看来,CHR非常适合那些从很多可能性开始然后抵消坏可能性的程序。也许取消可以继续,直到您收敛到解决方案。这就是这个程序的工作方式,我们生成所有可能的名字/姓氏集,然后使用不可能约束来减少可能的姓氏集,直到它们收敛到一个,然后我们从其他名字/姓氏集中删除它们,直到一切都收敛。

前两行介绍了库和我们将使用的约束:

:- use_module(library(chr)).
:- chr_constraint name/1, surnames/1, impossible/2, matched/2, possible/2.

第一个约束产生了我们需要克服的可能性。

gen_possibilities @
name(Name), surnames(Surnames)
==> possible(Name, Surnames).

这里的想法是,我们已经在一个列表中有了姓氏,我们只是在每个名字和所有可能的姓氏之间制作一对名为possible的姓氏。

impossibility @
impossible(Name, Surname), possible(Name, Surnames)
<=> select(Surname, Surnames, Remaining) 
| possible(Name, Remaining).

一旦我们被告知某件事是不可能的,我们可以简单地将其从该名称的可能姓氏列表中删除。select/3对于从列表中删除单个项目并为您提供其余部分非常有用。我们在这里使用一个守卫,以防姓氏已经不在可能的姓氏列表中,就像应用第四个约束后可能发生的那样。

only_possiblity @
possible(Name, [Surname])
<=> matched(Name, Surname).

一旦可能性列表减少到一个名字,我们就成功地进行了匹配。

remove_matched @
matched(_, Surname), possible(Name, _)
==> impossible(Name, Surname).

如果我们进行了匹配,那么对于所有其他名字来说,这个姓氏就变得不可能了。

如果由于名称已处理而无法吸收不可能约束,则可以添加额外的清理约束,但不是必需的:

irrelevant_impossibility @
possible(Name, Surnames) 
 impossible(Name, Surname)
<=> + memberchk(Surname, Surnames) 
| true.

现在我们可以运行该程序了。我冒昧地为 5 年级/6 年级和不同的父亲内联逻辑。我觉得通过阅读很容易理解意图,我认为通过专门建模不会获得太多好处。@RobertBaron为他的解决方案带来麻烦而致敬!

main :-
name(misha),
name(vova),
name(petya),
surnames([ivanov, semyonov, gerasimov]),
impossible(misha, gerasimov),  % stated impossible
impossible(vova, gerasimov),   % different grades
impossible(vova, ivanov).      % different fathers

执行此操作的结果是:

?- main.
name(petya),
name(vova),
name(misha),
surnames([ivanov, semyonov, gerasimov]),
matched(petya, gerasimov),
matched(misha, ivanov),
matched(vova, semyonov).

我相信这满足了摆在你们面前的限制。

相关内容

  • 没有找到相关文章

最新更新