Clojure core.logic CLP(FD) проецирует переменные FD
Я работаю над простым алгоритмом квадратной упаковки, используя библиотеку Clojure core.logic CLP(FD) (core.logic версия 0.8.3).
Квадраты представлены так:
[[[x11 y11] [x12 y12]]
[[x21 y21] [x22 y22] ...]]
с каждым квадратом, представленным как координаты его верхнего левого и нижнего правого углов.
Координаты являются переменными FD, в пределах определенного интервала.
Я хочу определить размер решения как расстояние между верхним правым и нижним правым углами ближайшего и дальнего квадратов к началу координат соответственно
(defne solution-size-o [size squares]
([s sqrs]
(fresh [closest farthest
x11 y11 x22 y22 _1 _2]
(closest-square [[x11 y11] _1] sqrs)
(farthest-square [_2 [x22 y22]] sqrs)
(project [x11 y11 x22 y22]
(let [a (- y22 y11)
b (- x22 x11)]
(== s (-> (+ (* a a) (* b b)) Math/sqrt Math/ceil int)))))))
Это, кажется, работает нормально с простыми целыми числами:
(run 1 [q]
(solution-size-o q [[[0 0] [1 1]] [[1 1] [2 2]]]))
=> (3)
И даже с полностью ограниченными переменными FD
(defn constrained-solution-size []
(run 1 [q]
(fresh [size x11 y11
x12 y12
x21 y21
x22 y22 squares]
(fd/in x11 y11 x12 y12 x21 y21 x22 y22 (fd/interval 0 2))
(fd/eq
(= x11 0) (= y11 0) (= x21 1) (= y21 1)
(= x12 (+ x11 1)) (= y12 (+ y11 1))
(= x22 (+ x21 1)) (= y22 (+ y21 1)))
(== squares [[[x11 y11] [x12 y12]] [[x21 y21] [x22 y22]]])
(solution-size-o size squares)
(== q {:squares squares :size size}))))
(constrained-solution-size)
=> ({:squares [[[0 0] [1 1]] [[1 1] [2 2]]], :size 3})
Но, похоже, он ломается, когда домены переменных не полностью ограничены. Например, если я уберу ограничение, которое y21 = 1
, имея в виду y11
а также y21
иметь более одного значения в своих доменах:
(defn unconstrained-solution-size []
(run 1 [q]
(fresh [size x11 y11
x12 y12
x21 y21
x22 y22 squares]
(fd/in x11 y11 x12 y12 x21 y21 x22 y22 (fd/interval 0 2))
(fd/eq
(= x11 0) (= y11 0) (= x21 1)
(= x12 (+ x11 1)) (= y12 (+ y11 1))
(= x22 (+ x21 1)) (= y22 (+ y21 1)))
(== squares [[[x11 y11] [x12 y12]] [[x21 y21] [x22 y22]]])
(solution-size-o size squares)
(== q {:squares squares :size size}))))
я получил
(unconstrained-solution-size)
=> ClassCastException clojure.core.logic.LVar cannot be cast to java.lang.Number clojure.lang.Numbers.minus (Numbers.java:135)
Кажется, что project
работает только с переменными FD, когда их домены полностью ограничены. Это так и должно быть? Если да, есть ли у кого-нибудь предложения о том, как проводить нереляционную арифметику с переменными FD?
Спасибо!
1 ответ
Да, вы не можете проецировать конечные доменные переменные, которые не были ограничены одним значением. Я рекомендую взглянуть на существующие решения вашей проблемы в Prolog, которые используют CLP(FD). Вполне возможно, что мы не поддерживаем достаточно ограничений, чтобы сделать эту проблему простой для выражения - мы работаем над этим.