Prolog 逻辑任务中的互斥
有三个朋友-米莎,佩蒂娅,沃瓦。 姓氏:伊万诺夫、塞米约诺夫、格拉西莫夫Prolog 逻辑任务中的互斥,prolog,gnu-prolog,Prolog,Gnu Prolog,有三个朋友-米莎,佩蒂娅,沃瓦。 姓氏:伊万诺夫、塞米约诺夫、格拉西莫夫 name(misha). name(vova). name(petya). surname(ivanov). surname(semyonov). surname(gerasimov). full_name(misha,X) :- surname(X), X \= gerasimov. 米莎不是格拉西莫夫 name(misha). name(vova). name(petya). surname(ivanov).
name(misha).
name(vova).
name(petya).
surname(ivanov).
surname(semyonov).
surname(gerasimov).
full_name(misha,X) :-
surname(X),
X \= gerasimov.
米莎不是格拉西莫夫
name(misha).
name(vova).
name(petya).
surname(ivanov).
surname(semyonov).
surname(gerasimov).
full_name(misha,X) :-
surname(X),
X \= gerasimov.
沃瓦在六年级学习。杰拉西莫夫在5号。
如何定义vova的姓氏(几个)
沃瓦的父亲是工程师,伊万诺夫的父亲是锁匠
father(vova,ingeneer).
father(ivanov,locksmith).
如何定义vova的姓氏(一) 首先,我们需要了解一个事实,即每个名字都有一个给定的姓氏
is_one_of(Name, [ivanov, semyonov, gerasimov]) :-
member(Name, [misha, vova, petya]).
impossibility @
impossible(Name, Surname), possible(Name, Surnames)
<=> select(Surname, Surnames, Remaining)
| possible(Name, Remaining).
我们还被赋予了名字和姓氏的特征(学习,父亲),每个都有不同的价值观。这由以下谓词捕获
name_characteristic(vova, studying, sixth_grade).
name_characteristic(vova, father, ingeneer).
surname_characteristic(gerasimov, studying, fifth_grade).
surname_characteristic(ivanov, father, locksmith).
我们还得知,gerasimov
不是misha
的姓
is_not(misha, gerasimov).
规则1:名称
不能有姓氏
,如果对于某些常见字符,它们的值不同
is_not(Name, Surname) :-
name_characteristic(Name, Characteristic, Value1),
surname_characteristic(Surname, Characteristic, Value2),
Value1 \= Value2.
规则2:姓名
必须有姓氏
,如果其他可能的姓氏都不是姓名
的姓氏
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 = semyonov
Name = misha,
Surname = gerasimov
Name = vova,
Surname = gerasimov
Name = vova,
Surname = ivanov
查询不是(姓名)
产生:
Surname = semyonov
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).
这里的想法是,我们已经在一个列表中列出了姓氏,我们只是在每个名字和所有可能姓氏之间创建一对名为可能的
is_one_of(Name, [ivanov, semyonov, gerasimov]) :-
member(Name, [misha, vova, petya]).
impossibility @
impossible(Name, Surname), possible(Name, Surnames)
<=> select(Surname, Surnames, Remaining)
| possible(Name, Remaining).
一旦这个可能性列表缩小到一个名字,我们就成功地匹配了
remove_matched @
matched(_, Surname), possible(Name, _)
==> impossible(Name, Surname).
如果我们找到了一个匹配的姓氏,那么这个姓氏就不可能用于所有其他的名字
如果由于名称已被处理而无法吸收不可能约束,则可以添加额外的清理约束,但这不是必需的:
irrelevant_impossibility @
possible(Name, Surnames)
\ impossible(Name, Surname)
<=> \+ memberchk(Surname, Surnames)
| true.
执行此操作的结果是:
?- main.
name(petya),
name(vova),
name(misha),
surnames([ivanov, semyonov, gerasimov]),
matched(petya, gerasimov),
matched(misha, ivanov),
matched(vova, semyonov).
我相信这满足了摆在您面前的约束条件。我认为这对CHR来说是一项很好的任务,而不是普通的序言。谢谢。如何使用Prolog语法为该任务编制CHR程序?