QCon 演讲火热征集中,快来分享技术实践与洞见! 了解详情
写点什么

Google SoC 系列:使用 Ruby 实现约束规划

  • 2007-06-26
  • 本文字数:2383 字

    阅读完需:约 8 分钟

Gecode/R 是一个得到 Google SoC 资助的 Ruby 项目,目的是使得 Ruby 语言的开发者同样可以使用运筹学中的约束规划(Constraint Programming)方法,项目的发起人 Andreas Launila 对于约束规划这样解释道:

约束规划是一种声明式的规划范式(Declarative Programming Paradigm),开发者描述需要何种解决方案,而不是告诉程序如何进行具体的计算。当使用约束规划时,开发者可以试图为问题建立模型,并将模型集中提交给问题处理程序。问题处理程序通过检索问题域中的所有可行解,并利用模型中的约束条件来去除这些解中的部分,而不需要真正去访问到这部分的可能解。 一个常见的例子就是数独游戏(Soduko),通过约束规划解决数独问题的过程是:为问题处理程序填写约束规则(比方说每一行的数字必须是各不相同的),然后寻找令所有约束条件同时满足的解决方案。

当问及现实世界中是否有使用约束规划解决问题的例子时,Andreas 解释道:

约束规划是用于处理 NP 难解组合问题的常用方法,在这种情况下,一般只存在有限的选择,但需要根据特定条件进行搜索。现实世界中的例子包括时序安排,周期分配以及人员工作时间设置等问题。

Gecode/R 实际上是建立在 C++ 约束规划函数库 Gecode基础之上的 Ruby 语言封装,关于为何使用 Ruby 语言来实现 Gecode 的功能,Andreas 这样解释道:

对我来说,约束规划是在我常用工具箱中一个非常有用的工具。当使用约束规划来处理恰当的问题类型时,会为我们节省大量的时间和工作。由于可以进行快速编码实现,当更好的算法存在并且运行效率并非是首要考虑的因素(或者性能上的差别比起在研究和实现算法上需要花的额外时间是可以忽略不计)时,约束规划可以用来很快的解决问题。

一个有趣的话题是关于如何使用 Ruby 语言来定义约束规划:

我的目的是为了创建一个前端,而不仅仅是一个绑定。我称之为类库而不仅是一种 DSL(Domain Specific Language,领域特定语言),尽管两者之间的边界并非有十分严格的界定。因为项目即将开始,至今还没有定义精确的语法规则。下面简单的代码段给出项目的大致指导方向,但这不一定是项目最终使用的语法规则。代码段示例解决了“send+more=money”这个经典的问题。 通过这样的途径,比较方法和算术方法被用于表示线性约束,并且通过对数组进行拓展来表达特殊约束来用于分支选择。变量在创建时需要记录,以便于跟踪他们。其中一个不足之处是符号“!=”没有被定义为一个方法,所以使用不等式时的语法与其他语言并不相同。

下面是程序代码编写的样例:

# 经典的 send+more=money 问题。<br></br>class SendMoreMoneyProblem < Gecode::Space<br></br> def initialize<br></br> # 设置变量,在 0..9 之间的 8 个字母.<br></br> s,e,n,d,m,o,r,y = letters = IntVar.array(8, 0..9)<br></br> # 设置约束条件.<br></br> constrain equation_row(s, e, n, d) +<br></br> equation_row(m, o, r, e) ==<br></br> equation_row(m, o, n, e, y)<br></br> constrain s.not_equal(0) # 并不是写成"s != 0" 因为我们无法重定义符号 != .<br></br> constrain m.not_equal(0)<br></br> letters.all_distinct<br></br> # 选择搜索解决方案时要使用的启发式分支.<br></br> letters.branch_using(:variable => :min_size, :value => :min)<br></br> end<p>private</p><br></br> # 使用线性方程有更好的方法。取出变量中的一个数字,<br></br> # 并且计算线性组合就像变量是基于 10 个字符的阿拉伯数字。<br></br> # 例如:x,y,z 成为 100*x + 10*y + z .<br></br> def equation_row(*variables)<br></br> variables.inject(0){ |result, variable| variable + 10*result }<br></br> end<br></br>end<br></br># 打印出问题的第一种解决方案 <br></br>p SendMoreMoneyProblem.new.solutions(:first)如果想了解更多细节,可以查看维基百科上面“send+more=money”词条相关的文章

当使用 Ruby 语言定义业务逻辑或者数据时,常有可能使用内部 DSL来编写更加简练并且可读性更强的代码。Andreas 关于代码可能的样式这样解释道:

另一个使得代码看起来更像 DSL 的方法是在编码中跳过类声明之类的。这个方法在快速处理单一样例的问题时更加出色,但是会妨碍与其它 Ruby 代码协同来使用约束规划。

下面是使用 DSL 方法的代码样例:

find_first_solution_to define_problem do |p|<br></br> # 设置变量,在 0..9 之间的 8 个字母。<br></br> s,e,n,d,m,o,r,y = letters = p.create_int_vars(8, 0..9)<br></br> # 设置约束。<br></br> p.add 1000*s + 100*e + 10*n + d +<br></br> 1000*m + 100*o + 10*r + e ==<br></br> 10000*m + 1000*o + 100*n + 10*e + y<br></br> p.add s.not_equal(0)<br></br> p.add m.not_equal(0)<br></br> p.add all_distinct(letters)<br></br> # 选择启发式分支。<br></br> p.branch_on letters, :variable => :min_size, :value => :min<br></br>end由于 Gecode/R 是在本地类库基础之上的绑定实现,这样就存在一个潜在的瓶颈问题。Andreas 非常自信的认为这不会是一个影响项目发展的问题:

在 Gecode 中已经实现了通用约束的传播机制,所以这些约束的实际传播过程已在此处完成。如果用户设置自定义的传播机制,则需要在 C 语言和 Ruby 语言之间进行来回切换,目前我还不清楚这样是否存在性能问题。但 Gecod 的设计可以使其能很好地与外界进行交互,并且可以很好的与 Java 语言协同工作,所以如果有人说 Gecode/R 在本地类库上实现绑定将会成为瓶颈,我肯定会对此表示惊讶。

Gecode/R 是建立在 RubyForge 上的开放源代码项目,这同时也是吸引对此感兴趣开发者加入的优秀站点。约束规范相关的API 接口和语法的可以在链接中的Wiki 页面深入了解。Andreas 同时也维护着建立在O’Reilly Ruby 站点上的Gecode/R 项目相关博客

查看英文原文: Google SoC Series: Constraint programming with Ruby

2007-06-26 19:301113
用户头像

发布了 74 篇内容, 共 12.6 次阅读, 收获喜欢 3 次。

关注

评论

发布
暂无评论
发现更多内容

Apache IoTDB PMC Chair 黄向东主办 2023 开放原子开发者大会开源工业物联网大数据分论坛,诚邀您的参加!

Apache IoTDB

西班牙语 Alt 代码表

HoneyMoose

极狐GitLab 镜像仓库使用技巧

极狐GitLab

DevOps gitlab 镜像 CI/CD 镜像仓库

一起学Elasticsearch系列-搜索推荐

Java随想录

Java 大数据 elastic 搜索

高校刮起元宇宙风!3DCAT实时云渲染助力川轻化元校园建设

3DCAT实时渲染

实时云渲染 元宇宙解决方案

Kyligence 荣登甲子光年 2023 AIGC 技术应用领域最具商业潜力榜

Kyligence

数据分析 智能决策

马斯克回应聊天机器人 Grok 抄 ChatGPT 作业;Figma 推出宏编程键盘丨 RTE 开发者日报 Vol.105

声网

法语 Alt 代码表

HoneyMoose

群晖(Synology)新建存储池使用 Home 服务

HoneyMoose

2023-12-13:用go语言,密码是一串长度为n的小写字母,一则关于密码的线索纸条, 首先将字母a到z编号为0到25编号, 纸条上共有n个整数ai,其中a1表示密码里第一个字母的编号, 若i>1的

福大大架构师每日一题

福大大架构师每日一题

从Rustup出发看Rust语言的编译生态

程序饲养员

编译器 rust语言

德语 Alt 代码表

HoneyMoose

Trace 在多线程异步体系下传递

观测云

Trace 链路

让艺术触手可及!3DCAT实时云渲染赋能真浪数字艺术馆首展

3DCAT实时渲染

实时云渲染 元宇宙解决方案

内置功率 MOSFET 的高频同步整流降压开关变换器

芯动大师

物联网与低代码:构建智能化的连接世界

快乐非自愿限量之名

低代码 物联网 IoT

技术写作及技术作者的概述和重要性 - 了解技术写

小万哥

技术 程序人生 写作 软件开发 作者

场场爆满的昇腾 AI 开发者创享日:照见产业数智化的涓涓动力

Alter

大模型扫盲问题集

小判

大模型

1.5万字 + 25张图盘点RocketMQ 11种消息类型,你知道几种?

快乐非自愿限量之名

RocketMQ 事务管理

深入了解埋点分析:Clklog助你优化用户体验

ClkLog

多链铭文聚合协议20Exchange将为Ordi、SATS持仓用户快照空投

股市老人

下一站 Gen AI 城市巡展指南来了!“码”上出发,Let's 构!

亚马逊云科技 (Amazon Web Services)

AIGC

大模型助力科技革命:2023年的里程碑与大模型的未来展望

屿小夏

年度总结 大模型

天谋科技荣获国家高新技术企业认证

Apache IoTDB

想突破转化瓶颈?安排上 AI ,比漏斗图更高效、更实用!

Kyligence

数据分析 转化分析

第31期 | GPTSecurity周报

云起无垠

实时数据推送应用

玄兴梦影

消息推送 实时数据

重磅发布!!!蚂蚁图团队开源高性能原生图存储系统CStore

TuGraphAnalytics

数据库 分布式 图计算 图存储 图原生

【写作训练营打卡|07】你知道文章的配图哪来的吗?

Caché/M 数据库上面的那个 é 怎么打

HoneyMoose

Google SoC系列:使用Ruby实现约束规划_Ruby_Werner Schuster_InfoQ精选文章