【问题标题】:Is there a way to provide hints to the solver, about which paths are better?有没有办法向求解器提供关于哪些路径更好的提示?
【发布时间】:2019-09-27 20:59:41
【问题描述】:

在求解过程中,有没有办法让某些路径优先于其他路径?这确实是一个性能问题。当我将所有逻辑放在一起时,它会生成 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)

【问题讨论】:

  • 我不知道 fd,但对于普通逻辑变量,您可以简单地将“首选”路径放在 conde 或其他任何其他路径之前,然后首先搜索。

标签: clojure clojure-core.logic


【解决方案1】:

扩展@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 中对域进行排序没有影响。但是,如果我按照我喜欢的顺序将域条目 intp 移动到 conde,那就可以了。如果没有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 组会失败,因为在此示例中,整体逻辑无法通过 multiple=6 成功。谁能帮我理解为什么这不能按我的预期工作?

【讨论】:

    猜你喜欢
    • 2021-11-20
    • 2011-05-10
    • 2011-09-24
    • 1970-01-01
    • 2022-11-04
    • 1970-01-01
    • 1970-01-01
    • 2020-02-24
    • 1970-01-01
    相关资源
    最近更新 更多