2015-01-13 2 views
18

현재 ISO 표준의 the built-ins을 사용하는 두 개의 고유 변수 목록이 정확하게 동일한 변수를 포함하는지 테스트 (따라서 성공 또는 실패 만)하는 메타 논리 술어를 정의하는 방법 (ISO/IEC 13211- 1 : 1995, Cor.2 포함).두 개의 변수 목록이 동일 함

고유 변수의 한 목록이 다른 하나의 순열 일 경우 조건부가 성공해야합니다. library(ordsets) 유사하게,의는 ord_seteq/2 대조적으로,이 술어는 단순히 As == Bs 수 없습니다,이 메타 논리적 술어 varset_seteq(As, Bs).

주를 호출 할 수 있습니다.

+2

두 인수 중 하나라도 고유 변수 목록이 아닌 경우 조건부가 실패해야합니까? –

+1

그냥 기다리고, 아마도 더 많은 다른 대답이 있습니다. – false

+2

나는 다른 것을 시도하고 있었지만'As '와'Bs'가 실제로 자유 변수의 집합인지 확인해야했습니다. 내 대답은'term_variables/2'의 두 번째 인수와 통합해야한다는 사실에 의해 보장됩니다. –

답변

14

내가 제안이 솔루션은 BsAs 이상 여분의 변수가없는 경우 확인 term_variables/2를 사용하고 AsBs에 나타나지 않는 어떤 변수가 없다는 것을.

varset_seteq(As, Bs):- 
    term_variables(As-Bs, As), 
    term_variables(Bs-As, Bs). 

위의 솔루션 는 자유 변수의 세트없는 인수 성공 속은 수 있습니다

| ?- varset_seteq([A], [a]). 

A = a 

yes 

는 것을 방지하기 위해, 통일 동등성 시험으로 대체 할 수 있습니다

varset_seteq(As, Bs):- 
    term_variables(As-Bs, A0), 
    A0 == As, 
    term_variables(Bs-As, B0), 
    B0 == Bs. 
+2

당신의 반례가 실제로 최고입니다! 그렇지 않으면'term_variables/2'가 두 번째 인수의 잘 정의 된 성을 검사해야한다는 사실을 악용 할 수 있기 때문에 안타깝습니다. 따라서 길이를 세는 것이 자유 롭기 때문에 더 일찍 실패 할 수도 있습니다. – false

+0

나는이 접근법을 좋아한다! 그러나 목록이 바 일 뿐이라는 것도 확인해야합니까? 나는 지금 내 컴퓨터가 아니지만'varset_seteq ([A, B, a], [A, B])'가 성공하지 못하겠습니까? –

+2

아니요, 성공하지 못합니다. 바는 무엇입니까? –

4

다른 솔루션 튜더 ' 영리 솔루션 S 및 추천 따라서 하지,하지만 여전히 내가 여러 경우에 사용되는 참조 여기에 언급 할 가치가있다 :

varset_seteq(As, Bs) :- 
    sort(As, Sa), sort(Bs, Sb), Sa == Sb. 
+1

내 원래 대답은 막 :)에 대해, varlist/1' 술어를 추가하여 두 목록이 모두 변수로 구성되어 있는지 확인했습니다. 그러나 Tudor Berariu는이 접근법은 예를 들어'As = [A, A, B, C], Bs = [B, C, B, C, A]'에서 성공할 것이라고 지적했다. 아마 원래의 시도를 그대로 두었어야했을 것입니다. –

+2

이 솔루션은 구체적인 Prolog 구현에서 작동하지만 Prolog 구현의 구현 종속 속성에 의존합니다. 목표'Sa == Sb'에서는'Sa'와'Sb'가 여전히 정렬되어 있다고 보장하지 않습니다. 변수 정렬을 보존하지 않는 구현에서 GC가 발생한다고 생각해보십시오.이 정렬은'sort/2 '중에 GC를 호출하지 않을 때 여전히 준수 할 수 있습니다. – false

+2

@aBathologist 참으로 :-) 명백한 대체 솔루션의 함정은 항상 가치가 있습니다. 그럼에도 불구하고 원래 질문은 입력이 "* 고유 * 변수의 두 목록"(강조 표시)이라고 명시합니다. –

3

또 다른 방법. 우리는 (각 자신에 유용)이 높은 순서 술어,

select_with(_, _, [], []). 
select_with(P, X, [Y|Ys], Ys)  :- call(P, X, Y), !. 
select_with(P, X, [Y|Ys], [Y|Ks]) :- 
    select_with(P, X, Ys, Ks). 

foldl(_,[],Vn,Vn). 
foldl(P,[X|Xs],V0,Vn) :- 
    call(P,X,V0,V1), 
    foldl_(P,Xs,V1,Vn). 

자신을 제공하는 경우 각 구성원 하나 개의 목록이 다른에서 동일한 요소가있는 경우 우리는 쉽게 사용 (사실 술어를 정의 할 수 있습니다 ==/2) : 우리가 들어오는 인수가 varsets 있는지 확인하는 경우

members_equal(A, B :- 
    foldl(select_with(==), A, B, []). 

이 술어

은 명시된 목적을 위해 전문 수 있습니다. 다음은 내가 그 방향을 마련 할 수있었습니다 최고입니다 (하지만 꽤 몇 가지 추론 먹는다) :

is_varset([]). 
is_varset([V|Vs]) :- 
    var(V), 
    maplist(\==(V), Vs), 
    is_varset(Vs). 

(적어도 SWI 프롤로그에, sort/2 사용하여 위보다 적은 추론을 걸립니다 아마도 이것은 정렬이 C로 이루어지기 때문입니다. 또한이 대답은 여전히 ​​term_vars/2 접근법의 우아함에 접근하지 않습니다. 예를 들어 "의미 상 승강"의 힘입니다.

7

두 개의 목록에는 고유 한 변수가 포함되어 있으며 이중 부정의 사용은 다음과 같이 작동합니다.

varset_seteq(As, Bs) :- 
    \+ \+ (numbered_from(As, 1), 
      sort(Bs, SBs), 
      As == SBs). 

numbered_from([], _). 
numbered_from([X|Xs], X) :- 
    X1 is X + 1, 
    numbered_from(Xs, X1). 

이것은 Paulo의 솔루션과 비슷하지만 ISO/IEC 13211-1에서만 변수 순서가 sort/2의 단일 실행 내에서 일관성이 있어야한다는 문제를 방지합니다.