2014-02-05 5 views
2

: L의 변수에 제약 조건을 적용프롤로그 제약는 프로그래밍도 찾아 홀수 내가 술어 만들 필요가

applyConstraints(L) 

을 같은 L에 두 개의 연속적인 요소는 모두 홀수 또는 내가 할 수있는 방법조차 없다는 것을 그? 고정 크기 L을 사용하면 간단하지만 가변 크기 L은 어떨까요? sicstus-prolog clpfd 라이브러리를 사용하여이 작업을 수행해야합니다.

+0

은 루프보다 더 간단 할 수있는 방법을 상상할 수 없습니다. – CapelliC

답변

2

@ MatsCarlsson의 버전에서 영감을 얻어 관련 제약 변수의 수를 최소화하려고 시도했습니다.

applyConstraints(Xs) :- 
    S #\= R, 
    applyConstraints(Xs, S, R). 

applyConstraints([], _, _). 
applyConstraints([X|Xs], S, R) :- 
    X mod 2 #= S, 
    applyConstraints(Xs, R, S). 

편집 :이 버전은 목표가 applyConstraints([])인데 쉽게 볼 수없는 결함이 있습니다. 사실, 하나는과 같이 SICStus에 full_answer 모드로 전환 할 필요가 :

| ?- applyConstraints([]). 
yes 
| ?- assertz(clpfd:full_answer). 
yes 
| ?- applyConstraints([]). 
clpfd:(_A#\=_B), 
_A in inf..sup, 
_B in inf..sup ? ; 
no 

그래서 우리는 자원을 먹을 수있는 주위를 어슬렁이 쓸모없는 제약이있다. 이 결핍을 극복하기 위해, 특별한 케이스가 필요하다 :

applyConstraints([]). 
applyConstraints([X|Xs]) :- 
    X mod 2 #= S, 
    S #\= R, 
    applyConstraints(Xs, R, S). 

주 1 — YAP SWI 또는에서 전체 응답 모드를 전환하는 직접적인 방법이 없습니다. 문제의 보류를 얻을 수있는 유일한 방법과 같이 call_residue_vars/2 주위에 쿼리를 래핑하는 것입니다 :

?- applyConstraints([]). 
true. 

?- call_residue_vars(applyConstraints([]),RVs). 
RVs = [_G794, _G797], 
_G794#\=_G797. 

주에게 @mat 2 개 — 감사, SWI 7.3 이후 비슷한 기능이있다 (기억이 SWI 7 필요 --traditional 호환성) :

?- set_prolog_flag(toplevel_residue_vars, true). 
true. 

?- applyConstraints([]). 
% with detached residual goals 
_G430#\=_G433. 

("분리 된"은 이러한 맥락에서 의미해야하는지 아주 명확하지 않다, 결국 이 잔류 목표 대답은 진정한하게, 진실하게 반군 디 태치먼트가 없습니다 그래서. .)

+1

SWI 7.3 이상에서는'? - set_prolog_flag (toplevel_residue_vars, true) .'를 사용하여 * 모든 * 잔여 제약 조건을 볼 수 있습니다. – mat

+0

위를 참조하십시오. – false

1

그냥 요소

applyConstraints([A,B|R]) :- 
    A mod 2 #\= B mod 2, 
    applyConstraints([B|R]). 
applyConstraints([_]). 

테스트

한 쌍의

?- L=[X,Y,Z], applyConstraints(L), L ins 1..4, label(L). 
L = [1, 2, 1], 
X = Z, Z = 1, 
Y = 2 ; 
L = [1, 2, 3], 
X = 1, 
Y = 2, 
Z = 3 ; 
... 
+0

먼저 공통 부분을 쓰지 않는 이유는 무엇입니까? 당신의 글은 불필요한 오버 헤드를 유발합니다. – false

+0

@false : 색인 생성이 없어지는 것이 맞습니까? – CapelliC

+0

이유 : 현재 구현에서 인덱싱이 없지만 가장 일반적인 쿼리에 대한 대답을 생성 할 수 없기 때문에 진단의 맥락에서 매우 유용합니다. – false

5
% SICStus: 

applyConstraints([]). 
applyConstraints([X|Xs]) :- 
    X mod 2 #= R, 
    applyConstraints(Xs, R). 

applyConstraints([], _). 
applyConstraints([X|Xs], R) :- 
    X mod 2 #= S, 
    S #\= R, 
    applyConstraints(Xs, S). 

% Query: 

| ?- applyConstraints(L), length(L,2), !, domain(L,-2,2), labeling([],L). 
L = [-2,-1] ? ; 
L = [-2,1] ? ; 
L = [-1,-2] ? ; 
L = [-1,0] ? ; 
L = [-1,2] ? ; 
L = [0,-1] ? ; 
L = [0,1] ? ; 
L = [1,-2] ? ; 
L = [1,0] ? ; 
L = [1,2] ? ; 
L = [2,-1] ? ; 
L = [2,1] ? ; 
no 
() SWI - 프롤로그 라이브러리 (clpfd를 사용하여가, 어쩌면 당신이 Sicstus에서 상대와 인/2를 대체해야합니다) 고려
+1

원래 한 줄짜리 해결책을 버릴 필요가 없다고 생각합니다. OP가 * 가변 크기 L *에 대해 말하면 아마 컴파일 시간에 고정되어 있지 않을 것입니다 *. 제약 조건 설정 단계에서 선택 점이있는 프로그램을 보여줌으로써 나쁜 예가 될 수 있습니다. – jschimpf