Informatique Pour Tous Interrogation n°3 I

publicité
Nom :
Prénom :
Informatique Pour Tous
Interrogation n°3
I-Syntaxe Python
I-1) Quelle est la commande Python qui permet d’ouvrir en lecture un fichier nommé MonFichier.txt
dans le répertoire courant du disque dur pour en utiliser ensuite le contenu ?
VarFichier = open(‘MonFichier.txt’,’r’)
I-2) On rappelle qu’en Python, la fonction sum(liste) produit la somme de tous les éléments de
liste
et que la forme liste = [valeur for i in range(entier)] produit exactement la même
chose que :
liste = []
for i in range(entier)
liste.append(valeur)
Soit la variable var = [(0,0,0,0),(1,0,0,0),(0,1,0,0),(0,0,1,0),(1,1,1,1)]
a) Quelle est la valeur de var[2]
(0, 1, 0, 0)
b) Quelle est la valeur de len(var)
5
c) Quelle est la valeur de len(var[1])
4
d) Quelle est la valeur de [var[i][1] for i in range(2,4)]
[1, 0]
e) Quelle est la valeur de [var[1][i] for i in range(2,4)]
[0, 0]
f) Quelle est la valeur de [var[i][i] for i in range(4)]
[0, 0, 0, 0]
II-Analyse de code
II-1) On rappelle qu’en Python l’opérateur % donne le reste de la division. Par exemple, 10%2 donne
0, 10%3 donne 1.
Qu’affiche à l’écran le script suivant :
def fonction(n, a):
terme = a
for k in range(n):
terme = (k*a*terme+a**2) % 256
return terme
Informatique Pour Tous
page 1/6
PCSI1 2016-2017
n = 2
a = 10
print("resultat1 = ", fonction (n, a))
print("resultat2 = ", fonction (a, n))
print("resultat3 = ",(n, a))
resultat1 = 76
resultat2 = 204
resultat3 = (2, 10)
II-2) Extrait de la documentation Python : « enumerate(thing), where thing is either an iterator or a
sequence, returns a iterator that will return the tuples (0, thing[0]), (1, thing[1]), (2,
thing[2]), and so forth.. »
Qu’affiche à l’écran le script suivant :
def fonction(t,p):
t1, t2 = [], t
for (i, x) in enumerate(t):
if x <= p :
t1.append(x)
else:
t2[i] = p
return t1, t2
t1 = [10, 1515, 2048, -10, 42]
t2 = [42, 73]
print(t1,t2)
print(t1,t2,fonction(t1 , 42))
[10, 1515, 2048, -10, 42] [42, 73]
[10, 42, 42, -10, 42] [42, 73] ([10, -10, 42], [10, 42, 42, -10, 42])
III-Projet : Prévention des collisions aériennes (d’après Centrale Informatique commune MP, PC, PSI, TSI )
Lors du dépôt d’un plan de vol, une compagnie aérienne doit préciser à quel niveau de vol elle souhaite
faire évoluer son avion lors de la phase de croisière. Ce niveau de vol souhaité, le RFL pour requested
flight level, correspond le plus souvent à l’altitude à laquelle la consommation de carburant sera minimale. Cette altitude dépend du type d’avion, de sa charge, de la distance à parcourir, des conditions météorologiques, etc.
Cependant, du fait des similitudes entre les différents avions qui équipent les compagnies aériennes, certains niveaux de vols sont très demandés ce qui engendre des conflits potentiels, deux avions risquant de
se croiser à des altitudes proches. Les contrôleurs aériens de la région concernée par un conflit doivent
alors gérer le croisement de ces deux avions.
Pour alléger le travail des contrôleurs et diminuer les risques, le système de régulation s’autorise à faire
voler un avion à un niveau différent de son RFL. Cependant, cela engendre généralement une augmentation de la consommation de carburant. C’est pourquoi on limite le choix aux niveaux immédiatement
supérieur et inférieur au RFL.
Ce problème de régulation est modélisé par un graphe dans lequel chaque vol est représenté par trois
sommets. Le sommet 0 correspond à l’attribution du RFL, le sommet + au niveau supérieur et le sommet
− au niveau inférieur. Chaque conflit potentiel entre deux vols sera représenté par une arête reliant les
Informatique Pour Tous
page 2/6
PCSI1 2016-2017
deux sommets concernés. Le coût d’un conflit potentiel (plus ou moins important en fonction de sa durée,
de la distance minimale entre les avions, etc.) sera représenté par une valuation sur l’arête correspondante.
Exemple de conflits potentiels entre trois vols
Dans l’exemple de la figure , faire voler les trois avions à leur RFL engendre un coût de régulation entre
A et B de 100 et un coût de régulation entre B et C de 400, soit un coût total de la régulation de 500 (il n’y
a pas de conflit entre A et C). Faire voler l’avion A à son RFL et les avions B et C au-dessus de leur RFL
engendre un conflit potentiel de coût 100 entre A et B et 150 entre A et C, soit un coût total de 250 (il n’y
a plus de conflit entre B et C).
On peut observer que cet exemple possède des solutions de coût nul, par exemple faire voler A et C à leur
RFL et B au-dessous de son RFL. Mais en général le nombre d’avions en vol est tel que des conflits potentiels sont inévitables. Le but de la régulation est d’imposer des plans de vol qui réduisent le plus possible le coût total de la résolution des conflits.
Chaque vol étant représenté par trois sommets, le graphe des conflits associé à n vols v0, v1, …, vn–1 possède 3n sommets que nous numéroterons de 0 à 3n − 1. Nous conviendrons que pour 0 ≤ k < n :
le sommet 3k représente le vol vk à son RFL ;
le sommet 3k + 1 représente le vol vk au-dessus de son RFL ;
le sommet 3k + 2 représente le vol vk au-dessous de son RFL ;
Le coût de chaque conflit potentiel est stocké dans une liste de 3n listes de 3n entiers (tableau 3n × 3n)
accessible grâce à la variable globale conflit (donc utilisable si nécessaire dans les fonctions à écrire cidessous) : si i et j désignent deux sommets du graphe, alors conflit[i][j] est égal au coût du conflit
potentiel (s’il existe) entre les plans de vol représentés par les sommets i et j. S’il n’y a pas de conflit entre
ces deux sommets, conflit[i][j] vaut 0. On convient que conflit[i][j] vaut 0 si les sommets i et j
correspondent au même vol (figure 4).
On notera que pour tout couple de sommets (i, j), conflit[i][j] et conflit[j][i], représentent un seul
et même conflit et donc conflit[i][j] = = conflit[j][i].
Tableau des coûts des conflits associé au graphe représenté sur la figure précédente
Informatique Pour Tous
page 3/6
PCSI1 2016-2017
III-1-a) Écrire en Python une fonction nb_conflits() sans paramètre qui renvoie le nombre de conflits
potentiels, c’est-à-dire le nombre d’arêtes de valuation non nulles du graphe décrit par la variable globale
conflit.
def nb_conflits() :
nb_lst = len(conflit)
#nombre de listes contenues dans de la liste conflit
nb= 0
for i in range(nb_lst):
# on boucle sur l’indice de toutes les lignes
for j in range(i+1, nb_lst): # on boucle sur les éléments au dessus de la diagonale
if conflit[i][j] != 0 :
# il y a conflit dans ce cas
nb = nb + 1
return nb
print(nb_conflits())
b) Exprimer la complexité de cette fonction en fonction de n.
La boucle Comme nb_lst = 3n,
la complexité de la fonction est donc
.
III-2) Régulation
Pour un vol vk on appelle niveau relatif l’entier rk valant 0, 1 ou 2 tel que :
rk = 0 représente le vol vk à son RFL ;
rk = 1 représente le vol vk au-dessus de son RFL ;
rk = 2 représente le vol vk au-dessous de son RFL.
On appelle régulation la liste (r0, r1,..., rn). Par exemple, la régulation (0, 0, …, 0) représente la situation
dans laquelle chaque avion se voit attribuer son RFL. Une régulation sera implantée en Python par une
liste d’entiers.
Il pourra être utile d’observer que les sommets du graphe des conflits choisis par la régulation r portent
les numéros 3k + rk pour 0 ≤ k < n.
Écrire en Python une fonction nb_vol_par_niveau_relatif(regulation)
nb_vol_par_niveau_relatif(regulation) qui prend en paramètre une
régulation (liste de n entiers) et qui renvoie une liste de 3 entiers [a, b, c] dans laquelle a est le nombre
de vols à leurs niveaux RFL, b le nombre de vols au-dessus de leurs niveaux RFL et c le nombre de vols
au-dessous de leurs niveaux RFL.
proposition simple
def nb_vol_par_niveau_relatif(regulation) :
a,b,c = 0,0,0
# initialisation des variables
for i in range(len(regulation)) :# on boucle sur les indices de tous les éléments de la liste regulation
r = regulation[i]
if r == 0 : a = a + 1
elif r == 1: b = b + 1
else : c = c + 1
return [a,b,c]
Informatique Pour Tous
# on prend l’élément d’indice i
# on teste les différents cas possibles
page 4/6
PCSI1 2016-2017
III-3) Coût d’une régulation
On appelle coût d’une régulation la somme des coûts des conflits potentiels que cette régulation engendre.
a) Écrire en Python une fonction cout_regulation(regulation)
cout_regulation(regulation) qui prend en paramètre une liste
représentant une régulation et qui renvoie le coût de celle-ci.
def cout_regulation1(regulation) :
cout = 0
# on initialise le cout à 0
lst_vols = []
# on commence par créer la liste des vols associés à la régulation
for (k, r) in enumerate(regulation) :
# on utilise la remarque de l’énoncé pour fabriquer ...
lst_vols.append(3*k + r )
nb_vols = len(lst_vols)
# le numéro du vol correspondant à chaque élément de regulation
# c’est le nombre de vols
for i in range(nb_vols) :
# on boucle sur l’indice de toutes les vols
for j in range(i+1,nb_vols):
# on boucle sur les éléments au dessus de la diagonale
cout = cout + conflit[lst_vols[i]][lst_vols[j]] #on ajoute le coût
#de l’éventuel conflit entre les deux vols d’indice i et j
return cout
b) Évaluer la complexité de cette fonction en fonction de n.
On remarque que le nb_vols == len(regulation) == n.
La première boucle for fait n itérations à 2 opérations donc une complexité en O(n). Les deux boucles imbriquées suivantes en fo
nt n(n – 1
) comme vu plus haut donc la complexité totale de la fonction est aussi en
c) Déduire de la question a) une fonction cout_RFL() qui renvoie le coût de la régulation pour laquelle chaque avion vole à son RFL.
Il suffit d’appliquer la fonction cout_regulation à une liste regulation ne contenant que des 0.
def cout_RFL() :
n = len(conflit[0])//3
« » » on détermine le nombre de vols à partir du premier élément de la liste conflit.
Attention à utiliser // pour obtenir un int, si l’on utilise /, on obtient un float qui ne permet pas de faire
la concaténation # multiple qui suit « » »
regul = [0] * n
# on crée la régulation RFL
return cout_regulation(regul)
d) Combien existe-t-il de régulations possibles pour n vols ?
e) Est-il envisageable de calculer les coûts de toutes les régulations possibles pour trouver celle de
cout minimal ?
Informatique Pour Tous
page 5/6
PCSI1 2016-2017
III-4) Recuit simulé
L’algorithme de recuit simulé part d’une régulation initiale quelconque (par exemple la régulation pour
laquelle chacun des avions vole à son RFL) et d’une valeur positive T choisie empiriquement. Il réalise
un nombre fini d’étapes se déroulant ainsi :
un vol vk est tiré au hasard ;
on modifie rk en tirant au hasard parmi les deux autres valeurs possibles ;
si cette modification diminue le coût de la régulation, cette modification est conservée ;
sinon, cette modification n’est conservée qu’avec une probabilité p = exp(–∆c/T), où ∆c est
l’augmentation de coût liée à la modification de la régulation ;
le paramètre T est diminué d’une certaine quantité.
Remarque. Dans la pratique, l’algorithme de recuit simulé est appliqué plusieurs fois de suite en partant à
chaque fois de la régulation obtenue à l’étape précédente, jusqu’à ne plus trouver d’amélioration notable.
On suppose importées les fonctions suivantes, que l’on pourra utiliser :
exp(x) qui renvoie l’exponentielle de x ;
randint(0,n) qui renvoie un entier tiré au sort dans [0, n] ;
random() qui renvoie un réel tiré au sort dans [0, 1]. Ainsi, un événement qui ne se produit que si
random() <= p a une probabilité p de se produire.
Écrire en Python une fonction recuit(regulation)
recuit(regulation) qui modifie la liste regulation passée en paramètre
en appliquant l’algorithme du recuit simulé. On fera débuter l’algorithme avec la valeur T = 1000 et à
chaque étape la valeur de T sera diminuée de 1%. L’algorithme se terminera lorsque T < 1.
def recuit(regulation) :
n = len(regulation)
# on calcule le nombre de vols
cout = cout_regulation(regulation) # on calcule le coût de la régulation initiale
T = 1000
# on initialise la variable de boucle
while T >= 1 :
vol = randint(0,n-1)
# on tire au sort l'indice d'un vol dans la liste regulation
old_r = regulation[vol]
# on garde la valeur actuelle du niveau du vol
r = randint(0,2)
# on tire au sort un niveau de vol
while r == old_r :
# on recommence tant que r n'est pas différent du niveau initial du vol
r = randint(0,2)
# une formule comme r = (old_r + randint (0,1) +1) % 3
# peut remplace la boucle
regulation[vol] = r
# on change le niveau du vol
nouv_cout = cout_regulation(regulation)
# on calcule le coût de la nouvelle
# régulation
delta_c = nouv_cout - cout
p = exp(-delta_c/T)
# calcul de la probabilité
if nouv_cout >= cout and random() > p:
# si le coût augmente ...
# et si la nouvelle régulation n’est pas conservée
regulation[vol] = old_r
Informatique Pour Tous
#on remet l'ancienne valeur du niveau,
page 6/6
PCSI1 2016-2017
Téléchargement