2

Let`s sagen, ich habe ein paar einfachen Boolesche AusdruckWie wird man mit in Booleschen Ausdrücken von Klammern befreit AND und OR

(A || B) && (C || D) 

Das Ziel ist, in diesem Ausdruck los Klammer zu erhalten, zum Beispiel

(A || B) && (C || D) => A && C || A && D || B && C || B && D 

Wir wissen, dass && wertet vor || von links nach rechts. Um dies zu erreichen ich den folgenden algebraischen Datentyp erstellt habe:

sealed trait Predicate 
case class Or(left: Predicate, right: Predicate) extends Predicate 
case class And(left: Predicate, right: Predicate) extends Predicate 
case object True extends Predicate 
case object False extends Predicate 

Let`s davon aus, dass wir bereits eine Art von String-Parsern haben, die Zeichenfolge zu Predicate umwandelt, baut es eine Art Zusammenfassung syntaktischen Baumes. Zum Beispiel für den Ausdruck (true || true) && (true || true) haben wir den folgenden Baum: And(Or(True, True), Or(True, True)). Hier kommen die Zahnspangen in Betracht. Wir müssen Or(Or(And(A, C), And(A, D)), Or(And(B, C), And(B,D))) bekommen. ich mit folgenden Lösung fest:

def extractOr(pred: Predicate): Predicate = pred match { 
    case And(Or(l, r), Or(ll, rr)) => Or(Or(And(l, ll), And(l, rr)), Or(And(r, ll), And(r, rr))) 
    case And(Or(l, r), p) => Or(And(l, p), And(r, p)) 
    case And(p, Or(l, r)) => Or(And(p, l), And(p, r)) 
    case p => p 
} 

def popOrPredicateUp(pred: Predicate): Predicate = pred match { 
    case And(l, r) => extractOr(And(popOrPredicateUp(l), popOrPredicateUp(r))) 
    case Or(l, r) => Or(popOrPredicateUp(l), popOrPredicateUp(r)) 
    case p => p 
} 

Aber es funktioniert nicht korrekt zum Beispiel für diesen Fall: And(False, Or(And(Or(True, True), False), True))

UPD: Wie @coredump wies darauf hin, ich brauche schließlich DNF(sum of products)

+1

Aufgrund Ihrer Titelfrage und der Einleitung war zunächst nicht klar, ob Sie das https://en.wikipedia.org/wiki/Disjunctive_normal_form berechnen wollen oder ob Sie Ihren Code irgendwie umgestalten wollen. Oder vielleicht willst du ja auch kein DNF. Sind das Hausaufgaben? – coredump

+0

@coredump: DNF (Summe der Produkte) - genau das, was ich suche! guter Punkt. – ponkin

+0

In "Und (Falsch, Oder (Und (Oder (Wahr, Wahr), Falsch), Wahr))" möchten Sie nicht, dass es sofort mit False kurzgeschlossen wird, denn wenn 1 Falsch in einem ist Und es bewertet zu falsch? –

Antwort

0

zu bekommen, mit große Hilfe @coredump (er wies auf die richtige Richtung) und Haskell Paket hatt (insbesondere, dass code). Ich kam zu folgenden Lösung:

sealed trait Predicate 
case class Or(left: Predicate, right: Predicate) extends Predicate 
case class And(left: Predicate, right: Predicate) extends Predicate 
case class Not(pred: Predicate) extends Predicate 
case object True extends Predicate 
case object False extends Predicate 

object PredicateOps{ 

    def toNNF(pred: Predicate): Predicate = pred match { 
    case a @ (True | False) => a 
    case a @ Not(True | False) => a 
    case Not(Not(p)) => p 
    case And(l, r) => And(toNNF(l), toNNF(r)) 
    case Not(And(l, r)) => toNNF(Or(Not(l), Not(r))) 
    case Or(l, r) => Or(toNNF(l), toNNF(r)) 
    case Not(Or(l,r)) => toNNF(And(Not(l), Not(r))) 
    } 

    def dist(predL: Predicate, predR: Predicate): Predicate = (predL, predR) match { 
    case (Or(l, r), p) => Or(dist(l, p), dist(r, p)) 
    case (p, Or(l, r)) => Or(dist(p, l), dist(p, r)) 
    case (l, r) => And(l, r) 
    } 

    def toDNF(pred: Predicate): Predicate = pred match { 
    case And(l, r) => dist(toDNF(l), toDNF(r)) 
    case Or(l, r) => Or(toDNF(l), toDNF(r)) 
    case p => p 
    } 

} 

Hier ist, wie es funktioniert:

val expr = And(False, Or(And(Or(True, True), False), True)) 
val dnf = (PredicateOps.toNNF _ andThen PredicateOps.toDNF _).apply(expr) 
println(dnf) 

Und die Ausgabe Or(Or(And(False,And(True,False)),And(False,And(True,False))),And(False,True)) die richtige DNF ist.

+0

DNF für jeden komplexen Begriff kann sehr groß sein. Warum eliminierst du keine Begriffe, die TRUE oder FALSE beinhalten, was du auswerten kannst, wodurch das Ergebnis kleiner wird, während du gehst? [Ihr Beispiel würde dann FALSE erzeugen] –

+0

@IraBaxter Das Endziel der Lösung ist nicht die gesamte Aussage zu bewerten, sondern die Aussage in Disjunktionsklauseln aufzuteilen. – ponkin

+0

. Ich verstehe das (ich habe genau solche Disjunktionsbauer gebaut). Die Vergrößerung der Größe kann atemberaubend sein (exponentiell); Wir fanden heraus, dass wir alle Hilfe benötigten, um die Größe zu verwalten. Begriffe, die tautologisch sind ... nutzlos. Diese Optimierung wird Sie nicht daran hindern, das Formular zu erweitern, wenn es Variablen enthält, in denen es Variablen enthält. –

Verwandte Themen