16

私はcore.logicで遊んで始めたばかりで、それに取り組むために、現在専門的に取り組んでいる問題に似た単純なものを実装しようとしています。しかし、問題の一部が私を困惑させました...

例を単純化すると、アイテムのカタログがあり、そのうちのいくつかは特定の国でしか入手できず、一部は特定の国では入手できないとします。アイテムのリストと例外を次のように指定できるようにしたいと思います。

(defrel items Name Color)
(defrel restricted-to Country Name)
(defrel not-allowed-in Country Name)

(facts items [['Purse 'Blue]
              ['Car 'Red]
              ['Banana 'Yellow]])

(facts restricted-to [['US 'Car]])

(facts not-allowed-in [['UK 'Banana]
                       ['France 'Purse]])

可能であれば、制限のあるアイテムのセットは比較的小さいため、すべての国で許可されていることを指定したくありません。また、特定のアイテムの許可/除外を 1 つの変更で行えるようにしたいと考えています。国。

次の制約を使用して、国のアイテム/色のリストを提供するルールを作成するにはどうすればよいですか:

  • アイテムはアイテムのリストにある必要があります
  • 国/アイテムは「許可されていない」リストに含まれていてはなりません
  • また:
    • そのアイテムの制限対象リストに国がありません
    • 国/アイテムのペアは制限リストに含まれています

これを行う方法はありますか?私は物事を完全に間違った方法で考えていますか?

4

2 に答える 2

14

通常、ロジック プログラミングで目標を否定し始めるときは、非リレーショナル操作 (Prolog のカット、core.logic の conda) に到達する必要があります。

このソリューションは、ground 引数でのみ呼び出す必要があります。

(defn get-items-colors-for-country [country]
  (run* [q]
    (fresh [item-name item-color not-country]
      (== q [item-name item-color])
      (items item-name item-color)
      (!= country not-country)

      (conda
        [(restricted-to country item-name)
         (conda
           [(not-allowed-in country item-name)
            fail]
           [succeed])]
        [(restricted-to not-country item-name)
         fail]
        ;; No entry in restricted-to for item-name
        [(not-allowed-in country item-name)
         fail]
        [succeed]))))

(get-items-colors-for-country 'US)
;=> ([Purse Blue] [Banana Yellow] [Car Red])

(get-items-colors-for-country 'UK)
;=> ([Purse Blue])

(get-items-colors-for-country 'France)
;=> ([Banana Yellow])

(get-items-colors-for-country 'Australia)
;=> ([Purse Blue] [Banana Yellow])

完全なソリューション

于 2012-01-03T21:37:22.603 に答える
2

Conda はコードを複雑にする可能性があり、nafc を使用すると、必要に応じて目標をより簡単に並べ替えることができます。これはまだ非リレーショナルです。:)

(ns somenamespace
  (:refer-clojure :exclude [==])
  (:use [clojure.core.logic][clojure.core.logic.pldb]))

(db-rel items Name Color)
(db-rel restricted-to Country Name)
(db-rel not-allowed-in Country Name)

(def stackoverflow-db 
  (db [items 'Purse 'Blue]
      [items  'Car 'Red]
      [items 'Banana 'Yellow]
      [restricted-to 'US 'Car]
      [not-allowed-in 'UK 'Banana]
      [not-allowed-in 'France 'Purse]))


(defn get-items-colors-for-country [country]
  (with-db stackoverflow-db
    (run* [it co]
         (items  it co)
         (nafc not-allowed-in country it)
         (conde 
          [(restricted-to country it)]
          [(nafc #(fresh [not-c] (restricted-to not-c %)) it)]))))

(get-items-colors-for-country 'US)
;=> ([Purse Blue] [Banana Yellow] [Car Red])

(get-items-colors-for-country 'UK)
;=> ([Purse Blue])

(get-items-colors-for-country 'France)
;=> ([Banana Yellow])

(get-items-colors-for-country 'Australia)
;=> ([Purse Blue] [Banana Yellow])

その他の例: https://gist.github.com/ahoy-jon/cd0f025276234de464d5

于 2014-01-20T00:36:12.940 に答える