2014-01-12 7 views
6

는 다음 코드 샘플을 감안할 때 :PROLOG CLPFD 제약 조건을 통해이를 표현하는 방법은 무엇입니까?

example(Ls) :- 
    Ls = [X,Y], 
    Ls ins 1..2, 
    Cost #= max((X #= 1)*3 + (Y #= 1)*5, 
       (X #= 2)*3 + (Y #= 2)*5), 
    labeling([minimize(Cost)], Ls). 
아이디어는이 간단한 예제에서 (비용을 최소화 LS의 변수에 할당을 찾는 것입니다

, 그것은 것을 중 X = 1, Y = 2, 또는 X = 2 및 Y = 1).

제약 # =/2는 검증 할 수 있다는 사실을 이용하려고합니다. 이는 진리 값을 정수 0과 1로 표현 된 부울 값에 반영한다는 것을 의미합니다 (설명서 http://www.swi-prolog.org/man/clpfd.html에서 가져옴).

그러나 작동하지 않습니다. 다음 오류가 발생합니다.

ERROR: Domain error: `clpfd_expression' expected, found `_G3154#=1' 

무엇이 상응하는 올바른 버전입니까?

답변

5

구체화는 예를 들어 사용할 수 있습니다, (등 #<==>/2, #==>/2)제약 별도의 포함과 같은 :

example(Ls) :- 
    Ls = [X,Y], 
    Ls ins 1..2, 
    X #= 1 #<==> B1, 
    Y #= 1 #<==> B2, 
    X #= 2 #<==> B3, 
    Y #= 2 #<==> B4, 
    Cost #= max(B1*3 + B2*5, B3*3 + B4*5), 
    labeling([min(Cost)], Ls). 

샘플 쿼리 및 그 결과 :

?- example(Ls). 
Ls = [1, 2] ; 
Ls = [2, 1] ; 
Ls = [1, 1] ; 
Ls = [2, 2] ; 
false. 
+0

는 중간 변수 B1..B4를 사용하지 않고 같은 어떤 방법이 있습니까? 실제 프로그램에는 200 개가 넘습니다. – user2460978

+1

저는 100x100 체스 판에서 100-queens 문제를 해결할 때 검색 프로세스에 애니메이션을 적용하는 것과 같은 문제없이 중간 변수를 10,000 개 이상 사용했습니다. 그래서, 나는 그것이 효과가 있는지 먼저 시도해 보시고 정말로 필요한 경우에만보다 효율적인 공식을 찾으시기 바랍니다. 물론 더 큰 예제에서는 수동으로 이러한 중간 변수를 도입하지 않고 지정하거나 입력 한 일부 입력 데이터를 통해 변수 및 값 목록과 관련시키는 보조 조건부를 통해이를 설정합니다. – mat

+0

예제의 메서드를 사용하면 작업 할 수 있습니다. 그러나 Ls에있는 10 개 이상의 변수와 각 요소에 대한 7 개의 가능한 값으로 인해 완료하는 데 1 분 이상 소요됩니다. – user2460978

3

하는 대신 구체화를 사용하면 표현식에서 동등성을 "캡처"하기 위해 추가 산술 제약 조건을 사용할 수도 있습니다.

example([X,Y]) :- 
    X in 1..2, 
    Y in 1..2, 
    Cost #= max(3*(1-min(1,abs(X-1))) + 5*(1-min(1,abs(Y-1))), 
       3*(1-min(1,abs(X-2))) + 5*(1-min(1,abs(Y-2)))), 
    labeling([min(Cost)], [X,Y]). 

Cost #= max(...) 내부 표현은 약간 단순화 될 수 있습니다.

샘플 사용 :

?- example(Ls). 
    Ls = [1,2] 
; Ls = [2,1] 
; Ls = [1,1] 
; Ls = [2,2] 
; false.