package formulae_test

/* ---------------------------------------------------------------- *
 * UNIT TESTING
 * ---------------------------------------------------------------- */

import (
	"logik/aussagenlogik/formulae"
	"logik/aussagenlogik/schema"
	"testing"

	"github.com/stretchr/testify/assert"
)

/* ---------------------------------------------------------------- *
 * TESTCASE KNF
 * ---------------------------------------------------------------- */

func TestRecogniseKNF(test *testing.T) {
	var assert = assert.New(test)
	var fml formulae.Formula

	fml = schema.ParseExpr("A7")
	assert.True(fml.IsKNF())
	fml = schema.ParseExpr("! A7")
	assert.True(fml.IsKNF())
	fml = schema.ParseExpr("!! A7")
	assert.False(fml.IsKNF())

	fml = schema.ParseExpr("(A0 || ! A1 || A7)")
	assert.True(fml.IsKNF())
	fml = schema.ParseExpr("(A0 && ! A1 && A7)")
	assert.True(fml.IsKNF())
	fml = schema.ParseExpr("(A0 && !! A1 && A7)")
	assert.False(fml.IsKNF())

	fml = schema.ParseExpr("(A0 || ! A1 || A7) && (A4 || ! A5) && A1")
	assert.True(fml.IsKNF())
	fml = schema.ParseExpr("(A0 && ! A1 && A7) || (A4 && ! A5) || A1")
	assert.False(fml.IsKNF())
	fml = schema.ParseExpr("((A0 || ! A1 || A7) && (A4 || ! A5)) || A8")
	assert.False(fml.IsKNF())
}

func TestRecogniseDNF(test *testing.T) {
	var assert = assert.New(test)
	var fml formulae.Formula

	fml = schema.ParseExpr("A7")
	assert.True(fml.IsDNF())
	fml = schema.ParseExpr("! A7")
	assert.True(fml.IsDNF())
	fml = schema.ParseExpr("!! A7")
	assert.False(fml.IsDNF())

	fml = schema.ParseExpr("(A0 && ! A1 && A7)")
	assert.True(fml.IsDNF())
	fml = schema.ParseExpr("(A0 || ! A1 || A7)")
	assert.True(fml.IsDNF())
	fml = schema.ParseExpr("(A0 || !! A1 || A7)")
	assert.False(fml.IsDNF())

	fml = schema.ParseExpr("(A0 && ! A1 && A7) || (A4 && ! A5) || A1")
	assert.True(fml.IsDNF())
	fml = schema.ParseExpr("(A0 || ! A1 || A7) && (A4 || ! A5) && A1")
	assert.False(fml.IsDNF())
	fml = schema.ParseExpr("((A0 && ! A1 && A7) || (A4 && ! A5)) && A8")
	assert.False(fml.IsDNF())
}

/* ---------------------------------------------------------------- *
 * TESTCASE Horn
 * ---------------------------------------------------------------- */

func TestRecogniseHorn(test *testing.T) {
	var assert = assert.New(test)
	var fml formulae.Formula

	fml = schema.ParseExpr("A7")
	assert.True(fml.IsHornFml())
	fml = schema.ParseExpr("! A7")
	assert.True(fml.IsHornFml())
	fml = schema.ParseExpr("!! A7")
	assert.False(fml.IsHornFml())

	fml = schema.ParseExpr("(! A0 || ! A1 || A7)")
	assert.True(fml.IsHornFml())
	fml = schema.ParseExpr("(A0 && ! A1 && A7)")
	assert.True(fml.IsHornFml())
	fml = schema.ParseExpr("(A0 && !! A1 && A7)")
	assert.False(fml.IsHornFml())

	fml = schema.ParseExpr("(A0 && ! A1 && ! A7) || (A4 && ! A5) || (! A1 && ! A8)")
	assert.False(fml.IsHornFml())
	fml = schema.ParseExpr("(A0 && ! A1 && ! A7) || (A4 && ! A5) || (! A1 && ! A8)")
	assert.False(fml.IsHornFml())
	fml = schema.ParseExpr("(A0 || ! A1 || ! A7) && (A4 || ! A5) && (! A1 || ! A8)")
	assert.True(fml.IsHornFml())
	fml = schema.ParseExpr("((A0 || ! A1 || A7) && (A4 || ! A5)) || A8")
	assert.False(fml.IsHornFml())
}

func TestTransformHornToFormula(test *testing.T) {
	var assert = assert.New(test)
	var fml formulae.Formula
	var horn formulae.FormulaHorn
	var hornClauses []formulae.FormulaHornClause

	fml = schema.ParseExpr("A8")
	assert.True(fml.IsHornFml())
	horn = fml.GetHornParts()
	hornClauses = horn
	assert.Equal(1, len(hornClauses))
	assert.ElementsMatch([]string{"A8"}, hornClauses[0].Pos.GetAtoms())
	assert.ElementsMatch([]string{}, hornClauses[0].Neg.GetAtoms())
	assert.Equal("(1 -> A8)", horn.ToFormula().GetExpr())

	fml = schema.ParseExpr("!A8")
	assert.True(fml.IsHornFml())
	horn = fml.GetHornParts()
	hornClauses = horn
	assert.Equal(1, len(hornClauses))
	assert.ElementsMatch([]string{}, hornClauses[0].Pos.GetAtoms())
	assert.ElementsMatch([]string{"A8"}, hornClauses[0].Neg.GetAtoms())
	assert.Equal("(A8 -> 0)", horn.ToFormula().GetExpr())

	fml = schema.ParseExpr("!A3 || A2 || !A7 || !A9")
	assert.True(fml.IsHornFml())
	horn = fml.GetHornParts()
	hornClauses = horn
	assert.Equal(1, len(hornClauses))
	assert.ElementsMatch([]string{"A2"}, hornClauses[0].Pos.GetAtoms())
	assert.ElementsMatch([]string{"A3", "A7", "A9"}, hornClauses[0].Neg.GetAtoms())
	assert.Equal("((A3 && A7 && A9) -> A2)", horn.ToFormula().GetExpr())

	fml = schema.ParseExpr("!A3 || !A2 || !A7 || !A9")
	assert.True(fml.IsHornFml())
	horn = fml.GetHornParts()
	hornClauses = horn
	assert.Equal(1, len(hornClauses))
	assert.ElementsMatch([]string{}, hornClauses[0].Pos.GetAtoms())
	assert.ElementsMatch([]string{"A2", "A3", "A7", "A9"}, hornClauses[0].Neg.GetAtoms())
	assert.Equal("((A3 && A2 && A7 && A9) -> 0)", horn.ToFormula().GetExpr())

	fml = schema.ParseExpr("!A3 && A2 && !A7 && A9 && A7")
	assert.True(fml.IsHornFml())
	horn = fml.GetHornParts()
	hornClauses = horn
	assert.Equal(5, len(hornClauses))
	assert.Equal("((A3 -> 0) && (1 -> A2) && (A7 -> 0) && (1 -> A9) && (1 -> A7))", horn.ToFormula().GetExpr())

	fml = schema.ParseExpr("(A0 || ! A1 || ! A7) && (A4 || ! A5) && (! A1 || ! A8)")
	assert.True(fml.IsHornFml())
	horn = fml.GetHornParts()
	hornClauses = horn
	assert.Equal(3, len(hornClauses))
	assert.Equal("(((A1 && A7) -> A0) && (A5 -> A4) && ((A1 && A8) -> 0))", horn.ToFormula().GetExpr())
}
