Scala中的基本逻辑编程

时间:2012-05-14 06:39:14

标签: scala logic predicate logic-programming

我有一个有趣的小问题,我会看到像这样的逻辑子句:

Rule 1. A, B and C are unique, and are numbers from 1 to 3 (so every number is used).
Rule 2. B < 2
Rule 3. C > 2

现在(假设这个简单的例子我刚刚提出实际验证:P),很容易看到

A = 2
B = 1
C = 3

但这是一个非常人为的例子。

如果您有20(或一万)规则,并且它们重叠,那该怎么办?假设存在有效的单一答案,并且您可以以某种方式访问​​规则(无论是谓词列表)。

有一个很好的,通用的,直观的解决方案吗?我知道Prolog可以用某些库解决它,但我的尝试证明是徒劳的。我知道我可以通过暴力强制排列范围内的所有数字,然后手动检查它们是否符合规则。但这似乎很蹩脚。

3 个答案:

答案 0 :(得分:4)

暴力解决方案

首先,我根据规则1创建所有可能的输入,这恰好是所有排列:

val all = (1 to 3).permutations

然后我定义了剩余的规则:

val rule2 = (a: Int, b: Int, c: Int) => b < 2
val rule3 = (a: Int, b: Int, c: Int) => c > 2

我只是过滤掉了与所有规则不符的解决方案:

val solutions = all.
  filter(i => rule2(i(0), i(1), i(2))).
  filter(i => rule3(i(0), i(1), i(2))).
  toList

solutions.toList打印出唯一有效的解决方案:

List(Vector(2, 1, 3))

请注意,由于排列是懒惰生成的,因此此实现并非真正无效(例如rule3仅适用于通过rule2)的解决方案。

您可以使用foldLeft()应用任意数量的谓词:

val rules = List(rule2, rule3)

rules.
  foldLeft(all)((solutionsSoFar, rule) => 
    solutionsSoFar.filter(s => 
      rule(s(0), s(1), s(2))
    )
  )

的Drools

查看Drools业务规则引擎。只需将所有可能的解决方案作为知识库,并使用不错的DSL定义规则。

答案 1 :(得分:3)

这是约束的工作。 java有几个约束求解器。我最喜欢的是JaCoP。有一个很好的scala DSL,所以它几乎看起来像Prolog约束。以下是典型的SENDMOREMONEY示例:http://www.hakank.org/jacop/SendMoreMoney.scala

答案 2 :(得分:2)

您可能对此博客感兴趣,作者在一篇由三部分组成的文章中展示了如何在Scala中进行逻辑编程:

http://ambassadortothecomputers.blogspot.com/feeds/posts/default?alt=rss