有限域减法上的 Clojure core.logic 未按预期工作且未记录

问题描述 投票:0回答:1

我编写了一个 Clojure 程序来解决一个相当简单的问题。考虑一个我们需要用整数填充的固定大小的向量。我们必须遵守以下规则。

  1. 必须从一组给定的整数中选择每个整数。
  2. 向量中的每个点都有自己的最小值。赋值必须大于或等于
  3. 任意两个相邻整数之间的差值必须不超过给定的 maxStep
  4. 输出中最多只能使用 maxDistinct 个不同的整数。

这是我用评论解决问题的尝试

(ns thickness-optimizer.core
  (:refer-clojure :exclude [==])
  (:use clojure.core.logic)
  (:require [clojure.core.logic.fd :as fd]))


; This is not working properly. It seems very much directional, in that
; it matters if I use lower-upper or upper-lower. The result changes if
; I swap the order of the arguments on the last line of this function.
; I suspect it's an issue where the diff needs to be in the same domain
; as the lower and upper or that possibly negatives are not allowed?
(defn stepLimit [maxStep]
  (fn [lower upper]
    (let [diffDom (apply fd/domain (range (- maxStep) (+ maxStep 1)))]
      (fresh [diff]
        (fd/dom diff diffDom)
        (fd/- lower upper diff)))))
 

(defn solve [minimums valids maxStep maxDistinct]
  ; The result is a list of integers the same length as given minimums.
  (let [result (lvars (count minimums))]
    (run* [q]
      ; I'm not sure if this is okay style, but I initialize the result
      ; outside as a normal list and assign to q inside here so that I
      ; can use 'rest and 'map on it later.
      (== q result)

      ; Every lvar in the result list is in the domain of given valids.
      (everyg #(fd/dom % (apply fd/domain valids)) result)

      ; Every item in result is pairwise >= the corresponding minimum.
      (and* (map #(fd/>= %1 %2) result minimums))

      ; Between each item in result there's no more than 20 difference.
      (and* (map (stepLimit maxStep) result (rest result)))

      ; There shpuld be no more than maxDistinct distinct values in
      ; the result. This is not working obviously because I cannot take
      ; the normal clojure list of distinct values on a list of lvars.
      ; I'm not really sure how to do this with clore.logic or fd.
      ;(<= (count (distinct result)) maxDistinct)
      )))


(defn main []
  (run! println
    (solve
      [10 10 50]
      [10 20 45 50]
      20
      2)))

相信问题出在我对 fd/- 的使用上。遗憾的是,这个函数没有记录。我也想知道我是否可以为那个 -maxStep - maxStep 域使用间隔,但也没有记录间隔,我真的不知道它们是否可以互换。

输出只是[50 50 50]。我希望 [20 45 50] 是有效的,因为没有超过 20 的跳跃。当然,独特的功能会消除那个,但它被注释掉了。但是 [45 45 50] 也应该可以工作。不过我只得到 [50 50 50]。

我对任何关于 core.logic 风格使用的批评感兴趣,或者我如何才能做得更好。

clojure clojure-core.logic
1个回答
0
投票

如果你看一下

domain
的实现,很明显它的成员不能是负数。那肯定会破坏您对
stepLimit 
.

的实施

我不是

fd
专家,但看起来你可以只使用正数。仅构建 positive 增量的域,并使用
conde
验证
(- x y)
在该域中,或者
(- y x)
是。

© www.soinside.com 2019 - 2024. All rights reserved.