2013-04-27 3 views
2

Я работаю над наивным алгоритмом квадратной упаковки, используя библиотеку CoreLogic CLP (FD) Clojure (core.logic версия 0.8.3).Clojure core.logic CLP (FD) Проецируемые переменные FD

Квадраты представлены следующим образом:

[[[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?

Спасибо!

ответ

3

Да, вы не можете проектировать конечные доменные вары, которые не были ограничены одним значением. Я рекомендую посмотреть существующие решения вашей проблемы в Prolog, которые используют CLP (FD). Вполне возможно, что мы не поддерживаем достаточно ограничений, чтобы упростить эту проблему, - мы работаем над этим.

+0

Ах спасибо, приятно знать! –

+0

Нужна форма исключения квантификатора, чтобы уменьшить количество ограничений, что не всегда возможно, когда домен бесконечен. Но никто не мешает возвращению решения с квантификаторами впереди. Если квантификатор является экзистенциальным квантором, вам даже не нужно его показывать, за исключением учета возможного варианта исключения. Переменная может участвовать в устранении прямой константы, когда она не помечена как сама. Вот почему чаще всего работают свежие переменные Prolog, например, введенные в рекурсивные предикаты с использованием CLP (FD). –

Смежные вопросы