/* A -> (N v Q) ~(N v ~A) A -> Q (conclusion) */ func SatValid(t *testing.T) { a := literal.Literal{"A", false} na := a.Negation() n := literal.Literal{"N", false} nn := n.Negation() q := literal.Literal{"Q", false} nq := q.Negation() one := clause.Clause{} one.Append(a) two := clause.Clause{} two.Append(nq) three := clause.Clause{} three.Append(nn) four := clause.Clause{} four.Append(na) four.Append(n) four.Append(q) CS := clauseset.ClauseSet{} CS.Append(one) CS.Append(two) CS.Append(three) CS.Append(four) sat, _ := Satisfiable(CS) if sat { t.Errorf("ClauseSet %q was Satisfiable, so it is an invalid argument (it should be valid)", CS) } }
/* A -> B ~A ~B (conclusion) */ func SatInvalid(t *testing.T) { na := literal.Literal{"A", true} b := literal.Literal{"B", false} one := clause.Clause{} one.Append(na) two := clause.Clause{} two.Append(b) three := clause.Clause{} three.Append(na) three.Append(b) CS := clauseset.ClauseSet{} CS.Append(one) CS.Append(two) CS.Append(three) CS.Indent = 0 sat, _ := Satisfiable(CS) if !sat { t.Errorf("ClauseSet %q was not Satisfiable, so it is a valid argument (it should be invalid)", CS) } }
//FindValidity finds the validity of the argument (given as a ClauseSet) func FindValidity(CS clauseset.ClauseSet, filename string) { fmt.Printf("Starting ClauseSet: %s\n", CS) CS.Indent = 0 sat, tree := Satisfiable(CS) treeJson, _ := json.Marshal(tree) f, _ := os.Create(filename) f.WriteString(string(treeJson)) fmt.Print("Conclusion: ") if sat { fmt.Printf("Satisfiable(%s) == %t; INVALID\n", CS, sat) } else { fmt.Printf("Satisfiable(%s) == %t; VALID\n", CS, sat) } }
func ToCNF(statement string) clauseset.ClauseSet { rows := getRows(getLiterals(statement)) new_clauseset := clauseset.ClauseSet{} for _, row := range rows { sort.Sort(ByLength(row)) statement_cpy := statement[:1] + statement[1:] for _, l := range row { // @ == TRUE "!" == FALSE replacement_string := "N/A" if len(l) == 1 { replacement_string = "@" } else { replacement_string = "!" l = l[2:3] } // do the straight replacement r := regexp.MustCompile(fmt.Sprintf("%s", l)) statement_cpy = r.ReplaceAllString(statement_cpy, replacement_string) } for statement_cpy != "TRUE" && statement_cpy != "FALSE" { r := regexp.MustCompile("(~@|~\\(@\\))") statement_cpy = r.ReplaceAllString(statement_cpy, "FALSE") r = regexp.MustCompile("(~!|~\\(!\\))") statement_cpy = r.ReplaceAllString(statement_cpy, "TRUE") r = regexp.MustCompile("\\(@\\)") statement_cpy = r.ReplaceAllString(statement_cpy, "TRUE") r = regexp.MustCompile("\\(!\\)") statement_cpy = r.ReplaceAllString(statement_cpy, "FALSE") r = regexp.MustCompile("@") statement_cpy = r.ReplaceAllString(statement_cpy, "TRUE") r = regexp.MustCompile("!") statement_cpy = r.ReplaceAllString(statement_cpy, "FALSE") r = regexp.MustCompile("\\(TRUE\\)") statement_cpy = r.ReplaceAllString(statement_cpy, "TRUE") r = regexp.MustCompile("\\(FALSE\\)") statement_cpy = r.ReplaceAllString(statement_cpy, "FALSE") r = regexp.MustCompile("(~TRUE|~\\(TRUE\\))") statement_cpy = r.ReplaceAllString(statement_cpy, "FALSE") r = regexp.MustCompile("(~FALSE|~\\(FALSE\\))") statement_cpy = r.ReplaceAllString(statement_cpy, "TRUE") r = regexp.MustCompile("TRUEv(TRUE|FALSE)") statement_cpy = r.ReplaceAllString(statement_cpy, "TRUE") r = regexp.MustCompile("(TRUE|FALSE)vTRUE") statement_cpy = r.ReplaceAllString(statement_cpy, "TRUE") r = regexp.MustCompile("FALSEvFALSE") statement_cpy = r.ReplaceAllString(statement_cpy, "FALSE") r = regexp.MustCompile("TRUE\\^TRUE") statement_cpy = r.ReplaceAllString(statement_cpy, "TRUE") r = regexp.MustCompile("(TRUE|FALSE)\\^FALSE") statement_cpy = r.ReplaceAllString(statement_cpy, "FALSE") r = regexp.MustCompile("FALSE\\^(TRUE|FALSE)") statement_cpy = r.ReplaceAllString(statement_cpy, "FALSE") r = regexp.MustCompile("FALSE->(TRUE|FALSE)") statement_cpy = r.ReplaceAllString(statement_cpy, "TRUE") r = regexp.MustCompile("TRUE\\->FALSE") statement_cpy = r.ReplaceAllString(statement_cpy, "FALSE") r = regexp.MustCompile("TRUE\\->TRUE") statement_cpy = r.ReplaceAllString(statement_cpy, "TRUE") r = regexp.MustCompile("TRUE<\\->TRUE") statement_cpy = r.ReplaceAllString(statement_cpy, "TRUE") r = regexp.MustCompile("FALSE<\\->FALSE") statement_cpy = r.ReplaceAllString(statement_cpy, "TRUE") r = regexp.MustCompile("TRUE<\\->FALSE") statement_cpy = r.ReplaceAllString(statement_cpy, "FALSE") r = regexp.MustCompile("FALSE<\\->TRUE") statement_cpy = r.ReplaceAllString(statement_cpy, "FALSE") } if statement_cpy == "FALSE" { new_clause := clause.Clause{} for _, l := range row { if len(l) == 1 { lit := literal.Literal{Name: l, Negated: true} new_clause.Append(lit) } else { lit := literal.Literal{Name: l[2:3], Negated: false} new_clause.Append(lit) } } new_clauseset.Append(new_clause) } } return new_clauseset }
//Satisfiable implements above function func Satisfiable(CS clauseset.ClauseSet) (bool, Tree) { tree := Tree{Name: CS.String(), Split: ""} fmt.Printf("\n%sSatisfiable(%s)\n", strings.Repeat(" ", CS.Indent), CS) CS.Indent += 2 //if CS = {} : return true if CS.Len() == 0 { fmt.Printf("%sEmpty ClauseSet, returning true\n", strings.Repeat(" ", CS.Indent)) openTree := Tree{Name: "O", Split: ""} tree.Children = append(tree.Children, openTree) return true, tree } //if {} in CS : return false firstElement, err := CS.FirstElement() if err != nil { log.Fatal(err) } if clause.Len(firstElement) == 0 { fmt.Printf("%s{} found in ClauseSet, returning false\n", strings.Repeat(" ", CS.Indent)) closedTree := Tree{Name: "X", Split: ""} tree.Children = append(tree.Children, closedTree) return false, tree } //select L in lit(CS): return Satisfiable(CS_L) || Satisfiable(CS_L') nextLiteral, err2 := CS.NextLiteral() if err2 != nil { log.Fatal(err2) } fmt.Printf("%sSpliting on %s\n", strings.Repeat(" ", CS.Indent), nextLiteral) CSL := CS.Reduce(nextLiteral) CSL.Indent = CS.Indent CSR := CS.Reduce(nextLiteral.Negation()) CSR.Indent = CS.Indent left, tree_l := Satisfiable(CSL) right, tree_r := Satisfiable(CSR) tree_l.Split = nextLiteral.String() tree_r.Split = nextLiteral.Negation().String() tree.Children = append(tree.Children, tree_l) tree.Children = append(tree.Children, tree_r) return left || right, tree }