refonte de la construction des lambda-termes
This commit is contained in:
parent
b4b9bb8b22
commit
7c957049db
1581
lambda_calcul.ipynb
1581
lambda_calcul.ipynb
File diff suppressed because it is too large
Load Diff
241
lambda_calcul.md
241
lambda_calcul.md
@ -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
|
||||
|
177
lambda_calcul.py
177
lambda_calcul.py
@ -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,28 +99,105 @@ class Lambda_termeError(Exception):
|
||||
self.message = msg
|
||||
|
||||
class Lambda_terme():
|
||||
def __init__(self, categorie, *args):
|
||||
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):
|
||||
raise Lambda_termeError('mauvaise construction pour une variable')
|
||||
elif categorie == 1:
|
||||
if (len(args) != 2 or
|
||||
not isinstance(args[0], str) or
|
||||
not isinstance(args[1], Lambda_terme)):
|
||||
raise Lambda_termeError('mauvaise construction pour une abstraction')
|
||||
'''
|
||||
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:
|
||||
if (len(args) != 2 or
|
||||
not isinstance(args[0], Lambda_terme) or
|
||||
not isinstance(args[1], Lambda_terme)):
|
||||
raise Lambda_termeError('mauvaise construction pour une application')
|
||||
self._content = (categorie,) + tuple(args)
|
||||
|
||||
categorie = args[0]
|
||||
if categorie not in (0, 1, 2):
|
||||
raise Lambda_termeError('categorie non valide')
|
||||
if categorie == 0:
|
||||
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
|
||||
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)
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user