io.github.pirocks.nd.Introduction.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of simple-logic-lib Show documentation
Show all versions of simple-logic-lib Show documentation
A simple library for working with first order logic and natural deduction proofs
The newest version!
package io.github.pirocks.nd
import io.github.pirocks.logic.*
abstract class NDIntroductionStatement : NDStatementBase()
/**
* A for all introduction has a forall const leading to a conclusion. end result removes forall cconst and replaces with general
* statement
*/
class ForAllIntroduction(val forAllConst: VariableName, val body: List) : NDIntroductionStatement() {
override fun verify(context: VerifierContext): Boolean {
context.push()
return body.all {
context.verify(it)
}.also {
context.pop()
}
}
override val proves: FOLFormula
init {
if (body.isEmpty()) {
throw IllegalArgumentException("ForAll Introduction requires at least one statement in body")
}
proves = ForAll(body.last().proves, forAllConst)
}
}
class ExistsIntroduction(val specificExample: NDStatement, val varToTarget: VariableName) : NDIntroductionStatement() {
override fun verify(context: VerifierContext): Boolean {
return context.known(specificExample)
}
override val proves: FOLFormula
init {
val boundVar = VariableName()
proves = Exists(renameVar(specificExample.proves, varToTarget, boundVar), boundVar)
}
}
class AndIntroduction(val left: NDStatement, val right: NDStatement) : NDIntroductionStatement() {
override val proves: FOLFormula = And(left.proves, right.proves)
override fun verify(context: VerifierContext): Boolean {
return context.known(left) && context.known(right)
}
}
class OrIntroductionRight(val left: NDStatement, val right: FOLFormula) : NDIntroductionStatement() {
override fun verify(context: VerifierContext): Boolean {
return context.known(left)
}
override val proves: FOLFormula = Or(left.proves, right)
}
class OrIntroductionLeft(val left: FOLFormula, val right: NDStatement) : NDIntroductionStatement() {
override fun verify(context: VerifierContext): Boolean {
return context.known(right)
}
override val proves: FOLFormula = Or(left, right.proves)
}
class ImpliesIntroduction(val assumption: AssumptionStatement, val steps: List) : NDIntroductionStatement() {
override fun verify(context: VerifierContext): Boolean {
context.push()
context.assume(assumption)
return steps.all {
context.verify(it)
}.also { context.pop() }
}
override val proves: FOLFormula
init {
val result = steps.lastOrNull()?.proves
?: throw MalformedProofException("Empty proof body for implies introduction")
proves = Implies(assumption.proves, result)
}
}
class AssumptionStatement(val assumption: FOLFormula) : NDIntroductionStatement() {
override fun verify(context: VerifierContext): Boolean {
return false//Assumption statements should always be skipped when added correctly via Implies/NotIntro.
}
override val proves: FOLFormula = assumption
}
class IFFIntroduction(val leftImplies: NDStatement, val rightImplies: NDStatement) : NDIntroductionStatement() {
override fun verify(context: VerifierContext): Boolean {
return verifyMatching() &&
context.known(leftImplies) &&
context.known(rightImplies)
}
private fun verifyMatching(): Boolean {
val leftGiven = (leftImplies.proves as? Implies)?.given ?: return false
val rightGiven = (rightImplies.proves as? Implies)?.given ?: return false
val leftResult = (leftImplies.proves as? Implies)?.result ?: return false
val rightResult = (rightImplies.proves as? Implies)?.result ?: return false
return leftGiven == rightResult &&
leftResult == rightGiven
}
override val proves: FOLFormula
init {
if (!verifyMatching()) {
throw MalformedProofException("IFF intro incompatible left and right implications ")
}
val leftOfIFF = (leftImplies.proves as Implies).given
val rightOfIFF = (leftImplies.proves as Implies).result
proves = IFF(leftOfIFF, rightOfIFF)
}
}
class NegationIntroduction(val assumption: AssumptionStatement, val steps: List) : NDIntroductionStatement() {
override fun verify(context: VerifierContext): Boolean {
context.push()
context.assume(assumption)
return steps.all {
context.verify(it)
}.also { context.pop() } && steps.lastOrNull()?.proves is False
}
override val proves: FOLFormula
init {
if (steps.isEmpty()) {
throw MalformedProofException("Negation introduction received empty proof body")
}
proves = Not(assumption.proves)
}
}
class TruthIntroduction : NDIntroductionStatement() {
override fun verify(context: VerifierContext): Boolean {
return true
}
override val proves: FOLFormula = True()
}
class FalseIntroduction(val contradictoryLeft: NDStatement, val contradictoryRight: NDStatement) : NDIntroductionStatement() {
override fun verify(context: VerifierContext): Boolean {
val leftNegated = (contradictoryLeft.proves as? Not)?.child?.let {
it == contradictoryRight.proves
} ?: false
val rightNegated = (contradictoryRight.proves as? Not)?.child?.let {
it == contradictoryLeft.proves
} ?: false
return (leftNegated || rightNegated) && context.known(contradictoryLeft) && context.known(contradictoryRight)
}
override val proves: FOLFormula = False()
}
/**
* effectively copies a statement. needed for completeness reasons
*/
class IDIntroduction(val toCopy: NDStatement) : NDIntroductionStatement() {
override fun verify(context: VerifierContext): Boolean {
return context.known(toCopy)
}
override val proves: FOLFormula = toCopy.proves
}