Browse Source

master > master: codego - auslagern, erzeugungsmethode verbessert, SyntaxBaum -> Formula

master
RD 1 year ago
parent
commit
73b7817dcd
  1. 283
      codego/aussagenlogik/formulae/formulae.go
  2. 165
      codego/aussagenlogik/formulae/formulae_generate.go
  3. 34
      codego/aussagenlogik/formulae/formulae_types.go
  4. 20
      codego/aussagenlogik/recursion/recursion_atoms.go
  5. 49
      codego/aussagenlogik/recursion/recursion_count.go
  6. 42
      codego/aussagenlogik/recursion/recursion_eval.go
  7. 77
      codego/aussagenlogik/recursion/recursion_nnf.go
  8. 359
      codego/aussagenlogik/recursion/recursion_test.go
  9. 70
      codego/aussagenlogik/rekursion/rekursion.go
  10. 51
      codego/aussagenlogik/rekursion/rekursion_aux.go
  11. 295
      codego/aussagenlogik/rekursion/rekursion_test.go
  12. 90
      codego/aussagenlogik/schema/schema.go
  13. 12
      codego/aussagenlogik/schema/schema_test.go
  14. 154
      codego/aussagenlogik/syntaxbaum/syntaxbaum.go
  15. 4
      codego/core/utils/utils.go
  16. 6
      codego/core/utils/utils_test.go
  17. 41
      codego/main.go

283
codego/aussagenlogik/formulae/formulae.go

@ -0,0 +1,283 @@
package formulae
import (
"fmt"
"strings"
)
/* ---------------------------------------------------------------- *
* TYPE Formula
* ---------------------------------------------------------------- */
type Formula struct {
kind string
expr string
valence int
subformulae [](*Formula)
}
/* ---------------------------------------------------------------- *
* METHODS
* ---------------------------------------------------------------- */
func (fml *Formula) SetKind(kind string) {
fml.kind = kind
}
func (fml Formula) GetKind() string {
return fml.kind
}
func (fml *Formula) SetExpr(expr string) {
fml.expr = expr
}
func (fml Formula) GetExpr() string {
return fml.expr
}
func (fml *Formula) SetSubformulae(children [](*Formula)) {
fml.subformulae = children
fml.valence = len(children)
}
func (fml Formula) GetSubFormulae() []Formula {
var n int = fml.valence
var children = make([]Formula, n)
for i, subfml := range fml.subformulae {
children[i] = *subfml
}
return children
}
func (fml Formula) GetChild(indexOpt ...int) Formula {
var index int = 0
if len(indexOpt) > 0 {
index = indexOpt[0]
}
var subfml Formula
if 0 <= index && index < fml.valence {
subfml = *(fml.subformulae[index])
} else {
panic(fmt.Sprintf("Instance has no child of index %d !", index))
}
return subfml
}
func (fml Formula) Pretty(preindentOpt ...string) string {
var preindent string = ""
if len(preindentOpt) > 0 {
preindent = preindentOpt[0]
}
return fml.pretty(preindent, " ", "", 0)
}
func (fml Formula) pretty(preindent string, tab string, prepend string, depth int) string {
var indent string = preindent + strings.Repeat(tab, depth)
switch fml.valence {
case 0:
switch kind := fml.kind; kind {
case "atom", "generic":
return indent + prepend + kind + " " + fml.expr
default:
return indent + prepend + kind
}
default:
var lines string = indent + prepend + fml.kind
prepend = "|__ "
for _, subfml := range fml.subformulae {
lines += "\n" + subfml.pretty(preindent, tab, prepend, depth+1)
}
return lines
}
}
func (fml Formula) Deepcopy() Formula {
var children = make([](*Formula), len(fml.subformulae))
for i, child := range fml.subformulae {
childCopy := child.Deepcopy()
children[i] = &childCopy
}
return Formula{
expr: fml.expr,
kind: fml.kind,
valence: fml.valence,
subformulae: children,
}
}
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
* METHODS: Basic constructions
* ---------------------------------------------------------------- */
var Tautology = Formula{
kind: "taut",
expr: "1",
valence: 0,
subformulae: [](*Formula){},
}
var Contradiction = Formula{
kind: "contradiction",
expr: "0",
valence: 0,
subformulae: [](*Formula){},
}
func Atom(expr string) Formula {
return Formula{
kind: "atom",
expr: expr,
valence: 0,
subformulae: [](*Formula){},
}
}
func NegatedAtom(expr string) Formula {
return Negation(Atom(expr))
}
func Generic(expr string) Formula {
return Formula{
kind: "generic",
expr: expr,
valence: 0,
subformulae: [](*Formula){},
}
}
func Negation(fml Formula) Formula {
return Formula{
kind: "not",
expr: "!" + " " + fml.expr,
valence: 1,
subformulae: [](*Formula){&fml},
}
}
func Conjunction2(fml1 Formula, fml2 Formula) Formula {
return Formula{
kind: "and2",
expr: "(" + fml1.expr + " && " + fml2.expr + ")",
valence: 2,
subformulae: [](*Formula){&fml1, &fml2},
}
}
func Conjunction(fmls []Formula) Formula {
var expr string = ""
var children = make([](*Formula), len(fmls))
for i, fml := range fmls {
if i > 0 {
expr += " && "
}
expr += fml.expr
children[i] = &fml
}
return Formula{
kind: "and",
expr: "(" + expr + ")",
valence: len(children),
subformulae: children,
}
}
func Disjunction2(fml1 Formula, fml2 Formula) Formula {
return Formula{
kind: "or2",
expr: "(" + fml1.expr + " || " + fml2.expr + ")",
valence: 2,
subformulae: [](*Formula){&fml1, &fml2},
}
}
func Disjunction(fmls []Formula) Formula {
var expr string = ""
var children = make([](*Formula), len(fmls))
for i, fml := range fmls {
if i > 0 {
expr += " || "
}
expr += fml.expr
children[i] = &fml
}
return Formula{
kind: "or",
expr: "(" + expr + ")",
valence: len(children),
subformulae: children,
}
}
func Implies(fml1 Formula, fml2 Formula) Formula {
return Formula{
kind: "implies",
expr: "(" + fml1.expr + " -> " + fml2.expr + ")",
valence: 2,
subformulae: [](*Formula){&fml1, &fml2},
}
}
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
* METHODS: Recognition of Formula-Types
* ---------------------------------------------------------------- */
func (fml Formula) IsIrreducible() bool {
return fml.valence == 0
}
func (fml Formula) IsAtom() bool {
return fml.kind == "atom"
}
func (fml Formula) IsPositiveLiteral() bool {
return fml.IsAtom()
}
func (fml Formula) IsNegativeLiteral() bool {
return fml.IsNegation() && fml.GetChild().IsAtom()
}
func (fml Formula) IsLiteral() bool {
return fml.IsPositiveLiteral() || fml.IsNegativeLiteral()
}
func (fml Formula) IsGeneric() bool {
return fml.kind == "generic"
}
func (fml Formula) IsTautologySymbol() bool {
return fml.kind == "taut"
}
func (fml Formula) IsContradictionSymbol() bool {
return fml.kind == "contradiction"
}
func (fml Formula) IsConnective() bool {
return fml.valence > 0
}
func (fml Formula) IsNegation() bool {
return fml.kind == "not"
}
func (fml Formula) IsConjunction2() bool {
return fml.kind == "and2"
}
func (fml Formula) IsConjunction() bool {
return fml.kind == "and" || fml.kind == "and2"
}
func (fml Formula) IsDisjunction2() bool {
return fml.kind == "or2"
}
func (fml Formula) IsDisjunction() bool {
return fml.kind == "or" || fml.kind == "or2"
}
func (fml Formula) IsImplication() bool {
return fml.kind == "implies"
}

165
codego/aussagenlogik/formulae/formulae_generate.go

@ -0,0 +1,165 @@
package formulae
// NOTE: GoLang hat noch keine generics. Erst 2022.
/* ---------------------------------------------------------------- *
* Generate int-value FN from scheme
* ---------------------------------------------------------------- */
func CreateFromSchemeIntValued(scheme func(fml Formula, prevValues []int) int) func(fml Formula) int {
var fn func(fml Formula) int
var subFn = func(ch chan int, subfml Formula) { ch <- fn(subfml) }
fn = func(fml Formula) int {
var subfmls = fml.GetSubFormulae()
var n = len(subfmls)
var subChan = make([](chan int), n)
var prevValues = make([]int, len(subfmls))
// start parallel computations on subformulas
for i, subfml := range subfmls {
subChan[i] = make(chan int) // create Channel, since currently nil
go subFn(subChan[i], subfml)
}
// successively read values
for i := 0; i < n; i++ {
prevValues[i] = <-subChan[i]
}
// apply schema to get value for formula
return scheme(fml, prevValues)
}
return fn
}
/* ---------------------------------------------------------------- *
* Generate string-value FN from scheme
* ---------------------------------------------------------------- */
func CreateFromSchemeStringValued(scheme func(fml Formula, prevValues []string) string) func(fml Formula) string {
var fn func(fml Formula) string
var subFn = func(ch chan string, subfml Formula) { ch <- fn(subfml) }
fn = func(fml Formula) string {
var subfmls = fml.GetSubFormulae()
var n = len(subfmls)
var subChan = make([](chan string), n)
var prevValues = make([]string, len(subfmls))
// start parallel computations on subformulas
for i, subfml := range subfmls {
subChan[i] = make(chan string) // create Channel, since currently nil
go subFn(subChan[i], subfml)
}
// successively read values
for i := 0; i < n; i++ {
prevValues[i] = <-subChan[i]
}
// apply schema to get value for formula
return scheme(fml, prevValues)
}
return fn
}
/* ---------------------------------------------------------------- *
* Generate *[]string-value Fn from scheme
* ---------------------------------------------------------------- */
func CreateFromSchemeStringsValued(scheme func(fml Formula, prevValues [][]string) []string) func(fml Formula) []string {
var fn func(fml Formula) []string
var subFn = func(ch chan []string, subfml Formula) { ch <- fn(subfml) }
fn = func(fml Formula) []string {
var subfmls = fml.GetSubFormulae()
var n = len(subfmls)
var subChan = make([](chan []string), n)
var prevValues = make([][]string, len(subfmls))
// start parallel computations on subformulas
for i, subfml := range subfmls {
subChan[i] = make(chan []string) // create Channel, since currently nil
go subFn(subChan[i], subfml)
}
// successively read values
for i := 0; i < n; i++ {
prevValues[i] = <-subChan[i]
}
// apply schema to get value for formula
return scheme(fml, prevValues)
}
return fn
}
/* ---------------------------------------------------------------- *
* Generate Formula-value Fn from scheme
* ---------------------------------------------------------------- */
func CreateFromSchemeFmlValued(scheme func(fml Formula, prevValues []Formula) Formula) func(fml Formula) Formula {
var fn func(fml Formula) Formula
var subFn = func(ch chan Formula, subfml Formula) { ch <- fn(subfml) }
fn = func(fml Formula) Formula {
var subfmls = fml.GetSubFormulae()
var n = len(subfmls)
var subChan = make([](chan Formula), n)
var prevValues = make([]Formula, len(subfmls))
// start parallel computations on subformulas
for i, subfml := range subfmls {
subChan[i] = make(chan Formula) // create Channel, since currently nil
go subFn(subChan[i], subfml)
}
// successively read values
for i := 0; i < n; i++ {
prevValues[i] = <-subChan[i]
}
// apply schema to get value for formula
return scheme(fml, prevValues)
}
return fn
}
/* ---------------------------------------------------------------- *
* Generate *[]Formula-value Fn from scheme
* ---------------------------------------------------------------- */
func CreateFromSchemeFmlsValued(scheme func(fml Formula, prevValues [](*[]Formula)) *[]Formula) func(fml Formula) *[]Formula {
var fn func(fml Formula) *[]Formula
var subFn = func(ch chan *[]Formula, subfml Formula) { ch <- fn(subfml) }
fn = func(fml Formula) *[]Formula {
var subfmls = fml.GetSubFormulae()
var n = len(subfmls)
var subChan = make([](chan *[]Formula), n)
var prevValues = make([](*[]Formula), len(subfmls))
// start parallel computations on subformulas
for i, subfml := range subfmls {
subChan[i] = make(chan *[]Formula) // create Channel, since currently nil
go subFn(subChan[i], subfml)
}
// successively read values
for i := 0; i < n; i++ {
prevValues[i] = <-subChan[i]
}
// apply schema to get value for formula
return scheme(fml, prevValues)
}
return fn
}
/* ---------------------------------------------------------------- *
* Generate {pos: Formula, ne: Formula}-value Fn from scheme
* ---------------------------------------------------------------- */
func CreateFromSchemeFmlPairValued(scheme func(fml Formula, prevValues []FormulaPair) FormulaPair) func(fml Formula) FormulaPair {
var fn func(fml Formula) FormulaPair
var subFn = func(ch chan FormulaPair, subfml Formula) { ch <- fn(subfml) }
fn = func(fml Formula) FormulaPair {
var subfmls = fml.GetSubFormulae()
var n = len(subfmls)
var subChan = make([](chan FormulaPair), n)
var prevValues = make([]FormulaPair, len(subfmls))
// start parallel computations on subformulas
for i, subfml := range subfmls {
subChan[i] = make(chan FormulaPair) // create Channel, since currently nil
go subFn(subChan[i], subfml)
}
// successively read values
for i := 0; i < n; i++ {
prevValues[i] = <-subChan[i]
}
// apply schema to get value for formula
return scheme(fml, prevValues)
}
return fn
}

34
codego/aussagenlogik/formulae/formulae_types.go

@ -0,0 +1,34 @@
package formulae
/* ---------------------------------------------------------------- *
* TYPE FormulaPair, FormulaPairs
* ---------------------------------------------------------------- */
type FormulaPair struct {
Pos Formula
Neg Formula
}
type FormulaPairs []FormulaPair
/* ---------------------------------------------------------------- *
* Methods for FormulaPairs
* ---------------------------------------------------------------- */
func NewFormulaPairs(pairs []FormulaPair) FormulaPairs { return pairs }
func (pairs FormulaPairs) Pos() []Formula {
var fmls = make([]Formula, len(pairs))
for i, pair := range pairs {
fmls[i] = pair.Pos
}
return fmls
}
func (pairs FormulaPairs) Neg() []Formula {
var fmls = make([]Formula, len(pairs))
for i, pair := range pairs {
fmls[i] = pair.Neg
}
return fmls
}

20
codego/aussagenlogik/recursion/recursion_atoms.go

@ -0,0 +1,20 @@
package recursion
import (
"logik/aussagenlogik/formulae"
)
/* ---------------------------------------------------------------- *
* METHOD: Atoms
* ---------------------------------------------------------------- */
func Atoms(tree formulae.Formula) []string {
// Definiere Schema:
var schema = func(tree formulae.Formula, prevValues [][]string) []string {
// Herausforderung: schreibe diese Funktion!
return []string{}
}
// Erzeuge Funktion aus Schema und berechne Wert:
fn := formulae.CreateFromSchemeStringsValued(schema)
return fn(tree)
}

49
codego/aussagenlogik/recursion/recursion_count.go

@ -0,0 +1,49 @@
package recursion
import (
"logik/aussagenlogik/formulae"
)
/* ---------------------------------------------------------------- *
* METHOD: Formula Depth
* ---------------------------------------------------------------- */
func FmlDepth(tree formulae.Formula) int {
// Definiere Schema:
var schema = func(tree formulae.Formula, prevValues []int) int {
// Herausforderung: schreibe diese Funktion!
return 0
}
// Erzeuge Funktion aus Schema und berechne Wert:
fn := formulae.CreateFromSchemeIntValued(schema)
return fn(tree)
}
/* ---------------------------------------------------------------- *
* METHOD: Formula Length
* ---------------------------------------------------------------- */
func FmlLength(tree formulae.Formula) int {
// Definiere Schema:
var schema = func(tree formulae.Formula, prevValues []int) int {
// Herausforderung: schreibe diese Funktion!
return 0
}
// Erzeuge Funktion aus Schema und berechne Wert:
fn := formulae.CreateFromSchemeIntValued(schema)
return fn(tree)
}
/* ---------------------------------------------------------------- *
* METHOD: Number of Parentheses
* ---------------------------------------------------------------- */
func NrParentheses(tree formulae.Formula) int {
// Definiere Schema:
var schema = func(tree formulae.Formula, prevValues []int) int {
// Herausforderung: schreibe diese Funktion!
return 0
}
// Erzeuge Funktion aus Schema und berechne Wert:
fn := formulae.CreateFromSchemeIntValued(schema)
return fn(tree)
}

42
codego/aussagenlogik/recursion/recursion_eval.go

@ -0,0 +1,42 @@
package recursion
import (
"logik/aussagenlogik/formulae"
"logik/core/utils"
)
/* ---------------------------------------------------------------- *
* METHOD: Evaluation of fomulae in models
* ---------------------------------------------------------------- */
func Eval(tree formulae.Formula, I []string) int {
// Definiere (parameterisiertes) Schema:
var schema = func(_I []string) func(formulae.Formula, []int) int {
return func(tree formulae.Formula, prevValues []int) int {
if tree.IsAtom() || tree.IsGeneric() {
return utils.BoolToInt(utils.StrListContains(_I, tree.GetExpr()))
} else if tree.IsTautologySymbol() {
return 1
} else if tree.IsContradictionSymbol() {
return 0
} else if tree.IsNegation() {
return 1 - prevValues[0]
} else if tree.IsConjunction2() {
return utils.Min2(prevValues[0], prevValues[1])
} else if tree.IsConjunction() {
return utils.MinList(prevValues)
} else if tree.IsDisjunction2() {
return utils.Max2(prevValues[0], prevValues[1])
} else if tree.IsDisjunction() {
return utils.MaxList(prevValues)
} else if tree.IsImplication() {
return utils.BoolToInt(prevValues[0] <= prevValues[1])
} else {
panic("Could not evaluate expression!")
}
}
}
// Erzeuge Funktion aus Schema und berechne Wert:
fn := formulae.CreateFromSchemeIntValued(schema(I))
return fn(tree)
}

77
codego/aussagenlogik/recursion/recursion_nnf.go

@ -0,0 +1,77 @@
package recursion
import (
"logik/aussagenlogik/formulae"
)
/* ---------------------------------------------------------------- *
* METHOD: compute NNF
* ---------------------------------------------------------------- */
// NOTE: diese bedarf einer Art Doppeltrekursion
func NNF(tree formulae.Formula) formulae.Formula {
// Definiere Schema:
var schema = func(tree formulae.Formula, prevValues []formulae.FormulaPair) formulae.FormulaPair {
// separate out positive and negative parts:
var pairs = formulae.NewFormulaPairs(prevValues)
var prevPos = pairs.Pos()
var prevNeg = pairs.Neg()
// compute value from previous positive/negative parts:
if tree.IsPositiveLiteral() {
return formulae.FormulaPair{
Pos: tree.Deepcopy(),
Neg: formulae.Negation(tree),
}
} else if tree.IsNegativeLiteral() {
return formulae.FormulaPair{
Pos: tree.Deepcopy(),
Neg: prevPos[0],
}
} else if tree.IsTautologySymbol() {
return formulae.FormulaPair{
Pos: formulae.Tautology,
Neg: formulae.Contradiction,
}
} else if tree.IsContradictionSymbol() {
return formulae.FormulaPair{
Pos: formulae.Contradiction,
Neg: formulae.Tautology,
}
} else if tree.IsNegation() {
return formulae.FormulaPair{
Pos: prevNeg[0],
Neg: prevPos[0],
}
} else if tree.IsConjunction2() {
return formulae.FormulaPair{
Pos: formulae.Conjunction2(prevPos[0], prevPos[1]),
Neg: formulae.Disjunction2(prevNeg[0], prevNeg[1]),
}
} else if tree.IsConjunction() {
return formulae.FormulaPair{
Pos: formulae.Conjunction(prevPos),
Neg: formulae.Disjunction(prevNeg),
}
} else if tree.IsDisjunction2() {
return formulae.FormulaPair{
Pos: formulae.Disjunction2(prevPos[0], prevPos[1]),
Neg: formulae.Conjunction2(prevNeg[0], prevNeg[1]),
}
} else if tree.IsDisjunction() {
return formulae.FormulaPair{
Pos: formulae.Disjunction(prevPos),
Neg: formulae.Conjunction(prevNeg),
}
} else if tree.IsImplication() {
return formulae.FormulaPair{
Pos: formulae.Implies(prevPos[0], prevPos[1]),
Neg: formulae.Conjunction2(prevPos[0], prevNeg[1]),
}
} else {
panic("Could not evaluate expression!")
}
}
// Erzeuge Funktion aus Schema und berechne Wert:
fn := formulae.CreateFromSchemeFmlPairValued(schema)
return fn(tree).Pos
}

359
codego/aussagenlogik/recursion/recursion_test.go

@ -0,0 +1,359 @@
package recursion_test
/* ---------------------------------------------------------------- *
* UNIT TESTING
* ---------------------------------------------------------------- */
import (
"logik/aussagenlogik/formulae"
"logik/aussagenlogik/recursion"
"logik/aussagenlogik/schema"
"logik/core/utils"
"testing"
"github.com/stretchr/testify/assert"
)
/* ---------------------------------------------------------------- *
* TESTCASE eval(·, ·)
* ---------------------------------------------------------------- */
func TestEvalLiteral(test *testing.T) {
var assert = assert.New(test)
var val int
var fml formulae.Formula
var I []string
fml = schema.ParseExpr("A0")
I = []string{"A0"}
val = recursion.Eval(fml, I)
assert.Equal(1, val)
fml = schema.ParseExpr("A0")
I = []string{}
val = recursion.Eval(fml, I)
assert.Equal(0, val)
fml = schema.ParseExpr("! A0")
I = []string{"A0"}
val = recursion.Eval(fml, I)
assert.Equal(0, val)
fml = schema.ParseExpr("! A0")
I = []string{}
val = recursion.Eval(fml, I)
assert.Equal(1, val)
}
func TestEvalComplex1(test *testing.T) {
var assert = assert.New(test)
var val int
var fml formulae.Formula
var I []string
fml = schema.ParseExpr("( ! A0 || (( A0 && A3 ) || A2 ))")
I = []string{"A0", "A2"}
val = recursion.Eval(fml, I)
assert.Equal(1, val)
I = []string{"A0", "A3"}
val = recursion.Eval(fml, I)
assert.Equal(1, val)
I = []string{"A0"}
val = recursion.Eval(fml, I)
assert.Equal(0, val)
I = []string{"A4", "A8"}
val = recursion.Eval(fml, I)
assert.Equal(1, val)
}
func TestEvalComplex2(test *testing.T) {
var assert = assert.New(test)
var val int
var fml formulae.Formula
var I []string
fml = schema.ParseExpr("( ! A0 || (( A0 && A3 ) || ! A2 ))")
I = []string{"A0", "A2"}
val = recursion.Eval(fml, I)
assert.Equal(0, val)
I = []string{"A0", "A3"}
val = recursion.Eval(fml, I)
assert.Equal(1, val)
}
/* ---------------------------------------------------------------- *
* TESTCASE Atoms(·)
* ---------------------------------------------------------------- */
func TestAtomsNoduplicates(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
var assert = assert.New(test)
var fml formulae.Formula
var val []string
fml = schema.ParseExpr("( A4 && ( A4 || A4 ))")
val = recursion.Atoms(fml)
var n int = len(utils.FilterStrings(&val, func(x string) bool { return x == "A4" }))
assert.Equal(1, n, "Atome dürfen nicht mehrfach vorkommen!")
}
func TestAtomsNononatoms(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
test.Skip("Syntax for generic expressions in ANTLR4 g4 needs to be implemented.")
var assert = assert.New(test)
var fml formulae.Formula
var val []string
fml = schema.ParseExpr("( {F} || A3 )")
val = recursion.Atoms(fml)
utils.SortStrings(&val)
assert.NotContains(val, "F", "Nichtatomare Formeln dürfen nicht vorkommen!")
}
func TestAtomsCalc1(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
var assert = assert.New(test)
var fml formulae.Formula
var val []string
fml = schema.ParseExpr("A0")
val = recursion.Atoms(fml)
utils.SortStrings(&val)
assert.Equal([]string{"A0"}, val)
}
func TestAtomsCalc2(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
var assert = assert.New(test)
var fml formulae.Formula
var val []string
fml = schema.ParseExpr("((( ! A8 && A3 ) || A4 ) && A0 )")
val = recursion.Atoms(fml)
utils.SortStrings(&val)
assert.Equal([]string{"A0", "A3", "A4", "A8"}, val)
}
/* ---------------------------------------------------------------- *
* TESTCASE depth(·, ·)
* ---------------------------------------------------------------- */
func TestDepthCalc1(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
var assert = assert.New(test)
var val int
var fml formulae.Formula
fml = schema.ParseExpr("A0")
val = recursion.FmlDepth(fml)
assert.Equal(0, val)
}
func TestDepthCalc2(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
var assert = assert.New(test)
var val int
var fml formulae.Formula
fml = schema.ParseExpr("!! A8")
val = recursion.FmlDepth(fml)
assert.Equal(2, val)
}
func TestDepthCalc3(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
var assert = assert.New(test)
var val int
var fml formulae.Formula
fml = schema.ParseExpr("( ! A0 && A3 )")
val = recursion.FmlDepth(fml)
assert.Equal(2, val)
}
func TestDepthCalc4(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
var assert = assert.New(test)
var val int
var fml formulae.Formula
fml = schema.ParseExpr("((( ! A0 && A3 ) || A4 ) && A8 )")
val = recursion.FmlDepth(fml)
assert.Equal(4, val)
}
func TestDepthCalc5(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
var assert = assert.New(test)
var val int
var fml formulae.Formula
fml = schema.ParseExpr("! ((( ! A0 && A3 ) || A4 ) && A8 )")
val = recursion.FmlDepth(fml)
assert.Equal(5, val)
}
/* ---------------------------------------------------------------- *
* TESTCASE length(·)
* ---------------------------------------------------------------- */
func TestLengthCalc1(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
var assert = assert.New(test)
var val int
var fml formulae.Formula
fml = schema.ParseExpr("A0")
val = recursion.FmlLength(fml)
assert.Equal(1, val)
}
func TestLengthCalc2(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
var assert = assert.New(test)
var val int
var fml formulae.Formula
fml = schema.ParseExpr("!! A8")
val = recursion.FmlLength(fml)
assert.Equal(3, val)
}
func TestLengthCalc3(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
var assert = assert.New(test)
var val int
var fml formulae.Formula
fml = schema.ParseExpr("( ! A0 && A3 )")
val = recursion.FmlLength(fml)
assert.Equal(4, val)
}
func TestLengthCalc4(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
var assert = assert.New(test)
var val int
var fml formulae.Formula
fml = schema.ParseExpr("((( ! A0 && A3 ) || A4 ) && A8 )")
val = recursion.FmlLength(fml)
assert.Equal(8, val)
}
func TestLengthCalc5(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
var assert = assert.New(test)
var val int
var fml formulae.Formula
fml = schema.ParseExpr("! ((( ! A0 && A3 ) || A4 ) && A8 )")
val = recursion.FmlLength(fml)
assert.Equal(9, val)
}
/* ---------------------------------------------------------------- *
* TESTCASE #Parentheses(·)
* ---------------------------------------------------------------- */
func TestParenthesesCalc1(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
var assert = assert.New(test)
var val int
var fml formulae.Formula
fml = schema.ParseExpr("A0")
val = recursion.NrParentheses(fml)
assert.Equal(0, val)
}
func TestParenthesesCalc2(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
var assert = assert.New(test)
var val int
var fml formulae.Formula
fml = schema.ParseExpr("!! A8")
val = recursion.NrParentheses(fml)
assert.Equal(0, val)
}
func TestParenthesesCalc3(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
var assert = assert.New(test)
var val int
var fml formulae.Formula
fml = schema.ParseExpr("( ! A0 && A3 )")
val = recursion.NrParentheses(fml)
assert.Equal(2, val)
}
func TestParenthesesCalc4(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
var assert = assert.New(test)
var val int
var fml formulae.Formula
fml = schema.ParseExpr("((( ! A0 && A3 ) || A4 ) && A8 )")
val = recursion.NrParentheses(fml)
assert.Equal(6, val)
}
func TestParenthesesCalc5(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
var assert = assert.New(test)
var val int
var fml formulae.Formula
fml = schema.ParseExpr("! ((( ! A0 && A3 ) || A4 ) && A8 )")
val = recursion.NrParentheses(fml)
assert.Equal(6, val)
}
/* ---------------------------------------------------------------- *
* TESTCASE NNF
* ---------------------------------------------------------------- */
func TestNNFatoms(test *testing.T) {
var assert = assert.New(test)
var fml formulae.Formula
var nnf_expected formulae.Formula
nnf_expected = formulae.Atom("A7")
fml = schema.ParseExpr("A7")
assert.Equal(nnf_expected.GetExpr(), recursion.NNF(fml).GetExpr())
fml = schema.ParseExpr("!! A7")
assert.Equal(nnf_expected.GetExpr(), recursion.NNF(fml).GetExpr())
nnf_expected = formulae.NegatedAtom("A7")
fml = schema.ParseExpr("! A7")
assert.Equal(nnf_expected.GetExpr(), recursion.NNF(fml).GetExpr())
fml = schema.ParseExpr("!!! A7")
assert.Equal(nnf_expected.GetExpr(), recursion.NNF(fml).GetExpr())
}
func TestNNFconj(test *testing.T) {
var assert = assert.New(test)
var fml formulae.Formula
var nnf_expected formulae.Formula
nnf_expected = formulae.Disjunction2(formulae.NegatedAtom("A0"), formulae.NegatedAtom("A1"))
fml = schema.ParseExpr("! (A0 && A1)")
assert.Equal(nnf_expected.GetExpr(), recursion.NNF(fml).GetExpr())
nnf_expected = formulae.Disjunction2(formulae.Atom("A0"), formulae.Atom("A1"))
fml = schema.ParseExpr("! (! A0 && ! A1)")
assert.Equal(nnf_expected.GetExpr(), recursion.NNF(fml).GetExpr())
nnf_expected = formulae.Conjunction2(formulae.Atom("A0"), formulae.NegatedAtom("A1"))
fml = schema.ParseExpr("(A0 && ! A1)")
assert.Equal(nnf_expected.GetExpr(), recursion.NNF(fml).GetExpr())
}
func TestNNFdisj(test *testing.T) {
var assert = assert.New(test)
var fml formulae.Formula
var nnf_expected formulae.Formula
nnf_expected = formulae.Conjunction2(formulae.NegatedAtom("A0"), formulae.NegatedAtom("A1"))
fml = schema.ParseExpr("! (A0 || A1)")
assert.Equal(nnf_expected.GetExpr(), recursion.NNF(fml).GetExpr())
nnf_expected = formulae.Conjunction2(formulae.Atom("A0"), formulae.Atom("A1"))
fml = schema.ParseExpr("! (! A0 || ! A1)")
assert.Equal(nnf_expected.GetExpr(), recursion.NNF(fml).GetExpr())
nnf_expected = formulae.Disjunction2(formulae.Atom("A0"), formulae.NegatedAtom("A1"))
fml = schema.ParseExpr("(A0 || ! A1)")
assert.Equal(nnf_expected.GetExpr(), recursion.NNF(fml).GetExpr())
}
func TestNNFcalcComplex(test *testing.T) {
var assert = assert.New(test)
var fml formulae.Formula
var nnf_expected formulae.Formula
fml = schema.ParseExpr("! (! (!A0 || A1) || ! ! A8)")
nnf_expected = schema.ParseExpr("((!A0 || A1) && ! A8)")
assert.Equal(nnf_expected.GetExpr(), recursion.NNF(fml).GetExpr())
fml = schema.ParseExpr("! (! (!A0 || !(A1 && ! A7)) && ! A8)")
nnf_expected = schema.ParseExpr("((!A0 || (! A1 || A7)) || A8)")
assert.Equal(nnf_expected.GetExpr(), recursion.NNF(fml).GetExpr())
}

70
codego/aussagenlogik/rekursion/rekursion.go

@ -1,70 +0,0 @@
package rekursion
import (
"logik/aussagenlogik/syntaxbaum"
"logik/core/utils"
)
/* ---------------------------------------------------------------- *
* EXPORTS
* ---------------------------------------------------------------- */
type RekursiveChannelInt struct {
channel chan int
}
func RekursivEval(ch chan int, tree syntaxbaum.SyntaxBaum, I []string) {
// Werte für Teilformeln rekursiv berechnen
fn := func(_ch chan int, _tree syntaxbaum.SyntaxBaum) { RekursivEval(_ch, _tree, I) }
var values = RekursiveCallInt(fn, tree.GetChildren())
// Aus Werten für Teilformeln Wert für Formeln berechnen
if tree.IsAtom() || tree.IsGeneric() {
ch <- utils.BoolToInt(utils.StrListContains(I, tree.GetExpr()))
} else if tree.IsTautologySymbol() {
ch <- 1
} else if tree.IsContradictionSymbol() {
ch <- 0
} else if tree.IsNegation() {
ch <- 1 - values[0]
} else if tree.IsConjunction2() {
ch <- utils.Min2(values[0], values[1])
} else if tree.IsConjunction() {
ch <- utils.MinList(values)
} else if tree.IsDisjunction2() {
ch <- utils.Max2(values[0], values[1])
} else if tree.IsDisjunction() {
ch <- utils.MaxList(values)
} else if tree.IsImplication() {
ch <- utils.BoolToInt(values[0] <= values[1])
} else {
panic("Could not evaluate expression!")
}
}
func RekursivAtoms(ch chan []string, tree syntaxbaum.SyntaxBaum) {
// // Werte für Teilformeln rekursiv berechnen
// var values = RekursiveCallStringList(RekursivAtoms, tree.GetChildren())
// Herausforderung: schreibe diese Funktion!
ch <- []string{}
}
func RekursivDepth(ch chan int, tree syntaxbaum.SyntaxBaum) {
// // Werte für Teilformeln rekursiv berechnen
// var values = RekursiveCallInt(RekursivDepth, tree.GetChildren())
// Herausforderung: schreibe diese Funktion!
ch <- 0
}
func RekursivLength(ch chan int, tree syntaxbaum.SyntaxBaum) {
// // Werte für Teilformeln rekursiv berechnen
// var values = RekursiveCallInt(RekursivLength, tree.GetChildren())
// Herausforderung: schreibe diese Funktion!
ch <- 0
}
func RekursivParentheses(ch chan int, tree syntaxbaum.SyntaxBaum) {
// // Werte für Teilformeln rekursiv berechnen
// var values = RekursiveCallInt(RekursivParentheses, tree.GetChildren())
// Herausforderung: schreibe diese Funktion!
ch <- 0
}

51
codego/aussagenlogik/rekursion/rekursion_aux.go

@ -1,51 +0,0 @@
package rekursion
import (
"logik/aussagenlogik/syntaxbaum"
)
/* ---------------------------------------------------------------- *
* EXPORTS
* ---------------------------------------------------------------- */
func RekursiveCallInt(fn func(ch chan int, tree syntaxbaum.SyntaxBaum), children []syntaxbaum.SyntaxBaum) []int {
subChannel := make(chan int)
values := make([]int, len(children))
// start parallel computations on subformulae
for _, subtree := range children {
go fn(subChannel, subtree)
}
// successively read values
for i := 0; i < len(children); i++ {
values[i] = <-subChannel
}
return values
}
func RekursiveCallString(fn func(ch chan string, tree syntaxbaum.SyntaxBaum), children []syntaxbaum.SyntaxBaum) []string {
subChannel := make(chan string)
values := make([]string, len(children))
// start parallel computations
for _, subtree := range children {
go fn(subChannel, subtree)
}
// successively read values
for i := 0; i < len(children); i++ {
values[i] = <-subChannel
}
return values
}
func RekursiveCallStringList(fn func(ch chan []string, tree syntaxbaum.SyntaxBaum), children []syntaxbaum.SyntaxBaum) [][]string {
subChannel := make(chan []string)
values := make([][]string, len(children))
// start parallel computations
for _, subtree := range children {
go fn(subChannel, subtree)
}
// successively read values
for i := 0; i < len(children); i++ {
values[i] = <-subChannel
}
return values
}

295
codego/aussagenlogik/rekursion/rekursion_test.go

@ -1,295 +0,0 @@
package rekursion_test
/* ---------------------------------------------------------------- *
* UNIT TESTING
* ---------------------------------------------------------------- */
import (
"logik/aussagenlogik/rekursion"
"logik/aussagenlogik/schema"
"logik/aussagenlogik/syntaxbaum"
"logik/core/utils"
"testing"
"github.com/stretchr/testify/assert"
)
/* ---------------------------------------------------------------- *
* TESTCASE eval(·, ·)
* ---------------------------------------------------------------- */
func TestRekursivEvalLiteral(test *testing.T) {
var assert = assert.New(test)
var ch = make(chan int)
var tree syntaxbaum.SyntaxBaum
var I []string
tree = schema.ParseExpr("A0")
I = []string{"A0"}
go rekursion.RekursivEval(ch, tree, I)
assert.Equal(1, <-ch)
tree = schema.ParseExpr("A0")
I = []string{}
go rekursion.RekursivEval(ch, tree, I)
assert.Equal(0, <-ch)
tree = schema.ParseExpr("! A0")
I = []string{"A0"}
go rekursion.RekursivEval(ch, tree, I)
assert.Equal(0, <-ch)
tree = schema.ParseExpr("! A0")
I = []string{}
go rekursion.RekursivEval(ch, tree, I)
assert.Equal(1, <-ch)
}
func TestRekursivEvalComplex1(test *testing.T) {
var assert = assert.New(test)
var ch = make(chan int)
var tree syntaxbaum.SyntaxBaum
var I []string
tree = schema.ParseExpr("( ! A0 || (( A0 && A3 ) || A2 ))")
I = []string{"A0", "A2"}
go rekursion.RekursivEval(ch, tree, I)
assert.Equal(1, <-ch)
I = []string{"A0", "A3"}
go rekursion.RekursivEval(ch, tree, I)
assert.Equal(1, <-ch)
I = []string{"A0"}
go rekursion.RekursivEval(ch, tree, I)
assert.Equal(0, <-ch)
I = []string{"A4", "A8"}
go rekursion.RekursivEval(ch, tree, I)
assert.Equal(1, <-ch)
}
func TestRekursivEvalComplex2(test *testing.T) {
var assert = assert.New(test)
var ch = make(chan int)
var tree syntaxbaum.SyntaxBaum
var I []string
tree = schema.ParseExpr("( ! A0 || (( A0 && A3 ) || ! A2 ))")
I = []string{"A0", "A2"}
go rekursion.RekursivEval(ch, tree, I)
assert.Equal(0, <-ch)
I = []string{"A0", "A3"}
go rekursion.RekursivEval(ch, tree, I)
assert.Equal(1, <-ch)
}
/* ---------------------------------------------------------------- *
* TESTCASE Atoms(·)
* ---------------------------------------------------------------- */
func TestRekursivAtomsNoduplicates(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
var assert = assert.New(test)
var ch = make(chan []string)
var tree syntaxbaum.SyntaxBaum
var val []string
tree = schema.ParseExpr("( A4 && ( A4 || A4 ))")
go rekursion.RekursivAtoms(ch, tree)
val = <-ch
var n int = len(utils.FilterStrings(&val, func(x string) bool { return x == "A4" }))
assert.Equal(1, n, "Atome dürfen nicht mehrfach vorkommen!")
}
func TestRekursivAtomsNononatoms(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
test.Skip("Syntax for generic expressions in ANTLR4 g4 needs to be implemented.")
var assert = assert.New(test)
var ch = make(chan []string)
var tree syntaxbaum.SyntaxBaum
var val []string
tree = schema.ParseExpr("( {F} || A3 )")
go rekursion.RekursivAtoms(ch, tree)
val = <-ch
utils.SortStrings(&val)
assert.NotContains(val, "F", "Nichtatomare Formeln dürfen nicht vorkommen!")
}
func TestRekursivAtomsCalc1(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
var assert = assert.New(test)
var ch = make(chan []string)
var tree syntaxbaum.SyntaxBaum
var val []string
tree = schema.ParseExpr("A0")
go rekursion.RekursivAtoms(ch, tree)
val = <-ch
utils.SortStrings(&val)
assert.Equal([]string{"A0"}, val)
}
func TestRekursivAtomsCalc2(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
var assert = assert.New(test)
var ch = make(chan []string)
var tree syntaxbaum.SyntaxBaum
var val []string
tree = schema.ParseExpr("((( ! A8 && A3 ) || A4 ) && A0 )")
go rekursion.RekursivAtoms(ch, tree)
val = <-ch
utils.SortStrings(&val)
assert.Equal([]string{"A0", "A3", "A4", "A8"}, val)
}
/* ---------------------------------------------------------------- *
* TESTCASE depth(·, ·)
* ---------------------------------------------------------------- */
func TestRekursivDepthCalc1(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
var assert = assert.New(test)
var ch = make(chan int)
var tree syntaxbaum.SyntaxBaum
tree = schema.ParseExpr("A0")
go rekursion.RekursivDepth(ch, tree)
assert.Equal(0, <-ch)