2016-04-18 15 views
1

Ich habe ein Prädikat, das seine Argumente vereinen kann, zum Beispiel:Erkennen, ob ein Prädikat beweisen Unified etwas

foo(X) :- X = 42.

Wie kann ich feststellen, ob, während foo(X) beweist, Vereinigung X verändert? Zum Beispiel würde ich gerne wissen, ob writeln(X), foo(X), writeln(X) den gleichen Wert für X zweimal drucken würde, ohne tatsächlich zu drucken.

Meine eigentliche Implementierung von foo/1 ist eigentlich viel komplexer, also bitte nicht spezifisch für die vereinfachte Version oben vorschlagen. In meinem Programm foo(X) vereinfacht X mit Unification, aber foo(X) muss möglicherweise mehrmals bewiesen werden, bis alle Vereinfachungen durchgeführt worden sind. Ich möchte in der Lage sein, ein foohelper(X) Prädikat zu schreiben, das foo(X) aufruft, bis X stoppt, vereinheitlicht zu werden.

+0

** Wann möchten Sie mitteilen, ob 'X' instanziiert wurde? (Wir ändern 'X' nicht, wir instanziieren es) – false

+0

Ich möchte wissen, ob' X' instanziiert wurde, während '' foo (X) 'an der Stelle des zweiten' writeln (X) 'in meinem Beispiel bewiesen wurde. –

Antwort

2

Vielleicht können Sie den Standard term_variables/2 Prädikat verwenden? Sie können es vor und nach dem Aufruf des Ziels mit Ihrem Ziel aufrufen und prüfen, ob die zurückgegebenen Variablenlisten unterschiedlich sind. Etwas wie:

..., 
term_variables(foo(X), Vars0), 
foo(X), 
term_variables(foo(X), Vars), 
( Vars0 == Vars -> 
    write(simplified) 
; write(not_simplified) 
), 
... 
+0

"vereinfacht" sollte eher "identisch" sein – false

+0

@false Lesen Sie die Frage. Dort finden Sie, warum ich das Wort "vereinfacht" verwendet habe. –

+0

Ich denke, das sollte funktionieren - danke! Ich bin gespannt, ob es bessere Möglichkeiten für einen "Schnappschuss" eines Begriffs gibt. –

3

Angenommen, wir nur syntaktische Vereinigung haben - das heißt, keine Einschränkungen:

:- meta_predicate(call_instantiated(0,?)). 

call_instantiated(Goal_0, Instantiated) :- 
    copy_term(Goal_0, Copy_0), 
    Goal_0, 
    ( subsumes_term(Goal_0, Copy_0) -> % succeeds iff equal u.t.r. 
     Instantiated = false 
    ; Instantiated = true 
    ). 

Beachten Sie, dass Goal_0 wird oder nicht weiter instanziert werden. Obiges subsumes_term/2 testet, ob Goal_0 jetzt "allgemeiner" ist als Copy_0. Natürlich kann es nicht allgemeiner sein, so effektiv, dass der Test testet, ob die Begriffe bis zur Umbenennung von Variablen identisch sind oder nicht.

Im Vergleich zur Verwendung von term_variables/2, wie @PauloMoura angezeigt hat, könnte dies möglicherweise nicht effizienter sein. Es hängt in erster Linie von der Effizienz von subsumes_term/2 ab.

+0

'Goal_0' sollte' call (Goal_0) 'sein. Schlechter Programmierstil mit nackten (Meta -) Variablen. Auch ihre Semantik kann oder kann nicht äquivalent zu "call/1" sein, abhängig von dem Prolog-System (wobei wr.t. opak oder transparent für Schnitte ist). –

+0

@PauloMoura ?? Das ist wohldefiniertes Verhalten. Welches Prolog-System behandelt das nicht korrekt? – false

+0

Ist keine Frage der Korrektheit, sondern eine Frage der gewählten Semantik für nackte Meta-Variablen. ECLiPSe ist ein Beispiel für ein System, in dem nackte Meta-Variablen für Schnitte transparent sind. –