Compare commits
2 Commits
cbf8e29a84
...
66beff5792
| Author | SHA1 | Date |
|---|---|---|
|
|
66beff5792 | |
|
|
dcad494c7d |
|
|
@ -3,8 +3,11 @@
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# from ..proof import Context, Proof
|
# from ..proof import Context, Proof
|
||||||
from ..props import Eq, Or, Prop
|
from ..props import Eq, Exists, Or, Prop
|
||||||
from ..terms import App, Const, A1, A2, L1, L2, L3, Lambda, Term, Var, register_known_const
|
from ..terms import (
|
||||||
|
App, Const, A1, A2, L1, L2, L3, Lambda, Term,
|
||||||
|
register_known_const, register_known_norm
|
||||||
|
)
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# Identity function
|
# Identity function
|
||||||
|
|
@ -59,8 +62,35 @@ def kernel_from_int(n : int) -> Term:
|
||||||
|
|
||||||
return t
|
return t
|
||||||
|
|
||||||
# def is_nat(x : Term) -> Prop:
|
def is_nat(x : Term) -> Prop:
|
||||||
# return Or(
|
return Or(
|
||||||
# Eq(x=x, y=zero),
|
Eq(x=x, y=zero),
|
||||||
# Eq(bool_f, bool_t) # TODO: Construct x = Succ n where isNat(n),
|
Exists(lambda n : Eq(x=x, y=A1(Const("Nat.Succ"), n))),
|
||||||
# )
|
)
|
||||||
|
|
||||||
|
def __nat_add(t : Term) -> Term:
|
||||||
|
match t:
|
||||||
|
case App(f=Const("Nat.add"), x=Const("Nat.Zero")):
|
||||||
|
return id_func
|
||||||
|
|
||||||
|
case App(f=Const("Nat.add"), x=App(f=Const("Nat.Succ"), x=a)):
|
||||||
|
return L1(lambda b : A1(succ, A2(Const("Nat.add"), a, b)))
|
||||||
|
|
||||||
|
case _:
|
||||||
|
return t
|
||||||
|
register_known_norm(__nat_add)
|
||||||
|
|
||||||
|
def __nat_leq(t : Term) -> Term:
|
||||||
|
match t:
|
||||||
|
case App(f=Const("Nat.leq"), x=Const("Nat.Zero")):
|
||||||
|
return bool_t
|
||||||
|
|
||||||
|
case App(App(f=Const("Nat.leq"), x=_), x=Const("Nat.Zero")):
|
||||||
|
return bool_f
|
||||||
|
|
||||||
|
case App(f=App(f=Const("Nat.leq"), x=App(f=Const("Nat.Succ"), x=a)), x=App(f=Const("Nat.Succ"), x=b)):
|
||||||
|
return A2(Const("Nat.leq"), a, b)
|
||||||
|
|
||||||
|
case _:
|
||||||
|
return t
|
||||||
|
register_known_norm(__nat_leq)
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
from typing import Callable
|
||||||
|
|
||||||
from .terms import Term
|
from .terms import Term
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
|
@ -65,6 +66,23 @@ class Eq(Prop):
|
||||||
def as_proof(self) -> list[list[tuple[list[Prop], Prop]]]:
|
def as_proof(self) -> list[list[tuple[list[Prop], Prop]]]:
|
||||||
return super().as_proof()
|
return super().as_proof()
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class Exists(Prop):
|
||||||
|
"""
|
||||||
|
Create a statement that demonstrates there exists an x such that the
|
||||||
|
given statement is true.
|
||||||
|
"""
|
||||||
|
|
||||||
|
x : Callable[[Term], Prop]
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class ForAll(Prop):
|
||||||
|
"""
|
||||||
|
Create a statement that is true for all x
|
||||||
|
"""
|
||||||
|
|
||||||
|
x : Callable[[Term], Prop]
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class Implies(Prop):
|
class Implies(Prop):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
from typing import Callable
|
from typing import Callable, Generator
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
|
|
@ -24,6 +24,24 @@ USABLE_VAR_NAMES = [
|
||||||
'μ', 'ν', 'ξ', 'ο', 'π', 'ρ', 'σ', 'τ', 'υ', 'φ', 'χ', 'ψ', 'ω'
|
'μ', 'ν', 'ξ', 'ο', 'π', 'ρ', 'σ', 'τ', 'υ', 'φ', 'χ', 'ψ', 'ω'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def contains(haystack : Term, needle : Term) -> bool:
|
||||||
|
"""
|
||||||
|
Determine whether a given small term value is contained in a bigger
|
||||||
|
term.
|
||||||
|
|
||||||
|
:param haystack: The term to search through.
|
||||||
|
:type haystack: Term
|
||||||
|
:param needle: The term to find.
|
||||||
|
:type needle: Term
|
||||||
|
:return: Whether the needle was found in the haystack.
|
||||||
|
:rtype: bool
|
||||||
|
"""
|
||||||
|
for term in haystack.rec_iter():
|
||||||
|
if term == needle:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
def normalize(term : Term) -> Term:
|
def normalize(term : Term) -> Term:
|
||||||
"""
|
"""
|
||||||
Create a normalization function. This function simplifies functions as
|
Create a normalization function. This function simplifies functions as
|
||||||
|
|
@ -78,6 +96,21 @@ def std_norm_iter(term : Term) -> Term:
|
||||||
return term
|
return term
|
||||||
_known_norms.append(std_norm_iter)
|
_known_norms.append(std_norm_iter)
|
||||||
|
|
||||||
|
def replace(term : Term, old : Term, new : Term) -> Term:
|
||||||
|
"""
|
||||||
|
Find and replace occurrences of a sub-term in a given term.
|
||||||
|
|
||||||
|
:param term: The original term to update.
|
||||||
|
:type term: Term
|
||||||
|
:param old: The term to find and replace.
|
||||||
|
:type old: Term
|
||||||
|
:param new: The new term to replace the old one with.
|
||||||
|
:type new: Term
|
||||||
|
:return: The replaced term result.
|
||||||
|
:rtype: Term
|
||||||
|
"""
|
||||||
|
return traverse_bottom_up(f=lambda t : new if t == old else t, term=term)
|
||||||
|
|
||||||
def traverse(f : Callable[[Term], Term], term : Term) -> Term:
|
def traverse(f : Callable[[Term], Term], term : Term) -> Term:
|
||||||
"""
|
"""
|
||||||
Traverse through the tree back-and-forth, aiming to run the given
|
Traverse through the tree back-and-forth, aiming to run the given
|
||||||
|
|
@ -96,7 +129,7 @@ def traverse(f : Callable[[Term], Term], term : Term) -> Term:
|
||||||
a, b = Term(), term
|
a, b = Term(), term
|
||||||
|
|
||||||
while a != b:
|
while a != b:
|
||||||
a, b = b, traverse_bottom_up(f=f, term=traverse_top_down(f=f, term=term))
|
a, b = b, traverse_bottom_up(f=f, term=traverse_top_down(f=f, term=b))
|
||||||
|
|
||||||
return b
|
return b
|
||||||
|
|
||||||
|
|
@ -171,12 +204,6 @@ class Term:
|
||||||
Base class for all terms.
|
Base class for all terms.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __eq__(self, other) -> bool:
|
|
||||||
"""
|
|
||||||
Determine whether two terms are equal.
|
|
||||||
"""
|
|
||||||
return str(self) == str(other)
|
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
"""
|
"""
|
||||||
Create a representation of a term.
|
Create a representation of a term.
|
||||||
|
|
@ -185,6 +212,12 @@ class Term:
|
||||||
|
|
||||||
def normalize(self) -> Term:
|
def normalize(self) -> Term:
|
||||||
return normalize(term=self)
|
return normalize(term=self)
|
||||||
|
|
||||||
|
def replace(self, old : Term, new : Term) -> Term:
|
||||||
|
return replace(term=self, old=old, new=new)
|
||||||
|
|
||||||
|
def rec_iter(self) -> Generator[Term, None, None]:
|
||||||
|
yield self
|
||||||
|
|
||||||
def to_str(self, vars : dict[str, Var]) -> str:
|
def to_str(self, vars : dict[str, Var]) -> str:
|
||||||
return "<undefined>"
|
return "<undefined>"
|
||||||
|
|
@ -204,6 +237,11 @@ class App(Term):
|
||||||
Create a representation of a term.
|
Create a representation of a term.
|
||||||
"""
|
"""
|
||||||
return self.to_str(vars={})
|
return self.to_str(vars={})
|
||||||
|
|
||||||
|
def rec_iter(self) -> Generator[Term, None, None]:
|
||||||
|
yield self
|
||||||
|
yield from self.f.rec_iter()
|
||||||
|
yield from self.x.rec_iter()
|
||||||
|
|
||||||
def to_str(self, vars: dict[str, Var]) -> str:
|
def to_str(self, vars: dict[str, Var]) -> str:
|
||||||
f_str = self.f.to_str(vars=vars)
|
f_str = self.f.to_str(vars=vars)
|
||||||
|
|
@ -246,6 +284,18 @@ class Lambda(Term):
|
||||||
out : Term
|
out : Term
|
||||||
var : Var
|
var : Var
|
||||||
|
|
||||||
|
def __eq__(self, value: object) -> bool:
|
||||||
|
if not isinstance(value, Lambda):
|
||||||
|
return False
|
||||||
|
|
||||||
|
for c in USABLE_VAR_NAMES:
|
||||||
|
if not contains(self.out, Const(c)):
|
||||||
|
return self.substitute(Const(c)) == value.substitute((Const(c)))
|
||||||
|
else:
|
||||||
|
raise ValueError(
|
||||||
|
"Ran out of usable variables for comparing lambda structures"
|
||||||
|
)
|
||||||
|
|
||||||
def __init__(self, f : Callable[[Var], Term]) -> None:
|
def __init__(self, f : Callable[[Var], Term]) -> None:
|
||||||
self.var = Var()
|
self.var = Var()
|
||||||
self.out = f(self.var)
|
self.out = f(self.var)
|
||||||
|
|
@ -256,6 +306,10 @@ class Lambda(Term):
|
||||||
"""
|
"""
|
||||||
return self.to_str(vars={})
|
return self.to_str(vars={})
|
||||||
|
|
||||||
|
def rec_iter(self) -> Generator[Term, None, None]:
|
||||||
|
yield self
|
||||||
|
yield from self.out.rec_iter()
|
||||||
|
|
||||||
def replace_content(self, term : Term) -> Lambda:
|
def replace_content(self, term : Term) -> Lambda:
|
||||||
"""
|
"""
|
||||||
Replace the content of the lambda function with the given term.
|
Replace the content of the lambda function with the given term.
|
||||||
|
|
@ -427,3 +481,15 @@ if __name__ == "__main__":
|
||||||
g = L1(lambda b : A2(b, bool_f, bool_t))
|
g = L1(lambda b : A2(b, bool_f, bool_t))
|
||||||
print(g)
|
print(g)
|
||||||
print(g.normalize())
|
print(g.normalize())
|
||||||
|
|
||||||
|
print("\nFIND & REPLACE")
|
||||||
|
print(30 * "=")
|
||||||
|
|
||||||
|
h = A3(Const("f"), Const("x"), Const("y"), Const("z"))
|
||||||
|
i = A3(Const("f"), Const("x"), Const("b"), Const("z")).replace(
|
||||||
|
old=Const("b"), new=Const("y"),
|
||||||
|
)
|
||||||
|
|
||||||
|
print(h)
|
||||||
|
print(i)
|
||||||
|
assert h == i
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
from checker import lib, proof, props
|
from checker import lib, proof, props
|
||||||
from checker.terms import App, Const
|
from checker.terms import A2, App, Const
|
||||||
|
from checker.lib.basic import kernel_from_int
|
||||||
|
|
||||||
# Prove : true == not false
|
# Prove : true == not false
|
||||||
p = proof.reflexivity(
|
p = proof.reflexivity(
|
||||||
|
|
@ -18,3 +19,11 @@ p = proof.reflexivity(
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
p.check()
|
p.check()
|
||||||
|
|
||||||
|
# Prove : 4 + 1 == 2 + 3
|
||||||
|
p = proof.reflexivity(
|
||||||
|
props.Eq(
|
||||||
|
x=A2(Const("Nat.add"), kernel_from_int(4), kernel_from_int(1)),
|
||||||
|
y=A2(Const("Nat.add"), kernel_from_int(2), kernel_from_int(3)),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue