如何用z3py优雅地解决爱因斯坦之谜?

如何解决如何用z3py优雅地解决爱因斯坦之谜?

z3py伙计们提供了一个基于https://github.com/0vercl0k/z3-playground/blob/master/einstein_riddle_z3.py的代码。但是,与该https://artificialcognition.github.io/who-owns-the-zebra相比,该解决方案相当复杂,冗长且难看。我真的不希望切换库,因为z3py似乎更高级和更易于维护。因此,我开始使用我的版本,但是我未能声明某些部分(缺乏知识或无法实现?)。这是我所拥有的以及卡住的地方(2条评论):

from z3 import *

color = Int('color')
nationality = Int('nationality')
beverage = Int('beverage')
cigar = Int('cigar')
pet = Int('pet')
house = Int('house')

color_variations = Or(color==1,color==2,color==3,color==4,color==5)
nationality_variations = Or(nationality==1,nationality==2,nationality==3,nationality==4,nationality==5)
beverage_variations = Or(beverage==1,beverage==2,beverage==3,beverage==4,beverage==5)
cigar_variations = Or(cigar==1,cigar==2,cigar==3,cigar==4,cigar==5)
pet_variations = Or(pet==1,pet==2,pet==3,pet==4,pet==5)
house_variations = Or(house==1,house==2,house==3,house==4,house==5)

s = Solver()

s.add(color_variations)
s.add(nationality_variations)
s.add(beverage_variations)
s.add(cigar_variations)
s.add(pet_variations)
s.add(house_variations)

# This is not right
#s.add(Distinct([color,nationality,beverage,cigar,pet]))

s.add(And(Implies(nationality==1,color==1),Implies(color==1,nationality==1))) #the Brit (nationality==1) lives in the red (color==1) house
s.add(And(Implies(nationality==2,pet==1),Implies(pet==1,nationality==2))) #the Swede (nationality==2) keeps dogs (pet==1) as pets
s.add(And(Implies(nationality==3,beverage==1),Implies(beverage==1,nationality==3))) #the Dane (nationality==3) drinks tea (beverage=1)
s.add(And(Implies(color==2,beverage==2),Implies(beverage==2,color==2))) #the green (color==2) house's owner drinks coffee (beverage==2)
s.add(And(Implies(cigar==1,pet==2),Implies(pet==2,cigar==1))) #the person who smokes Pall Mall (cigar==1) rears birds ([pet==2])
s.add(And(Implies(color==4,cigar==2),Implies(cigar==2,color==4))) #the owner of the yellow (color==4) house smokes Dunhill (cigar==2)
s.add(And(Implies(house==3,beverage==3),Implies(beverage==3,house==3))) #the man living in the center (hause==3) house drinks milk (beverage==3)
s.add(And(Implies(nationality==4,house==1),Implies(house==1,nationality==4))) #the Norwegian (nationality==4) lives in the first house (house==1)
s.add(And(Implies(cigar==3,beverage==4),Implies(beverage==4,cigar==3))) #the owner who smokes BlueMaster (cigar==3) drinks beer (beverage==4)
s.add(And(Implies(nationality==5,cigar==4),Implies(cigar==4,nationality==5))) #the German (nationality==5) smokes Prince (cigar==4)

# I can't figure our this part,so I can keep it short and efficient
# the green (color==2) house is on the left of the white (color==3) house

当前正在研究ForAllFunction s的方向

解决方法

您应该在此处对各种事物使用枚举。同样,您不能只拥有一个颜色变量:毕竟,每所房子都有不同的颜色,并且您希望对其进行单独跟踪。一个更好的主意是使colornationality等都是未解释的函数;将数字分别映射到颜色,国家等。

这是针对此问题的Haskell解决方案,它使用SBV库,该库通过我描述的策略通过SMTLib接口使用z3:https://hackage.haskell.org/package/sbv-8.8/docs/src/Documentation.SBV.Examples.Puzzles.Fish.html

将此策略转换为Python,我们有:

from z3 import *

# Sorts of things we have
Color,(Red,Green,White,Yellow,Blue)   = EnumSort('Color',('Red','Green','White','Yellow','Blue'))
Nationality,(Briton,Dane,Swede,Norwegian,German) = EnumSort('Nationality',('Briton','Dane','Swede','Norwegian','German'))
Beverage,(Tea,Coffee,Milk,Beer,Water)  = EnumSort('Beverage',('Tea','Coffee','Milk','Beer','Water'))
Pet,(Dog,Horse,Cat,Bird,Fish)   = EnumSort('Pet',('Dog','Horse','Cat','Bird','Fish'))
Sport,(Football,Baseball,Volleyball,Hockey,Tennis) = EnumSort('Sport',('Football','Baseball','Volleyball','Hockey','Tennis'))

# Uninterpreted functions to match "houses" to these sorts. We represent houses by regular symbolic integers.
c = Function('color',IntSort(),Color)
n = Function('nationality',Nationality)
b = Function('beverage',Beverage)
p = Function('pet',Pet)
s = Function('sport',Sport)

S = Solver()

# Create a new fresh variable. We don't care about its name
v = 0
def newVar():
    global v
    i = Int("v" + str(v))
    v = v + 1
    S.add(1 <= i,i <= 5)
    return i

# Assert a new fact. This is just a synonym for add,but keeps everything uniform
def fact0(f):
    S.add(f)

# Assert a fact about a new fresh variable
def fact1(f):
    i = newVar()
    S.add(f(i))

# Assert a fact about two fresh variables
def fact2(f):
    i = newVar()
    j = newVar()
    S.add(i != j)
    S.add(f(i,j))

# Assert two houses are next to each other
def neighbor(i,j):
    return (Or(i == j+1,j == i+1))

fact1 (lambda i   : And(n(i) == Briton,c(i) == Red))                       # The Briton lives in the red house.
fact1 (lambda i   : And(n(i) == Swede,p(i) == Dog))                       # The Swede keeps dogs as pets.
fact1 (lambda i   : And(n(i) == Dane,b(i) == Tea))                       # The Dane drinks tea.
fact2 (lambda i,j: And(c(i) == Green,c(j) == White,i == j-1))           # The green house is left to the white house.
fact1 (lambda i   : And(c(i) == Green,b(i) == Coffee))                    # The owner of the green house drinks coffee.
fact1 (lambda i   : And(s(i) == Football,p(i) == Bird))                      # The person who plays football rears birds.
fact1 (lambda i   : And(c(i) == Yellow,s(i) == Baseball))                  # The owner of the yellow house plays baseball.
fact0 (                 b(3) == Milk)                                           # The man living in the center house drinks milk.
fact0 (                 n(1) == Norwegian)                                      # The Norwegian lives in the first house.
fact2 (lambda i,j: And(s(i) == Volleyball,p(j) == Cat,neighbor(i,j)))  # The man who plays volleyball lives next to the one who keeps cats.
fact2 (lambda i,j: And(p(i) == Horse,s(j) == Baseball,j)))  # The man who keeps the horse lives next to the one who plays baseball.
fact1 (lambda i   : And(s(i) == Tennis,b(i) == Beer))                      # The owner who plays tennis drinks beer.
fact1 (lambda i   : And(n(i) == German,s(i) == Hockey))                    # The German plays hockey.
fact2 (lambda i,j: And(n(i) == Norwegian,c(j) == Blue,j)))  # The Norwegian lives next to the blue house.
fact2 (lambda i,b(j) == Water,j)))  # The man who plays volleyball has a neighbor who drinks water.

# Determine who owns the fish
fishOwner = Const("fishOwner",Nationality)
fact1 (lambda i: And(n(i) == fishOwner,p(i) == Fish))

r = S.check()
if r == sat:
    m = S.model()
    print(m[fishOwner])
else:
    print("Solver said: %s" % r)

运行此命令时,我得到:

$ python a.py
German

表明鱼的主人是德国人。我认为您的原始问题有不同但相似的约束条件,您可以轻松地使用相同的策略来解决原始问题。

查看以下内容的输出也具有指导意义:

print(m)
sat中为

。打印:

[v5 = 4,v9 = 1,v16 = 2,v12 = 5,v14 = 1,v2 = 2,v0 = 3,v10 = 2,v18 = 4,v15 = 2,v6 = 3,v7 = 1,v4 = 5,v8 = 2,v17 = 1,v11 = 1,v1 = 5,v13 = 4,fishOwner = German,v3 = 4,nationality = [5 -> Swede,2 -> Dane,1 -> Norwegian,4 -> German,else -> Briton],color = [5 -> White,4 -> Green,1 -> Yellow,2 -> Blue,else -> Red],pet = [3 -> Bird,1 -> Cat,2 -> Horse,4 -> Fish,else -> Dog],beverage = [4 -> Coffee,3 -> Milk,5 -> Beer,1 -> Water,else -> Tea],sport = [1 -> Baseball,2 -> Volleyball,5 -> Tennis,4 -> Hockey,else -> Football]]

忽略对vN变量的所有分配,这些分配是我们内部用于建模目的的分配。但是您可以看到z3如何将每个未解释的函数映射到相应的值。对于所有这些,映射的值是房屋数量到满足拼图约束的相应值。您可以根据需要使用此模型中包含的信息,以编程方式提取该难题的完整解决方案。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res