- jeu. 01 février 2018
- Cours
- #ipython jupyter
Table des matières
- 1 Base de la programmation
- 2 Erreur sous Python
- 3 Python 3
- 4 Programmation sctructuré
- 5 Exemple: simulation de l’alunissage de Neil Amstrong (Apollo 11)
- 6 FIN
%matplotlib inline
#%autosave 300
import numpy as np
import scipy as sp
import matplotlib.pyplot as plt
from matplotlib import rcParams
rcParams['font.family'] = 'serif'
rcParams['font.size'] = 14
from IPython.core.display import HTML
from IPython.display import display
from matplotlib import animation
css_file = 'style.css'
HTML(open(css_file, "r").read())
# edit metadata "livereveal": {"scroll": true }
# https://damianavila.github.io/RISE/customize.html"
Base de la programmation¶
Marc BUFFAT, dpt mécanique, Université Claude Bernard Lyon 1
Rappel de programmation Python¶
Python tutor: http://pythontutor.com¶
Outil en ligne permettant de visualiser l’execution d’un programme Python
Variable¶
variable:
- case mémoire pour stocker de l’information
- doit être déclaré (initialisé) avant d’être utilisé
x=1
x=x+1
y=2*x+1
x=y+1
Type de variable¶
fonction du type de l’information (entier, réel, chaine)
x=1
print(type(x))
x=1.0
print(type(x))
x='1'
print(type(x))
Initialisation d’une variable¶
attention on doit définir une variable (sa valeur) avant de l’utiliser !!
# erreur !
Y=X
# modification: X,Y,x sont 3 variables #
Y=x
X=2
print(X,Y,x)
x=3
print(X,Y,x)
Portée d’une variable¶
Attention: dans une fonction les arguments et les variables dans la fonction sont locales.
Quelles sont les valeurs des variables a,b,c après execution du programme ci-dessous ?
a=3
c=-3
def func1(a,b):
c=0
def func2(a,b):
c = a - b
return c
c=func2(b,a)
return c
a=func1(2,1)
execution du code avec pythontutor¶
%load_ext tutormagic
%%tutor --lang python3 -h 400
a=3
c=-3
def func1(a,b):
c=0
def func2(a,b):
c = a - b
return c
c=func2(b,a)
return c
a=func1(2,1)
argument d’une fonction¶
Lors de l’appel d’une fonction, les arguments peuvent être des expressions, des valeurs ou des variables (si elles sont initialisées)
# exemple d'arguments
func1(x,x+1)
func1(c,2)
a=func1(a,a)
liste et tableau¶
liste: ensemble ordonné de valeurs
- ajout et suppression d’éléments
- la taille et le type peuvent variés
tableau: ensemble ordonné de valeurs de même type
- vecteurs, matrices
- taille fixée
indice: on compte à partir de 0
- indice à partir de 0
- [ ] pour sélectionner un élèment
- [0] premier element
- [-1] dernier element
- [n0:n1:p] selection des elements de l’indice n0 (defaut 0) à n1 (exclus) avec un pas p (defaut 1)
- aliasing attention à la copie
- A=B aliasing (A et B sont identiques)
- A=B[:] copie
# manipulation de liste
L=[1,2,3]
L1=L[:]
L1[-1]=4
L[0]=5
print(L,L1)
execution du code avec pythontutor¶
%%tutor --lang python3
L=[1,2,3]
L1=L[:]
L1[-1]=4
L[0]=5
# manipulation de tableau (avec aliasing)
X=np.linspace(1,5,5)
Y=X
Z=2*X
Y[0]=0
X[0]=Y[1]
Z[0]=1
print(X,Y,Z)
# decalage a droite: version 1
n = 5
X = np.linspace(1,5,5)
a = X[-1]
for i in range(n-1):
X[i+1]=X[i]
X[0]=a
# decalage a droite: version 2
n=5
Y=np.linspace(1,n,n)
x=Y[-1]
for i in range(1,n):
Y[n-i]=Y[n-i-1]
Y[0]=x
# validation
print(X)
print(Y)
exemple 2¶
Calcul de l’expression
pour i de a N
$$ Y_i = Y_i - \frac{\sum_{j=1}^{N} A_{ij} Y_j - B_i}{A_{ii}} $$
fin i
Pour calculer cette expression, on utilise l’une des deux fonctions suivantes. L’une est algorithmiquement fausse. Laquelle ?
# version 1
def iteration1(A,B,X):
n = X.shape[0]
Y = X[:]
for i in range(n):
sum=0.0
for j in range(n):
sum = sum + A[i,j]*Y[j]
Y[i] = Y[i] - (sum - B[i])/A[i,i]
return Y
# version 2
def iteration2(A,B,X):
n = X.shape[0]
Y = X[:]
for i in range(n):
sum=0.0
for j in range(n):
sum = sum + A[i,j]*Y[j]
Y[i] = Y[i] - (sum - B[i])/A[i,i]
return Y
# exemple de validation
n=3
X=np.random.rand(n)
A=np.random.rand(n,n)
B=np.random.rand(n)
#
X1=iteration1(A,B,X)
print("X1=",X1)
X2=iteration2(A,B,X)
print("X2=",X2)
programmation récursive¶
- la fonction s’appelle elle-même
- calcul factorielle n!
- n! = n*(n-1)!
Que calcule la fonction récursive suivante ?
def fonc(L):
print("appel fonc avec ",L)
if not L:
return 0
else:
return 1 + fonc(L[1:])
# resultat
fonc([1,2,3,4])
Erreur sous Python¶
retour erreur
Traceback (most recent call last):
File "test.py", line 6, in <module>
test()
File "test.py", line 3, in test
print table[4]
IndexError: list index out of range
code d’erreurs
IndentationError :
expected an indented block
IndexError:
list index out of range
SyntaxError :
inconsistent use of tabs and spaces in indentation
NameError :
name 'X' is not defined
ImportError :
no module named X
ZeroDivisionError :
X division or modulo by zero
Python 3¶
print est une fonction
print("Bonjour")
au lieu de (python 2.7)
print "Bonjour"
la division / est une division réelle (entière sous python 2.7)
4 / 2 = 2.0 4 // 2 = 2
# fonction de formattage
print("Bonjour {} {}".format("Marc","Buffat"))
# division entière et réelle
print("division : ",4/2, 4//2)
print("division : ",1/2, 1//2)
Programmation sctructuré¶
principe: “Divide and Conquer”
analyse descendante: top-down design¶
- définition des différentes étapes pour résoudre le problème
- on découpe le problème en une série de sous-problèmes plus simples (si possible indépendant)
- on spécifie ce qui doit résolu dans chacun des sous-problèmes sans forcément dire comment
- puis on itère au niveau des sous problèmes.
programmation ascendante: bottom-up programming¶
- on programme d’abord les sous-problèmes(sous forme de fonction)
- on validation les fonctions
- puis on réitère en remontant dans l’arbre jusqu’au programme principal
- on crée une bibliothéque
on éffectue l’analyse et la validation globale
règles réutiliser les fonctions déjà écrites et validées (bibliothèques): principe du moindre effort !
Exemple: simulation de l’alunissage de Neil Amstrong (Apollo 11)¶
On a perdu le pilotage automatique et il faut oser le module lunaire (LEM) sur la lune en arrivant avec une vitesse quasiment nulle. Pour cela on dispose de rétro-fusées permettant de ralentir la chute du LEM.
- On contrôle manuellement ces rétro-fusées en sélectionnant une poussée (de 0 à 9), correspondant à l’éjection de carburant avec un débit $Qe$ variable et une vitesse $Ue$ fixe.
- Mais on dispose d’une quantité limitée de carburant que l’on doit utiliser avec modération pour pouvoir atterrir en douceur.
modèle physique¶
Le LEM, de masse initiale $M0$, est soumis à la gravité $g$ de la lune et à la poussée des rétro-fusées, correspondant à l’éjection d’un débit de fuel $Qe$ à un vitesse $Ve$ .
modèle mathématique¶
Equation du mouvement: $$ \frac{d^2 Z}{dt^2} = -g + \frac{Qe*Ue}{M0-Qe*t}$$
en intégrant sur la durée d’une commande $T$ $\rightarrow$ vitesse $V$ $$ V = V0 + g*T + Ue * \ln{(1 - \frac{Qe*T}{M0})} $$ La masse du LEM $M$ diminue $$M = M0 -Qe*T$$ Approximation par DL car $X=\frac{Qe*T}{M0} \ll 1$ $$ V = V0 + g*T - Ue*(X + \frac{X^2}{2} + \frac{X^3}{3} + \frac{X^4}{4} + \frac{X^5}{5})$$ d’où l’altitude $Z$ $$ Z = Z0 - V0*T - g \frac{T^2}{2} + Ue*T*(\frac{X}{2} + \frac{X^2}{6} + \frac{X^3}{12} + \frac{X^4}{20} + \frac{X^5}{30})$$ expression utilisée dans les premiers programmes en BASIC.
cas particuliers¶
Si le fuel est épuisé ($Qe=0$), le LEM atteins la surface lunaire au bout d’un temps $T$ solution de l’équation du 2nd degré: $$ 0 = Z0 - V0*T -g \frac{T^2}{2}$$ soit $T = (-V0 + \sqrt{V0^2 + 2 g Z0})/g$
Près de la surface, $T$ trop grand $\rightarrow$ prédiction $Z0 < 0$
- calcul $T$ donnant l’altitude $Z=0$, solution d’une équation du 6ième degré.
- calcul par approximations successives en utilisant un DL de $Z(t)$
- estimation $T0$ de $T$ $$ T0 = \frac{-V0 + \sqrt{V0^2 + 2 (g-\frac{Ue*Qe}{M0}) Z0}}{g-\frac{Ue*Qe}{M0}} $$
- recalcule $V0$ et $Z0$, puis recommence.
Algorithme: analyse top-down¶
problème global¶
sous-problème lecture commande¶
sous-problème VitesseAltitude¶
applications des formules mathématiques de l’analyse précédente
$$ V = V0 + g*T - Ue*(X + \frac{X^2}{2} + \frac{X^3}{3} + \frac{X^4}{4} + \frac{X^5}{5})$$$$ Z = Z0 - V0*T - g \frac{T^2}{2} + Ue*T*(\frac{X}{2} + \frac{X^2}{6} + \frac{X^3}{12} + \frac{X^4}{20} + \frac{X^5}{30})$$sous-problème Alunissage¶
Implémentation fonctions python¶
%%bash
cat alunissage.py
programme principale¶
from alunissage import Lecture_Cde, VitesseAltitude, Alunissage
# conditions initiales
#Z0 = 190000. # position
Z0 = 100000
V0 = 1580. # et vitesse
M0 = 15000. # masse initiale du LEM
Me = 8000. # dont une masse de fuel
t = 0. # temps simulation
dt = 10. # pas en temps entre chaque commande
# sauvegarde données
alt=[Z0]
vit=[V0]
tps=[0.]
fuel=[Me]
print("Simulation alunissage")
while np.abs(Z0)>1.e-2 :
ch = input("commande (0-9):")
Qe,T = Lecture_Cde(V0,Z0,Me,dt,ch)
# calcul de la nouvelle position du LEM
V1,Z1 = VitesseAltitude(V0,Z0,Qe*T/M0,T)
# test si alunnissage
if Z1 < 1.e-2 :
V1,Z1,T = Alunissage(V0,Z0,M0,Qe)
# mise a jour de la position du LEM
Z0 = Z1; V0 = V1
Me = Me-Qe*T; M0 = M0-Qe*T
t = t + T
print("t=",int(t),"s Z=",int(Z0),"m V=",int(V0),"m/s fuel=",int(Me),"kg")
# sauvegarde donnérs
alt.append(Z0)
vit.append(V0)
tps.append(t)
fuel.append(Me)
# fin simulation
print("Alunissage avec une vitesse ",int(V0)," m/s")
if V0<=0.5 :
print("Alunissage parfait")
elif V0<=5. :
print("Bon alunissage, mais perfectible")
elif V0<=27.:
print("Accident à l'alunissage. Attendez les secours en esperant que vous avez assez d'oxygene !!!")
else :
print("Crash fatal: aucun survivant")
plt.figure(figsize=(16,8))
plt.subplot(1,3,1)
plt.plot(tps,alt,lw=2)
plt.title("altitude")
plt.subplot(1,3,2)
plt.plot(tps,vit,lw=2)
plt.title("vitesse")
plt.subplot(1,3,3)
plt.plot(tps,fuel,lw=2)
plt.title("fuel")
version avec ncurses¶
python lunar_landing.py
FIN¶