Swi-prolog 双向子句/事实
Posted
技术标签:
【中文标题】Swi-prolog 双向子句/事实【英文标题】:Swi-prolog two-way clause/fact 【发布时间】:2017-02-14 11:15:11 【问题描述】:我需要帮助在 Swi-Prolog 中描述以下事实:
克拉克和琼斯住在同一所房子里,一起下棋。
和
经理和建筑师住在同一栋房子里,没有其他员工住在那栋房子里。
我有这样的结构:
[person(_, _), person(_, _), ...]
person
描述如下:
person(Name, Occupation)
我正在解决的谜题包含更多事实,但我无法描述这些双向事实。
为了简单起见,我使解决方案非常类似于函数式编程,我将所有内容拆分为函数。我有一个名为fact1(List)
的方法,它接受前面描述的结构(person
结构列表)。
如何形容克拉克和琼斯住在同一所房子里?
name(clark).
name(jones).
name(person(Name, _), Name).
occupation(person(_, Occupation), Occupation).
fact1(List):-
name(Clark, clark),
name(Jones, jones),
???. % have references to Clark and Jones, but what now?
↓ 更新 ↓
整个拼图如下(我知道和上面的例子不符)。
Brown、Clark、Jones 和 Smith 是 Beartown 第一国民银行的会计师、出纳员、经理和行长,但不一定分别担任这些职务的人的名字。
虽然收银员一直在打败他,但总裁会和别人下棋。
经理和收银员都是比会计更好的棋手。
琼斯和史密斯是隔壁邻居,晚上经常一起下棋。
克拉克比琼斯下棋更好。
会计师住在总裁附近,但不靠近任何其他人。
在朋友的帮助下,我设法通过预先执行一些逻辑任务来解决它。
我结合事实一、三和五,得到以下事实:
收银员只和总裁玩。
琼斯和史密斯住在一起,一起玩耍。
会计师与总裁同住。
结论:琼斯和史密斯既不能当总裁也不能当收银员,因为他们住在一起玩,但是总裁和会计住在一起,只和收银员一起玩。
然后我添加了以下限制,然后我得到了一个确定性的单一答案:
\+ member(person(jones, accountant), Persons)
\+ member(person(smith, accountant), Persons)
\+ member(person(jones, president), Persons)
\+ member(person(smith, president), Persons)
【问题讨论】:
这不是一个糟糕的开始,但可能有一种更 Prolog 式的方式来写下你的事实。如果您(在问题中)告诉我们您的最终目标是什么,那么建议一个可行的解决方案会更容易。 如果您搜索“爱因斯坦拼图”或“斑马拼图”,您可能会得到一些想法。这只是基于您的两个事实用英语表述的方式的猜测。 嘿鲍里斯!感谢您的建议。我设法解决了这个难题,如果您有兴趣,可以阅读更新后的原帖。 【参考方案1】:不确定但是...如果您想选择一个普通的房子,我想您应该在您的个人结构中添加一个房子字段(您的示例仅包含姓名和职业)。
如果你的 person 结构是
person(Name, Occupation, House)
如果您想检查名称为jones
和clarke
的人是否共享同一所房子,并且假设您必须检查person
的列表,我建议创建一个子句getHouse/3
为关注
getHouse([person(Name, _, House) | _], Name, House).
getHouse([_ | T], Name, House) :-
getHouse(T, Name, House).
从人员列表中提取给定名称的房屋(或给定房屋的名称)。
使用getHouse/3
,我想你可以把你的fact1/1
写成
fact1(L) :-
getHouse(L, clarke, CommonHouse),
getHouse(L, jones, CommonHouse).
【讨论】:
我真的不需要知道这个人的房子。目标是找出哪个名字与哪个职业相匹配。只有这样的事实,谁和谁住在一起,谁不和谁住在一起,以减少数据集。我想在那种情况下,没有必要添加 house 字段?以上是关于Swi-prolog 双向子句/事实的主要内容,如果未能解决你的问题,请参考以下文章
将 Spring Security(双向 SSL)配置为仅对 CORS 预检 OPTIONS 请求进行身份验证