É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.
<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 />
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.
import numpy as np<br />
import matplotlib.pyplot as pl<br />
<br />
# ============ define relevant functions =============<br />
<br />
# an efficient function to compute a mean over neighboring cells<br />
def apply_laplacian(mat):<br />
"""This function applies a discretized Laplacian<br />
in periodic boundary conditions to a matrix<br />
For more information see<br />
https://en.wikipedia.org/wiki/Discrete_Laplace_operator#Implementation_via_operator_discretization<br />
"""<br />
<br />
# the cell appears 4 times in the formula to compute<br />
# the total difference<br />
neigh_mat = -4*mat.copy()<br />
<br />
# Each direct neighbor on the lattice is counted in<br />
# the discrete difference formula<br />
neighbors = [<br />
( 1.0, (-1, 0) ),<br />
( 1.0, ( 0,-1) ),<br />
( 1.0, ( 0, 1) ),<br />
( 1.0, ( 1, 0) ),<br />
]<br />
<br />
# shift matrix according to demanded neighbors<br />
# and add to this cell with corresponding weight<br />
for weight, neigh in neighbors:<br />
neigh_mat += weight * np.roll(mat, neigh, (0,1))<br />
<br />
return neigh_mat<br />
<br />
# Define the update formula for chemicals A and B<br />
def update(A, B, DA, DB, f, k, delta_t):<br />
"""Apply the Gray-Scott update formula"""<br />
<br />
# compute the diffusion part of the update<br />
diff_A = DA * apply_laplacian(A)<br />
diff_B = DB * apply_laplacian(B)<br />
<br />
# Apply chemical reaction<br />
reaction = A*B**2<br />
diff_A -= reaction<br />
diff_B += reaction<br />
<br />
# Apply birth/death<br />
diff_A += f * (1-A)<br />
diff_B -= (k+f) * B<br />
<br />
A += diff_A * delta_t<br />
B += diff_B * delta_t<br />
<br />
return A, B<br />
<br />
def get_initial_A_and_B(N, random_influence = 0.2):<br />
"""get the initial chemical concentrations"""<br />
<br />
# get initial homogeneous concentrations<br />
A = (1-random_influence) * np.ones((N,N))<br />
B = np.zeros((N,N))<br />
<br />
# put some noise on there<br />
A += random_influence * np.random.random((N,N))<br />
B += random_influence * np.random.random((N,N))<br />
<br />
# get center and radius for initial disturbance<br />
N2, r = N//2, 50<br />
<br />
# apply initial disturbance<br />
A[N2-r:N2+r, N2-r:N2+r] = 0.50<br />
B[N2-r:N2+r, N2-r:N2+r] = 0.25<br />
<br />
return A, B<br />
<br />
def draw(A, B):<br />
"""return the matplotlib artists for animation"""<br />
fig, ax = pl.subplots(1,2,figsize=(5.65,3))<br />
imA = ax[0].imshow(A, animated=True,vmin=0,cmap='Greys')<br />
imB = ax[1].imshow(B, animated=True,vmax=1,cmap='Greys')<br />
ax[0].axis('off')<br />
ax[1].axis('off')<br />
ax[0].set_title('A')<br />
ax[1].set_title('B')<br />
<br />
return fig, imA, imB<br />
<br />
# =========== define model parameters ==========<br />
<br />
# update in time<br />
delta_t = 1.0<br />
<br />
# Diffusion coefficients<br />
DA = 0.16<br />
DB = 0.08<br />
<br />
# define birth/death rates<br />
f = 0.060<br />
k = 0.062<br />
<br />
# grid size<br />
N = 200<br />
<br />
# intialize the chemical concentrations<br />
A, B = get_initial_A_and_B(N)<br />
<br />
N_simulation_steps = 10000<br />
for step in range(N_simulation_steps):<br />
A, B = update(A, B, DA, DB, f, k, delta_t)<br />
<br />
draw(A, B)<br />
<br />
# show the result<br />
pl.show()<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 />
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 />
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.
<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 />
Ernest Guisset
Assistant
Ernest Guisset est étudiant en master de mathématiques de l'EPFL, avec un intérêt particulier pour l'informatique. Il a fait auparavant du volontariat dans un Coding Club, où il enseignait la programmation à des enfants très jeunes. Il a aussi participé à l'enseignement de la "Semaine Théorie des jeux & IA." Il vient de Bruxelles, où il a effectué son bachelor.
<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 />
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.