今天我们利用google or-tools的cp_model建模语言来求解一个著名的逻辑问题:斑马问题。

斑马问题

1. 一条街上有五座不同颜色的房子,每座房子住着不同国籍的人,每个人抽不同的烟,喝不同的饮料,养不同的宠物。
2. 英国人住在红房子里。
3. 西班牙人养狗。
4. 住在绿房子里的人喝咖啡。
5. 乌克兰人喝茶。
6. 绿房子就在乳白色房子的右边。
7. 抽流金岁月(烟名)的人养蜗牛。
8. 抽薄荷烟的住在黄房子里。
9. 住在中间的房子里的人喝牛奶。
10. 挪威人住在第一座房子里。
11. 抽契斯特菲尔德(烟名)的人住在养狐狸的人旁边。
12. 抽薄荷烟的人住在养马的人旁边。
13. 抽好彩(烟名)的人喝橙汁。
14. 日本人抽百乐门(烟名)。
15. 挪威人住在蓝房子隔壁。

最后请问:谁喝水?谁养斑马?

解答

求解此类问题时,我们首先对问题中出现的名词进行分类,然后寻找各类名词之间的对应关系:

房屋颜色:红色、绿色、黄色、蓝色、乳白色。
国籍:英国人、西班牙人、日本人、乌克兰人、挪威人。
动物:狗、蜗牛、狐狸、斑马、马。
饮料:茶、咖啡、水、牛奶、橙汁
烟名:抽流金岁月、抽薄荷烟、契斯特菲尔德、好彩、百乐门。

创建变量

我们发现我们可以将问题中的所有名称分成5个分类,并且5个分类下有5个对应的名词。接下来我们为每一个名词创建一个整形变量:

from ortools.sat.python import cp_model
model = cp_model.CpModel()
#房屋颜色
red = model.NewIntVar(1, 5, 'red')
green = model.NewIntVar(1, 5, 'green')
yellow = model.NewIntVar(1, 5, 'yellow')
blue = model.NewIntVar(1, 5, 'blue')
ivory = model.NewIntVar(1, 5, 'ivory')
#国籍
englishman = model.NewIntVar(1, 5, 'englishman')
spaniard = model.NewIntVar(1, 5, 'spaniard')
japanese = model.NewIntVar(1, 5, 'japanese')
ukrainian = model.NewIntVar(1, 5, 'ukrainian')
norwegian = model.NewIntVar(1, 5, 'norwegian')
#动物
dog = model.NewIntVar(1, 5, 'dog')
snails = model.NewIntVar(1, 5, 'snails')
fox = model.NewIntVar(1, 5, 'fox')
zebra = model.NewIntVar(1, 5, 'zebra')
horse = model.NewIntVar(1, 5, 'horse')
#饮料
tea = model.NewIntVar(1, 5, 'tea')
coffee = model.NewIntVar(1, 5, 'coffee')
water = model.NewIntVar(1, 5, 'water')
milk = model.NewIntVar(1, 5, 'milk')
fruit_juice = model.NewIntVar(1, 5, 'fruit juice')
#烟名
old_gold = model.NewIntVar(1, 5, 'old gold')
kools = model.NewIntVar(1, 5, 'kools')
chesterfields = model.NewIntVar(1, 5, 'chesterfields')
lucky_strike = model.NewIntVar(1, 5, 'lucky strike')
parliaments = model.NewIntVar(1, 5, 'parliaments')

添加约束

因为每个分类下的名词都是唯一的,所以这里我们要对各个分类下的所有成员分别添加一个AddAllDifferent()约束:

model.AddAllDifferent([red, green, yellow, blue, ivory])
model.AddAllDifferent([englishman, spaniard, japanese, ukrainian, norwegian])
model.AddAllDifferent([dog, snails, fox, zebra, horse])
model.AddAllDifferent([tea, coffee, water, milk, fruit_juice])
model.AddAllDifferent([parliaments, kools, chesterfields, lucky_strike, old_gold])

接下来我们根据题目中所有已知条件来添加各类名词之间的对应关系约束:

#英国人住红房子
model.Add(englishman == red)
#西班牙人养狗
model.Add(spaniard == dog)
#绿房子里的人喝咖啡
model.Add(coffee == green)
#乌克兰人喝茶
model.Add(ukrainian == tea)
#绿房子就在乳白色房子的右边
model.Add(green == ivory + 1)
#抽流金岁月(烟名)的人养蜗牛
model.Add(old_gold == snails)
#抽薄荷烟的住在黄房子里
model.Add(kools == yellow)
#住在中间的房子里的人喝牛奶
model.Add(milk == 3)
#挪威人住在第一座房子里
model.Add(norwegian == 1)

以上我们对能够明确对应关系的名词对建立了关联关系,剩下我们还有3个关系不明确的条件:

1. 抽契斯特菲尔德(烟名)的人住在养狐狸的人旁边。
2. 抽薄荷烟的人住在养马的人旁边。
3. 挪威人住在蓝房子隔壁。

对于像旁边、隔壁这类地点状语,我们也可以推断出两个相关变量之间差的绝对值应该是1:

抽契斯特菲尔德(烟名)的人住在养狐狸的人旁边:
| chesterfields - fox | = 1

抽薄荷烟的人住在养马的人旁边:
| horse - kools | = 1

挪威人住在蓝房子隔壁:
| norwegian - blue | = 1

为此我们还需要为这三个条件添加3个绝对值约束:

#抽契斯特菲尔德(烟名)的人住在养狐狸的人旁边:
diff_fox_chesterfields = model.NewIntVar(-4, 4, 'diff_fox_chesterfields')
model.Add(diff_fox_chesterfields == fox - chesterfields)
model.AddAbsEquality(1, diff_fox_chesterfields)#抽薄荷烟的人住在养马的人旁边:
diff_horse_kools = model.NewIntVar(-4, 4, 'diff_horse_kools')
model.Add(diff_horse_kools == horse - kools)
model.AddAbsEquality(1, diff_horse_kools)#挪威人住在蓝房子隔壁:
diff_norwegian_blue = model.NewIntVar(-4, 4, 'diff_norwegian_blue')
model.Add(diff_norwegian_blue == norwegian - blue)
model.AddAbsEquality(1, diff_norwegian_blue)

求解

solver = cp_model.CpSolver()
status = solver.Solve(model)if status == cp_model.OPTIMAL:people = [englishman, spaniard, japanese, ukrainian, norwegian]#找出喝水的人water_drinker = [p for p in people if solver.Value(p) == solver.Value(water)][0]#找出养斑马的人zebra_owner = [p for p in people if solver.Value(p) == solver.Value(zebra)][0]print('The', water_drinker.Name(), 'drinks water.')print('The', zebra_owner.Name(), 'owns the zebra.')
else:print('No solutions to the zebra problem, this is unusual!')

参考资料

以上代码来自于: https://github.com/google/or-tools/blob/master/examples/python/zebra_sat.py

利用google or-tools 求解逻辑难题:斑马问题相关推荐

  1. 前端性能优化必备技能 - 利用 Chrome Dev Tools 进行页面性能分析

    背景 我们经常使用 Chrome Dev Tools 来开发调试,但是很少知道怎么利用它来分析页面性能,这篇文章,我将详细说明怎样利用 Chrome Dev Tools 进行页面性能分析及性能报告数据 ...

  2. 使用.Net Core与Google Optimization Tools实现员工排班计划Scheduling

    上一篇说完<Google Optimization Tools介绍>,让大家初步了解了Google Optimization Tools是一款约束求解(CP)的高效套件.那么我们用.Net ...

  3. 前端性能优化之利用 Chrome Dev Tools 进行页面性能分析

    背景 我们经常使用 Chrome Dev Tools 来开发调试,但是很少知道怎么利用它来分析页面性能,这篇文章,我将详细说明怎样利用 Chrome Dev Tools 进行页面性能分析及性能报告数据 ...

  4. 使用.NET Core与Google Optimization Tools实现加工车间任务规划

    前一篇文章<使用.NET Core与Google Optimization Tools实现员工排班计划Scheduling>算是一种针对内容的规划,而针对时间顺序任务规划,加工车间的工活儿 ...

  5. Google Optimization Tools介绍

    Google Optimization Tools(OR-Tools)是一款专门快速而便携地解决组合优化问题的套件.它包含了: 约束编程求解器. 简单而统一的接口,用于多种线性规划和混合整数规划求解, ...

  6. python 根据地址求经纬度 谷歌_利用google的API获取世界城市经纬度(python实现)

    google API 需要 --. #-*- coding: utf8 -*- from xml.dom import minidom import urllib2, urllib #这个KEY本来是 ...

  7. 利用Matlab优化工具箱求解旅行商最短路径问题

    前面介绍了利用Matlab二元整数规划求解数独问题,对于另一个问题-旅行商问题也可以用它来求解. 旅行商问题就是找到经过所有站点的最短闭合路径,如下图为在美国地图框架内产生的200个旅行站点,而旅行商 ...

  8. 蒙蒂霍尔问题_常见的逻辑难题–骑士和刀,蒙蒂·霍尔和就餐哲学家的问题解释...

    蒙蒂霍尔问题 While not strictly related to programming, logic puzzles are a good warm up to your next codi ...

  9. Google Webmaster Tools 结构化数据标记使用入门指南

    要想使自己的产品在Google搜索结果有一个好的排名,我们不仅可以在提高Google搜索排名上下功夫,也可以改善我们的产品在Google搜索结果页的结构化数据样式,这样就能够以更准确.更具吸引力的方式 ...

最新文章

  1. Android判断应用是否拥有某种权限
  2. java设计模式face_24种设计模式--门面模式【Facede Pattern】
  3. 设计模式:状态模式(State)
  4. python-面向对象编程设计与开发
  5. [css] 怎么使图片宽度自适应呢?
  6. Windows Server 2008 Active Directory的安装
  7. 超级计算机燕 排名,特斯拉超级计算机算力全球第五,展现无人驾驶领域野心...
  8. Unity 使用BmFont制作艺术字体
  9. 大学生必学练习题 - C 语言经典50例
  10. EasyCamera开源摄像机接入海康威视摄像机PS流转ES流
  11. 服务器443端口响应代码,使用443端口远程服务器
  12. python面向对象编程思想_面向对象编程思想及其特点
  13. python打开文件写入内容_python-11 文件的打开和写入
  14. jQuery ? NO, Axios——请求数据
  15. altium designer利用向导画封装库详解
  16. 报错:The media could not be loaded, either because the server or network failed or ...
  17. 五、HTML标签——图文详解
  18. 2009-2019:卢松松博客10周年
  19. 通过pc算法和随机游走来做根因定位,CloudRanger论文解读
  20. open3d学习教程2--点云1

热门文章

  1. 练手小项目——canvas放大镜效果 放大图片
  2. MySQL课程设计2022 · 员工考勤管理系统
  3. 扩展程序 - Google Chrome
  4. Mysql -- 管理工具
  5. JVM相关命令查看GC情况
  6. Linux僵尸进程分析清除
  7. 基于HTML的环境网站设计 HTML+CSS环保网站项目实现 带设计说明psd
  8. 计算机网络学习 :互联网与万维网的区别
  9. Python 环境安装系统教程——PyCharm
  10. python 如果文件夹不存在 创建文件夹