Есть ли способ дать подсказки решателю, какие пути лучше? - PullRequest
0 голосов
/ 27 сентября 2019

Есть ли способ отдавать предпочтение определенным путям перед другими при решении?Это действительно вопрос производительности.Когда я соединяю всю свою логику, она генерирует тысячи решений, и это занимает экспоненциально возрастающее время.Это действительно все правильные решения, поэтому я мог бы сделать что-то вроде (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).

1 Ответ

0 голосов
/ 29 сентября 2019

Расширяя предложение @ 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))
=> ()

Iожидал бы, что первая группа condu потерпит неудачу, так как общая логика не может быть успешной, w / кратный = 6, в этом примереМожет кто-нибудь помочь мне понять, почему это не работает, как я ожидаю?

...