Équipe pédagogique
import numpy as np<br />
<br />
import matplotlib.pyplot as pl<br />
<br />
<br />
<br />
# ============ define relevant functions =============<br />
<br />
<br />
<br />
# an efficient function to compute a mean over neighboring cells<br />
<br />
def apply_laplacian(mat):<br />
<br />
"""This function applies a discretized Laplacian<br />
<br />
in periodic boundary conditions to a matrix<br />
<br />
For more information see<br />
<br />
https://en.wikipedia.org/wiki/Discrete_Laplace_operator#Implementation_via_operator_discretization<br />
<br />
"""<br />
<br />
<br />
<br />
# the cell appears 4 times in the formula to compute<br />
<br />
# the total difference<br />
<br />
neigh_mat = -4*mat.copy()<br />
<br />
<br />
<br />
# Each direct neighbor on the lattice is counted in<br />
<br />
# the discrete difference formula<br />
<br />
neighbors = [<br />
<br />
( 1.0, (-1, 0) ),<br />
<br />
( 1.0, ( 0,-1) ),<br />
<br />
( 1.0, ( 0, 1) ),<br />
<br />
( 1.0, ( 1, 0) ),<br />
<br />
]<br />
<br />
<br />
<br />
# shift matrix according to demanded neighbors<br />
<br />
# and add to this cell with corresponding weight<br />
<br />
for weight, neigh in neighbors:<br />
<br />
neigh_mat += weight * np.roll(mat, neigh, (0,1))<br />
<br />
<br />
<br />
return neigh_mat<br />
<br />
<br />
<br />
# Define the update formula for chemicals A and B<br />
<br />
def update(A, B, DA, DB, f, k, delta_t):<br />
<br />
"""Apply the Gray-Scott update formula"""<br />
<br />
<br />
<br />
# compute the diffusion part of the update<br />
<br />
diff_A = DA * apply_laplacian(A)<br />
<br />
diff_B = DB * apply_laplacian(B)<br />
<br />
<br />
<br />
# Apply chemical reaction<br />
<br />
reaction = A*B**2<br />
<br />
diff_A -= reaction<br />
<br />
diff_B += reaction<br />
<br />
<br />
<br />
# Apply birth/death<br />
<br />
diff_A += f * (1-A)<br />
<br />
diff_B -= (k+f) * B<br />
<br />
<br />
<br />
A += diff_A * delta_t<br />
<br />
B += diff_B * delta_t<br />
<br />
<br />
<br />
return A, B<br />
<br />
<br />
<br />
def get_initial_A_and_B(N, random_influence = 0.2):<br />
<br />
"""get the initial chemical concentrations"""<br />
<br />
<br />
<br />
# get initial homogeneous concentrations<br />
<br />
A = (1-random_influence) * np.ones((N,N))<br />
<br />
B = np.zeros((N,N))<br />
<br />
<br />
<br />
# put some noise on there<br />
<br />
A += random_influence * np.random.random((N,N))<br />
<br />
B += random_influence * np.random.random((N,N))<br />
<br />
<br />
<br />
# get center and radius for initial disturbance<br />
<br />
N2, r = N//2, 50<br />
<br />
<br />
<br />
# apply initial disturbance<br />
<br />
A[N2-r:N2+r, N2-r:N2+r] = 0.50<br />
<br />
B[N2-r:N2+r, N2-r:N2+r] = 0.25<br />
<br />
<br />
<br />
return A, B<br />
<br />
<br />
<br />
def draw(A, B):<br />
<br />
"""return the matplotlib artists for animation"""<br />
<br />
fig, ax = pl.subplots(1,2,figsize=(5.65,3))<br />
<br />
imA = ax[0].imshow(A, animated=True,vmin=0,cmap='Greys')<br />
<br />
imB = ax[1].imshow(B, animated=True,vmax=1,cmap='Greys')<br />
<br />
ax[0].axis('off')<br />
<br />
ax[1].axis('off')<br />
<br />
ax[0].set_title('A')<br />
<br />
ax[1].set_title('B')<br />
<br />
<br />
<br />
return fig, imA, imB<br />
<br />
<br />
<br />
# =========== define model parameters ==========<br />
<br />
<br />
<br />
# update in time<br />
<br />
delta_t = 1.0<br />
<br />
<br />
<br />
# Diffusion coefficients<br />
<br />
DA = 0.16<br />
<br />
DB = 0.08<br />
<br />
<br />
<br />
# define birth/death rates<br />
<br />
f = 0.060<br />
<br />
k = 0.062<br />
<br />
<br />
<br />
# grid size<br />
<br />
N = 200<br />
<br />
<br />
<br />
# intialize the chemical concentrations<br />
<br />
A, B = get_initial_A_and_B(N)<br />
<br />
<br />
<br />
N_simulation_steps = 10000<br />
<br />
for step in range(N_simulation_steps):<br />
<br />
A, B = update(A, B, DA, DB, f, k, delta_t)<br />
<br />
<br />
<br />
draw(A, B)<br />
<br />
<br />
<br />
# show the result<br />
<br />
pl.show()<br />
<br />
Michael Kapralov
Direction Scientifique
Mikhail Kapralov est un spécialiste de l’informatique théorique. Ses recherches sur les algorithmes sublinéaires ont abouti à des percées majeures dans les secteurs du big data et de l’analyse des données. Mikhail Kapralov a reçu plusieurs prix, dont une bourse ERC Starting Grant en 2017. Alors que ses travaux sont de nature théorique, il entretient néanmoins des liens forts avec l’industrie. Ses contacts avec des partenaires industriels comme le Microsoft Research Lab et Google Research ouvrent des perspectives professionnelles inédites à ses étudiantes et étudiants.
import numpy as np<br />
<br />
import matplotlib.pyplot as pl<br />
<br />
<br />
<br />
# ============ define relevant functions =============<br />
<br />
<br />
<br />
# an efficient function to compute a mean over neighboring cells<br />
<br />
def apply_laplacian(mat):<br />
<br />
"""This function applies a discretized Laplacian<br />
<br />
in periodic boundary conditions to a matrix<br />
<br />
For more information see<br />
<br />
https://en.wikipedia.org/wiki/Discrete_Laplace_operator#Implementation_via_operator_discretization<br />
<br />
"""<br />
<br />
<br />
<br />
# the cell appears 4 times in the formula to compute<br />
<br />
# the total difference<br />
<br />
neigh_mat = -4*mat.copy()<br />
<br />
<br />
<br />
# Each direct neighbor on the lattice is counted in<br />
<br />
# the discrete difference formula<br />
<br />
neighbors = [<br />
<br />
( 1.0, (-1, 0) ),<br />
<br />
( 1.0, ( 0,-1) ),<br />
<br />
( 1.0, ( 0, 1) ),<br />
<br />
( 1.0, ( 1, 0) ),<br />
<br />
]<br />
<br />
<br />
<br />
# shift matrix according to demanded neighbors<br />
<br />
# and add to this cell with corresponding weight<br />
<br />
for weight, neigh in neighbors:<br />
<br />
neigh_mat += weight * np.roll(mat, neigh, (0,1))<br />
<br />
<br />
<br />
return neigh_mat<br />
<br />
<br />
<br />
# Define the update formula for chemicals A and B<br />
<br />
def update(A, B, DA, DB, f, k, delta_t):<br />
<br />
"""Apply the Gray-Scott update formula"""<br />
<br />
<br />
<br />
# compute the diffusion part of the update<br />
<br />
diff_A = DA * apply_laplacian(A)<br />
<br />
diff_B = DB * apply_laplacian(B)<br />
<br />
<br />
<br />
# Apply chemical reaction<br />
<br />
reaction = A*B**2<br />
<br />
diff_A -= reaction<br />
<br />
diff_B += reaction<br />
<br />
<br />
<br />
# Apply birth/death<br />
<br />
diff_A += f * (1-A)<br />
<br />
diff_B -= (k+f) * B<br />
<br />
<br />
<br />
A += diff_A * delta_t<br />
<br />
B += diff_B * delta_t<br />
<br />
<br />
<br />
return A, B<br />
<br />
<br />
<br />
def get_initial_A_and_B(N, random_influence = 0.2):<br />
<br />
"""get the initial chemical concentrations"""<br />
<br />
<br />
<br />
# get initial homogeneous concentrations<br />
<br />
A = (1-random_influence) * np.ones((N,N))<br />
<br />
B = np.zeros((N,N))<br />
<br />
<br />
<br />
# put some noise on there<br />
<br />
A += random_influence * np.random.random((N,N))<br />
<br />
B += random_influence * np.random.random((N,N))<br />
<br />
<br />
<br />
# get center and radius for initial disturbance<br />
<br />
N2, r = N//2, 50<br />
<br />
<br />
<br />
# apply initial disturbance<br />
<br />
A[N2-r:N2+r, N2-r:N2+r] = 0.50<br />
<br />
B[N2-r:N2+r, N2-r:N2+r] = 0.25<br />
<br />
<br />
<br />
return A, B<br />
<br />
<br />
<br />
def draw(A, B):<br />
<br />
"""return the matplotlib artists for animation"""<br />
<br />
fig, ax = pl.subplots(1,2,figsize=(5.65,3))<br />
<br />
imA = ax[0].imshow(A, animated=True,vmin=0,cmap='Greys')<br />
<br />
imB = ax[1].imshow(B, animated=True,vmax=1,cmap='Greys')<br />
<br />
ax[0].axis('off')<br />
<br />
ax[1].axis('off')<br />
<br />
ax[0].set_title('A')<br />
<br />
ax[1].set_title('B')<br />
<br />
<br />
<br />
return fig, imA, imB<br />
<br />
<br />
<br />
# =========== define model parameters ==========<br />
<br />
<br />
<br />
# update in time<br />
<br />
delta_t = 1.0<br />
<br />
<br />
<br />
# Diffusion coefficients<br />
<br />
DA = 0.16<br />
<br />
DB = 0.08<br />
<br />
<br />
<br />
# define birth/death rates<br />
<br />
f = 0.060<br />
<br />
k = 0.062<br />
<br />
<br />
<br />
# grid size<br />
<br />
N = 200<br />
<br />
<br />
<br />
# intialize the chemical concentrations<br />
<br />
A, B = get_initial_A_and_B(N)<br />
<br />
<br />
<br />
N_simulation_steps = 10000<br />
<br />
for step in range(N_simulation_steps):<br />
<br />
A, B = update(A, B, DA, DB, f, k, delta_t)<br />
<br />
<br />
<br />
draw(A, B)<br />
<br />
<br />
<br />
# show the result<br />
<br />
pl.show()<br />
<br />
Olivier Lévêque
Enseignant
Olivier Lévêque est maître d’enseignement et de recherche à la Faculté Informatique et Communications de l’EPFL. Ayant d’abord obtenu son diplôme de physique à l’EPFL en 1995, puis soutenu sa thèse en mathématiques en 2001, toujours à l’EPFL, il a ensuite rejoint la Faculté Informatique et Communications. Son domaine de spécialisation est celui des probabilités: pendant sa thèse, il a travaillé plus spécifiquement sur les équations aux dérivées partielles stochastiques, et depuis son arrivée à la Facuilté I&C, il s’est intéressé plus particulièrement à la théorie des matrices aléatoires, ainsi qu’à ses nombreuses applications.
D’autre part, Olivier s’est beaucoup investi ces dernières années dans la formation des enseignants d’informatique au gymnase (avec le programme GymInf, notamment) pour préparer l’arrivée de la nouvelle discipline obligatoire.
<span style="color:red">import numpy as np</span><br />
<br />
import matplotlib.pyplot as pl<br />
<br />
<br />
<br />
# ============ define relevant functions =============<br />
<br />
<br />
<br />
# an efficient function to compute a mean over neighboring cells<br />
<br />
def apply_laplacian(mat):<br />
<br />
"""This function applies a discretized Laplacian<br />
<br />
in periodic boundary conditions to a matrix<br />
<br />
For more information see<br />
<br />
https://en.wikipedia.org/wiki/Discrete_Laplace_operator#Implementation_via_operator_discretization<br />
<br />
"""<br />
<br />
<br />
<br />
# the cell appears 4 times in the formula to compute<br />
<br />
# the total difference<br />
<br />
neigh_mat = -4*mat.copy()<br />
<br />
<br />
<br />
# Each direct neighbor on the lattice is counted in<br />
<br />
# the discrete difference formula<br />
<br />
neighbors = [<br />
<br />
( 1.0, (-1, 0) ),<br />
<br />
( 1.0, ( 0,-1) ),<br />
<br />
( 1.0, ( 0, 1) ),<br />
<br />
( 1.0, ( 1, 0) ),<br />
<br />
]<br />
<br />
<br />
<br />
# shift matrix according to demanded neighbors<br />
<br />
# and add to this cell with corresponding weight<br />
<br />
for weight, neigh in neighbors:<br />
<br />
neigh_mat += weight * np.roll(mat, neigh, (0,1))<br />
<br />
<br />
<br />
return neigh_mat<br />
<br />
<br />
<br />
# Define the update formula for chemicals A and B<br />
<br />
def update(A, B, DA, DB, f, k, delta_t):<br />
<br />
"""Apply the Gray-Scott update formula"""<br />
<br />
<br />
<br />
# compute the diffusion part of the update<br />
<br />
diff_A = DA * apply_laplacian(A)<br />
<br />
diff_B = DB * apply_laplacian(B)<br />
<br />
<br />
<br />
# Apply chemical reaction<br />
<br />
reaction = A*B**2<br />
<br />
diff_A -= reaction<br />
<br />
diff_B += reaction<br />
<br />
<br />
<br />
# Apply birth/death<br />
<br />
diff_A += f * (1-A)<br />
<br />
diff_B -= (k+f) * B<br />
<br />
<br />
<br />
A += diff_A * delta_t<br />
<br />
B += diff_B * delta_t<br />
<br />
<br />
<br />
return A, B<br />
<br />
<br />
<br />
def get_initial_A_and_B(N, random_influence = 0.2):<br />
<br />
"""get the initial chemical concentrations"""<br />
<br />
<br />
<br />
# get initial homogeneous concentrations<br />
<br />
A = (1-random_influence) * np.ones((N,N))<br />
<br />
B = np.zeros((N,N))<br />
<br />
<br />
<br />
# put some noise on there<br />
<br />
A += random_influence * np.random.random((N,N))<br />
<br />
B += random_influence * np.random.random((N,N))<br />
<br />
<br />
<br />
# get center and radius for initial disturbance<br />
<br />
N2, r = N//2, 50<br />
<br />
<br />
<br />
# apply initial disturbance<br />
<br />
A[N2-r:N2+r, N2-r:N2+r] = 0.50<br />
<br />
B[N2-r:N2+r, N2-r:N2+r] = 0.25<br />
<br />
<br />
<br />
return A, B<br />
<br />
<br />
<br />
def draw(A, B):<br />
<br />
"""return the matplotlib artists for animation"""<br />
<br />
fig, ax = pl.subplots(1,2,figsize=(5.65,3))<br />
<br />
imA = ax[0].imshow(A, animated=True,vmin=0,cmap='Greys')<br />
<br />
imB = ax[1].imshow(B, animated=True,vmax=1,cmap='Greys')<br />
<br />
ax[0].axis('off')<br />
<br />
ax[1].axis('off')<br />
<br />
ax[0].set_title('A')<br />
<br />
ax[1].set_title('B')<br />
<br />
<br />
<br />
return fig, imA, imB<br />
<br />
<br />
<br />
# =========== define model parameters ==========<br />
<br />
<br />
<br />
# update in time<br />
<br />
delta_t = 1.0<br />
<br />
<br />
<br />
# Diffusion coefficients<br />
<br />
DA = 0.16<br />
<br />
DB = 0.08<br />
<br />
<br />
<br />
# define birth/death rates<br />
<br />
f = 0.060<br />
<br />
k = 0.062<br />
<br />
<br />
<br />
# grid size<br />
<br />
N = 200<br />
<br />
<br />
<br />
# intialize the chemical concentrations<br />
<br />
A, B = get_initial_A_and_B(N)<br />
<br />
<br />
<br />
N_simulation_steps = 10000<br />
<br />
for step in range(N_simulation_steps):<br />
<br />
A, B = update(A, B, DA, DB, f, k, delta_t)<br />
<br />
<br />
<br />
draw(A, B)<br />
<br />
<br />
<br />
# show the result<br />
<br />
pl.show()<br />
<br />
Romain Edelmann
Enseignant
Romain Edelmann enseigne l'informatique au Gymnase de Burier, là-même où il avait obtenu sa maturité et découvert sa passion pour l'informatique. Sa maturité en poche, Romain a décidé d'étudier à l'EPFL et y a obtenu un bachelor, un master et finalement un doctorat en informatique.
Durant ses études, Romain a largement profité des nombreuses occasions de partir à l'étranger. Il a notamment passé une année à l'université nationale de Singapour et 6 mois à Google Zurich. Depuis la fin de ses études, Romain a été très actif dans l'enseignement de l'informatique. Récemment, il a été impliqué dans la création de ressources pour l'enseignement de l'informatique au gymnase et donne des Summer Schools à l'EPFL pour les gymnasiens.
import numpy as np<br />
<br />
import matplotlib.pyplot as pl<br />
<br />
<br />
<br />
# ============ define relevant functions =============<br />
<br />
<br />
<br />
# an efficient function to compute a mean over neighboring cells<br />
<br />
def apply_laplacian(mat):<br />
<br />
"""This function applies a discretized Laplacian<br />
<br />
in periodic boundary conditions to a matrix<br />
<br />
For more information see<br />
<br />
https://en.wikipedia.org/wiki/Discrete_Laplace_operator#Implementation_via_operator_discretization<br />
<br />
"""<br />
<br />
<br />
<br />
# the cell appears 4 times in the formula to compute<br />
<br />
# the total difference<br />
<br />
neigh_mat = -4*mat.copy()<br />
<br />
<br />
<br />
# Each direct neighbor on the lattice is counted in<br />
<br />
# the discrete difference formula<br />
<br />
neighbors = [<br />
<br />
( 1.0, (-1, 0) ),<br />
<br />
( 1.0, ( 0,-1) ),<br />
<br />
( 1.0, ( 0, 1) ),<br />
<br />
( 1.0, ( 1, 0) ),<br />
<br />
]<br />
<br />
<br />
<br />
# shift matrix according to demanded neighbors<br />
<br />
# and add to this cell with corresponding weight<br />
<br />
for weight, neigh in neighbors:<br />
<br />
neigh_mat += weight * np.roll(mat, neigh, (0,1))<br />
<br />
<br />
<br />
return neigh_mat<br />
<br />
<br />
<br />
# Define the update formula for chemicals A and B<br />
<br />
def update(A, B, DA, DB, f, k, delta_t):<br />
<br />
"""Apply the Gray-Scott update formula"""<br />
<br />
<br />
<br />
# compute the diffusion part of the update<br />
<br />
diff_A = DA * apply_laplacian(A)<br />
<br />
diff_B = DB * apply_laplacian(B)<br />
<br />
<br />
<br />
# Apply chemical reaction<br />
<br />
reaction = A*B**2<br />
<br />
diff_A -= reaction<br />
<br />
diff_B += reaction<br />
<br />
<br />
<br />
# Apply birth/death<br />
<br />
diff_A += f * (1-A)<br />
<br />
diff_B -= (k+f) * B<br />
<br />
<br />
<br />
A += diff_A * delta_t<br />
<br />
B += diff_B * delta_t<br />
<br />
<br />
<br />
return A, B<br />
<br />
<br />
<br />
def get_initial_A_and_B(N, random_influence = 0.2):<br />
<br />
"""get the initial chemical concentrations"""<br />
<br />
<br />
<br />
# get initial homogeneous concentrations<br />
<br />
A = (1-random_influence) * np.ones((N,N))<br />
<br />
B = np.zeros((N,N))<br />
<br />
<br />
<br />
# put some noise on there<br />
<br />
A += random_influence * np.random.random((N,N))<br />
<br />
B += random_influence * np.random.random((N,N))<br />
<br />
<br />
<br />
# get center and radius for initial disturbance<br />
<br />
N2, r = N//2, 50<br />
<br />
<br />
<br />
# apply initial disturbance<br />
<br />
A[N2-r:N2+r, N2-r:N2+r] = 0.50<br />
<br />
B[N2-r:N2+r, N2-r:N2+r] = 0.25<br />
<br />
<br />
<br />
return A, B<br />
<br />
<br />
<br />
def draw(A, B):<br />
<br />
"""return the matplotlib artists for animation"""<br />
<br />
fig, ax = pl.subplots(1,2,figsize=(5.65,3))<br />
<br />
imA = ax[0].imshow(A, animated=True,vmin=0,cmap='Greys')<br />
<br />
imB = ax[1].imshow(B, animated=True,vmax=1,cmap='Greys')<br />
<br />
ax[0].axis('off')<br />
<br />
ax[1].axis('off')<br />
<br />
ax[0].set_title('A')<br />
<br />
ax[1].set_title('B')<br />
<br />
<br />
<br />
return fig, imA, imB<br />
<br />
<br />
<br />
# =========== define model parameters ==========<br />
<br />
<br />
<br />
# update in time<br />
<br />
delta_t = 1.0<br />
<br />
<br />
<br />
# Diffusion coefficients<br />
<br />
DA = 0.16<br />
<br />
DB = 0.08<br />
<br />
<br />
<br />
# define birth/death rates<br />
<br />
f = 0.060<br />
<br />
k = 0.062<br />
<br />
<br />
<br />
# grid size<br />
<br />
N = 200<br />
<br />
<br />
<br />
# intialize the chemical concentrations<br />
<br />
A, B = get_initial_A_and_B(N)<br />
<br />
<br />
<br />
N_simulation_steps = 10000<br />
<br />
for step in range(N_simulation_steps):<br />
<br />
A, B = update(A, B, DA, DB, f, k, delta_t)<br />
<br />
<br />
<br />
draw(A, B)<br />
<br />
<br />
<br />
# show the result<br />
<br />
pl.show()<br />
<br />
Joachim Hugonot
Enseignant
Joachim Hugonot est enseignant d'informatique au gymnase de Renens. Il a obtenu son master et son bachelor en informatique à l'EPFL et a travaillé pendant 5 ans comme ingénieur de recherche dans deux laboratoires de l'EPFL. Joachim est passionné par l'intelligence artificielle, les réseaux de neurones, les modèles génératifs et la façon dont ces algorithmes se sont insinués dans nos vies. Il a pour volonté de développer la pensée critique, la curiosité et la prise de conscience chez ses élèves quant aux enjeux de société liés à l’informatique.
import numpy as np<br />
<br />
import matplotlib.pyplot as pl<br />
<br />
<br />
<br />
# ============ define relevant functions =============<br />
<br />
<br />
<br />
# an efficient function to compute a mean over neighboring cells<br />
<br />
def apply_laplacian(mat):<br />
<br />
"""This function applies a discretized Laplacian<br />
<br />
in periodic boundary conditions to a matrix<br />
<br />
For more information see<br />
<br />
https://en.wikipedia.org/wiki/Discrete_Laplace_operator#Implementation_via_operator_discretization<br />
<br />
"""<br />
<br />
<br />
<br />
# the cell appears 4 times in the formula to compute<br />
<br />
# the total difference<br />
<br />
neigh_mat = -4*mat.copy()<br />
<br />
<br />
<br />
# Each direct neighbor on the lattice is counted in<br />
<br />
# the discrete difference formula<br />
<br />
neighbors = [<br />
<br />
( 1.0, (-1, 0) ),<br />
<br />
( 1.0, ( 0,-1) ),<br />
<br />
( 1.0, ( 0, 1) ),<br />
<br />
( 1.0, ( 1, 0) ),<br />
<br />
]<br />
<br />
<br />
<br />
# shift matrix according to demanded neighbors<br />
<br />
# and add to this cell with corresponding weight<br />
<br />
for weight, neigh in neighbors:<br />
<br />
neigh_mat += weight * np.roll(mat, neigh, (0,1))<br />
<br />
<br />
<br />
return neigh_mat<br />
<br />
<br />
<br />
# Define the update formula for chemicals A and B<br />
<br />
def update(A, B, DA, DB, f, k, delta_t):<br />
<br />
"""Apply the Gray-Scott update formula"""<br />
<br />
<br />
<br />
# compute the diffusion part of the update<br />
<br />
diff_A = DA * apply_laplacian(A)<br />
<br />
diff_B = DB * apply_laplacian(B)<br />
<br />
<br />
<br />
# Apply chemical reaction<br />
<br />
reaction = A*B**2<br />
<br />
diff_A -= reaction<br />
<br />
diff_B += reaction<br />
<br />
<br />
<br />
# Apply birth/death<br />
<br />
diff_A += f * (1-A)<br />
<br />
diff_B -= (k+f) * B<br />
<br />
<br />
<br />
A += diff_A * delta_t<br />
<br />
B += diff_B * delta_t<br />
<br />
<br />
<br />
return A, B<br />
<br />
<br />
<br />
def get_initial_A_and_B(N, random_influence = 0.2):<br />
<br />
"""get the initial chemical concentrations"""<br />
<br />
<br />
<br />
# get initial homogeneous concentrations<br />
<br />
A = (1-random_influence) * np.ones((N,N))<br />
<br />
B = np.zeros((N,N))<br />
<br />
<br />
<br />
# put some noise on there<br />
<br />
A += random_influence * np.random.random((N,N))<br />
<br />
B += random_influence * np.random.random((N,N))<br />
<br />
<br />
<br />
# get center and radius for initial disturbance<br />
<br />
N2, r = N//2, 50<br />
<br />
<br />
<br />
# apply initial disturbance<br />
<br />
A[N2-r:N2+r, N2-r:N2+r] = 0.50<br />
<br />
B[N2-r:N2+r, N2-r:N2+r] = 0.25<br />
<br />
<br />
<br />
return A, B<br />
<br />
<br />
<br />
def draw(A, B):<br />
<br />
"""return the matplotlib artists for animation"""<br />
<br />
fig, ax = pl.subplots(1,2,figsize=(5.65,3))<br />
<br />
imA = ax[0].imshow(A, animated=True,vmin=0,cmap='Greys')<br />
<br />
imB = ax[1].imshow(B, animated=True,vmax=1,cmap='Greys')<br />
<br />
ax[0].axis('off')<br />
<br />
ax[1].axis('off')<br />
<br />
ax[0].set_title('A')<br />
<br />
ax[1].set_title('B')<br />
<br />
<br />
<br />
return fig, imA, imB<br />
<br />
<br />
<br />
# =========== define model parameters ==========<br />
<br />
<br />
<br />
# update in time<br />
<br />
delta_t = 1.0<br />
<br />
<br />
<br />
# Diffusion coefficients<br />
<br />
DA = 0.16<br />
<br />
DB = 0.08<br />
<br />
<br />
<br />
# define birth/death rates<br />
<br />
f = 0.060<br />
<br />
k = 0.062<br />
<br />
<br />
<br />
# grid size<br />
<br />
N = 200<br />
<br />
<br />
<br />
# intialize the chemical concentrations<br />
<br />
A, B = get_initial_A_and_B(N)<br />
<br />
<br />
<br />
N_simulation_steps = 10000<br />
<br />
for step in range(N_simulation_steps):<br />
<br />
A, B = update(A, B, DA, DB, f, k, delta_t)<br />
<br />
<br />
<br />
draw(A, B)<br />
<br />
<br />
<br />
# show the result<br />
<br />
pl.show()<br />
<br />
Sébastien Kobler
Assistant
Sébastien Kobler est étudiant d'informatique à l'EPFL et ancien élève du cours Euler.
import numpy as np<br />
<br />
import matplotlib.pyplot as pl<br />
<br />
<br />
<br />
# ============ define relevant functions =============<br />
<br />
<br />
<br />
# an efficient function to compute a mean over neighboring cells<br />
<br />
def apply_laplacian(mat):<br />
<br />
"""This function applies a discretized Laplacian<br />
<br />
in periodic boundary conditions to a matrix<br />
<br />
For more information see<br />
<br />
https://en.wikipedia.org/wiki/Discrete_Laplace_operator#Implementation_via_operator_discretization<br />
<br />
"""<br />
<br />
<br />
<br />
# the cell appears 4 times in the formula to compute<br />
<br />
# the total difference<br />
<br />
neigh_mat = -4*mat.copy()<br />
<br />
<br />
<br />
# Each direct neighbor on the lattice is counted in<br />
<br />
# the discrete difference formula<br />
<br />
neighbors = [<br />
<br />
( 1.0, (-1, 0) ),<br />
<br />
( 1.0, ( 0,-1) ),<br />
<br />
( 1.0, ( 0, 1) ),<br />
<br />
( 1.0, ( 1, 0) ),<br />
<br />
]<br />
<br />
<br />
<br />
# shift matrix according to demanded neighbors<br />
<br />
# and add to this cell with corresponding weight<br />
<br />
for weight, neigh in neighbors:<br />
<br />
neigh_mat += weight * np.roll(mat, neigh, (0,1))<br />
<br />
<br />
<br />
return neigh_mat<br />
<br />
<br />
<br />
# Define the update formula for chemicals A and B<br />
<br />
def update(A, B, DA, DB, f, k, delta_t):<br />
<br />
"""Apply the Gray-Scott update formula"""<br />
<br />
<br />
<br />
# compute the diffusion part of the update<br />
<br />
diff_A = DA * apply_laplacian(A)<br />
<br />
diff_B = DB * apply_laplacian(B)<br />
<br />
<br />
<br />
# Apply chemical reaction<br />
<br />
reaction = A*B**2<br />
<br />
diff_A -= reaction<br />
<br />
diff_B += reaction<br />
<br />
<br />
<br />
# Apply birth/death<br />
<br />
diff_A += f * (1-A)<br />
<br />
diff_B -= (k+f) * B<br />
<br />
<br />
<br />
A += diff_A * delta_t<br />
<br />
B += diff_B * delta_t<br />
<br />
<br />
<br />
return A, B<br />
<br />
<br />
<br />
def get_initial_A_and_B(N, random_influence = 0.2):<br />
<br />
"""get the initial chemical concentrations"""<br />
<br />
<br />
<br />
# get initial homogeneous concentrations<br />
<br />
A = (1-random_influence) * np.ones((N,N))<br />
<br />
B = np.zeros((N,N))<br />
<br />
<br />
<br />
# put some noise on there<br />
<br />
A += random_influence * np.random.random((N,N))<br />
<br />
B += random_influence * np.random.random((N,N))<br />
<br />
<br />
<br />
# get center and radius for initial disturbance<br />
<br />
N2, r = N//2, 50<br />
<br />
<br />
<br />
# apply initial disturbance<br />
<br />
A[N2-r:N2+r, N2-r:N2+r] = 0.50<br />
<br />
B[N2-r:N2+r, N2-r:N2+r] = 0.25<br />
<br />
<br />
<br />
return A, B<br />
<br />
<br />
<br />
def draw(A, B):<br />
<br />
"""return the matplotlib artists for animation"""<br />
<br />
fig, ax = pl.subplots(1,2,figsize=(5.65,3))<br />
<br />
imA = ax[0].imshow(A, animated=True,vmin=0,cmap='Greys')<br />
<br />
imB = ax[1].imshow(B, animated=True,vmax=1,cmap='Greys')<br />
<br />
ax[0].axis('off')<br />
<br />
ax[1].axis('off')<br />
<br />
ax[0].set_title('A')<br />
<br />
ax[1].set_title('B')<br />
<br />
<br />
<br />
return fig, imA, imB<br />
<br />
<br />
<br />
# =========== define model parameters ==========<br />
<br />
<br />
<br />
# update in time<br />
<br />
delta_t = 1.0<br />
<br />
<br />
<br />
# Diffusion coefficients<br />
<br />
DA = 0.16<br />
<br />
DB = 0.08<br />
<br />
<br />
<br />
# define birth/death rates<br />
<br />
f = 0.060<br />
<br />
k = 0.062<br />
<br />
<br />
<br />
# grid size<br />
<br />
N = 200<br />
<br />
<br />
<br />
# intialize the chemical concentrations<br />
<br />
A, B = get_initial_A_and_B(N)<br />
<br />
<br />
<br />
N_simulation_steps = 10000<br />
<br />
for step in range(N_simulation_steps):<br />
<br />
A, B = update(A, B, DA, DB, f, k, delta_t)<br />
<br />
<br />
<br />
draw(A, B)<br />
<br />
<br />
<br />
# show the result<br />
<br />
pl.show()<br />
<br />
Jennyfer Steiner
Assistante
Jennyfer est en 3ème année de Bachelor de Systèmes de Communication à l'EPFL et a notamment pu enseigner dans les cours "Internet et code pour les filles" ainsi que "Toi aussi crée ton appli" proposés par l'EPFL.
import numpy as np<br />
<br />
import matplotlib.pyplot as pl<br />
<br />
<br />
<br />
# ============ define relevant functions =============<br />
<br />
<br />
<br />
# an efficient function to compute a mean over neighboring cells<br />
<br />
def apply_laplacian(mat):<br />
<br />
"""This function applies a discretized Laplacian<br />
<br />
in periodic boundary conditions to a matrix<br />
<br />
For more information see<br />
<br />
https://en.wikipedia.org/wiki/Discrete_Laplace_operator#Implementation_via_operator_discretization<br />
<br />
"""<br />
<br />
<br />
<br />
# the cell appears 4 times in the formula to compute<br />
<br />
# the total difference<br />
<br />
neigh_mat = -4*mat.copy()<br />
<br />
<br />
<br />
# Each direct neighbor on the lattice is counted in<br />
<br />
# the discrete difference formula<br />
<br />
neighbors = [<br />
<br />
( 1.0, (-1, 0) ),<br />
<br />
( 1.0, ( 0,-1) ),<br />
<br />
( 1.0, ( 0, 1) ),<br />
<br />
( 1.0, ( 1, 0) ),<br />
<br />
]<br />
<br />
<br />
<br />
# shift matrix according to demanded neighbors<br />
<br />
# and add to this cell with corresponding weight<br />
<br />
for weight, neigh in neighbors:<br />
<br />
neigh_mat += weight * np.roll(mat, neigh, (0,1))<br />
<br />
<br />
<br />
return neigh_mat<br />
<br />
<br />
<br />
# Define the update formula for chemicals A and B<br />
<br />
def update(A, B, DA, DB, f, k, delta_t):<br />
<br />
"""Apply the Gray-Scott update formula"""<br />
<br />
<br />
<br />
# compute the diffusion part of the update<br />
<br />
diff_A = DA * apply_laplacian(A)<br />
<br />
diff_B = DB * apply_laplacian(B)<br />
<br />
<br />
<br />
# Apply chemical reaction<br />
<br />
reaction = A*B**2<br />
<br />
diff_A -= reaction<br />
<br />
diff_B += reaction<br />
<br />
<br />
<br />
# Apply birth/death<br />
<br />
diff_A += f * (1-A)<br />
<br />
diff_B -= (k+f) * B<br />
<br />
<br />
<br />
A += diff_A * delta_t<br />
<br />
B += diff_B * delta_t<br />
<br />
<br />
<br />
return A, B<br />
<br />
<br />
<br />
def get_initial_A_and_B(N, random_influence = 0.2):<br />
<br />
"""get the initial chemical concentrations"""<br />
<br />
<br />
<br />
# get initial homogeneous concentrations<br />
<br />
A = (1-random_influence) * np.ones((N,N))<br />
<br />
B = np.zeros((N,N))<br />
<br />
<br />
<br />
# put some noise on there<br />
<br />
A += random_influence * np.random.random((N,N))<br />
<br />
B += random_influence * np.random.random((N,N))<br />
<br />
<br />
<br />
# get center and radius for initial disturbance<br />
<br />
N2, r = N//2, 50<br />
<br />
<br />
<br />
# apply initial disturbance<br />
<br />
A[N2-r:N2+r, N2-r:N2+r] = 0.50<br />
<br />
B[N2-r:N2+r, N2-r:N2+r] = 0.25<br />
<br />
<br />
<br />
return A, B<br />
<br />
<br />
<br />
def draw(A, B):<br />
<br />
"""return the matplotlib artists for animation"""<br />
<br />
fig, ax = pl.subplots(1,2,figsize=(5.65,3))<br />
<br />
imA = ax[0].imshow(A, animated=True,vmin=0,cmap='Greys')<br />
<br />
imB = ax[1].imshow(B, animated=True,vmax=1,cmap='Greys')<br />
<br />
ax[0].axis('off')<br />
<br />
ax[1].axis('off')<br />
<br />
ax[0].set_title('A')<br />
<br />
ax[1].set_title('B')<br />
<br />
<br />
<br />
return fig, imA, imB<br />
<br />
<br />
<br />
# =========== define model parameters ==========<br />
<br />
<br />
<br />
# update in time<br />
<br />
delta_t = 1.0<br />
<br />
<br />
<br />
# Diffusion coefficients<br />
<br />
DA = 0.16<br />
<br />
DB = 0.08<br />
<br />
<br />
<br />
# define birth/death rates<br />
<br />
f = 0.060<br />
<br />
k = 0.062<br />
<br />
<br />
<br />
# grid size<br />
<br />
N = 200<br />
<br />
<br />
<br />
# intialize the chemical concentrations<br />
<br />
A, B = get_initial_A_and_B(N)<br />
<br />
<br />
<br />
N_simulation_steps = 10000<br />
<br />
for step in range(N_simulation_steps):<br />
<br />
A, B = update(A, B, DA, DB, f, k, delta_t)<br />
<br />
<br />
<br />
draw(A, B)<br />
<br />
<br />
<br />
# show the result<br />
<br />
pl.show()<br />
<br />
Roman Paccaud
Assistant
Roman est en première année de Master en Informatique, avec une orientation en sciences de l'éducation. Il a notamment enseigné au cours "Décoder les QR codes" proposé par l'EPFL, et a été membre du comité national d'organisation du TFJM² (Tournoi Français des Jeunes Mathématiciennes et Mathématiciens) en 2023, un tournoi de mathématiques à destination des lycéens et lycéennes français·e·s leur proposant de résoudre en groupe des problèmes de recherche ne connaissant pas de solution complète connue.
import numpy as np<br />
<br />
import matplotlib.pyplot as pl<br />
<br />
<br />
<br />
# ============ define relevant functions =============<br />
<br />
<br />
<br />
# an efficient function to compute a mean over neighboring cells<br />
<br />
def apply_laplacian(mat):<br />
<br />
"""This function applies a discretized Laplacian<br />
<br />
in periodic boundary conditions to a matrix<br />
<br />
For more information see<br />
<br />
https://en.wikipedia.org/wiki/Discrete_Laplace_operator#Implementation_via_operator_discretization<br />
<br />
"""<br />
<br />
<br />
<br />
# the cell appears 4 times in the formula to compute<br />
<br />
# the total difference<br />
<br />
neigh_mat = -4*mat.copy()<br />
<br />
<br />
<br />
# Each direct neighbor on the lattice is counted in<br />
<br />
# the discrete difference formula<br />
<br />
neighbors = [<br />
<br />
( 1.0, (-1, 0) ),<br />
<br />
( 1.0, ( 0,-1) ),<br />
<br />
( 1.0, ( 0, 1) ),<br />
<br />
( 1.0, ( 1, 0) ),<br />
<br />
]<br />
<br />
<br />
<br />
# shift matrix according to demanded neighbors<br />
<br />
# and add to this cell with corresponding weight<br />
<br />
for weight, neigh in neighbors:<br />
<br />
neigh_mat += weight * np.roll(mat, neigh, (0,1))<br />
<br />
<br />
<br />
return neigh_mat<br />
<br />
<br />
<br />
# Define the update formula for chemicals A and B<br />
<br />
def update(A, B, DA, DB, f, k, delta_t):<br />
<br />
"""Apply the Gray-Scott update formula"""<br />
<br />
<br />
<br />
# compute the diffusion part of the update<br />
<br />
diff_A = DA * apply_laplacian(A)<br />
<br />
diff_B = DB * apply_laplacian(B)<br />
<br />
<br />
<br />
# Apply chemical reaction<br />
<br />
reaction = A*B**2<br />
<br />
diff_A -= reaction<br />
<br />
diff_B += reaction<br />
<br />
<br />
<br />
# Apply birth/death<br />
<br />
diff_A += f * (1-A)<br />
<br />
diff_B -= (k+f) * B<br />
<br />
<br />
<br />
A += diff_A * delta_t<br />
<br />
B += diff_B * delta_t<br />
<br />
<br />
<br />
return A, B<br />
<br />
<br />
<br />
def get_initial_A_and_B(N, random_influence = 0.2):<br />
<br />
"""get the initial chemical concentrations"""<br />
<br />
<br />
<br />
# get initial homogeneous concentrations<br />
<br />
A = (1-random_influence) * np.ones((N,N))<br />
<br />
B = np.zeros((N,N))<br />
<br />
<br />
<br />
# put some noise on there<br />
<br />
A += random_influence * np.random.random((N,N))<br />
<br />
B += random_influence * np.random.random((N,N))<br />
<br />
<br />
<br />
# get center and radius for initial disturbance<br />
<br />
N2, r = N//2, 50<br />
<br />
<br />
<br />
# apply initial disturbance<br />
<br />
A[N2-r:N2+r, N2-r:N2+r] = 0.50<br />
<br />
B[N2-r:N2+r, N2-r:N2+r] = 0.25<br />
<br />
<br />
<br />
return A, B<br />
<br />
<br />
<br />
def draw(A, B):<br />
<br />
"""return the matplotlib artists for animation"""<br />
<br />
fig, ax = pl.subplots(1,2,figsize=(5.65,3))<br />
<br />
imA = ax[0].imshow(A, animated=True,vmin=0,cmap='Greys')<br />
<br />
imB = ax[1].imshow(B, animated=True,vmax=1,cmap='Greys')<br />
<br />
ax[0].axis('off')<br />
<br />
ax[1].axis('off')<br />
<br />
ax[0].set_title('A')<br />
<br />
ax[1].set_title('B')<br />
<br />
<br />
<br />
return fig, imA, imB<br />
<br />
<br />
<br />
# =========== define model parameters ==========<br />
<br />
<br />
<br />
# update in time<br />
<br />
delta_t = 1.0<br />
<br />
<br />
<br />
# Diffusion coefficients<br />
<br />
DA = 0.16<br />
<br />
DB = 0.08<br />
<br />
<br />
<br />
# define birth/death rates<br />
<br />
f = 0.060<br />
<br />
k = 0.062<br />
<br />
<br />
<br />
# grid size<br />
<br />
N = 200<br />
<br />
<br />
<br />
# intialize the chemical concentrations<br />
<br />
A, B = get_initial_A_and_B(N)<br />
<br />
<br />
<br />
N_simulation_steps = 10000<br />
<br />
for step in range(N_simulation_steps):<br />
<br />
A, B = update(A, B, DA, DB, f, k, delta_t)<br />
<br />
<br />
<br />
draw(A, B)<br />
<br />
<br />
<br />
# show the result<br />
<br />
pl.show()<br />
<br />
Cédric Donner
Enseignant
Cédric Donner enseigne l’informatique au Collège du Sud (Gymnase), à Bulle, où il a obtenu sa maturité et développé sa passion pour l’informatique. Il a ensuite débuté des études d’informatique / physique à l’Université de Fribourg, pour bifurquer ensuite en mathématiques et y obtenir son master en 2008.
Déjà bien avant l’introduction de l’informatique comme discipline obligatoire au gymnase, Cédric a été très actif dans le développement de ressources pédagogiques d’enseignement de l’informatique, dans le cadre de son enseignement, du TJGroup et l'ETHZ. Il a contribué à la traduction et à la rédaction de plusieurs ouvrages pédagogiques pour l’école obligatoire et le gymnase. Actuellement, il contribue au développement d’outils et environnements d’apprentissage de l’informatique, notamment le nouvel IDE WebTigerPython, successeur de TigerJython.
import numpy as np<br />
<br />
import matplotlib.pyplot as pl<br />
<br />
<br />
<br />
# ============ define relevant functions =============<br />
<br />
<br />
<br />
# an efficient function to compute a mean over neighboring cells<br />
<br />
def apply_laplacian(mat):<br />
<br />
"""This function applies a discretized Laplacian<br />
<br />
in periodic boundary conditions to a matrix<br />
<br />
For more information see<br />
<br />
https://en.wikipedia.org/wiki/Discrete_Laplace_operator#Implementation_via_operator_discretization<br />
<br />
"""<br />
<br />
<br />
<br />
# the cell appears 4 times in the formula to compute<br />
<br />
# the total difference<br />
<br />
neigh_mat = -4*mat.copy()<br />
<br />
<br />
<br />
# Each direct neighbor on the lattice is counted in<br />
<br />
# the discrete difference formula<br />
<br />
neighbors = [<br />
<br />
( 1.0, (-1, 0) ),<br />
<br />
( 1.0, ( 0,-1) ),<br />
<br />
( 1.0, ( 0, 1) ),<br />
<br />
( 1.0, ( 1, 0) ),<br />
<br />
]<br />
<br />
<br />
<br />
# shift matrix according to demanded neighbors<br />
<br />
# and add to this cell with corresponding weight<br />
<br />
for weight, neigh in neighbors:<br />
<br />
neigh_mat += weight * np.roll(mat, neigh, (0,1))<br />
<br />
<br />
<br />
return neigh_mat<br />
<br />
<br />
<br />
# Define the update formula for chemicals A and B<br />
<br />
def update(A, B, DA, DB, f, k, delta_t):<br />
<br />
"""Apply the Gray-Scott update formula"""<br />
<br />
<br />
<br />
# compute the diffusion part of the update<br />
<br />
diff_A = DA * apply_laplacian(A)<br />
<br />
diff_B = DB * apply_laplacian(B)<br />
<br />
<br />
<br />
# Apply chemical reaction<br />
<br />
reaction = A*B**2<br />
<br />
diff_A -= reaction<br />
<br />
diff_B += reaction<br />
<br />
<br />
<br />
# Apply birth/death<br />
<br />
diff_A += f * (1-A)<br />
<br />
diff_B -= (k+f) * B<br />
<br />
<br />
<br />
A += diff_A * delta_t<br />
<br />
B += diff_B * delta_t<br />
<br />
<br />
<br />
return A, B<br />
<br />
<br />
<br />
def get_initial_A_and_B(N, random_influence = 0.2):<br />
<br />
"""get the initial chemical concentrations"""<br />
<br />
<br />
<br />
# get initial homogeneous concentrations<br />
<br />
A = (1-random_influence) * np.ones((N,N))<br />
<br />
B = np.zeros((N,N))<br />
<br />
<br />
<br />
# put some noise on there<br />
<br />
A += random_influence * np.random.random((N,N))<br />
<br />
B += random_influence * np.random.random((N,N))<br />
<br />
<br />
<br />
# get center and radius for initial disturbance<br />
<br />
N2, r = N//2, 50<br />
<br />
<br />
<br />
# apply initial disturbance<br />
<br />
A[N2-r:N2+r, N2-r:N2+r] = 0.50<br />
<br />
B[N2-r:N2+r, N2-r:N2+r] = 0.25<br />
<br />
<br />
<br />
return A, B<br />
<br />
<br />
<br />
def draw(A, B):<br />
<br />
"""return the matplotlib artists for animation"""<br />
<br />
fig, ax = pl.subplots(1,2,figsize=(5.65,3))<br />
<br />
imA = ax[0].imshow(A, animated=True,vmin=0,cmap='Greys')<br />
<br />
imB = ax[1].imshow(B, animated=True,vmax=1,cmap='Greys')<br />
<br />
ax[0].axis('off')<br />
<br />
ax[1].axis('off')<br />
<br />
ax[0].set_title('A')<br />
<br />
ax[1].set_title('B')<br />
<br />
<br />
<br />
return fig, imA, imB<br />
<br />
<br />
<br />
# =========== define model parameters ==========<br />
<br />
<br />
<br />
# update in time<br />
<br />
delta_t = 1.0<br />
<br />
<br />
<br />
# Diffusion coefficients<br />
<br />
DA = 0.16<br />
<br />
DB = 0.08<br />
<br />
<br />
<br />
# define birth/death rates<br />
<br />
f = 0.060<br />
<br />
k = 0.062<br />
<br />
<br />
<br />
# grid size<br />
<br />
N = 200<br />
<br />
<br />
<br />
# intialize the chemical concentrations<br />
<br />
A, B = get_initial_A_and_B(N)<br />
<br />
<br />
<br />
N_simulation_steps = 10000<br />
<br />
for step in range(N_simulation_steps):<br />
<br />
A, B = update(A, B, DA, DB, f, k, delta_t)<br />
<br />
<br />
<br />
draw(A, B)<br />
<br />
<br />
<br />
# show the result<br />
<br />
pl.show()<br />
<br />
Solal Pirelli
Enseignant
Solal Pirelli est chercheur en systèmes informatiques et méthodes formelles.
Il a obtenu son bachelor, master, et doctorat en informatique à l'EPFL, se spécialisant dans la vérification automatisée de logiciels réseaux comme les pare-feux.
À l'EPFL, il a co-enseigné les cours de Génie Logiciel et de Projet de Développement Logiciel, permettant aux étudiants de dépasser la simple écriture de code pour comprendre comment planifier, développer, et maintenir un produit logiciel.
Il a également organisé des évènements tels que le Helvetic Coding Contest, plus grand concours suisse de programmation, et LauzHack, un hackathon par et pour des étudiants.
import numpy as np<br />
<br />
import matplotlib.pyplot as pl<br />
<br />
<br />
<br />
# ============ define relevant functions =============<br />
<br />
<br />
<br />
# an efficient function to compute a mean over neighboring cells<br />
<br />
def apply_laplacian(mat):<br />
<br />
"""This function applies a discretized Laplacian<br />
<br />
in periodic boundary conditions to a matrix<br />
<br />
For more information see<br />
<br />
https://en.wikipedia.org/wiki/Discrete_Laplace_operator#Implementation_via_operator_discretization<br />
<br />
"""<br />
<br />
<br />
<br />
# the cell appears 4 times in the formula to compute<br />
<br />
# the total difference<br />
<br />
neigh_mat = -4*mat.copy()<br />
<br />
<br />
<br />
# Each direct neighbor on the lattice is counted in<br />
<br />
# the discrete difference formula<br />
<br />
neighbors = [<br />
<br />
( 1.0, (-1, 0) ),<br />
<br />
( 1.0, ( 0,-1) ),<br />
<br />
( 1.0, ( 0, 1) ),<br />
<br />
( 1.0, ( 1, 0) ),<br />
<br />
]<br />
<br />
<br />
<br />
# shift matrix according to demanded neighbors<br />
<br />
# and add to this cell with corresponding weight<br />
<br />
for weight, neigh in neighbors:<br />
<br />
neigh_mat += weight * np.roll(mat, neigh, (0,1))<br />
<br />
<br />
<br />
return neigh_mat<br />
<br />
<br />
<br />
# Define the update formula for chemicals A and B<br />
<br />
def update(A, B, DA, DB, f, k, delta_t):<br />
<br />
"""Apply the Gray-Scott update formula"""<br />
<br />
<br />
<br />
# compute the diffusion part of the update<br />
<br />
diff_A = DA * apply_laplacian(A)<br />
<br />
diff_B = DB * apply_laplacian(B)<br />
<br />
<br />
<br />
# Apply chemical reaction<br />
<br />
reaction = A*B**2<br />
<br />
diff_A -= reaction<br />
<br />
diff_B += reaction<br />
<br />
<br />
<br />
# Apply birth/death<br />
<br />
diff_A += f * (1-A)<br />
<br />
diff_B -= (k+f) * B<br />
<br />
<br />
<br />
A += diff_A * delta_t<br />
<br />
B += diff_B * delta_t<br />
<br />
<br />
<br />
return A, B<br />
<br />
<br />
<br />
def get_initial_A_and_B(N, random_influence = 0.2):<br />
<br />
"""get the initial chemical concentrations"""<br />
<br />
<br />
<br />
# get initial homogeneous concentrations<br />
<br />
A = (1-random_influence) * np.ones((N,N))<br />
<br />
B = np.zeros((N,N))<br />
<br />
<br />
<br />
# put some noise on there<br />
<br />
A += random_influence * np.random.random((N,N))<br />
<br />
B += random_influence * np.random.random((N,N))<br />
<br />
<br />
<br />
# get center and radius for initial disturbance<br />
<br />
N2, r = N//2, 50<br />
<br />
<br />
<br />
# apply initial disturbance<br />
<br />
A[N2-r:N2+r, N2-r:N2+r] = 0.50<br />
<br />
B[N2-r:N2+r, N2-r:N2+r] = 0.25<br />
<br />
<br />
<br />
return A, B<br />
<br />
<br />
<br />
def draw(A, B):<br />
<br />
"""return the matplotlib artists for animation"""<br />
<br />
fig, ax = pl.subplots(1,2,figsize=(5.65,3))<br />
<br />
imA = ax[0].imshow(A, animated=True,vmin=0,cmap='Greys')<br />
<br />
imB = ax[1].imshow(B, animated=True,vmax=1,cmap='Greys')<br />
<br />
ax[0].axis('off')<br />
<br />
ax[1].axis('off')<br />
<br />
ax[0].set_title('A')<br />
<br />
ax[1].set_title('B')<br />
<br />
<br />
<br />
return fig, imA, imB<br />
<br />
<br />
<br />
# =========== define model parameters ==========<br />
<br />
<br />
<br />
# update in time<br />
<br />
delta_t = 1.0<br />
<br />
<br />
<br />
# Diffusion coefficients<br />
<br />
DA = 0.16<br />
<br />
DB = 0.08<br />
<br />
<br />
<br />
# define birth/death rates<br />
<br />
f = 0.060<br />
<br />
k = 0.062<br />
<br />
<br />
<br />
# grid size<br />
<br />
N = 200<br />
<br />
<br />
<br />
# intialize the chemical concentrations<br />
<br />
A, B = get_initial_A_and_B(N)<br />
<br />
<br />
<br />
N_simulation_steps = 10000<br />
<br />
for step in range(N_simulation_steps):<br />
<br />
A, B = update(A, B, DA, DB, f, k, delta_t)<br />
<br />
<br />
<br />
draw(A, B)<br />
<br />
<br />
<br />
# show the result<br />
<br />
pl.show()<br />
<br />
Pierre Quinton
Enseignant
Pierre Quinton est chercheur et développeur passionné par l'informatique et les mathématiques. Il a obtenu son baccalauréat à Toulouse, puis a poursuivi ses études en informatique avec un Bachelor, suivi d'un Master en Data Science à l'EPFL. Son parcours l'a ensuite mené au Danemark, où il a effectué un stage chez B&O. Par la suite, il est retourné à l'EPFL pour y réaliser un doctorat en théorie de l'information.
Ses recherches se concentrent sur un large éventail de domaines, notamment la théorie de l'information, la théorie des probabilités, la théorie de la mesure, la théorie de l'ordre et l'optimisation multi-objective. En parallèle de ses activités de recherche, il est le développeur et le mainteneur de TorchJD (https://github.com/TorchJD/torchjd), une bibliothèque Python qui permet de faire de l'optimisation multi-objective basée sur PyTorch.
import numpy as np<br />
<br />
import matplotlib.pyplot as pl<br />
<br />
<br />
<br />
# ============ define relevant functions =============<br />
<br />
<br />
<br />
# an efficient function to compute a mean over neighboring cells<br />
<br />
def apply_laplacian(mat):<br />
<br />
"""This function applies a discretized Laplacian<br />
<br />
in periodic boundary conditions to a matrix<br />
<br />
For more information see<br />
<br />
https://en.wikipedia.org/wiki/Discrete_Laplace_operator#Implementation_via_operator_discretization<br />
<br />
"""<br />
<br />
<br />
<br />
# the cell appears 4 times in the formula to compute<br />
<br />
# the total difference<br />
<br />
neigh_mat = -4*mat.copy()<br />
<br />
<br />
<br />
# Each direct neighbor on the lattice is counted in<br />
<br />
# the discrete difference formula<br />
<br />
neighbors = [<br />
<br />
( 1.0, (-1, 0) ),<br />
<br />
( 1.0, ( 0,-1) ),<br />
<br />
( 1.0, ( 0, 1) ),<br />
<br />
( 1.0, ( 1, 0) ),<br />
<br />
]<br />
<br />
<br />
<br />
# shift matrix according to demanded neighbors<br />
<br />
# and add to this cell with corresponding weight<br />
<br />
for weight, neigh in neighbors:<br />
<br />
neigh_mat += weight * np.roll(mat, neigh, (0,1))<br />
<br />
<br />
<br />
return neigh_mat<br />
<br />
<br />
<br />
# Define the update formula for chemicals A and B<br />
<br />
def update(A, B, DA, DB, f, k, delta_t):<br />
<br />
"""Apply the Gray-Scott update formula"""<br />
<br />
<br />
<br />
# compute the diffusion part of the update<br />
<br />
diff_A = DA * apply_laplacian(A)<br />
<br />
diff_B = DB * apply_laplacian(B)<br />
<br />
<br />
<br />
# Apply chemical reaction<br />
<br />
reaction = A*B**2<br />
<br />
diff_A -= reaction<br />
<br />
diff_B += reaction<br />
<br />
<br />
<br />
# Apply birth/death<br />
<br />
diff_A += f * (1-A)<br />
<br />
diff_B -= (k+f) * B<br />
<br />
<br />
<br />
A += diff_A * delta_t<br />
<br />
B += diff_B * delta_t<br />
<br />
<br />
<br />
return A, B<br />
<br />
<br />
<br />
def get_initial_A_and_B(N, random_influence = 0.2):<br />
<br />
"""get the initial chemical concentrations"""<br />
<br />
<br />
<br />
# get initial homogeneous concentrations<br />
<br />
A = (1-random_influence) * np.ones((N,N))<br />
<br />
B = np.zeros((N,N))<br />
<br />
<br />
<br />
# put some noise on there<br />
<br />
A += random_influence * np.random.random((N,N))<br />
<br />
B += random_influence * np.random.random((N,N))<br />
<br />
<br />
<br />
# get center and radius for initial disturbance<br />
<br />
N2, r = N//2, 50<br />
<br />
<br />
<br />
# apply initial disturbance<br />
<br />
A[N2-r:N2+r, N2-r:N2+r] = 0.50<br />
<br />
B[N2-r:N2+r, N2-r:N2+r] = 0.25<br />
<br />
<br />
<br />
return A, B<br />
<br />
<br />
<br />
def draw(A, B):<br />
<br />
"""return the matplotlib artists for animation"""<br />
<br />
fig, ax = pl.subplots(1,2,figsize=(5.65,3))<br />
<br />
imA = ax[0].imshow(A, animated=True,vmin=0,cmap='Greys')<br />
<br />
imB = ax[1].imshow(B, animated=True,vmax=1,cmap='Greys')<br />
<br />
ax[0].axis('off')<br />
<br />
ax[1].axis('off')<br />
<br />
ax[0].set_title('A')<br />
<br />
ax[1].set_title('B')<br />
<br />
<br />
<br />
return fig, imA, imB<br />
<br />
<br />
<br />
# =========== define model parameters ==========<br />
<br />
<br />
<br />
# update in time<br />
<br />
delta_t = 1.0<br />
<br />
<br />
<br />
# Diffusion coefficients<br />
<br />
DA = 0.16<br />
<br />
DB = 0.08<br />
<br />
<br />
<br />
# define birth/death rates<br />
<br />
f = 0.060<br />
<br />
k = 0.062<br />
<br />
<br />
<br />
# grid size<br />
<br />
N = 200<br />
<br />
<br />
<br />
# intialize the chemical concentrations<br />
<br />
A, B = get_initial_A_and_B(N)<br />
<br />
<br />
<br />
N_simulation_steps = 10000<br />
<br />
for step in range(N_simulation_steps):<br />
<br />
A, B = update(A, B, DA, DB, f, k, delta_t)<br />
<br />
<br />
<br />
draw(A, B)<br />
<br />
<br />
<br />
# show the result<br />
<br />
pl.show()<br />
<br />
Pauline Raffestin
Administration
Pauline Raffestin est assistante administrative au sein de la Faculté Informatique et Communication de l’EPFL depuis 2016. Elle est gestionnaire du Laboratoire de Théorie du Calcul (THL4) du Prof. Michael Kapralov et du Laboratoire d’Informatique Réaliste (RGL) du Prof. Wenzel Jakob.
N’hésitez pas à la contacter pour toute question relative au Cours Turing. Elle se fera un plaisir de vous répondre.
24-08-2024
Algorithmique et programmation
Dans ce premier cours, vous découvrirez comment écrire un algorithme en Python et aussi comment étudier son efficacité, grâce à la notion de complexité temporelle.
Notes de cours -- Semaine 1Exercices -- Semaine 1 31-08-2024
Récursivité
Dans ce cours, vous apprendrez à utiliser des fonctions pour programmer et aussi comment programmer des algorithmes récursifs.
Notes de cours -- Semaine 2Exercices -- Semaine 2 07-09-2024
Collections en Python - listes, ensembles et dictionnaires
Dans ce cours, vous apprendrez à manipuler des structures de données couramment utilisées en Python, à savoir les listes, les ensembles et les dictionnaires.
Notes de cours -- Semaine 3Exercices -- Semaine 3 21-09-2024
Résolution de labyrinthes (I)
Dasn ce premier cours sur le sujet, vous apprendrez à générer (et aussi à représenter graphiquement) des labyrinthes.
Notes de cours -- Semaine 4Exercices -- Semaine 4 28-09-2024
Résolution de labyrinthes (II)
Dans ce cours, vous apprendrez des premières méthodes de résolution de labyrinthes en Python.
Notes de cours -- Semaine 5 05-10-2024
Résolution de labyrinthes (III)
Dans ce cours, nous poursuivrons l'exploration la résolution de labyrinthes au moyen d'algorithmes de résolution plus sophisiqués.
Notes de cours -- Semaine 6 02-11-2024
Cryptographie à clé secrète: perspective historique
Dans ce cours, nous ferons un tour d'horizon des algorithmes de cryptographie dits "classiques", du chiffre de César à celui utilisé dans la machine Enigma.
Notes de cours -- Semaine 7Exercices -- Semaine 7 09-11-2024
Représentation binaire et cryptographie moderne
Dans ce cours, nous aborderons la représentation binaire des nombres et son application à plusieurs algorithmes de cryptographie moderne (clé à usage unique, systèmes DES, AES).
Notes de cours -- Semaine 8Exercices -- Semaine 8 16-11-2024
Générateurs de nombres aléatoires et recherche de grands nombres premiers
Une machine peut-elle générer des suites de nombres complètement aléatoires, alors que fondamentalement, elle ne fait que suivre des instructions à la lettre? La question est non seulement passionnante, mais aussi très importante pour la cryptographie moderne. Dans la seconde partie du cours, nous aborderons la question de la recherche de grands nombres premiers.
Notes de cours -- Semaine 9Exercices -- Semaine 9 23-11-2024
Nombres premiers et factorisation
Dans ce cours, nous verrons comment tester efficacement si un nombre est premier, et aussi comment factoriser des nombres. Pour cela, nous aurons besoin des merveilles de l'arithmétique modulaire...
Notes de cours -- Semaine 10Exercices -- Semaine 10 30-11-2024
Cryptographie à clé publique
Dans ce cours, nous étudierons les principes de base la cryptographie à clé publique, avec notamment le célèbre algorithme d'échange de clé de Diffie-Hellman-Merkle qui utilise des fonctions à sens unique.
Notes de cours -- Semaine 11Exercices -- Semaine 11 07-12-2024
Cryptographie à clé publique: suite
Dans ce cours, vous découvrirez deux autres systèmes célèbres de cryptographie à clé publique, que sont le système de Rivest-Shamir-Adleman (RSA) et celui d'El Gamal.
Notes de cours -- Semaine 12Exercices -- Semaine 12 14-12-2024
Mini-compétition
Cette semaine, vous aurez l'occasion de vous mesurer en petites équipes sur les sujets appris tout au long de l'année. De la résolution de labyrinthes au déchiffrement d'énigmes, vous concourrez pour remporter la victoire de Noël!
11-01-2025
Représentation des images en informatique
Dans ce cours, vous découvrirez comment les images sont représentées en mémoire et commencerez à utiliser Python pour les manipuler.
Notes de cours -- Semaine 14Exercices -- Semaine 14 18-01-2025
Convolutions et noyaux
Dans ce cours, nous découvrirons l'opération de convolution qui nous permettra, entre autres, de rendre une image plus nette ou de détecter les contours.
Notes de cours -- Semaine 15Exercices -- Semaine 15 25-01-2025
Vision par ordinateur
Dans ce cours, nous découvrirons la Transformée de Hough et ses applications, mais aussi comment flouter l'arrière plan dans une image.
Notes de cours -- Semaine 16Exercices -- Semaine 16 01-02-2025
Réseaux de neurones convolutionnels
Dans ce cours, vous allez découvrir les bases des réseaux de neurones convolutionnels, comment les entraîner et les utiliser.
Notes de cours -- Semaine 17Exercices -- Semaine 17 08-02-2025
Coloriser des images en noir et blanc
Dans ce cours, vous utiliserez un réseau de neurones convolutionnel afin de coloriser des images en noir et blanc.
Notes de cours -- Semaine 18Exercices -- Semaine 18 01-03-2025
Les bases de la théorie des graphes
Dans ce cours, vous apprendrez les bases des graphes qui sont un outil puissant de modélisation. Nous découvrirons le problème des ponts de Königsberg mais également comment Google utilise des graphes pour son moteur de recherche
Notes de cours -- Semaine 19Exercices -- Semaine 19 08-03-2025
Le plus court chemin dans un graphe
Dans ce cours, nous découvrirons l'algorithme de Djikstra et l'algorithme A* qui permettent de trouver des chemins courts dans un graphe.
Notes de cours -- Semaine 20Exercices -- Semaine 20 15-03-2025
Maximiser le flot dans un graphe
Dans ce cours, vous découvrirez comment représenter le flot dans un graphe, l'algorithme de Ford et Fulkerson et ses variations.
Notes de cours -- Semaine 21Exercices -- Semaine 21 22-03-2025
Coloriage de graphes
Dans ce cours sera présenté le problème de coloriage de graphe qu'il est difficile de résoudre efficacement. Nous devrons donc comprendre comment définir formellement la complexité des algorithmes. Il sera également présenté les applications pratiques de ce problème.
Notes de cours -- Semaine 22Exercices -- Semaine 22 29-03-2025
Visiter tous les noeuds d'un graphe
Dans ce cours, nous découvrirons le problème du voyageur de commerce et l'importance des heuristiques pour résoudre certains problèmes efficacement.
Notes de cours -- Semaine 23Exercices -- Semaine 23 05-04-2025
Concevoir un interpréteur
La dernière partie de ce cours Turing est consacrée à la création d'un compilateur pour votre propre langage de programmation !
Nous commencerons cette première leçon par découvrir la notion d'arbre de syntaxe abstraite et la notion d'interpréteur.
Notes de cours -- Semaine 24Projet -- Semaine 24 03-05-2025
Analyse lexicale: du texte aux tokens
Nous nous intéresserons ensuite aux diverses phases qui composent généralement un compilateur, à commencer par la première, à savoir la phase d'analyse lexicale. Dans cette phase, le texte du programme à compiler est séparé en unités appelées tokens. Nous verrons plusieurs approches pour effectuer efficacement cette tâche.
Notes de cours -- Semaine 25Projet -- Semaine 25 10-05-2025
Analyse syntaxique: des tokens aux arbres de syntaxe
Le cours suivant est consacré à la phase suivante dans un compilateur: l'analyse syntaxique. C'est lors de cette phase que la séquence de tokens générée par la phase d'analyse lexicale est transformée en arbre de syntaxe abstraite. Nous aborderons diverses techniques pour effectuer cette transformation.
Notes de cours -- Semaine 26Projet -- Semaine 26 17-05-2025
Éviter que tout aille mal: le typage
Ensuite, nous aborderons la question des systèmes de types et de leurs utilisations. Nous verrons notamment comment les systèmes de types peuvent détecter des erreurs avant l'exécution des programmes.
Notes de cours -- Semaine 27Projet -- Semaine 27 24-05-2025
Génération de code
Finalement, nous aborderons la toute dernière phase de notre compilateur: la génération de code. Nous verrons comment, à partir d'un arbre de syntaxe abstraite, émettre une série d'instructions dans un langage plus bas niveau.
Notes de cours -- Semaine 28Projet -- Semaine 28