2017-03-21 33 views
0

Ich erkannte gerade, dass das eine dumme Frage war. Neugierig, wenn noch jemand eine Lücke finden kann.Wie man Rekursion nach einmaligem Looping verhindert

Quellcode:

married(trump,obama). 
married(trump,goat). 
married(pepee,pepper). 
married(X,Y) :- married(Y,X),!. % not awesome because of infinite recursion 

Goal: ex. married(trump, putin). 
trace(
first base case fails. 
second base case fails. 
third base case fails. 
married(trump,putin) = married(putin,trump),!. 

, was ich will ist verheiratet (putin, Trumpf) versuchen dabei wieder, aber alle früheren Basis Fällen wird wieder scheitern. Wir haben vorher versucht, die Argumente zu wechseln und sind gescheitert. Also rekrutiere nicht. Gib einfach falsch zurück.

Ich bekomme einen Stapelfehler, weil bis verheiratet (Putin, Trumpf) oder anders herum vorher! wird nie wahr oder falsch zurückgeben, so dass der Schnitt nicht ausgelöst werden kann.

Einfacher und vernünftiger Weg ist es, nur den Code neu zu schreiben, um Rekursion zu verhindern. Ich bin gespannt, ob es einen Weg gibt, die Argumente einmal zu wechseln und scheitern zu lassen, wenn das fehlschlägt. Wenn Sie eine lange Liste von Fakten haben, können Sie diese lange Liste um die Hälfte reduzieren, wenn Sie arg1, arg2 und umgekehrt versuchen können. Potenziell exponentiell, wenn wir verrückte Permutationsszenarien bekommen.

Alle Einblicke werden fantastisch sein, danke.

+0

Sind diese alternativen Fakten? – false

Antwort

3

Sie auf dem richtigen Weg sind mit „Schalt args einmal und Rückkehr fehlschlagen, wenn das fehlschlägt“, auch wenn diese sehr imperativ formuliert ist und deckt nicht alle Modi wir aus einer solchen Beziehung erwarten.

Damit dies funktioniert, müssen Sie dieses in zwei Prädikate trennen. Es ist leicht zu zeigen, dass ein einzelnes Prädikat mit der gegebenen Schnittstelle nicht ausreichend ist.

Zuerst wird das Hilfs Prädikat:

 
married_(a, b). 
married_(c, d). 
etc. 

Dann wird das Hauptprädikat, im Wesentlichen, wie Sie vorschlagen:

 
married(X, Y) :- married_(X, Y). 
married(X, Y) :- married_(Y, X). 

Verunreinigungen zu Ihrer Lösung Hinzufügen macht die Sache noch schlimmer: Fast immer , Sie werden die Allgemeinheit Ihrer Beziehungen zerstören und die Frage aufwerfen, warum Sie eine deklarative Sprache bei   alles verwenden.

Beispiel query:

 
?- married(X, Y). 
X = a, 
Y = b ; 
X = c, 
Y = d ; 
X = b, 
Y = a ; 
X = d, 
Y = c. 

Streng genommen kann man natürlich auch dies mit nur einem einzigen Prädikat, aber Sie müssen um zusätzliche Informationen tragen, wenn Sie es auf diese   Weise tun .

Zum Beispiel:

 
married(_, a, b). 
married(_, c, d). 
married(first, X, Y) :- married(second, Y, X). 

Beispiel query:

 
?- married(_, X, Y). 
X = a, 
Y = b ; 
X = c, 
Y = d ; 
X = b, 
Y = a ; 
X = d, 
Y = c. 

Dies folgt eng der Ansatz, den Sie beschreiben: "Wir haben versucht args vor dem Einschalten Also es nicht wieder tun.".

+0

Danke für den Kommentar, Mat. Das ist, was ich getan habe. Ich legte eine weitere Hilfsfunktion kurz vor dem Auslösen dieser Familienfunktion mit Ausschneiden-Funktion, um zu verhindern, diese Funktion auszulösen, wenn nicht-Familienmitglieder Paare gegeben sind. Es ist eine Banditenlösung, da es den grundlegenden Fehler dieser Beziehung nicht löst, aber es wird ausreichen. Ein anderer besserer Weg ist es, Rekursion einfach nicht zu benutzen, denn seien wir ehrlich, Rekursion, die Rekursion einmal durchführt, ist wie ein Olympiasieger zu sagen, dass man mit nur einem Schritt sehr schnell rennen muss. electionCheck (X, Y): - (verheiratet (X, Y); verheiratet (Y, X)). –

+0

Diese letzte Version, die Sie zeigen, entspricht der ersten Version, die ich gepostet habe: Ich habe zwei Klauseln verwendet, um die Alternativen darzustellen, und Sie verwenden '(';')/2', was auch logische Alternativen bedeutet und als Alternative verwendet werden kann für Klauseln. Beachten Sie jedoch, dass dieses Prädikat sehr allgemein ist (was gut ist!) Und nicht nur zum * Überprüfen *, sondern auch zum * Generieren von * und * vollständigen * Lösungen verwendet werden kann. Daher ist "Heiratskontrolle" eine Fehlbezeichnung und ein Problem, das sich auf die Fälle bezieht. – mat

+0

Scheint wie. Ich frage mich (kann prolog atm nicht ausführen), was passieren würde, wenn die Abfrage beendet ist. Es scheint, als müssten alle vorherigen Fakten umgeschrieben werden (da die verheiratete Funktion zwei Argumente annimmt, während die verheiratete Funktion 3 annimmt). Aber nehmen wir an, dass das kein Problem war. Trace es mit mir hier .. versucht alle Fakten, dann treffen wir verheiratet (erste, X, Y): - verheiratet (zweite, Y, X). es scannt alle Fakten erneut mit (Sekunden, Y, X). wenn das auch scheitert, laufen wir auf verheiratet (zweites, Y, X) V: - verheiratet (zweites, Y, X). was würde hier passieren? Ich kann nicht in meinen Gedanken verfolgen; sie sind gleich, also ... hört dort auf? –

Verwandte Themen