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` ## La classe `Lambda_terme`
```python ```python
T1 = Lambda_terme(0, "x") T1 = Lambda_terme("x")
T2 = Lambda_terme(1, "x", T1) T2 = Lambda_terme("(x x)")
T3 = Lambda_terme(2, T2, T1) T3 = Lambda_terme("!x.x")
T4 = Lambda_terme.cree('!x.(x x)') T4 = Lambda_terme('!x.(x x)')
T5 = Lambda_terme('(!x.(x y) z)')
``` ```
```python ```python
@ -39,55 +40,68 @@ print(T1)
print(T2) print(T2)
print(T3) print(T3)
print(T4) print(T4)
print(T5)
``` ```
```python ```python
tuple(t.est_variable() for t in (T1, T2, T3, T4)) termes = (T1, T2, T3, T4, T5)
``` ```
```python ```python
tuple(t.est_abstraction() for t in (T1, T2, T3, T4)) tuple(t.est_variable() for t in termes)
``` ```
```python ```python
tuple(t.est_application() for t in (T1, T2, T3, T4)) tuple(t.est_abstraction() for t in termes)
``` ```
```python ```python
tuple(t.est_redex() for t in (T1, T2, T3, T4)) tuple(t.est_application() for t in termes)
``` ```
```python ```python
tuple(t.est_forme_normale() for t in (T1, T2, T3, T4)) tuple(t.est_redex() for t in termes)
``` ```
```python ```python
tuple(t.variables_libres() for t in (T1, T2, T3, T4)) tuple(t.est_forme_normale() for t in termes)
``` ```
```python ```python
print(T1, '-->', T1.subs('y', Lambda_terme.cree('(y x)'))) tuple(t.variables_libres() for t in termes)
print(T1, '-->', T1.subs('x', Lambda_terme.cree('(y x)')))
``` ```
```python ```python
T5 = Lambda_terme.cree('!x.y') print(T1, '-->', T1.subs('y', Lambda_terme('(y x)')))
print(T5, '-->', T5.subs('x', Lambda_terme.cree('(y z)'))) print(T1, '-->', T1.subs('x', Lambda_terme('(y x)')))
print(T5, '-->', T5.subs('y', Lambda_terme.cree('(t z)')))
print(T5, '-->', T5.subs('y', Lambda_terme.cree('(x z)')))
``` ```
```python ```python
print(T3, '-->', T3.subs('y', Lambda_terme.cree('(y x)'))) T5 = Lambda_terme('!x.y')
print(T3, '-->', T3.subs('x', Lambda_terme.cree('(y x)'))) 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 ```python
print(T3, '-->', T3.subs('y', Lambda_terme('(y x)')))
print(T3, '-->', T3.subs('x', Lambda_terme('(y x)')))
``` ```
```python ```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 ```python
@ -117,119 +131,100 @@ print(est_red)
``` ```
```python ```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) print(res, est_red)
``` ```
```python ```python
def calcul(lambda_terme, nb_etapes_max=100, verbose=False): OMEGA.forme_normale(nb_etapes_max=10, verbose=True)
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)
``` ```
## Entiers, successeurs, addition, multiplication et exponentiation ## Entiers, successeurs, addition, multiplication et exponentiation
```python ```python
ZERO = Lambda_terme.cree('!f.!x.x') ZERO = Lambda_terme('!f.!x.x')
``` ```
```python ```python
UN = Lambda_terme.cree('!f.!x.(f x)') UN = Lambda_terme('!f.!x.(f x)')
``` ```
```python ```python
DEUX = Lambda_terme.cree('!f.!x.(f (f x))') DEUX = Lambda_terme('!f.!x.(f (f x))')
``` ```
```python ```python
SUC = Lambda_terme.cree('!n.!f.!x.(f ((n f) x))') SUC = Lambda_terme('!n.!f.!x.(f ((n f) x))')
``` ```
```python ```python
TROIS = calcul(SUC.applique(DEUX), verbose=True) TROIS = SUC.applique(DEUX).forme_normale(verbose=True)
``` ```
```python ```python
calcul(TROIS.applique(SUC).applique(ZERO), verbose=True) TROIS.applique(SUC).applique(ZERO).forme_normale(verbose=True)
``` ```
```python ```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 ```python
QUATRE = calcul(ADD.applique(UN).applique(TROIS), verbose=True) QUATRE = ADD.applique(UN).applique(TROIS).forme_normale(verbose=True)
``` ```
```python ```python
CINQ = calcul(ADD.applique(TROIS).applique(DEUX), verbose=True) CINQ = ADD.applique(TROIS).applique(DEUX).forme_normale(verbose=True)
``` ```
```python ```python
SEPT = calcul(ADD.applique(QUATRE).applique(TROIS), verbose=True) SEPT = ADD.applique(QUATRE).applique(TROIS).forme_normale(verbose=True)
``` ```
```python ```python
MUL = Lambda_terme.cree('!n.!m.!f.(n (m f))') MUL = Lambda_terme('!n.!m.!f.(n (m f))')
``` ```
```python ```python
SIX = calcul(MUL.applique(DEUX).applique(TROIS), verbose=True) SIX = MUL.applique(DEUX).applique(TROIS).forme_normale(verbose=True)
``` ```
```python ```python
EXP = Lambda_terme.cree('!n.!m.(m n)') EXP = Lambda_terme('!n.!m.(m n)')
``` ```
```python ```python
HUIT = calcul(EXP.applique(DEUX).applique(TROIS), verbose=True) HUIT = EXP.applique(DEUX).applique(TROIS).forme_normale(verbose=True)
``` ```
```python ```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 ## Booléens, opérateurs logiques et conditionnelles
```python ```python
VRAI = Lambda_terme.cree('!x.!y.x') VRAI = Lambda_terme('!x.!y.x')
``` ```
```python ```python
FAUX = Lambda_terme.cree('!x.!y.y') FAUX = Lambda_terme('!x.!y.y')
``` ```
```python ```python
COND = Lambda_terme.cree('!c.!a.!s.((c a) s)') COND = Lambda_terme('!c.!a.!s.((c a) s)')
``` ```
```python ```python
calcul(COND.applique(VRAI).applique(UN).applique(DEUX), verbose=True) COND.applique(VRAI).applique(UN).applique(DEUX).forme_normale(verbose=True)
``` ```
```python ```python
calcul(COND.applique(FAUX).applique(UN).applique(DEUX), verbose=True) COND.applique(FAUX).applique(UN).applique(DEUX).forme_normale(verbose=True)
``` ```
```python ```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 ```python
@ -237,55 +232,63 @@ print(ET)
``` ```
```python ```python
calcul(ET.applique(VRAI).applique(VRAI), verbose=True) ET.applique(VRAI).applique(VRAI).forme_normale(verbose=True)
``` ```
```python ```python
calcul(ET.applique(VRAI).applique(FAUX), verbose=True) ET.applique(VRAI).applique(FAUX).forme_normale(verbose=True)
``` ```
```python ```python
calcul(ET.applique(FAUX).applique(VRAI), verbose=True) ET.applique(FAUX).applique(VRAI).forme_normale(verbose=True)
``` ```
```python ```python
calcul(ET.applique(FAUX).applique(FAUX), verbose=True) ET.applique(FAUX).applique(FAUX).forme_normale(verbose=True)
``` ```
```python ```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 ```python
calcul(OU.applique(VRAI).applique(VRAI), verbose=True) print(OU)
``` ```
```python ```python
calcul(OU.applique(VRAI).applique(FAUX), verbose=True) OU.applique(VRAI).applique(VRAI).forme_normale(verbose=True)
``` ```
```python ```python
calcul(OU.applique(FAUX).applique(VRAI), verbose=True) OU.applique(VRAI).applique(FAUX).forme_normale(verbose=True)
``` ```
```python ```python
calcul(OU.applique(FAUX).applique(FAUX), verbose=True) OU.applique(FAUX).applique(VRAI).forme_normale(verbose=True)
``` ```
```python ```python
NON = COND.applique(Lambda_terme.cree('a')).applique(FAUX).applique(VRAI).abstrait('a') OU.applique(FAUX).applique(FAUX).forme_normale(verbose=True)
``` ```
```python ```python
calcul(NON.applique(VRAI), verbose=True) NON = COND.applique(Lambda_terme('a')).applique(FAUX).applique(VRAI).abstrait('a')
``` ```
```python ```python
calcul(NON.applique(FAUX), verbose=True) print(NON)
``` ```
```python ```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 ```python
@ -293,17 +296,17 @@ print(NUL)
``` ```
```python ```python
calcul(NUL.applique(ZERO), verbose=True) NUL.applique(ZERO).forme_normale(verbose=True)
``` ```
```python ```python
calcul(NUL.applique(TROIS), verbose=True) NUL.applique(TROIS).forme_normale(verbose=True)
``` ```
## Couples ## Couples
```python ```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 ```python
@ -311,11 +314,11 @@ print(CONS)
``` ```
```python ```python
UN_DEUX = calcul(CONS.applique(UN).applique(DEUX), verbose=True) UN_DEUX = CONS.applique(UN).applique(DEUX).forme_normale(verbose=True)
``` ```
```python ```python
CAR = Lambda_terme.cree('c').applique(VRAI).abstrait('c') CAR = Lambda_terme('!c.(c {:s})'.format(str(VRAI)))
``` ```
```python ```python
@ -323,120 +326,124 @@ print(CAR)
``` ```
```python ```python
calcul(CAR.applique(UN_DEUX), verbose=True) CAR.applique(UN_DEUX).forme_normale(verbose=True)
``` ```
```python ```python
CDR = Lambda_terme.cree('c').applique(FAUX).abstrait('c') CDR = Lambda_terme('!c.(c {:s})'.format(str(FAUX)))
``` ```
```python ```python
calcul(CDR.applique(UN_DEUX), verbose=True) print(CDR)
``` ```
```python ```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) print(M_PRED)
PRED = M_PRED.subs('CAR', CAR).subs('CONS', CONS).subs('CDR', CDR).subs('SUC', SUC).subs('ZERO', ZERO) PRED = M_PRED.subs('CAR', CAR).subs('CONS', CONS).subs('CDR', CDR).subs('SUC', SUC).subs('ZERO', ZERO)
print(PRED) print(PRED)
``` ```
```python ```python
calcul(PRED.applique(DEUX), verbose=True) PRED.applique(DEUX).forme_normale(verbose=True)
``` ```
```python ```python
calcul(PRED.applique(ZERO), verbose=True) PRED.applique(ZERO).forme_normale(verbose=True)
``` ```
```python ```python
M_SUB = Lambda_terme.cree('!n.!m.((m PRED) n)') M_SUB = Lambda_terme('!n.!m.((m PRED) n)')
print(M_SUB) print(M_SUB)
SUB = M_SUB.subs('PRED', PRED) SUB = M_SUB.subs('PRED', PRED)
print(SUB) print(SUB)
``` ```
```python ```python
calcul(SUB.applique(TROIS).applique(UN), verbose=True) SUB.applique(TROIS).applique(UN).forme_normale(verbose=True)
``` ```
```python ```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) print(M_INF)
INF = M_INF.subs('NUL', NUL).subs('SUB', SUB) INF = M_INF.subs('NUL', NUL).subs('SUB', SUB)
#lambda n: lambda m: est_nul(sub(m)(n))
``` ```
```python ```python
calcul(INF.applique(TROIS).applique(UN), verbose=True) print(INF.applique(TROIS).applique(UN).forme_normale())
``` ```
```python ```python
calcul(INF.applique(UN).applique(TROIS), verbose=True) print(INF.applique(UN).applique(TROIS).forme_normale())
``` ```
```python ```python
calcul(INF.applique(UN).applique(UN), verbose=True) print(INF.applique(UN).applique(UN).forme_normale())
``` ```
```python ```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) print(M_EGAL)
EGAL = M_EGAL.subs('ET', ET).subs('INF', INF) EGAL = M_EGAL.subs('ET', ET).subs('INF', INF)
print(EGAL) print(EGAL)
``` ```
```python ```python
print(calcul(EGAL.applique(UN).applique(UN))) print(EGAL.applique(UN).applique(UN).forme_normale())
``` ```
```python ```python
print(calcul(EGAL.applique(UN).applique(DEUX))) print(EGAL.applique(UN).applique(DEUX).forme_normale())
``` ```
## Itération ## Itération
```python ```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) 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) 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) print(FACTv1)
``` ```
```python ```python
print(calcul(FACTv1.applique(ZERO))) print(FACTv1.applique(ZERO).forme_normale())
``` ```
```python ```python
print(calcul(FACTv1.applique(UN))) print(FACTv1.applique(UN).forme_normale())
``` ```
```python ```python
print(calcul(FACTv1.applique(DEUX))) print(FACTv1.applique(DEUX).forme_normale())
``` ```
```python ```python
print(calcul(FACTv1.applique(DEUX), nb_etapes_max=200)) print(FACTv1.applique(DEUX).forme_normale(nb_etapes_max=200))
``` ```
```python ```python
print(calcul(FACTv1.applique(TROIS), nb_etapes_max=500)) print(FACTv1.applique(TROIS).forme_normale(nb_etapes_max=500))
``` ```
```python ```python
print(calcul(FACTv1.applique(QUATRE), nb_etapes_max=1700)) print(FACTv1.applique(QUATRE).forme_normale(nb_etapes_max=1700))
``` ```
## Et la récursivité ? ## Et la récursivité ?
```python ```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) 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) 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 ```python
BOTTOM = Lambda_terme.cree('!y.OMEGA').subs('OMEGA', OMEGA) BOTTOM = Lambda_terme('!y.OMEGA').subs('OMEGA', OMEGA)
print(BOTTOM) print(BOTTOM)
``` ```
@ -445,11 +452,11 @@ FACT0 = PHI_FACT.applique(BOTTOM)
``` ```
```python ```python
print(calcul(FACT0.applique(ZERO))) print(FACT0.applique(ZERO).forme_normale())
``` ```
```python ```python
calcul(FACT0.applique(UN), verbose=True) FACT0.applique(UN).forme_normale(verbose=True, nb_etapes_max=40)
``` ```
```python ```python
@ -457,15 +464,15 @@ FACT1 = PHI_FACT.applique(FACT0)
``` ```
```python ```python
print(calcul(FACT1.applique(ZERO))) print(FACT1.applique(ZERO).forme_normale())
``` ```
```python ```python
print(calcul(FACT1.applique(UN), nb_etapes_max=200)) print(FACT1.applique(UN).forme_normale(nb_etapes_max=200))
``` ```
```python ```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) print(FIX_CURRY)
``` ```
@ -474,31 +481,31 @@ FACTv2 = FIX_CURRY.applique(PHI_FACT)
``` ```
```python ```python
print(calcul(FACTv2.applique(ZERO))) print(FACTv2.applique(ZERO).forme_normale())
``` ```
```python ```python
print(calcul(FACTv2.applique(UN), nb_etapes_max=200)) print(FACTv2.applique(UN).forme_normale(nb_etapes_max=200))
``` ```
```python ```python
print(calcul(FACTv2.applique(DEUX), nb_etapes_max=700)) print(FACTv2.applique(DEUX).forme_normale(nb_etapes_max=700))
``` ```
```python ```python
print(calcul(FACTv2.applique(TROIS), nb_etapes_max=4000)) print(FACTv2.applique(TROIS).forme_normale(nb_etapes_max=4000))
``` ```
```python ```python
print(calcul(FACTv2.applique(QUATRE), nb_etapes_max=25000)) print(FACTv2.applique(QUATRE).forme_normale(nb_etapes_max=25000))
``` ```
```python ```python
PF = FIX_CURRY.applique(Lambda_terme.cree('M')) PF = FIX_CURRY.applique(Lambda_terme('M'))
``` ```
```python ```python
calcul(PF, verbose=True, nb_etapes_max=10) PF.forme_normale(verbose=True, nb_etapes_max=10)
``` ```
```python ```python

View File

@ -11,6 +11,7 @@ __doc__ = """
Module pour travailler avec le λ-calcul Module pour travailler avec le λ-calcul
""".format(__author__, __date_creation__) """.format(__author__, __date_creation__)
from sly import Lexer, Parser from sly import Lexer, Parser
@ -45,19 +46,37 @@ class Lambda_lexer(Lexer):
lexer = Lambda_lexer() lexer = Lambda_lexer()
class Lambda_parser(Parser): class Lambda_parser(Parser):
''' Grammaire décrivant les λ-termes
term : VAR
| LAMBDA VAR POINT term
| LPAR term term RPAR
'''
tokens = Lambda_lexer.tokens 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') @_('VAR')
def term(self, p): def term(self, p):
return Lambda_terme(0, p[0]) return (0, p[0])
@_('LAMBDA VAR POINT term') @_('LAMBDA VAR POINT term')
def term(self, p): def term(self, p):
return Lambda_terme(1, p[1], p.term) return (1, p[1], p.term)
@_('LPAR term term RPAR') @_('LPAR term term RPAR')
def term(self, p): def term(self, p):
return Lambda_terme(2, p.term0, p.term1) return (2, p.term0, p.term1)
parser = Lambda_parser() parser = Lambda_parser()
@ -80,28 +99,105 @@ class Lambda_termeError(Exception):
self.message = msg self.message = msg
class Lambda_terme(): class Lambda_terme():
def __init__(self, categorie, *args): '''
if categorie not in (0, 1, 2): Création de λ-terme
raise Lambda_termeError('categorie non valide')
if categorie == 0: >>> T1 = Lambda_terme('z')
if len(args) != 1 or not isinstance(args[0], str): >>> print(T1)
raise Lambda_termeError('mauvaise construction pour une variable') z
elif categorie == 1: >>> T2 = Lambda_terme('!x.(y x)')
if (len(args) != 2 or >>> print(T2)
not isinstance(args[0], str) or λx.(y x)
not isinstance(args[1], Lambda_terme)): >>> T3 = Lambda_terme('(!x.(y x) z)')
raise Lambda_termeError('mauvaise construction pour une abstraction') >>> 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: else:
if (len(args) != 2 or categorie = args[0]
not isinstance(args[0], Lambda_terme) or if categorie not in (0, 1, 2):
not isinstance(args[1], Lambda_terme)): raise Lambda_termeError('categorie non valide')
raise Lambda_termeError('mauvaise construction pour une application') if categorie == 0:
self._content = (categorie,) + tuple(args) 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 (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 (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 = (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 @staticmethod
def cree(descr): def _cree(descr):
return parser.parse(lexer.tokenize(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): def est_variable(self):
return self._content[0] == 0 return self._content[0] == 0
@ -111,6 +207,15 @@ class Lambda_terme():
def est_application(self): def est_application(self):
return self._content[0] == 2 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): def applique(self, terme):
if not isinstance(terme, Lambda_terme): if not isinstance(terme, Lambda_terme):
raise Lambda_termeError('Application impossible') raise Lambda_termeError('Application impossible')
@ -203,17 +308,27 @@ class Lambda_terme():
def reduit(self): def reduit(self):
return self._reduit() return self._reduit()
def __str__(self): def forme_normale(self, nb_etapes_max=100, verbose=False):
if self.est_variable(): lambda_terme = self
return self._content[1] etape = 0
elif self.est_abstraction(): forme_normale_atteinte = False
return 'λ{:s}.{:s}'.format(self._content[1], str(self._content[2])) 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: 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__': if __name__ == '__main__':
import doctest import doctest
doctest.testmod(optionflags=doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS, verbose=False) doctest.testmod(optionflags=doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS, verbose=True)