refonte de la construction des lambda-termes

This commit is contained in:
Éric Wegrzynowski 2021-01-31 12:00:32 +01:00
parent b4b9bb8b22
commit 7c957049db
3 changed files with 857 additions and 1142 deletions

File diff suppressed because it is too large Load Diff

View File

@ -28,10 +28,11 @@ Voici la grammaire du langage décrivant les $\lambda$-termes
## La classe `Lambda_terme`
```python
T1 = Lambda_terme(0, "x")
T2 = Lambda_terme(1, "x", T1)
T3 = Lambda_terme(2, T2, T1)
T4 = Lambda_terme.cree('!x.(x x)')
T1 = Lambda_terme("x")
T2 = Lambda_terme("(x x)")
T3 = Lambda_terme("!x.x")
T4 = Lambda_terme('!x.(x x)')
T5 = Lambda_terme('(!x.(x y) z)')
```
```python
@ -39,55 +40,68 @@ print(T1)
print(T2)
print(T3)
print(T4)
print(T5)
```
```python
tuple(t.est_variable() for t in (T1, T2, T3, T4))
termes = (T1, T2, T3, T4, T5)
```
```python
tuple(t.est_abstraction() for t in (T1, T2, T3, T4))
tuple(t.est_variable() for t in termes)
```
```python
tuple(t.est_application() for t in (T1, T2, T3, T4))
tuple(t.est_abstraction() for t in termes)
```
```python
tuple(t.est_redex() for t in (T1, T2, T3, T4))
tuple(t.est_application() for t in termes)
```
```python
tuple(t.est_forme_normale() for t in (T1, T2, T3, T4))
tuple(t.est_redex() for t in termes)
```
```python
tuple(t.variables_libres() for t in (T1, T2, T3, T4))
tuple(t.est_forme_normale() for t in termes)
```
```python
print(T1, '-->', T1.subs('y', Lambda_terme.cree('(y x)')))
print(T1, '-->', T1.subs('x', Lambda_terme.cree('(y x)')))
tuple(t.variables_libres() for t in termes)
```
```python
T5 = Lambda_terme.cree('!x.y')
print(T5, '-->', T5.subs('x', Lambda_terme.cree('(y z)')))
print(T5, '-->', T5.subs('y', Lambda_terme.cree('(t z)')))
print(T5, '-->', T5.subs('y', Lambda_terme.cree('(x z)')))
print(T1, '-->', T1.subs('y', Lambda_terme('(y x)')))
print(T1, '-->', T1.subs('x', Lambda_terme('(y x)')))
```
```python
print(T3, '-->', T3.subs('y', Lambda_terme.cree('(y x)')))
print(T3, '-->', T3.subs('x', Lambda_terme.cree('(y x)')))
T5 = Lambda_terme('!x.y')
print(T5, '-->', T5.subs('x', Lambda_terme('(y z)')))
print(T5, '-->', T5.subs('y', Lambda_terme('(t z)')))
print(T5, '-->', T5.subs('y', Lambda_terme('(x z)')))
```
```python
print(T3, '-->', T3.subs('y', Lambda_terme('(y x)')))
print(T3, '-->', T3.subs('x', Lambda_terme('(y x)')))
```
```python
OMEGA = Lambda_terme.cree('(!x.(x x) !x.(x x))')
for t in termes:
for v in ('x', 'y'):
print(t.abstrait(v))
```
```python
for t1 in termes:
for t2 in termes:
print(t1.applique(t2))
```
```python
OMEGA = Lambda_terme('(!x.(x x) !x.(x x))')
```
```python
@ -117,119 +131,100 @@ print(est_red)
```
```python
res, est_red = Lambda_terme.cree('(!x.(eric x) vero)').reduit()
res, est_red = Lambda_terme('(!x.(eric x) vero)').reduit()
print(res, est_red)
```
```python
def calcul(lambda_terme, nb_etapes_max=100, verbose=False):
etape = 0
forme_normale_atteinte = False
if verbose: print(lambda_terme)
while not forme_normale_atteinte and etape < nb_etapes_max:
etape += 1
terme_reduit, est_reduit = lambda_terme.reduit()
if verbose: print('{:3d}: ---> {:s}'.format(etape, str(lambda_terme), str(terme_reduit)))
forme_normale_atteinte = not est_reduit
lambda_terme = terme_reduit
if forme_normale_atteinte:
if verbose: print('Forme normale calculée : {:s}'.format(str(terme_reduit)))
return terme_reduit
else:
if verbose: print('Pas de forme normale atteinte après {:d} étapes de réduction'.format(etape))
return None
```
```python
calcul(OMEGA, nb_etapes_max=10, verbose=True)
OMEGA.forme_normale(nb_etapes_max=10, verbose=True)
```
## Entiers, successeurs, addition, multiplication et exponentiation
```python
ZERO = Lambda_terme.cree('!f.!x.x')
ZERO = Lambda_terme('!f.!x.x')
```
```python
UN = Lambda_terme.cree('!f.!x.(f x)')
UN = Lambda_terme('!f.!x.(f x)')
```
```python
DEUX = Lambda_terme.cree('!f.!x.(f (f x))')
DEUX = Lambda_terme('!f.!x.(f (f x))')
```
```python
SUC = Lambda_terme.cree('!n.!f.!x.(f ((n f) x))')
SUC = Lambda_terme('!n.!f.!x.(f ((n f) x))')
```
```python
TROIS = calcul(SUC.applique(DEUX), verbose=True)
TROIS = SUC.applique(DEUX).forme_normale(verbose=True)
```
```python
calcul(TROIS.applique(SUC).applique(ZERO), verbose=True)
TROIS.applique(SUC).applique(ZERO).forme_normale(verbose=True)
```
```python
ADD = Lambda_terme.cree('!n.!m.!f.!x.((n f) ((m f) x))')
ADD = Lambda_terme('!n.!m.!f.!x.((n f) ((m f) x))')
```
```python
QUATRE = calcul(ADD.applique(UN).applique(TROIS), verbose=True)
QUATRE = ADD.applique(UN).applique(TROIS).forme_normale(verbose=True)
```
```python
CINQ = calcul(ADD.applique(TROIS).applique(DEUX), verbose=True)
CINQ = ADD.applique(TROIS).applique(DEUX).forme_normale(verbose=True)
```
```python
SEPT = calcul(ADD.applique(QUATRE).applique(TROIS), verbose=True)
SEPT = ADD.applique(QUATRE).applique(TROIS).forme_normale(verbose=True)
```
```python
MUL = Lambda_terme.cree('!n.!m.!f.(n (m f))')
MUL = Lambda_terme('!n.!m.!f.(n (m f))')
```
```python
SIX = calcul(MUL.applique(DEUX).applique(TROIS), verbose=True)
SIX = MUL.applique(DEUX).applique(TROIS).forme_normale(verbose=True)
```
```python
EXP = Lambda_terme.cree('!n.!m.(m n)')
EXP = Lambda_terme('!n.!m.(m n)')
```
```python
HUIT = calcul(EXP.applique(DEUX).applique(TROIS), verbose=True)
HUIT = EXP.applique(DEUX).applique(TROIS).forme_normale(verbose=True)
```
```python
NEUF = calcul(EXP.applique(TROIS).applique(DEUX), verbose=True)
NEUF = EXP.applique(TROIS).applique(DEUX).forme_normale(verbose=True)
```
## Booléens, opérateurs logiques et conditionnelles
```python
VRAI = Lambda_terme.cree('!x.!y.x')
VRAI = Lambda_terme('!x.!y.x')
```
```python
FAUX = Lambda_terme.cree('!x.!y.y')
FAUX = Lambda_terme('!x.!y.y')
```
```python
COND = Lambda_terme.cree('!c.!a.!s.((c a) s)')
COND = Lambda_terme('!c.!a.!s.((c a) s)')
```
```python
calcul(COND.applique(VRAI).applique(UN).applique(DEUX), verbose=True)
COND.applique(VRAI).applique(UN).applique(DEUX).forme_normale(verbose=True)
```
```python
calcul(COND.applique(FAUX).applique(UN).applique(DEUX), verbose=True)
COND.applique(FAUX).applique(UN).applique(DEUX).forme_normale(verbose=True)
```
```python
ET = COND.applique(Lambda_terme.cree('a')).applique(Lambda_terme.cree('b')).applique(FAUX).abstrait('b').abstrait('a')
ET = COND.applique(Lambda_terme('a')).applique(Lambda_terme('b')).applique(FAUX).abstrait('b').abstrait('a')
```
```python
@ -237,55 +232,63 @@ print(ET)
```
```python
calcul(ET.applique(VRAI).applique(VRAI), verbose=True)
ET.applique(VRAI).applique(VRAI).forme_normale(verbose=True)
```
```python
calcul(ET.applique(VRAI).applique(FAUX), verbose=True)
ET.applique(VRAI).applique(FAUX).forme_normale(verbose=True)
```
```python
calcul(ET.applique(FAUX).applique(VRAI), verbose=True)
ET.applique(FAUX).applique(VRAI).forme_normale(verbose=True)
```
```python
calcul(ET.applique(FAUX).applique(FAUX), verbose=True)
ET.applique(FAUX).applique(FAUX).forme_normale(verbose=True)
```
```python
OU = COND.applique(Lambda_terme.cree('a')).applique(VRAI).applique(Lambda_terme.cree('b')).abstrait('b').abstrait('a')
OU = COND.applique(Lambda_terme('a')).applique(VRAI).applique(Lambda_terme('b')).abstrait('b').abstrait('a')
```
```python
calcul(OU.applique(VRAI).applique(VRAI), verbose=True)
print(OU)
```
```python
calcul(OU.applique(VRAI).applique(FAUX), verbose=True)
OU.applique(VRAI).applique(VRAI).forme_normale(verbose=True)
```
```python
calcul(OU.applique(FAUX).applique(VRAI), verbose=True)
OU.applique(VRAI).applique(FAUX).forme_normale(verbose=True)
```
```python
calcul(OU.applique(FAUX).applique(FAUX), verbose=True)
OU.applique(FAUX).applique(VRAI).forme_normale(verbose=True)
```
```python
NON = COND.applique(Lambda_terme.cree('a')).applique(FAUX).applique(VRAI).abstrait('a')
OU.applique(FAUX).applique(FAUX).forme_normale(verbose=True)
```
```python
calcul(NON.applique(VRAI), verbose=True)
NON = COND.applique(Lambda_terme('a')).applique(FAUX).applique(VRAI).abstrait('a')
```
```python
calcul(NON.applique(FAUX), verbose=True)
print(NON)
```
```python
NUL = Lambda_terme.cree('!n.((n !x.{:s}) {:s})'.format(str(FAUX), str(VRAI)))
NON.applique(VRAI).forme_normale(verbose=True)
```
```python
NON.applique(FAUX).forme_normale(verbose=True)
```
```python
NUL = Lambda_terme('!n.((n !x.{:s}) {:s})'.format(str(FAUX), str(VRAI)))
```
```python
@ -293,17 +296,17 @@ print(NUL)
```
```python
calcul(NUL.applique(ZERO), verbose=True)
NUL.applique(ZERO).forme_normale(verbose=True)
```
```python
calcul(NUL.applique(TROIS), verbose=True)
NUL.applique(TROIS).forme_normale(verbose=True)
```
## Couples
```python
CONS = COND.applique(Lambda_terme.cree('s')).applique(Lambda_terme.cree('x')).applique(Lambda_terme.cree('y')).abstrait('s').abstrait('y').abstrait('x')
CONS = Lambda_terme('!x.!y.!s.((({:s} s) x) y)'.format(str(COND)))
```
```python
@ -311,11 +314,11 @@ print(CONS)
```
```python
UN_DEUX = calcul(CONS.applique(UN).applique(DEUX), verbose=True)
UN_DEUX = CONS.applique(UN).applique(DEUX).forme_normale(verbose=True)
```
```python
CAR = Lambda_terme.cree('c').applique(VRAI).abstrait('c')
CAR = Lambda_terme('!c.(c {:s})'.format(str(VRAI)))
```
```python
@ -323,120 +326,124 @@ print(CAR)
```
```python
calcul(CAR.applique(UN_DEUX), verbose=True)
CAR.applique(UN_DEUX).forme_normale(verbose=True)
```
```python
CDR = Lambda_terme.cree('c').applique(FAUX).abstrait('c')
CDR = Lambda_terme('!c.(c {:s})'.format(str(FAUX)))
```
```python
calcul(CDR.applique(UN_DEUX), verbose=True)
print(CDR)
```
```python
M_PRED = Lambda_terme.cree('!n.(CAR ((n !c.((CONS (CDR c)) (SUC (CDR c)))) ((CONS ZERO) ZERO)))')
CDR.applique(UN_DEUX).forme_normale(verbose=True)
```
```python
M_PRED = Lambda_terme('!n.(CAR ((n !c.((CONS (CDR c)) (SUC (CDR c)))) ((CONS ZERO) ZERO)))')
print(M_PRED)
PRED = M_PRED.subs('CAR', CAR).subs('CONS', CONS).subs('CDR', CDR).subs('SUC', SUC).subs('ZERO', ZERO)
print(PRED)
```
```python
calcul(PRED.applique(DEUX), verbose=True)
PRED.applique(DEUX).forme_normale(verbose=True)
```
```python
calcul(PRED.applique(ZERO), verbose=True)
PRED.applique(ZERO).forme_normale(verbose=True)
```
```python
M_SUB = Lambda_terme.cree('!n.!m.((m PRED) n)')
M_SUB = Lambda_terme('!n.!m.((m PRED) n)')
print(M_SUB)
SUB = M_SUB.subs('PRED', PRED)
print(SUB)
```
```python
calcul(SUB.applique(TROIS).applique(UN), verbose=True)
SUB.applique(TROIS).applique(UN).forme_normale(verbose=True)
```
```python
M_INF = Lambda_terme.cree('!n.!m.(NUL ((SUB m) n))')
M_INF = Lambda_terme('!n.!m.(NUL ((SUB n) m))')
print(M_INF)
INF = M_INF.subs('NUL', NUL).subs('SUB', SUB)
#lambda n: lambda m: est_nul(sub(m)(n))
```
```python
calcul(INF.applique(TROIS).applique(UN), verbose=True)
print(INF.applique(TROIS).applique(UN).forme_normale())
```
```python
calcul(INF.applique(UN).applique(TROIS), verbose=True)
print(INF.applique(UN).applique(TROIS).forme_normale())
```
```python
calcul(INF.applique(UN).applique(UN), verbose=True)
print(INF.applique(UN).applique(UN).forme_normale())
```
```python
M_EGAL = Lambda_terme.cree('!n.!m.((ET ((INF n) m)) ((INF m) n))')
M_EGAL = Lambda_terme('!n.!m.((ET ((INF n) m)) ((INF m) n))')
print(M_EGAL)
EGAL = M_EGAL.subs('ET', ET).subs('INF', INF)
print(EGAL)
```
```python
print(calcul(EGAL.applique(UN).applique(UN)))
print(EGAL.applique(UN).applique(UN).forme_normale())
```
```python
print(calcul(EGAL.applique(UN).applique(DEUX)))
print(EGAL.applique(UN).applique(DEUX).forme_normale())
```
## Itération
```python
M_FACTv1 = Lambda_terme.cree('!n.(CDR ((n !c.((CONS (SUC (CAR c))) ((MUL (SUC (CAR c))) (CDR c)))) ((CONS ZERO) UN)))')
M_FACTv1 = Lambda_terme('!n.(CDR ((n !c.((CONS (SUC (CAR c))) ((MUL (SUC (CAR c))) (CDR c)))) ((CONS ZERO) UN)))')
print(M_FACTv1)
FACTv1 = M_FACTv1.subs('CONS', CONS).subs('CAR', CAR).subs('CDR', CDR).subs('SUC', SUC).subs('MUL', MUL).subs('UN', UN).subs('ZERO', ZERO)
print(FACTv1)
```
```python
print(calcul(FACTv1.applique(ZERO)))
print(FACTv1.applique(ZERO).forme_normale())
```
```python
print(calcul(FACTv1.applique(UN)))
print(FACTv1.applique(UN).forme_normale())
```
```python
print(calcul(FACTv1.applique(DEUX)))
print(FACTv1.applique(DEUX).forme_normale())
```
```python
print(calcul(FACTv1.applique(DEUX), nb_etapes_max=200))
print(FACTv1.applique(DEUX).forme_normale(nb_etapes_max=200))
```
```python
print(calcul(FACTv1.applique(TROIS), nb_etapes_max=500))
print(FACTv1.applique(TROIS).forme_normale(nb_etapes_max=500))
```
```python
print(calcul(FACTv1.applique(QUATRE), nb_etapes_max=1700))
print(FACTv1.applique(QUATRE).forme_normale(nb_etapes_max=1700))
```
## Et la récursivité ?
```python
M_PHI_FACT = Lambda_terme.cree('!f.!n.(((COND ((EGAL n) ZERO)) UN) ((MUL n) (f (PRED n))))')
M_PHI_FACT = Lambda_terme('!f.!n.(((COND ((EGAL n) ZERO)) UN) ((MUL n) (f (PRED n))))')
print(M_PHI_FACT)
PHI_FACT = M_PHI_FACT.subs('COND', COND).subs('EGAL', EGAL).subs('ZERO', ZERO).subs('UN', UN).subs('MUL', MUL).subs('PRED', PRED)
print(PHI_FACT)
```
```python
BOTTOM = Lambda_terme.cree('!y.OMEGA').subs('OMEGA', OMEGA)
BOTTOM = Lambda_terme('!y.OMEGA').subs('OMEGA', OMEGA)
print(BOTTOM)
```
@ -445,11 +452,11 @@ FACT0 = PHI_FACT.applique(BOTTOM)
```
```python
print(calcul(FACT0.applique(ZERO)))
print(FACT0.applique(ZERO).forme_normale())
```
```python
calcul(FACT0.applique(UN), verbose=True)
FACT0.applique(UN).forme_normale(verbose=True, nb_etapes_max=40)
```
```python
@ -457,15 +464,15 @@ FACT1 = PHI_FACT.applique(FACT0)
```
```python
print(calcul(FACT1.applique(ZERO)))
print(FACT1.applique(ZERO).forme_normale())
```
```python
print(calcul(FACT1.applique(UN), nb_etapes_max=200))
print(FACT1.applique(UN).forme_normale(nb_etapes_max=200))
```
```python
FIX_CURRY = Lambda_terme.cree('!f.(!x.(f (x x)) !x.(f (x x)))')
FIX_CURRY = Lambda_terme('!f.(!x.(f (x x)) !x.(f (x x)))')
print(FIX_CURRY)
```
@ -474,31 +481,31 @@ FACTv2 = FIX_CURRY.applique(PHI_FACT)
```
```python
print(calcul(FACTv2.applique(ZERO)))
print(FACTv2.applique(ZERO).forme_normale())
```
```python
print(calcul(FACTv2.applique(UN), nb_etapes_max=200))
print(FACTv2.applique(UN).forme_normale(nb_etapes_max=200))
```
```python
print(calcul(FACTv2.applique(DEUX), nb_etapes_max=700))
print(FACTv2.applique(DEUX).forme_normale(nb_etapes_max=700))
```
```python
print(calcul(FACTv2.applique(TROIS), nb_etapes_max=4000))
print(FACTv2.applique(TROIS).forme_normale(nb_etapes_max=4000))
```
```python
print(calcul(FACTv2.applique(QUATRE), nb_etapes_max=25000))
print(FACTv2.applique(QUATRE).forme_normale(nb_etapes_max=25000))
```
```python
PF = FIX_CURRY.applique(Lambda_terme.cree('M'))
PF = FIX_CURRY.applique(Lambda_terme('M'))
```
```python
calcul(PF, verbose=True, nb_etapes_max=10)
PF.forme_normale(verbose=True, nb_etapes_max=10)
```
```python

View File

@ -11,6 +11,7 @@ __doc__ = """
Module pour travailler avec le λ-calcul
""".format(__author__, __date_creation__)
from sly import Lexer, Parser
@ -45,19 +46,37 @@ class Lambda_lexer(Lexer):
lexer = Lambda_lexer()
class Lambda_parser(Parser):
''' Grammaire décrivant les λ-termes
term : VAR
| LAMBDA VAR POINT term
| LPAR term term RPAR
'''
tokens = Lambda_lexer.tokens
# @_('VAR')
# def term(self, p):
# return Lambda_terme(0, p[0])
# @_('LAMBDA VAR POINT term')
# def term(self, p):
# return Lambda_terme(1, p[1], p.term)
# @_('LPAR term term RPAR')
# def term(self, p):
# return Lambda_terme(2, p.term0, p.term1)
@_('VAR')
def term(self, p):
return Lambda_terme(0, p[0])
return (0, p[0])
@_('LAMBDA VAR POINT term')
def term(self, p):
return Lambda_terme(1, p[1], p.term)
return (1, p[1], p.term)
@_('LPAR term term RPAR')
def term(self, p):
return Lambda_terme(2, p.term0, p.term1)
return (2, p.term0, p.term1)
parser = Lambda_parser()
@ -80,27 +99,104 @@ class Lambda_termeError(Exception):
self.message = msg
class Lambda_terme():
def __init__(self, categorie, *args):
'''
Création de λ-terme
>>> T1 = Lambda_terme('z')
>>> print(T1)
z
>>> T2 = Lambda_terme('!x.(y x)')
>>> print(T2)
λx.(y x)
>>> T3 = Lambda_terme('(!x.(y x) z)')
>>> print(T3)
(λx.(y x) z)
Quelques prédicats
>>> [(t.est_variable(), t.est_abstraction(), t.est_application()) for t in (T1, T2, T3)]
[(True, False, False), (False, True, False), (False, False, True)]
Abstraction d'un terme
>>> T4 = T3.abstrait('z')
>>> print(T4)
λz.(λx.(y x) z)
Application d'un terme sur un autre
>>> T5 = T4.applique(Lambda_terme('t'))
>>> print(T5)
(λz.(λx.(y x) z) t)
Autres prédicats
>>> [(t.est_redex(), t.est_forme_normale()) for t in (T1, T2, T3, T4, T5)]
[(False, True), (False, True), (True, False), (False, False), (True, False)]
Calcul de forme normale
>>> print(T5.forme_normale())
(y t)
>>> print(T5.forme_normale(verbose=True))
(λz.(λx.(y x) z) t)
1: ---> (λz.(λx.(y x) z) t)
2: ---> (λx.(y x) t)
3: ---> (y t)
Forme normale calculée : (y t)
(y t)
>>> OMEGA = Lambda_terme('(!x.(x x) !x.(x x))')
>>> print(OMEGA.forme_normale(verbose=True, nb_etapes_max=10))
(λx.(x x) λx.(x x))
1: ---> (λx.(x x) λx.(x x))
2: ---> (λx.(x x) λx.(x x))
3: ---> (λx.(x x) λx.(x x))
4: ---> (λx.(x x) λx.(x x))
5: ---> (λx.(x x) λx.(x x))
6: ---> (λx.(x x) λx.(x x))
7: ---> (λx.(x x) λx.(x x))
8: ---> (λx.(x x) λx.(x x))
9: ---> (λx.(x x) λx.(x x))
10: ---> (λx.(x x) λx.(x x))
Pas de forme normale atteinte après 10 étapes de réduction
None
'''
def __init__(self, *args):
nb_args = len(args)
if nb_args not in (1, 2, 3):
raise Lambda_termeError('Lambda_terme : Nbre arguments incorrect')
if nb_args == 1:
if not isinstance(args[0], str):
raise Lambda_termeError('Lambda_terme : type argument incorrect')
self._content = Lambda_terme._cree(parser.parse(lexer.tokenize(args[0])))
else:
categorie = args[0]
if categorie not in (0, 1, 2):
raise Lambda_termeError('categorie non valide')
if categorie == 0:
if len(args) != 1 or not isinstance(args[0], str):
if nb_args != 2 or not isinstance(args[1], str):
raise Lambda_termeError('mauvaise construction pour une variable')
self._content = tuple(args)
elif categorie == 1:
if (len(args) != 2 or
not isinstance(args[0], str) or
not isinstance(args[1], Lambda_terme)):
if (nb_args != 3 or
not isinstance(args[1], str) or
not (isinstance(args[2], tuple) or isinstance(args[2], Lambda_terme))):
raise Lambda_termeError('mauvaise construction pour une abstraction')
self._content = (1, args[1],
Lambda_terme(*args[2]) if isinstance(args[2], tuple) else args[2])
else:
if (len(args) != 2 or
not isinstance(args[0], Lambda_terme) or
not isinstance(args[1], Lambda_terme)):
if (nb_args != 3 or
not (isinstance(args[1], tuple) or isinstance(args[1], Lambda_terme)) or
not (isinstance(args[2], tuple) or isinstance(args[2], Lambda_terme))):
raise Lambda_termeError('mauvaise construction pour une application')
self._content = (categorie,) + tuple(args)
self._content = (2,
Lambda_terme(*args[1]) if isinstance(args[1], tuple) else args[1],
Lambda_terme(*args[2]) if isinstance(args[2], tuple) else args[2])
@staticmethod
def cree(descr):
return parser.parse(lexer.tokenize(descr))
def _cree(descr):
if descr[0] == 0:
return descr
elif descr[0] == 1:
return (1, descr[1], Lambda_terme(*descr[2]))
else:
return (2, Lambda_terme(*descr[1]), Lambda_terme(*descr[2]))
def est_variable(self):
return self._content[0] == 0
@ -111,6 +207,15 @@ class Lambda_terme():
def est_application(self):
return self._content[0] == 2
def __str__(self):
if self.est_variable():
return self._content[1]
elif self.est_abstraction():
return 'λ{:s}.{:s}'.format(self._content[1], str(self._content[2]))
else:
return '({:s} {:s})'.format(str(self._content[1]), str(self._content[2]))
def applique(self, terme):
if not isinstance(terme, Lambda_terme):
raise Lambda_termeError('Application impossible')
@ -203,17 +308,27 @@ class Lambda_terme():
def reduit(self):
return self._reduit()
def __str__(self):
if self.est_variable():
return self._content[1]
elif self.est_abstraction():
return 'λ{:s}.{:s}'.format(self._content[1], str(self._content[2]))
def forme_normale(self, nb_etapes_max=100, verbose=False):
lambda_terme = self
etape = 0
forme_normale_atteinte = False
if verbose: print(lambda_terme)
while not forme_normale_atteinte and etape < nb_etapes_max:
etape += 1
terme_reduit, est_reduit = lambda_terme.reduit()
if verbose: print('{:3d}: ---> {:s}'.format(etape, str(lambda_terme), str(terme_reduit)))
forme_normale_atteinte = not est_reduit
lambda_terme = terme_reduit
if forme_normale_atteinte:
if verbose: print('Forme normale calculée : {:s}'.format(str(terme_reduit)))
return terme_reduit
else:
return '({:s} {:s})'.format(str(self._content[1]), str(self._content[2]))
if verbose: print('Pas de forme normale atteinte après {:d} étapes de réduction'.format(etape))
return None
if __name__ == '__main__':
import doctest
doctest.testmod(optionflags=doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS, verbose=False)
doctest.testmod(optionflags=doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS, verbose=True)