2014-01-12 5 views
6

den folgenden Beispielcode Gegeben:PROLOG CLPFD Wie kann dies über Einschränkungen ausgedrückt werden?

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). 

Die Idee ist, die Zuordnung zu Variablen von Ls zu finden, die Kosten (in diesem einfachen Beispiel minimiert, wäre es entweder X = 1 und Y = 2 oder X sein = 2 und Y = 1).

Ich versuche, die Tatsache zu verwenden, dass die Einschränkung # =/2 umsetzbar ist, was bedeutet, dass ihre Wahrheitswerte in Boolesche Werte dargestellt werden, die durch die Ganzzahlen 0 und 1 dargestellt werden. (Aus dem Handbuch http://www.swi-prolog.org/man/clpfd.html).

Es funktioniert jedoch nicht. Ich erhalte folgende Fehlermeldung:

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

Was wäre eine äquivalente, korrekte Version?

Antwort

5

Reification beinhaltet getrennte Einschränkungen (#<==>/2, #==>/2 etc.), können Sie sie zum Beispiel wie verwenden können:

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). 

Beispielabfrage und sein Ergebnis:

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

Gibt es eine Möglichkeit, um das gleiche, ohne die Zwischenvariablen B1..B4 mit? Im realen Programm wären es über 200. – user2460978

+1

Ich habe bis zu 10.000 solcher Zwischenvariablen (zum Beispiel um den Suchvorgang beim Lösen des 100-Königinnen-Problems auf einem 100x100-Schachbrett zu animieren) ohne Probleme verwendet. Also, ich schlage vor, dass Sie zuerst versuchen, ob es funktioniert, und versuchen Sie, effizientere Formulierungen nur zu finden, wenn Sie sie wirklich brauchen. In einem größeren Beispiel führen Sie diese Zwischenvariablen natürlich nicht manuell ein, sondern richten sie beispielsweise über ein Hilfsprädikat ein, das sie über einige Eingabedaten, die Sie angeben oder berechnen, mit der Liste der Variablen und Werte in Beziehung setzt. – mat

+0

Mit der Methode in Ihrem Beispiel habe ich es zum Laufen gebracht. Mit mehr als 10 Variablen in Ls und 7 möglichen Werten für jedes Element dauert es jedoch mehr als eine Minute, bis es fertig ist. – user2460978

3

Als Alternative zu Mithilfe von Verifikation können Sie auch zusätzliche arithmetische Integritätsregeln zum "Erfassen" der Gleichheit in einem Ausdruck verwenden:

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]). 

Beachten Sie, dass der Ausdruck innerhalb Cost #= max(...) leicht vereinfacht werden kann.

Beispiel Verwendung:

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