Mark Engelberg写了一篇有意思的帖子名为 逻辑编程被高估了。 我在那个帖子中摆出许多观点与之争论,同时我也愿意将其中的一些放到这里来讲一讲。
首先,确实,当搜索范围相当小而你又真的不在意性能的时候,列表推导式(list comprehensions)是一个优秀的简洁、易读的搜索方式。那就是说,如果基于某个有点兴趣的人写的blogpost代码,做出任何关于core.logic,以及它的解决问题的实用性的判断,在我看来没有什么意义——想象一下这么去判断面向对象式或函数式编程的实用性。
下面是关于我将如何处理这个问题的解释。这里主要的见解是,最初的问题是一个伪装的有限域问题——令人吃惊的是这与解决数独(sudoku)很相似。
在我的机器上,我的解决方案比 Mark 的优化列表解析版本快五倍,我的方案并没有改变命令的顺序。
诚然,相较于我的代码中关键词和整数之间的移动,Mark 的版本在可读性和简洁性方面更好 这个通过对 CLP(Set) 的支持将得以避免。这已经在 core.logic 的路线图中,我将在文章的末尾描述我的想法。
下面是我对问题的解决方案:
(defn puzzle [] (let [vs (take 20 (repeatedly lvar)) ps (->> (partition 4 vs) (map #(into {} (map vector [:name :cheese :mag :reserv] %))) (into []))] (run* [q] (== q ps) (everyg #(fd/in % (fd/interval 1 5)) vs) (everyg fd/distinct (apply map vector (map vals ps))) (conde [(ruleo q :name :landon :reserv :730pm) (ruleo q :name :jason :cheese :mozzarella)] [(ruleo q :name :landon :cheese :mozzarella) (ruleo q :name :jason :reserv :730pm)]) ;; 1 (ruleo q :cheese :blue :mag :fortune) ;; 2 (neg-ruleo q :cheese :muenster :mag :vogue) ;; 3 (peopleo q [[:mag :fortune] [:name :landon] [:reserv :5pm] [:cheese :mascarpone] [:mag :vogue]]) ;; 4 (neg-ruleo q :reserv :5pm :mag :time) ;; 5 (earliero q :mag :cosmopolitan :cheese :mascarpone) ;; 6 (earliero q :cheese :blue :name :bailey) ;; 7 (conde [(ruleo q :reserv :7pm :mag :fortune)] [(ruleo q :reserv :730pm :mag :fortune)]) ;; 8 (earliero q :mag :time :name :landon) ;; 9 (neg-ruleo q :name :jamari :mag :fortune) ;; 10 (ruleo q :reserv :5pm :cheese :mozzarella)))) ;; 11
在我的机器上,如果只请求第一个解决方案的话,上面的方案只需84ms,而列表解析则需要大约430ms。如果我们在引用puzzle结果时调用doal而非first,它将耗用270ms来确定一个唯一的解决方案。这依然比列表解析快。
像这样没有什么目的的解决方案的重排序性能怎么能胜过一个配置好的列表推导式呢?而后者大量的使用了统一的,有约束的构件以及其它昂贵的高级别东西?下面我提到的一些经典著作,洞察了其中的如何与为什么。
总的来说,你需要逻辑编程来解决逻辑难题吗?绝对不会!你应该使用core.logic来实现逻辑难题吗?非常肯定!重要的是,你必须尝试这两种方法以便理解其中的得失。Mark的帖子中困扰我的是,大量的观点缺少有core.logic经验的证据。
你可以在这里看到对此难题的完整解决方案。同样我对此不是很满意,我希望应该是更像这样,依依我个人浅见,它非常完美。
至于逻辑编程是否对“现实世界”问题有用,我推荐拿起Bratko的第4版人工智能Prolog编程和/或 计算机编程的概念,技术与模型 。 二者对于这些方法的广泛应用令人大开眼界。
如果你不信书就与Martin Trojer谈一谈,他在UBS银行使用过core.logic,或者与ThreatGRID谈一谈——他们在一个12片64核的刀片集群上运行core.logic来分析飞行风险(按规则领域专家写的——我猜想DSL对他们不是非常“复杂”)。
Mark的帖子有足够有效的观点,比如更好地与Clojure整合,跟踪目标执行,与外部连接器集成,我们正致力于此。
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。 2KB翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。2KB项目(www.2kb.com,源码交易平台),提供担保交易、源码交易、虚拟商品、在家创业、在线创业、任务交易、网站设计、软件设计、网络兼职、站长交易、域名交易、链接买卖、网站交易、广告买卖、站长培训、建站美工等服务