首页 > 解决方案 > 有没有办法向求解器提供关于哪些路径更好的提示?

问题描述

有没有办法在解决过程中更喜欢某些路径而不是其他路径?这确实是一个性能问题。当我将所有逻辑放在一起时,它会生成 1000 个解决方案,这需要成倍增加的时间。这些确实都是有效的解决方案,所以我可以做类似的事情(run 1 …)(run* …)但这给了我一个任意的解决方案。我想要做的是能够提供一些关于哪些路径更好的提示。

我知道,我可以通过使用自定义比较器对它们进行排序来获得最佳答案,但这无助于解决性能问题。

这是一个简化的、人为的示例:

(require
  '[clojure.core.logic :refer :all]
  '[clojure.core.logic.fd :as fd]))

(defn multipleo
  [multiple value domain]
  (fresh [n]
    (fd/in multiple domain)
    (fd/in n (fd/interval 1 10))
    (fd/* n multiple value)))

(run* [q]
  (multipleo q 60 (fd/domain 30 24 15 12)))
=> (12 15 30)

12、15 和 30 都是有效的解决方案,但我想要的是最大的(-> *1 sort last),但我想用求解器来做,所以(run 1 [q] (multipleo q 60 (fd/domain 30 24 15 12)))理想情况下会产生(30).

标签: clojureclojure-core.logic

解决方案


扩展@amlloy 的建议,我可以试试这个:

(defn multipleo
  [multiple value]
  (fresh [n]
    (conde
      [(== multiple 6)]
      [(== multiple 3)])
    (fd/in n (fd/interval 1 10))
    (fd/* n multiple value)))

(run* [q] (multipleo q 12))
=> (6 3)

这似乎有效。据我所知,在 fd/in 中对域进行排序没有影响。conde但是,如果我按照我喜欢的顺序移动域条目 intp a ,那就可以了。没有conde上面的代码就会产生(3 6)。但是,这比 fd/in 方法慢得多。我猜 fd/in 与 conde 相比有一些不错的性能技巧。

我也试过condu了,但这并没有像我预期的那样工作。

(defn multipleo
  [multiple value]
  (fresh [n]
    (condu
      [(== multiple 6)]
      [(== multiple 3)])
    (fd/in n (fd/interval 1 10))
    (fd/* n multiple value)))

(run* [q] (multipleo q 3))
=> ()

我本来预计第一condu组会失败,因为在这个例子中,整体逻辑不能成功 w/multiple=6。谁能帮我理解为什么这不能按我的预期工作?


推荐阅读