2012-01-02 6 views
16

저는 core.logic을 가지고 놀기 시작했습니다. 그리고 그것에 관해서는 현재 제가 전문적으로 연구하고있는 문제와 비슷한 간단한 것을 구현하려고합니다. 그러나 문제의 한 부분이 나를 곤혹스럽게 만들었습니다 ...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]]) 

가능하다면, 나는 차라리 지정할 수-의 모든 국가, 제한 항목의 집합으로 상대적으로 작기 때문에 특정 국가의 항목을 허용/제외하는 단일 변경을 할 수 있기를 바랍니다.

나는 다음과 같은 제약이있는 국가에 대한 항목/색상의 목록을 제공하는 규칙을 쓸 수있는 방법 :

  • 이 항목은 항목
  • 국가/항목이 반드시 목록에 있어야합니다을 '- 허용되지-에서'목록에
  • 어느하지 않을 수 :에는 국가가 없다
    • 제한된-해당 항목
    • 국가/항목 쌍 restricted-에 대해 나열

이 작업을 수행하는 몇 가지 방법이 있나요를 나열하려면? 완전히 잘못된 방식으로 생각하고 있습니까?

답변

14

보통 논리 프로그래밍에서 목표를 부정하기 시작할 때 비 관계형 연산 (core.logic에서 Prolog, conda로 축소)에 도달해야합니다.

이 해결 방법은 기본 인수로만 호출해야합니다. 당신이 원하는 경우

Full solution

+0

, 당신은 값보다는 쿼리 변수를 의미하는 것 같은데요? 죄송합니다. 논리 프로그래밍을 사용한 마지막 브러쉬는 약 25 년 전에 학부모 프롤로그 과정이었습니다 ... –

+1

언 바운드 또는 언 그라운드 변수 일 수 없습니다. 언 바운드 논리 변수를 포함하지 않은 경우 값은 접지됩니다 (예 : [1 2 0._]은 접지되지 않음). 함수가 목표이고 쿼리 변수를 인수로 전달하는 경우 관련성이 높아집니다. 이 요지에서,'item-colors-for-country'는 첫 번째 논의가 필요합니다. 목표는 나의 초기 답변보다 더 유연하고 구성 가능합니다. 예를 들어 미국에서 사용할 수있는 동전 색을 쿼리 할 수 ​​있습니다. https://gist.github.com/1557417 – Ambrose

+0

설명 주셔서 감사합니다! –

2

(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]) 
CONDA이 nafc를 사용하여 코드를 complexifies 수보다 쉽게 ​​목표를 재정렬 할 수 있습니다. 이것은 여전히 ​​비 관계형입니다! :) 더 많은 예를 들어

(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