CoursTuring


Algorithmes ? Programmation ?
Ils sont absolument partout dans votre quotidien.
Venez découvrir comment...


Avez-vous déjà passé des heures à regarder des vidéos en vous demandant comment la prochaine proposée est toujours plus captivante que la précédente ? Vous êtes-vous déjà demandé comment votre téléphone portable trouve le plus court chemin pour rentrer chez vous ? Ou peut-être aimez-vous simplement résoudre des énigmes et comprendre comment les choses fonctionnent ? Si oui, ce cours est pour vous : nous parlerons des algorithmes clés qui sont à la base de nos technologies modernes, en partant des fondements mathématiques jusqu’à leur implémentation concrète.

Public cible: élèves du gymnase (école de maturité, école de commerce, école de culture générale), 15-18 ans.

Pré-requis : une curiosité naturelle pour ces questions, une première expérience avec la programmation et le désir d’en apprendre plus.


Inscription

 Lien de pré-inscription

La date limite pour les pré-inscriptions est fixée au 30 juin 2024. Veuillez trouver ici le lien pour cette pré-inscription. Vous serez informé·e·s de votre inscription définitive d’ici au 15 juillet 2024. Afin de confirmer celle-ci, il vous sera alors demandé de régler 50.- de frais liés à ce cours.

Horaire du cours : le samedi, de 9h00 à 12h00
Les cours seront donnés en salle INF 3.

Plan d'accès

Contact

 Contact mail

Pour toutes demandes d'informations complémentaires ou autres remarques, vous pouvez vous adresser par mail à Fabienne Ubezio.

EPFL IC Cours Turing
BC 246 (Bâtiment BC)
Station 14
CH-1015 Lausanne



Partenaires

Ce cours a reçu le généreux soutien de:

- l'entreprise Camptocamp
- la fondation Inspir
- la fondation Goehner


É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 />

Benjamin Faltin
Assistant
Benjamin Faltin est étudiant en mathématiques à l'EPFL. En 2022, il a représenté l'Irlande aux Olympiades Internationales d'Informatique, et en 2023, il a représenté l'EPFL à la Compétition Internionale de Mathématiques. Il est impliqué maintenant dans l'enseignement et l'élaboration de problèmes pour les Olympiades Suisses d'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 />

Juliette Parchet
Assistante
Juliette Parchet est étudiante de Master en Data Science à l'EPFL, avec une orientation en sciences de l'éducation.
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 />

Fabienne Ubezio
Administration
Fabienne Ubezio est assistante administrative à l'EPFL depuis 13 années, avec une expérience au sein de laboratoires de recherche dans différentes facultés et 6 années passées à la direction de l'Ecole pour assister le Vice-Président de la Recherche.

Elle se réjouit de soutenir les étudiants et professeurs dans le lancement de ce nouveau cours Turing. N'hésitez pas à la contacter pour toutes questions, elle se fera un plaisir de vous répondre.

Programme

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 1
Exercices -- 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 2
Exercices -- 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 3
Exercices -- 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 4
Exercices -- Semaine 4



28-09-2024 

Résolution de labyrinthes (II)

Dans ce cours, vous étudierez quelques premiers algorithmes de résolution simples de labyrinthes, qui font appel à des algorithmes de recherche du plus court chemin dans un graphe.
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 7
Exercices -- 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 8
Exercices -- 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 9
Exercices -- 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 10
Exercices -- 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 11
Exercices -- 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 12
Exercices -- 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 14
Exercices -- 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 15
Exercices -- 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 16
Exercices -- 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 17
Exercices -- 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 18
Exercices -- 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 19
Exercices -- 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 20
Exercices -- 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 21
Exercices -- 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 22
Exercices -- 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 23
Exercices -- 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 24
Projet -- 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 25
Projet -- 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 26
Projet -- 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 27
Projet -- 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 28
Projet -- Semaine 28