2. Méthodes numériques avancées et programmation#

Marc BUFFAT,dpt mécanique, Lyon 1

images/algorithm.png

certains exemples sont tirés du cours « Scientific Python Lectures » de Robert Johansson

%matplotlib inline
from IPython.display import HTML,display
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 matplotlib import animation
def printmd(string):
    display(Markdown(string))
from metakernel import register_ipython_magics
register_ipython_magics()

2.1. Algorithmique et calcul scientifique sous Python#

2.1.1. Exigences du calcul scientifique#

« Le logiciel (software) est une des pierres angulaires de la science moderne. Sans logiciel, la science du vingt et unième siècle serait impossible. Mais sans de meilleurs logiciels, la science ne peut pas progresser »

    • importance de la documentation

    • importance de la validation

    • importance de la maîtrise du code (logiciels libres)

    • comprendre la méthode/démarche plus que la syntaxe

    • l’algorithme est plus important que le langage

# zen du Python
import this
import importlib
importlib.reload(this)
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
<module 'this' from '/usr/lib/python3.10/this.py'>

2.1.2. Démarche du calcul scientifique#

    1. formulation mathématique du problème

    2. recherche d’une solution (eventuellement approchée par discrétisation)

    3. détermine ma méthode / algorithme pour le calcul de cette solution

      • top down design

    4. programmation de cette méthode

      • bottom up programming (using libraries)

    5. validation

    6. analyse

2.2. Questions préliminaires#

2.3. Un premier exemple#

2.3.1. Formulation: calcul de la somme d’une série#

\[ S_N = x - \frac{x^2}{2} + \frac{x^3}{3} + .. = \sum_{i=1}^n (-1)^{i+1} x^i/i \]

D.L. ordre N de \(log(1+x)\) $\( \lim_{N\rightarrow\infty} S_N = log(1+x) \)$

2.3.2. algorithmique#

1ere solution: traduction de la formule

Algorithme Serie(x,n)
import numpy as np
def Serie(x,n):
    Sn = 0.
    for i in range(1,n+1):
        Sn = Sn + ((-1)**(i+1)) * (x**i) / i
    return Sn
#
x0 = 0.2
S0 = Serie(x0,20)
print("S={} log(1+x)={}".format(S0,np.log(1+x0)))
S=0.18232155679395456 log(1+x)=0.1823215567939546
def Serie1(x,n):
    Sn = 0.
    coef = 1.
    for i in range(1,n+1):
        coef = -x*coef
        Sn = Sn - coef / i
    return Sn
x0 = 0.2
S1 = Serie1(x0,20)
print("S={} log(1+x)={}".format(S1,np.log(1+x0)))
    
S=0.18232155679395456 log(1+x)=0.1823215567939546

2.3.3. Solutions algorithmiques#

1ere solution: traduction de la formule

Algorithme Serie(x,n)
   somme = 0
   pour i de 1 a n
      somme = somme + (-1)^(i+1)*x^i/i
   retour somme

Solution non optimale !

2.3.4. Programmation Python#

  1. écriture d’une fonction

  2. validation

def Serie(x,n):
    '''calcul serie S=x-x^2/2 + x^2/3 '''
    somme = 0

    return somme
# test
x0 = 0.2
S = Serie(x0,20)
# solution
def Serie1(x,n):
    '''calcul serie S=x-x^2/2 + x^2/3 '''
    somme = 0
    for i in range(1,n+1):
        somme = somme + ((-1)**(i+1)) * (x**i)/i
    return somme
# test
x0 = 0.2
S1 = Serie1(x0,20)
print("S={} lim={}".format(S1,np.log(1+x0)))
S=0.18232155679395456 lim=0.1823215567939546
# version optimisée
def Serie2(x,n):
    """ calcul de la somme de n termes de la serie x-x^2/2+x^3/3- """
    coef=x
    somme=0.0
    for i in range(1,n+1):
        somme = somme + coef/i
        coef  = -coef*x
    return somme
# test
x0 = 0.2
S2 = Serie2(x0,20)
print("S={} lim={}".format(S2,np.log(1+x0)))
S=0.18232155679395456 lim=0.1823215567939546
%timeit Serie1(x0,1000)
369 μs ± 4.43 μs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
%timeit Serie2(x0,1000)
84.4 μs ± 497 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
sum([1,2,3])
[i**2 for i in range(20)]
[0,
 1,
 4,
 9,
 16,
 25,
 36,
 49,
 64,
 81,
 100,
 121,
 144,
 169,
 196,
 225,
 256,
 289,
 324,
 361]
# version sans boucle
def Serie3(x,n):
    return -sum([(-x0)**i/i for i in range(1,n+1)])
#
S3 = Serie3(x0,20)
print("S={} lim={}".format(S3,np.log(1+x0)))
S=0.18232155679395456 lim=0.1823215567939546
%timeit Serie3(x0,1000)
155 μs ± 636 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)

2.4. Les langages de programmation scientifiques#

2.4.1. Langage machine#

  • suite d’instruction binaire executer par le processeur: 01010111 (suite 0 ou 1 : bits)

  • représentation en hexadécimal (octet ou bytes):

    • f8 = 248

  • instructions et données sont stockées en mémoire (à une adresse donnée)

    • @000141 instruction f8

  • spécifiques au processeur (intel, ARM, power, AMD, ..)

  • spécifique au système d’exploitation OS

%%bash
g++ serie.C
od -x -N 100 a.out
./a.out
0000000 457f 464c 0102 0001 0000 0000 0000 0000
0000020 0003 003e 0001 0000 1120 0000 0000 0000
0000040 0040 0000 0000 0000 3970 0000 0000 0000
0000060 0000 0000 0040 0038 000d 0040 001f 001e
0000100 0006 0000 0004 0000 0040 0000 0000 0000
0000120 0040 0000 0000 0000 0040 0000 0000 0000
0000140 02d8 0000
0000144
Calcul de la serie pour n=20 et x=0.2
Somme   = 0.182322
Log(1+x)= 0.182322

2.4.2. Langage assembleur#

  • notation des instructions machines (move, push, load, add, mul)

  • programme + assembleur = code machine

%%bash
head -100 serie.s
	.file	"serie.C"
	.local	_ZStL8__ioinit
	.comm	_ZStL8__ioinit,1,1
	.text
	.globl	_Z5seriedi
	.type	_Z5seriedi, @function
_Z5seriedi:
.LFB971:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	movsd	%xmm0, -40(%rbp)
	movl	%edi, -44(%rbp)
	movq	-40(%rbp), %rax
	movq	%rax, -16(%rbp)
	movl	$0, %eax
	movq	%rax, -8(%rbp)
	movl	$1, -20(%rbp)
	jmp	.L2
.L3:
	cvtsi2sd	-20(%rbp), %xmm0
	movsd	-16(%rbp), %xmm1
	divsd	%xmm0, %xmm1
	movapd	%xmm1, %xmm0
	movsd	-8(%rbp), %xmm1
	addsd	%xmm1, %xmm0
	movsd	%xmm0, -8(%rbp)
	movsd	-16(%rbp), %xmm1
	movsd	.LC1(%rip), %xmm0
	xorpd	%xmm1, %xmm0
	mulsd	-40(%rbp), %xmm0
	movsd	%xmm0, -16(%rbp)
	addl	$1, -20(%rbp)
.L2:
	movl	-20(%rbp), %eax
	cmpl	-44(%rbp), %eax
	jle	.L3
	movq	-8(%rbp), %rax
	movq	%rax, -56(%rbp)
	movsd	-56(%rbp), %xmm0
	popq	%rbp
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE971:
	.size	_Z5seriedi, .-_Z5seriedi
	.section	.rodata
.LC3:
	.string	"Calcul de la serie pour n="
.LC4:
	.string	" et x="
.LC5:
	.string	"Somme de la serie = "
.LC7:
	.string	"Log(1+x)="
	.text
	.globl	main
	.type	main, @function
main:
.LFB972:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	pushq	%rbx
	subq	$56, %rsp
	.cfi_offset 3, -24
	movl	%edi, -36(%rbp)
	movq	%rsi, -48(%rbp)
	movl	$20, -28(%rbp)
	movabsq	$4596373779694328218, %rax
	movq	%rax, -24(%rbp)
	movl	$.LC3, %esi
	movl	$_ZSt4cout, %edi
	call	_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
	movl	-28(%rbp), %edx
	movl	%edx, %esi
	movq	%rax, %rdi
	call	_ZNSolsEi
	movl	$.LC4, %esi
	movq	%rax, %rdi
	call	_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
	movq	%rax, %rdx
	movq	-24(%rbp), %rax
	movq	%rax, -56(%rbp)
	movsd	-56(%rbp), %xmm0
	movq	%rdx, %rdi
	call	_ZNSolsEd
	movl	$_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, %esi
	movq	%rax, %rdi
	call	_ZNSolsEPFRSoS_E
	movl	-28(%rbp), %edx
	movq	-24(%rbp), %rax
	movl	%edx, %edi
	movq	%rax, -56(%rbp)

2.4.3. Langage compilé#

  • C++ Fortran C

  • programme source + compilateur = programme binaire

  • programme source = portable

  • programme binaire = spécifique à l’ordinateur (non portable)

2.4.4. Langage C (Unix)#

%%bash
cat serie.C
#include <stdlib.h>
#include <math.h>
#include <iostream>
//
// calcul de la somme de n termes de la serie x-x^2/2+x^3/3-
//
double serie(double x,int n)
{
	double coef=x;
	double somme=0.0;
	for (int i=1; i<=n; i++)
	{
		somme = somme + coef/i;
		coef = -coef*x;
	}
	return somme;
}
//
int main(int argc,char *argv[])
{
	int n=20;
	double x=0.2;
	std::cout<<"Calcul de la serie pour n="<<n<<" et x="<<x<<std::endl;
	std::cout<<"Somme   = "<<serie(x,n)<<std::endl;
	std::cout<<"Log(1+x)= "<<log(1+x)<<std::endl;
	return 0;
}

%%bash
g++ serie.C -o serie
./serie
Calcul de la serie pour n=20 et x=0.2
Somme   = 0.182322
Log(1+x)= 0.182322

2.4.5. Langage interprété#

  • Python, Matlab

  • programme + interpréteur

  • portable = indépendant du système (Linux, MacOS, Windows)

../../_images/matlab.png

Matlab

Matlab est un logiciel propriétaire qui est une boite à outils (toolbox) de calcul matriciel et numérique développé par Mathworks Inc. Il fonctionne sous Windows, Mac et Unix et permet d’écrire rapidement des scripts pour faire du calcul scientifique.

De nombreuses alternatives libres et de qualité existent, et notamment les logiciels: Scilab, Octave et surtout Python avec numpy.

%%bash
cat serie.m
% programme matlab
% ================
x=0.2; n=20;
% calcul de la serie
coef=x;
somme=0.0;
for i=1:n;
somme = somme+coef/i;
coef  = -coef*x;
end;
display(sprintf('Calcul de la serie pour x=%g et n=%d',x,n))
display(sprintf('somme    = %g',somme))
display(sprintf('log(1+x) = %g',log(1+x)))
exit
%%bash
# matlab -nojvm -r serie

Language Python

Python est un language de programmation moderne de haut niveau, logiciel libre, généraliste, multi-plateformes, multi-architecture, multi-OS (linux, windows, MacOS,..). Un programme python peut s’executer sur un tout petit raspberry Pi à 30€ (ARM), sur des smartphones, des portables, des PC jusqu’aux super-calculateurs HPC avec \(10^9\) coeurs de calcul.

../../_images/raspberry.jpg
%%bash
cat serie.py
#! /usr/bin/env python
# calcul de serie: Marc BUFFAT
from numpy import log

def serie(x,n):
    """ calcul de la somme de n termes de la serie x-x^2/2+x^3/3- """
    coef=x
    somme=0.0
    for i in range(1,n+1):
        somme = somme + coef/i
        coef  = -coef*x
    return somme
#
x=0.2
n=20
print("Calcul de la serie pour x=",x," et n=",n)
print("somme    = ",serie(x,n))
print("log(1+x) = ", log(1+x))
%%bash
python3 serie.py
Calcul de la serie pour x= 0.2  et n= 20
somme    =  0.18232155679395456
log(1+x) =  0.1823215567939546

2.4.6. Questions Algorithmiques en Python#

2.4.7. Choix du Langage Python#

Python (http://www.python.org/) est un langage de programmation moderne de haut niveau, orienté objet et d’usage général.

Caractéristiques générales de Python:

  • **Langage simple: ** facile à lire et à apprendre avec une syntaxe minimaliste.

  • **Langage concis et expressif: ** moins de lignes de code, moins de bugs, plus facile à maintenir.

Détails techniques:

  • Typé dynamiquement: Pas besoin de définir le type des variables, les arguments ou le type des fonctions.

  • La gestion automatique de la mémoire: Aucune nécessité d’allouer explicitement et désallouer la mémoire pour les variables et les tableaux de données. Aucun bug de fuite de mémoire.

  • Interprété: Pas besoin de compiler le code. L’interpréteur Python lit et exécute le code python directement.

2.4.8. Avantages:#

  • Le principal avantage est la facilité de programmation, qui minimise le temps nécessaire pour développer, déboguer et maintenir le code.

  • Langage bien conçu qui encouragent les bonnes pratiques de programmation:

    • Modulaire et orientée objet, permet l’encapsulation et la réutilisation de code. Il en résulte souvent un code plus transparent, maintenable et sans bug.

    • Documentation intégré avec le code.

  • De nombreuses bibliothèques standards, et de nombreux packages add-on.

2.5. Algorithmes#

2.5.1. Algorithme (al-Khwarizmi)#

Euclide Algorithme al-Khwarizmi

algorithme = suite finie et non ambigüe d’opérations ou d’instructions sur des données permettant d’obtenir un résultat (numérique) pour résoudre un problème

Ecriture

  • identifier les donnees (parametres)

  • identifier les résultats

  • définir les opérations de transformation des données pour obtenir les résultats

  • définir une méthode de validation (solution exacte, jeux de données particuliers)

2.6. Questions sur les algorithmes#

-Algorithme_questions.ipynb

2.7. Exemple d’algorithme#

Commençons par un exemple tiré du Bourgeois gentilhomme (Acte II Scène IV) de Molière. Le héros, Monsieur Jourdain, veut connaître toutes les manières « galantes » d’écrire un billet.

De la phrase Belle Marquise, vos beaux yeux, me font mourir d’amour, il pourrait tirer Vos beaux yeux, belle Marquise, d’amour me font mourir, puis Vos beaux yeux, me font mourir, belle Marquise, d’amour, puis Vos beaux yeux, me font mourir d’amour, belle Marquise et ainsi de suite.

2.7.1. idée d’algorithme#

on découpe la phrase P en 4 morceaux: « Belle Marquise, » « vos beaux yeux, » « me font mourir » « d’amour » et on construit toutes les permutations possibles:

def permutation(mots):
    '''construit la liste de toutes les permutations possibles de la liste mots, 
    le resultat est une liste de liste'''
    if len(mots)==1 :
        L = [mots]
    else :
        n = len(mots)
        perms = permutation(mots[1:n])
        L = []
        for P in perms:
            for k in range(n):
                l = P.copy()
                l.insert(k,mots[0])
                L.append(l)
    return L
permutation(['1','2','3'])
[['1', '2', '3'],
 ['2', '1', '3'],
 ['2', '3', '1'],
 ['1', '3', '2'],
 ['3', '1', '2'],
 ['3', '2', '1']]
def permutation(L):
    '''construit la liste de toutes les permutations possibles de la liste L, le resultat est une liste de liste'''
    n = len(L)
    if n == 1 :
        return [L]
    else:
        # on construit la liste de toutes les permutations possibles de la L moins le premier elt
        P1 = permutation(L[1:])
        # on inserre ensuite le 1er elt au debut, en second , .. a la fin 
        P = []       
        for p1 in P1:
            for k in range(n):
                p = p1.copy()
                p.insert(k,L[0])
                P.append(p)
        return P
   
# validation 
P = permutation(["1","2","3"])
print(P)
[['1', '2', '3'], ['2', '1', '3'], ['2', '3', '1'], ['1', '3', '2'], ['3', '1', '2'], ['3', '2', '1']]
# utilisation
Phrase = ["Belle Marquise,","vos beaux yeux,","me font mourir","d amour"]
P = permutation(Phrase)
for p in P:
    print(p)
['Belle Marquise,', 'vos beaux yeux,', 'me font mourir', 'd amour']
['vos beaux yeux,', 'Belle Marquise,', 'me font mourir', 'd amour']
['vos beaux yeux,', 'me font mourir', 'Belle Marquise,', 'd amour']
['vos beaux yeux,', 'me font mourir', 'd amour', 'Belle Marquise,']
['Belle Marquise,', 'me font mourir', 'vos beaux yeux,', 'd amour']
['me font mourir', 'Belle Marquise,', 'vos beaux yeux,', 'd amour']
['me font mourir', 'vos beaux yeux,', 'Belle Marquise,', 'd amour']
['me font mourir', 'vos beaux yeux,', 'd amour', 'Belle Marquise,']
['Belle Marquise,', 'me font mourir', 'd amour', 'vos beaux yeux,']
['me font mourir', 'Belle Marquise,', 'd amour', 'vos beaux yeux,']
['me font mourir', 'd amour', 'Belle Marquise,', 'vos beaux yeux,']
['me font mourir', 'd amour', 'vos beaux yeux,', 'Belle Marquise,']
['Belle Marquise,', 'vos beaux yeux,', 'd amour', 'me font mourir']
['vos beaux yeux,', 'Belle Marquise,', 'd amour', 'me font mourir']
['vos beaux yeux,', 'd amour', 'Belle Marquise,', 'me font mourir']
['vos beaux yeux,', 'd amour', 'me font mourir', 'Belle Marquise,']
['Belle Marquise,', 'd amour', 'vos beaux yeux,', 'me font mourir']
['d amour', 'Belle Marquise,', 'vos beaux yeux,', 'me font mourir']
['d amour', 'vos beaux yeux,', 'Belle Marquise,', 'me font mourir']
['d amour', 'vos beaux yeux,', 'me font mourir', 'Belle Marquise,']
['Belle Marquise,', 'd amour', 'me font mourir', 'vos beaux yeux,']
['d amour', 'Belle Marquise,', 'me font mourir', 'vos beaux yeux,']
['d amour', 'me font mourir', 'Belle Marquise,', 'vos beaux yeux,']
['d amour', 'me font mourir', 'vos beaux yeux,', 'Belle Marquise,']

2.8. Exemple: le problème d’Euclide:#

L’algorithme d’Euclide permet le pavage d’une piece.

Soit une pièce rectangulaire de coté a et b (en cm) que l’on souhaites paver avec des petits carreaux carrés hxh.

Quelle est la taille maximum h des carreaux ?

Algorithme

idée : découpage recursif / itératif de la pièce en carré

Propriétés:

  • Pavage(a,a) -> a

cas particulier

  • Pavage(15,21) - > 3

2.8.1. Algorithme#

2.8.2. Version récursive#

Algorithme PavageR(A,B)

détermine la taille maxi pour paver une piece de cotés AxB

# version recursive
si A > B alors
   retour PavageR(A-B,A)
sinon si A < B alors
   retour PavageR(A,B-A)
sinon
   retour A

2.8.3. Version itérative#

Algorithme Pavage(A,B)

détermine la taille maxi pour paver une piece de cotés AxB

# version itérative
tant que A # B faire
   si A > B alors
       A = A - B
   sinon
       B = B - A
fin tant que
# on a ici A=B donc
retour A

2.8.4. Traduction en Python#

  • version récursive

  • version itérative

def Pavage(a,b):
    
    return
def PavageI(a,b):
    '''Version iterative de l algorithme d'Euclide'''
  
    while a != b :
        if a > b :
            a = a - b
        else :
            b = b - a
    return a
def PavageR(a,b):
    '''Version récursive de l algorithme d'Euclide'''

    if a>b:
        return PavageR(a-b,b)
    elif a<b:
        return PavageR(a,b-a)
    else:
        return a
### validation
print(PavageI(15,21))
print(PavageR(15,21))
print(PavageI(15,15))
print(PavageR(15,15))
3
3
15
15

2.9. Algorithme pour calculer \(A^n\)#

étude de la complexité (nombre d’opérations de multiplication ) pour calculer \(A^n\)\(A\) est une matrice en utilisant uniquement des multiplications

2.9.1. solution naive#

coût (n-1) multiplication soit en \(O(n)\) $\(A^n = A*A* .. *A = \prod_{i=1}^n A\)$

Algorithme Power(A,n)

Algorithme Power(A,n)

  An = A
  pour i de 1 a n-1
      An = An*A
  fin pour
  retour An

2.9.2. méthode binaire#

en remarquant que

\[\begin{split} A^n = \begin{matrix} x^{n/2} x^{n/2} &\mbox{si n est pair}\\ x^{n/2} x^{n/2} x &\mbox{si n est impair}\\ \end{matrix} \end{split}\]

écrire un algorithme plus optimal

Algorithme Power(A,n)

Algorithme Power(A,n)

si n == 1 alors
   retour A
sinon
    An2 = Power(A,n/2)
    si n paire
      retour An2*An2
    sinon
       retour An2*An2*A

complexité \(O(log(n))\)

2.9.3. méthode des facteurs#

on décompose N en produits de facteurs premiers

  • écrire l’algorithme correspondant !

  • Avantages / inconvénient ?

2.9.4. implementation python#

def Power1(A,n):
    An = A.copy()
    for i in range(n-1):
        An = An @ A
    return An
def Power2(A,n):
    if n == 1 :
        return A
    else :
        An2 = Power2(A,n//2)
        An  = An2 @ An2
        if (n % 2 ==0):
            return An
        else :
            return An @ A
A = np.random.rand(5,5)

A1 = Power1(A,7)
A2 = Power2(A,7)
print(A1-A2)
[[-2.84217094e-14 -2.84217094e-14 -2.84217094e-14 -5.68434189e-14
   0.00000000e+00]
 [ 0.00000000e+00  0.00000000e+00  0.00000000e+00  0.00000000e+00
   0.00000000e+00]
 [ 0.00000000e+00  0.00000000e+00  0.00000000e+00  0.00000000e+00
   0.00000000e+00]
 [-1.42108547e-14 -2.84217094e-14 -1.42108547e-14  0.00000000e+00
   0.00000000e+00]
 [ 0.00000000e+00  0.00000000e+00  0.00000000e+00  0.00000000e+00
   0.00000000e+00]]
%timeit Power1(A,100)
%timeit Power2(A,100)
149 μs ± 2.11 μs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
12.1 μs ± 373 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)

2.10. Algorithme: chercher la star#

Dans un groupe de n personnes (numérotées de 1 à n pour les distinguer), une star est quelqu’un qui ne connaît personne mais que tous les autres connaissent. Pour démasquer une star, s’il en existe une, vous avez juste le droit de poser des questions à n’importe quel individu i du groupe, du type « est-ce que vous connaissez j? ». On suppose que les individus répondent toujours la vérité. On veut un algorithme qui trouve une star s’il en existe une, et qui garantit qu’il n’y en a pas sinon, en posant le moins de questions possibles.

indice

Lorsqu’on effectue le test i→j, c’est-à-dire lorsque l’on cherche à savoir si la personne i connaît la personne j, on obtient le résultat suivant:

  • si oui, alors i n’est pas une star, mais j en est potentiellement une

  • si non, alors j n’est pas une star, mais i en est potentiellement une

Algorithme Star(n)

Algorithme Star(n)

recherche star i potentiel

i = 1
j = 2
tant que j <= n faire
  si i connait j alors
     i = j
     j = j +1
  sinon
     j = j + 1 

vérification i est une star

istar = Vrai
j = 1
tant que j <=n et istar
  si j#i  et i connait j alors
      istar = Faux
  sinon
      j = j + 1
      
si istar retour i
sinon retour "aucune star"
def Star(R):
    n = R.shape[0]
    i = 0
    j = 1
    # recherche star possible
    while j < n :
        if R[i,j] :
            i = j
            j = j + 1
        else:
            j = j + 1
    istar = True
    j = 0
    # verification
    while (j < n) and istar :
        if (j != i ) and R[i,j]:
            istar = False
        else:
            j = j + 1
    if istar :
        print("la star est le numero ",i)
    else :
        print("aucune star")
    return
n = 10
R = np.random.randint(2,size=(n,n))
istar = np.random.randint(n)
print(istar)
R[istar,:]=0
R[:,istar]=1
print(R)
Star(R)
0
[[1 0 0 0 0 0 0 0 0 0]
 [1 0 0 0 1 0 0 0 1 1]
 [1 1 1 1 1 0 0 1 1 1]
 [1 0 1 1 0 0 1 1 1 0]
 [1 0 1 0 0 1 1 0 0 1]
 [1 1 0 0 1 0 0 1 1 1]
 [1 0 1 1 0 1 0 0 1 1]
 [1 0 0 0 1 0 0 1 1 1]
 [1 0 1 1 0 0 1 1 1 1]
 [1 1 1 1 0 1 0 0 0 1]]
la star est le numero  0

2.11. Algorithme :liste des nombres premiers#

Ecrire un algorithme pour déterminer la liste des nbre premiers <= N

2.11.1. Algorithme#

def NbrePremiers(n):
    '''determine la liste des nbres premiers < à n'''
def NbrePremiers(n):
    '''determine la liste des nbres premiers < à n'''

    L = np.zeros(n+1,dtype=int)
    Premiers = []
    for k in range(2,n+1):
        # test si k premier
        if L[k] == 0 :
            # elimine les multiples de k
            Premiers.append(k)
            p = 2*k
            while (p<=n):
                L[p] = 1
                p = p + k
    return Premiers
  
# test validation
NbrePremiers(43)
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43]

2.12. Ipython Notebook#

2.12.1. Ipython Notebook#

IPython notebook est un environnement portable sous HTML pour Python, similaire à Mathematica ou maple. Il est basé sur un shell IPython, mais offre un environnement à base de cellules avec une grande interactivité, où les calculs peuvent être organisées documentée de manière structurée.

Par defaut les cellules executent du code Python en cliquant sur le bouton « run » ou en entrant ctrl+entrée; avec le menu Cell->Run All on execute toutes les cellules dans l’ordre. On peut aussi éffacer toute les sorties avec All output -> Clear

print("hello ceci est mon premier programme")
hello ceci est mon premier programme

On peut aussi ajouter du texte en changeant le type de cellule de code a markdown

On peut alors utiliser des balises de mise en page markdown (documentation sur le lien ci-dessous)

[http://jupyter-notebook.readthedocs.io/en/latest/examples/Notebook/Working With Markdown Cells.html]

exemples

 #    titre niveau 1
 ##   titre niveau 2
 ###  titre niveau 3
 **texte**  écriture texte en gras 
 $ formule $ affichage formule en LaTeX
 $$ equation $$ ou une équation

remarque en double cliquant sur une cellule, on peut modifier cette cellule

De nombreux exemples de notebook sont accesibles [http://nbviewer.jupyter.org/] ou sur le site [http://jupyter.org/]

2.13. Référence sur la programmation sous Python#

  • Python. The official Python web site.

  • Python tutorials. The official Python tutorials.

  • Think Python. “”How to Think Like a Computer Scientist”” by Allen B. Downey (free book).

  • COURS InProS “”Introduction à la Programmation Scientifique””