我试着在core.logic:中键入一个查询
(run* [q] (== 0 (+ (* q q) (* 4 q) 4)))
提示说,
error: lvar cannot be cast to a number
如果我还没有完全误解逻辑编程的含义,那么有没有办法使用core.logic来解决这个问题?
据我所知,core.logic不能用代数来解这个方程。它可以进行基本的数学运算,尽管该数学运算的输入需要是实际值,而不是LVar
s,因为数学函数不能对以下内容进行操作:
user> (run* [q]
(fresh [x]
(== x 1)
(project [x] (== q (+ (* x x) 4)))))
(5)
当x有一个明确的值时工作,当x没有时失败:
user> (run* [q]
(fresh [x]
(== x q)
(project [x] (== q (+ (* x x) 4)))))
ClassCastException clojure.core.logic.LVar cannot be cast to java.lang.Number
你应该阅读《理性的Schemer》来获得想法。基本上,在逻辑程序中进行数学运算的方法是创建基于列表的数字编码,逻辑引擎可以根据需要进行扩展以尝试。我手边没有这本书,但它将整数编码为一个比特列表,以某种奇怪的方式,我记不清了:也许(1)
代表0,(0)
是非法的,MSB在列表中最后?
不管怎样,这是一项艰巨的工作;David Nolen最近也在core.logic中引入了一些关于有限域的内容。我不知道这些是如何工作的,但我认为它们通过让你指定要考虑哪种数字来解决问题,大大简化了问题。
core.logic目前的形式并不是作为数值方程求解器设计的,它更适合求解逻辑表达式和关系表达式。
你基本上有两条实用的求解数学方程的途径:
- 分析解算器-对于简单的情况,例如上面的二次方程,可以很容易地找到解,但很快就会变得越来越复杂,然后对许多方程来说变得不可能/不可行。这是一个巨大的开放性研究课题
- 数值求解器-这些技术更通用,几乎可以用于任何类型的方程。然而,结果并不准确,如果方程具有"恶劣"特征(不连续性、奇数梯度、局部极小值的复杂集合等),算法可能无法找到正确的解
方程求解器需要特殊的智能来理解数学方程的"规则",例如如何对多项式表达式进行因子运算(对于分析解)或如何估计导数(对于数值解)。
一些可能很有趣的链接:
- Incenter中的二次方程求解器
- http://programming.wonderhowto.com/how-to/solve-equations-for-any-variable-with-clojure-1-1-380687/
- Clojure中的简单数值求解器示例(Newton-Raphson方法)