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程序?