Lambda_Calcul/lambda_calcul.md

820 lines
14 KiB
Markdown
Raw Normal View History

2021-01-29 17:14:38 +01:00
---
jupyter:
jupytext:
formats: ipynb,md
text_representation:
extension: .md
format_name: markdown
format_version: '1.2'
jupytext_version: 1.6.0
kernelspec:
display_name: Python 3
language: python
name: python3
---
2021-01-29 17:17:08 +01:00
# $\lambda$-calcul
2021-01-29 17:14:38 +01:00
```python
from lambda_calcul import Lambda_terme
2021-01-29 17:14:38 +01:00
```
Voici la grammaire du langage décrivant les $\lambda$-termes
term ::= VAR | LAMBDA VAR POINT term | LPAR term term RPAR
## La classe `Lambda_terme`
```python
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)')
2021-01-29 17:14:38 +01:00
```
```python
print(T1)
print(T2)
print(T3)
print(T4)
print(T5)
2021-01-29 17:14:38 +01:00
```
```python
termes = (T1, T2, T3, T4, T5)
2021-01-29 17:14:38 +01:00
```
```python
tuple(t.est_variable() for t in termes)
2021-01-29 17:14:38 +01:00
```
```python
tuple(t.est_abstraction() for t in termes)
2021-01-29 17:14:38 +01:00
```
```python
tuple(t.est_application() for t in termes)
2021-01-29 17:14:38 +01:00
```
```python
tuple(t.est_redex() for t in termes)
2021-01-29 17:14:38 +01:00
```
```python
tuple(t.est_forme_normale() for t in termes)
2021-01-29 17:14:38 +01:00
```
```python
tuple(t.variables_libres() for t in termes)
2021-01-29 17:14:38 +01:00
```
```python
print(T1, '-->', T1.subs('y', Lambda_terme('(y x)')))
print(T1, '-->', T1.subs('x', Lambda_terme('(y x)')))
2021-01-29 17:14:38 +01:00
```
```python
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)')))
2021-01-29 17:14:38 +01:00
```
```python
print(T3, '-->', T3.subs('y', Lambda_terme('(y x)')))
print(T3, '-->', T3.subs('x', Lambda_terme('(y x)')))
```
2021-01-29 17:14:38 +01:00
```python
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))
2021-01-29 17:14:38 +01:00
```
```python
OMEGA = Lambda_terme('(!x.(x x) !x.(x x))')
2021-01-29 17:14:38 +01:00
```
```python
print(OMEGA)
```
```python
OMEGA.est_redex()
```
```python
OMEGA.est_forme_normale()
```
```python
OMEGA.variables_libres()
```
```python
```
```python
res, est_red = OMEGA.reduit()
print(res)
print(est_red)
```
```python
res, est_red = Lambda_terme('(!x.(eric x) vero)').reduit()
2021-01-29 17:14:38 +01:00
print(res, est_red)
```
```python
OMEGA.forme_normale(nb_etapes_max=10, verbose=True)
2021-01-29 17:14:38 +01:00
```
## Entiers, successeurs, addition, multiplication et exponentiation
```python
ZERO = Lambda_terme('!f.!x.x')
2021-01-29 17:14:38 +01:00
```
```python
UN = Lambda_terme('!f.!x.(f x)')
2021-01-29 17:14:38 +01:00
```
```python
DEUX = Lambda_terme('!f.!x.(f (f x))')
2021-01-29 17:14:38 +01:00
```
```python
SUC = Lambda_terme('!n.!f.!x.(f ((n f) x))')
2021-01-29 17:14:38 +01:00
```
```python
TROIS = SUC.applique(DEUX).forme_normale(verbose=True)
2021-01-29 17:14:38 +01:00
```
```python
TROIS.applique(SUC).applique(ZERO).forme_normale(verbose=True)
2021-01-29 17:14:38 +01:00
```
```python
ADD = Lambda_terme('!n.!m.!f.!x.((n f) ((m f) x))')
2021-01-29 17:14:38 +01:00
```
```python
QUATRE = ADD.applique(UN).applique(TROIS).forme_normale(verbose=True)
2021-01-29 17:14:38 +01:00
```
```python
CINQ = ADD.applique(TROIS).applique(DEUX).forme_normale(verbose=True)
2021-01-29 17:14:38 +01:00
```
```python
SEPT = ADD.applique(QUATRE).applique(TROIS).forme_normale(verbose=True)
2021-01-29 17:14:38 +01:00
```
```python
MUL = Lambda_terme('!n.!m.!f.(n (m f))')
2021-01-29 17:14:38 +01:00
```
```python
SIX = MUL.applique(DEUX).applique(TROIS).forme_normale(verbose=True)
2021-01-29 17:14:38 +01:00
```
```python
EXP = Lambda_terme('!n.!m.(m n)')
2021-01-29 17:14:38 +01:00
```
```python
HUIT = EXP.applique(DEUX).applique(TROIS).forme_normale(verbose=True)
2021-01-29 17:14:38 +01:00
```
```python
NEUF = EXP.applique(TROIS).applique(DEUX).forme_normale(verbose=True)
2021-01-29 17:14:38 +01:00
```
## Booléens, opérateurs logiques et conditionnelles
```python
VRAI = Lambda_terme('!x.!y.x')
2021-01-29 17:14:38 +01:00
```
```python
FAUX = Lambda_terme('!x.!y.y')
2021-01-29 17:14:38 +01:00
```
```python
COND = Lambda_terme('!c.!a.!s.((c a) s)')
2021-01-29 17:14:38 +01:00
```
```python
COND.applique(VRAI).applique(UN).applique(DEUX).forme_normale(verbose=True)
2021-01-29 17:14:38 +01:00
```
```python
COND.applique(FAUX).applique(UN).applique(DEUX).forme_normale(verbose=True)
2021-01-29 17:14:38 +01:00
```
```python
ET = COND.applique(Lambda_terme('a')).applique(Lambda_terme('b')).applique(FAUX).abstrait('b').abstrait('a')
2021-01-29 17:14:38 +01:00
```
```python
print(ET)
```
```python
ET.applique(VRAI).applique(VRAI).forme_normale(verbose=True)
2021-01-29 17:14:38 +01:00
```
```python
ET.applique(VRAI).applique(FAUX).forme_normale(verbose=True)
2021-01-29 17:14:38 +01:00
```
```python
ET.applique(FAUX).applique(VRAI).forme_normale(verbose=True)
2021-01-29 17:14:38 +01:00
```
```python
ET.applique(FAUX).applique(FAUX).forme_normale(verbose=True)
2021-01-29 17:14:38 +01:00
```
```python
OU = COND.applique(Lambda_terme('a')).applique(VRAI).applique(Lambda_terme('b')).abstrait('b').abstrait('a')
2021-01-29 17:14:38 +01:00
```
```python
print(OU)
2021-01-29 17:14:38 +01:00
```
```python
OU.applique(VRAI).applique(VRAI).forme_normale(verbose=True)
2021-01-29 17:14:38 +01:00
```
```python
OU.applique(VRAI).applique(FAUX).forme_normale(verbose=True)
2021-01-29 17:14:38 +01:00
```
```python
OU.applique(FAUX).applique(VRAI).forme_normale(verbose=True)
2021-01-29 17:14:38 +01:00
```
```python
OU.applique(FAUX).applique(FAUX).forme_normale(verbose=True)
2021-01-29 17:14:38 +01:00
```
```python
NON = COND.applique(Lambda_terme('a')).applique(FAUX).applique(VRAI).abstrait('a')
2021-01-29 17:14:38 +01:00
```
```python
print(NON)
2021-01-29 17:14:38 +01:00
```
```python
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)))
2021-01-29 17:14:38 +01:00
```
```python
print(NUL)
```
```python
NUL.applique(ZERO).forme_normale(verbose=True)
2021-01-29 17:14:38 +01:00
```
```python
NUL.applique(TROIS).forme_normale(verbose=True)
2021-01-29 17:14:38 +01:00
```
## Couples
```python
CONS = Lambda_terme('!x.!y.!s.((({:s} s) x) y)'.format(str(COND)))
2021-01-29 17:14:38 +01:00
```
```python
print(CONS)
```
```python
UN_DEUX = CONS.applique(UN).applique(DEUX).forme_normale(verbose=True)
2021-01-29 17:14:38 +01:00
```
```python
CAR = Lambda_terme('!c.(c {:s})'.format(str(VRAI)))
2021-01-29 17:14:38 +01:00
```
```python
print(CAR)
```
```python
CAR.applique(UN_DEUX).forme_normale(verbose=True)
```
```python
CDR = Lambda_terme('!c.(c {:s})'.format(str(FAUX)))
2021-01-29 17:14:38 +01:00
```
```python
print(CDR)
2021-01-29 17:14:38 +01:00
```
```python
CDR.applique(UN_DEUX).forme_normale(verbose=True)
2021-01-29 17:14:38 +01:00
```
```python
M_PRED = Lambda_terme('!n.(CAR ((n !c.((CONS (CDR c)) (SUC (CDR c)))) ((CONS ZERO) ZERO)))')
2021-01-29 17:14:38 +01:00
print(M_PRED)
PRED = M_PRED.subs('CAR', CAR).subs('CONS', CONS).subs('CDR', CDR).subs('SUC', SUC).subs('ZERO', ZERO)
print(PRED)
```
```python
PRED.applique(DEUX).forme_normale(verbose=True)
2021-01-29 17:14:38 +01:00
```
```python
PRED.applique(ZERO).forme_normale(verbose=True)
2021-01-29 17:14:38 +01:00
```
```python
M_SUB = Lambda_terme('!n.!m.((m PRED) n)')
2021-01-29 17:14:38 +01:00
print(M_SUB)
SUB = M_SUB.subs('PRED', PRED)
print(SUB)
```
```python
SUB.applique(TROIS).applique(UN).forme_normale(verbose=True)
2021-01-29 17:14:38 +01:00
```
```python
M_INF = Lambda_terme('!n.!m.(NUL ((SUB n) m))')
2021-01-29 17:14:38 +01:00
print(M_INF)
INF = M_INF.subs('NUL', NUL).subs('SUB', SUB)
```
```python
print(INF.applique(TROIS).applique(UN).forme_normale())
2021-01-29 17:14:38 +01:00
```
```python
print(INF.applique(UN).applique(TROIS).forme_normale())
2021-01-29 17:14:38 +01:00
```
```python
print(INF.applique(UN).applique(UN).forme_normale())
2021-01-29 17:14:38 +01:00
```
```python
M_EGAL = Lambda_terme('!n.!m.((ET ((INF n) m)) ((INF m) n))')
2021-01-29 17:14:38 +01:00
print(M_EGAL)
EGAL = M_EGAL.subs('ET', ET).subs('INF', INF)
print(EGAL)
```
```python
print(EGAL.applique(UN).applique(UN).forme_normale())
2021-01-29 17:14:38 +01:00
```
```python
print(EGAL.applique(UN).applique(DEUX).forme_normale())
2021-01-29 17:14:38 +01:00
```
## Itération
```python
M_FACTv1 = Lambda_terme('!n.(CDR ((n !c.((CONS (SUC (CAR c))) ((MUL (SUC (CAR c))) (CDR c)))) ((CONS ZERO) UN)))')
2021-01-29 17:14:38 +01:00
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(FACTv1.applique(ZERO).forme_normale())
2021-01-29 17:14:38 +01:00
```
```python
print(FACTv1.applique(UN).forme_normale())
2021-01-29 17:14:38 +01:00
```
```python
print(FACTv1.applique(DEUX).forme_normale())
2021-01-29 17:14:38 +01:00
```
```python
print(FACTv1.applique(DEUX).forme_normale(nb_etapes_max=200))
2021-01-29 17:14:38 +01:00
```
```python
print(FACTv1.applique(TROIS).forme_normale(nb_etapes_max=500))
2021-01-29 17:14:38 +01:00
```
```python
print(FACTv1.applique(QUATRE).forme_normale(nb_etapes_max=1700))
2021-01-29 17:14:38 +01:00
```
## Et la récursivité ?
```python
M_PHI_FACT = Lambda_terme('!f.!n.(((COND ((EGAL n) ZERO)) UN) ((MUL n) (f (PRED n))))')
2021-01-29 17:14:38 +01:00
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)
2021-01-29 17:14:38 +01:00
```
```python
BOTTOM = Lambda_terme('!y.OMEGA').subs('OMEGA', OMEGA)
2021-01-29 17:14:38 +01:00
print(BOTTOM)
```
```python
FACT0 = PHI_FACT.applique(BOTTOM)
```
```python
print(FACT0.applique(ZERO).forme_normale())
2021-01-29 17:14:38 +01:00
```
```python
FACT0.applique(UN).forme_normale(verbose=True, nb_etapes_max=40)
2021-01-29 17:14:38 +01:00
```
```python
FACT1 = PHI_FACT.applique(FACT0)
```
```python
print(FACT1.applique(ZERO).forme_normale())
2021-01-29 17:14:38 +01:00
```
```python
print(FACT1.applique(UN).forme_normale(nb_etapes_max=200))
2021-01-29 17:14:38 +01:00
```
```python
FIX_CURRY = Lambda_terme('!f.(!x.(f (x x)) !x.(f (x x)))')
2021-01-29 17:14:38 +01:00
print(FIX_CURRY)
```
```python
FACTv2 = FIX_CURRY.applique(PHI_FACT)
```
```python
print(FACTv2.applique(ZERO).forme_normale())
2021-01-29 17:14:38 +01:00
```
```python
print(FACTv2.applique(UN).forme_normale(nb_etapes_max=200))
2021-01-29 17:14:38 +01:00
```
```python
print(FACTv2.applique(DEUX).forme_normale(nb_etapes_max=700))
2021-01-29 17:14:38 +01:00
```
```python
print(FACTv2.applique(TROIS).forme_normale(nb_etapes_max=4000))
2021-01-29 17:14:38 +01:00
```
```python
print(FACTv2.applique(QUATRE).forme_normale(nb_etapes_max=25000))
2021-01-29 17:14:38 +01:00
```
```python
PF = FIX_CURRY.applique(Lambda_terme('M'))
2021-01-29 17:14:38 +01:00
```
```python
PF.forme_normale(verbose=True, nb_etapes_max=10)
2021-01-29 17:14:38 +01:00
```
```python
```
# $\lambda$-calcul avec les lambda-expressions de Python
<!-- #region toc-hr-collapsed=true toc-nb-collapsed=true -->
## Les entiers de Church
<!-- #endregion -->
```python
zero = lambda f: lambda x: x
```
```python
un = lambda f: lambda x: f(x)
```
```python
deux = lambda f: lambda x: f(f(x))
```
```python
trois = lambda f: lambda x: f(f(f(x)))
```
```python
def entier_church_en_int(ec):
return ec(lambda n: n+1)(0)
```
```python
tuple(entier_church_en_int(n) for n in (zero, un, deux, trois))
```
```python
suc = lambda n: lambda f: lambda x: f(n(f)(x))
```
```python
tuple(entier_church_en_int(suc(n)) for n in (zero, un, deux, trois))
```
```python
def int_en_entier_church(n):
if n == 0:
return zero
else:
return suc(int_en_entier_church(n - 1))
```
```python
tuple(entier_church_en_int(int_en_entier_church(n)) for n in range(10))
```
```python
add = lambda n: lambda m: lambda f: lambda x: n(f)(m(f)(x))
```
```python
cinq = add(deux)(trois)
entier_church_en_int(cinq)
```
```python
mul = lambda n: lambda m: lambda f: n(m(f))
```
```python
six = mul(deux)(trois)
entier_church_en_int(six)
```
```python
exp = lambda n: lambda m: m(n)
```
```python
huit = exp(deux)(trois)
entier_church_en_int(huit)
```
<!-- #region toc-hr-collapsed=true toc-nb-collapsed=true -->
## Les booléens
<!-- #endregion -->
```python
vrai = lambda x: lambda y: x
faux = lambda x: lambda y: y
```
```python
def booleen_en_bool(b):
return b(True)(False)
```
```python
tuple(booleen_en_bool(b) for b in (vrai, faux))
```
```python
cond = lambda c: lambda a: lambda s: c(a)(s)
```
```python
cond(vrai)(1)(2)
```
```python
cond(faux)(1)(2)
```
```python
cond(vrai)(1)(1/0)
```
```python
non = lambda b: cond(b)(faux)(vrai)
```
```python
tuple(booleen_en_bool(non(b)) for b in (vrai, faux))
```
```python
et = lambda b1: lambda b2: cond(b1)(b2)(faux)
```
```python
tuple(booleen_en_bool(et(b1)(b2)) for b1 in (vrai, faux) for b2 in (vrai, faux))
```
```python
ou = lambda b1: lambda b2: cond(b1)(vrai)(b2)
```
```python
tuple(booleen_en_bool(ou(b1)(b2)) for b1 in (vrai, faux) for b2 in (vrai, faux))
```
```python
est_nul = lambda n : n(lambda x: faux)(vrai)
```
```python
tuple(booleen_en_bool(est_nul(n)) for n in (zero, un, deux, trois, cinq, six, huit))
```
## Les couples
```python
cons = lambda x: lambda y: lambda z: z(x)(y)
```
```python
un_deux = cons(un)(deux)
```
```python
car = lambda c: c(vrai)
cdr = lambda c: c(faux)
```
```python
entier_church_en_int(car(un_deux)), entier_church_en_int(cdr(un_deux))
```
```python
pred = lambda n: car(n(lambda c: cons(cdr(c))(suc(cdr(c))))(cons(zero)(zero)))
```
```python
tuple(entier_church_en_int(pred(int_en_entier_church(n))) for n in range(10))
```
```python
sub = lambda n: lambda m: m(pred)(n)
```
```python
entier_church_en_int(sub(huit)(trois))
```
```python
est_inf_ou_egal = lambda n: lambda m: est_nul(sub(m)(n))
```
```python
tuple(booleen_en_bool(est_inf_ou_egal(cinq)(int_en_entier_church(n))) for n in range(10))
```
```python
est_egal = lambda n: lambda m: et(est_inf_ou_egal(n)(m))(est_inf_ou_egal(m)(n))
```
```python
tuple(booleen_en_bool(est_egal(cinq)(int_en_entier_church(n))) for n in range(10))
```
<!-- #region toc-hr-collapsed=true toc-nb-collapsed=true -->
## Itération
<!-- #endregion -->
```python
fact = lambda n: cdr(n(lambda c: (cons(suc(car(c)))(mul(suc(car(c)))(cdr(c)))))(cons(zero)(un)))
```
```python
tuple(entier_church_en_int(fact(int_en_entier_church(n))) for n in range(7))
```
## Combinateur de point fixe
```python
phi_fact = lambda f: lambda n: 1 if n == 0 else n*f(n-1)
```
```python
bottom = lambda x: (lambda y: y(y))(lambda y:y(y))
```
```python
f0 = phi_fact(bottom)
f1 = phi_fact(f0)
f2 = phi_fact(f1)
f3 = phi_fact(f2)
f4 = phi_fact(f3)
```
```python
tuple(f4(n) for n in range(4))
```
```python
def fact_rec(n):
if n == 0:
return 1
else:
return n * fact_rec(n - 1)
```
```python
fact2 = phi_fact(fact_rec)
```
```python
tuple(fact2(n) for n in range(7))
```
```python
fix_curry = lambda f: (lambda x: lambda y: f(x(x))(y))(lambda x: lambda y: f(x(x))(y))
```
```python
fact3 = fix_curry(phi_fact)
```
```python
tuple(fact3(n) for n in range(7))
```
<!-- #region toc-hr-collapsed=true toc-nb-collapsed=true -->
## Un programme obscur
<!-- #endregion -->
```python
print((lambda x: (lambda y: lambda z: x(y(y))(z))(lambda y: lambda z: x(y(y))(z)))
(lambda x: lambda y: '' if y == [] else chr(y[0])+x(y[1:]))
(((lambda x: (lambda y: lambda z: x(y(y))(z)) (lambda y: lambda z: x(y(y))(z)))
(lambda x: lambda y: lambda z: [] if z == [] else [y(z[0])]+x(y)(z[1:])))
(lambda x: (lambda x: (lambda y: lambda z: x(y(y))(z))(lambda y: lambda z: x(y(y))(z)))
(lambda x: lambda y: lambda z: lambda t: 1 if t == 0 else (lambda x: ((lambda u: 1 if u == 0 else z)(t % 2)) * x * x % y)
(x(y)(z)(t // 2)))(989)(x)(761))
([377, 900, 27, 27, 182, 647, 163, 182, 390, 27, 726, 937])))
```
```python
phiListEnChaine = lambda x: lambda y: '' if y == [] else chr(y[0]) + x(y[1:])
```
```python
fix_curry(phiListEnChaine)([65+k for k in range(26)])
```
```python
phiMap = lambda x: lambda y: lambda z: [] if z == [] else [y(z[0])] + x(y)(z[1:])
```
```python
fix_curry(phiMap)(lambda x: x*x)([1, 2, 3, 4])
```
```python
phiExpoMod = lambda x: lambda y: lambda z: lambda t: 1 if z == 0 else (lambda u: 1 if u == 0 else y)(z % 2) * x(y)(z//2)(t) ** 2 % t
```
```python
fix_curry(phiExpoMod)(2)(10)(1000)
```
```python
```
```python
```