tp3 matplotlib cor - lautre net · 2020. 11. 21. · tp3_matplotlib_cor november 21, 2020 1...

22
tp3_matplotlib_cor November 21, 2020 1 Représentation de graphes Dans ce TP,les points du plan sont définis par leur coordonnées. Celles-ci sont données sous forme de tableaux numpy : [1]: import numpy as np [2]: a = np.array([1,3])#point de coords (1,3) print(a) print(a.shape)#tableau à une dimension et de longueur 2 [1 3] (2,) [3]: # les tableaux se comportent comme des vecteurs A = np.array([1,3]) B = np.array([5,-3]) A+B, 3*A [3]: (array([6, 0]), array([3, 9])) 2 Bref tuto matplotlib Pour en savoir plus sur pyplot voir ici 2.1 Ligne brisée Pour tracer une ligne brisée sous matplotlib, il faut d’abord importer le module de tracé de courbes : [2]: import matplotlib.pyplot as plt [ ]: plt.annotate() Ensuite on donne une liste d’abscisses puis une liste d’ordonnées (de mêmes longueurs !). 1

Upload: others

Post on 14-Feb-2021

0 views

Category:

Documents


0 download

TRANSCRIPT

  • tp3_matplotlib_cor

    November 21, 2020

    1 Représentation de graphes

    Dans ce TP,les points du plan sont définis par leur coordonnées. Celles-ci sont données sous formede tableaux numpy :

    [1]: import numpy as np

    [2]: a = np.array([1,3])#point de coords (1,3)print(a)print(a.shape)#tableau à une dimension et de longueur 2

    [1 3](2,)

    [3]: # les tableaux se comportent comme des vecteursA = np.array([1,3])B = np.array([5,-3])A+B, 3*A

    [3]: (array([6, 0]), array([3, 9]))

    2 Bref tuto matplotlib

    Pour en savoir plus sur pyplot voir ici

    2.1 Ligne brisée

    Pour tracer une ligne brisée sous matplotlib, il faut d’abord importer le module de tracé de courbes:

    [2]: import matplotlib.pyplot as plt

    [ ]: plt.annotate()

    Ensuite on donne une liste d’abscisses puis une liste d’ordonnées (de mêmes longueurs !).

    1

    https://matplotlib.org/api/_as_gen/matplotlib.pyplot.plot.html

  • [5]: # liste des abscisseslesx=[2,-1,7,10]#les ordonnéeslesy=[-1,3,2,5]#commande de tracé de courbesp=plt.plot(lesx,lesy)#afficher le graphiqueplt.show()

    Tout est paramétrable. On peut imposer que le repère soit orthonormé, que la courbe soit verte,tracée en pointillés et d’épaisseur plus ou moins grande.

    [6]: plt.plot(lesx, lesy, color='green', marker='o',\linestyle='dashed',\

    linewidth=2, markersize=12)plt.show()

    2

  • On a demandé à ce que les sommets de la ligne brisée soit représentés par des cercles de taille 12,que la ligne elle-même soit d’épaisseur 2 et qu’elle soit constitué de tirets (dashed) et bien sûr quela couleur soit verte.

    Enfin, le repère n’est pas orthonormé par défaut. il faut récupérer le cadre de la figure et demanderl’orthonormalité (voir plus loin).

    Une petite chose pour finir. Faut-il écrire : - plt.plot(x,y) - ou bien p=plt.plot(x,y) ?

    Si vous ne désirez que tracer la ligne, la première solution est la plus simple. Mais en fait, lafonction plot crée un objet ligne. Parfois, on souhaite créer l’objet et le modifier (pointillés, couleur,épaisseur…) par la suite en fonction de contraintes qui ne seront connues que plus tard. Dans cecas la seconde solution est recomandée.

    2.2 Cercles

    Maintenant, traçons un cercle.il faut d’abord importer la fonction de bibliothèque nécessaire :

    [7]: from matplotlib.patches import Circle

    Dans l’exemple ci dessous, on crée une figure fig et son cadre ax. Puis on définit deux cercles, l’unvert à bord noir de centre (3, 4) et de rayon 2, l’autre blanc de rayon 1, centre (2, 2) et bord rouge.

    Une fois les cercles créés, on les ajoute au cadre avec la méthode

    ax.add_patch

    3

  • [8]: fig,ax = plt.subplots()#la figure, les axes# un cercle vertc1 = Circle((3,4),radius=2, edgecolor="black", facecolor = "green")#un cercle blancc2 = Circle((2,2),radius=1,edgecolor="red", facecolor = "white")#ajouter les cercles à la figureax.add_patch(c1)ax.add_patch(c2)#régler les abscisses min et maxax.set_xlim(-3,5)#les ordonnées min et maxax.set_ylim(-1,6)"""xbound better :The bound can changes automatically,if you later plot something that is not within the bound.In contrast, limits are fixed and do not change automatically."""#repère orthonorméax.axis("equal")plt.show()

    Mais il y a un problème. Comme on a ajouté le cercle blanc après le vert, il cache en partie soncompagnon plus gros.

    Pour éviter cela, on peut définir un coefficient de transparence grâce au paramètre alpha. Si celui-ci

    4

  • vaut 1,le cercle est opaque, à zéro, le cercle est invisble.

    [9]: fig,ax = plt.subplots()c1 = Circle((3,4),radius=2, edgecolor="black", facecolor = "green")#un cercle blanc, coef de transparnce alpha = 0.6c2 = Circle((2,2),radius=1,edgecolor="red", facecolor = "white",\

    alpha = 0.6)ax.add_patch(c1)ax.add_patch(c2)ax.set_xlim(-3,5)ax.set_ylim(-1,6)ax.axis("equal")plt.show()

    Maintenant nous allons inscrire du texte (une annotation) dans un cercle.

    [10]: fig,ax = plt.subplots()A=np.array([3,4])c1 = Circle(A,radius=2, edgecolor="black", facecolor = "green", alpha=0.6)ax.add_patch(c1)plt.annotate(xy=(3,4), s= "mon texte")ax.set_xlim(-3,5)ax.set_ylim(-1,6)ax.axis("equal")plt.show()

    5

  • On pourrait centrer un peu mieux, mais ça nous suffira.

    2.2.1 Limites vs Bound

    Au lieu de ax.set_xlim on peut utiliser ax.set_xbound. Dans ce dernier cas, les limites sur l’axedes x seront automatiquement adaptées si on ajoute une figure qui, pour être affichée, nécessite demodifier l’amplitude des abscisses.

    3 Exercices préliminaires

    3.1 Tracé d’un segment

    Si A et B sont deux points, l’ensemble des points de coordonnées tA+ (1− t)B pour 0 ≤ t ≤ 1 estexactement le segment [AB]. Si on prend 14 ≤ t ≤

    34 , on a une moitié de segment.

    [11]: #point AA=np.array([1,2])#point BB=np.array([5,-1])#milieu de [AB]I=1/2*A+1/2*Bprint(I)

    [3. 0.5]

    6

  • On observe que les tableaux numpy se comportent comme des vecteurs du cours de maths.

    On commence tout doucement :

    Erire une fonction

    def segment(A,B):

    qui prend en paramètres deux points (des tableaux numpy) et retourne l’objet ligne qui les relie.Les réglages par défaut suffiront.

    [12]: # ********************def segment(A,B):

    return plt.plot([A[0],B[0]],[A[1],B[1]])# ********************

    [13]: fig, ax = plt.subplots()A = np.array([1,2])B = np.array([5,-1])p=segment(A,B)xmin,xmax=min(A[0],B[0])-2,max(A[0],B[0])+2ymin,ymax=min(A[1],B[1])-2,max(A[1],B[1])+2ax.set_xlim(xmin,xmax)ax.set_ylim(ymin,ymax)plt.show()

    7

  • 3.2 Arête

    Ecrire une fonction

    def arete(A,B,p):

    qui prend en paramètres deux points A,B (des tableaux numpy) et un coefficient de proportion p(entre 0 et 1) et retourne les points C,D situés sur [AB] et tels que

    • C est à la distance pAB de A

    • D est à la distance pAB de B

    Avec p = 14 , A = (1, 2), B = (5,−1), la fonction retourne les points C et D comme sur le graphiqueci-dessous.

    [14]: # ******************def arete(A,B,p):

    return (1-p)*A+p*B,p*A+(1-p)*B# **********************

    [15]: A = np.array([1,2])B = np.array([5,-1])print(arete(A,B,1/4))

    (array([2. , 1.25]), array([ 4. , -0.25]))

    [16]: plt.clf()A = np.array([1,2])B = np.array([5,-1])segment(A,B)C,D = arete(A,B,1/4)segment(C,D)plt.show()

    8

  • [17]: # ***************************fig,ax=plt.subplots()A = np.array([1,2])B = np.array([5,-1])ax.set_xlim(-3,10)ax.set_ylim(-3,6)plt.annotate(xy=A,s="A")plt.annotate(xy=B,s="B")

    C,D= arete(A,B,1/4)

    plt.annotate(xy=C,s="C")plt.annotate(xy=D,s="D")#segment CDp=plt.plot([C[0],D[0]],[C[1],D[1]])plt.show()# ********************************

    9

  • 3.3 Distance euclidienne

    Ecrire une fonction

    def distance(A,B):

    qui retourne la distance euclidienne entre les points A et B

    [18]: # ***************def distance(A,B):

    AB=B-Areturn np.sqrt(AB[0]**2+AB[1]**2)

    # ************

    [19]: #*************def distance(A,B):

    return np.sqrt(((B-A)**2).sum())#***************

    [20]: A = np.array([1,2])B = np.array([5,-1])distance(A,B)

    [20]: 5.0

    10

  • [45]: A = np.array([1,2])B = np.array([5,-1])C = np.array([-3,1])l = [A,B,C]m = np.array([A,B,C])l

    [45]: [array([1, 2]), array([ 5, -1]), array([-3, 1])]

    3.4 Limites du graphique

    Ecrire une fonction

    def limites(t):

    qui prend en paramètres une liste de coordonnées et renvoie le minimum et le maximum desabscisses, le minimum et le maximum des ordonnée.

    [21]: def mini(l):m =l[0]for e in l:

    if e < m:m=e

    return m

    [36]: # ********************def limites(t):

    lesx=[p[0] for p in t]lesy=[p[1] for p in t]xmin=min(lesx)#min des abscisses des points de txmax=max(lesx)ymin=min(lesy)ymax=max(lesy)return xmin,xmax,ymin,ymax

    # ********************

    [37]: A = np.array([1,2])B = np.array([5,-1])C = np.array([2,4])t = [A,B,C]print(limites(t))

    (1, 5, -1, 4)

    3.5 Tracé de cercles

    Ecrire une fonction

    11

  • def trace_cercles(centres,rayons)

    qui prend en paramètres deux listes de même longueur, la première constituée des coordonnées descentres, la seconde des rayons des cercles.

    La fonction renvoie la liste constituée des cercles dont les centres sont indiqués dans la liste centreet les rayons dans la liste rayons

    Par défaut, les cercles ont un fond vert, un bord noir et un coefficient de transparence de 0.6.

    [38]: # ******************def trace_cercles(centres,rayons):

    cercles=[]for i in range(len(centres)):

    cercles.append(Circle(centres[i],\radius=rayons[i],\edgecolor="black", \facecolor="green",\alpha=0.6))

    return cercles# *******************

    [39]: fig,ax=plt.subplots()A = np.array([1,2])B = np.array([5,-1])C = np.array([2,4])centres=[A,B,C]rayons=[0.5]*3les_cercles = trace_cercles(centres,rayons)for c in les_cercles:

    ax.add_patch(c)xmin,xmax,ymin,ymax=limites(centres)ax.set_xbound(xmin-2,xmax+2)ax.set_ybound(ymin-2,ymax+2)ax.axis("equal")#orthonorméplt.show()

    12

  • 3.6 Sous-segments

    Ecrire une fonction

    def subsegment(A,B,r,c)

    qui prend en paramètres deux points A,B, un nombre r, tel que 0 ≤ r ≤ AB2 et une couleur deligne c. Le paramètre r représente le rayon de deux cercles centrés A et B. La fonction renvoiel’objet ligne qui est le sous-segment de [AB] de couleur définie par c et ne dépassant pas les bordsdes cercles.

    [40]: # *******************************def subsegment(A,B,r,c):

    assert r

  • #le sous segment est plus court que le segment completp2=subsegment(A,B,0.5,"blue")plt.show()

    [42]: type(p2)

    [42]: list

    Comme on peut le voir, le segment (rouge) est plus long que le sous-segment (bleu).

    3.7 Annotations

    Ecrire la fonction

    def trace_annotation(positions, textes):

    qui prend en argument une liste de positions et une liste de textes de même longueur.

    La fonction retourne une liste d’annotations.

    [43]: # ******************def trace_annotations(pos,text):

    res=[]for i in range(len(pos)):

    res.append(plt.annotate(xy=pos[i],s=text[i]))return res

    # ********************

    14

  • [44]: fig,ax=plt.subplots()A = np.array([1,2])B = np.array([5,-1])C = np.array([2,4])centres = [A,B,C]rayons = [0.5]*3

    #les cerclesles_cercles=trace_cercles(centres,rayons)for c in les_cercles:

    ax.add_patch(c)

    #les arêtessubsegment(A,B,0.5,"blue")subsegment(B,C,0.5,"red")subsegment(A,C,0.5,"black")

    #les annotationstrace_annotations(centres,["A","B","C"])

    #les limites du graphiquexmin,xmax,ymin,ymax=limites(centres)ax.set_xbound(xmin-2,xmax+2)ax.set_ybound(ymin-2,ymax+2)

    ax.axis("equal")#orthonorméplt.show()

    15

  • 4 Graphes non orientés

    Pour en savoir plus sur les graphes, voir ici

    Dans cette section, les graphes sont simples, non orientés et représentés par leurs matricesd’adjacence.

    Tout graphe G = (V,E) peut être en effet représenté par une matrice. Les relations entre arêteset sommets, appelées les relations d’incidence, sont toutes représentées par la matrice d’incidencedu graphe. Les relations d’adjacences (si deux sommets sont reliés par une arête ils sont adjacents)sont représentés par sa matrice d’adjacence. Elle est définie par

    aij =

    {1 si (vi, vj) ∈ E0 sinon.

    Par exemple, si on considère que A,B,C,D,E sont les sommets du graphe, la matrice d’adjacence

    M =

    0 1 0 1 01 0 1 0 00 1 0 1 11 0 1 0 10 0 1 1 0

    représente un grape à 5 sommets dessiné un peu plus bas.

    Comme le graphe est non orienté, la matrice est symétrique. Pour tous 0 ≤ i, j ≤ n− 1, on a ainsimi,j = mj,i.

    4.1 Tracer le graphe

    Ecrire une fonction

    def trace(m,coords, noms):

    qui prend en paramètres une matrice d’adjacence, la liste des coordonnées des sommets, celle deleurs noms et le cadre d’une figure. Bien sûr, si la matrice d’adjacence a n lignes, les longueurs desdeux autres lignes sont égales à n.

    La fonction crée tous les cercles, segments et annotations nécessaires. puis elle retourne la 3 listes(celles des cercles, des segments et des annotations).

    On pourrait affiner : définir les choix de couleur, de police de caractères, de lignes continues ounon… mais, pour simplifier, ces choix seront effectués par la fonction trace.

    [27]: # ****************def trace(m,coords,noms):

    nbl,nbc=m.shape

    16

    https://fr.wikipedia.org/wiki/Th%C3%A9orie_des_graphes

  • aretes,r=[],0.5cercles=trace_cercles(coords,[r]*len(coords))annotations=trace_annotations(coords,noms)for i in range(nbl):

    for j in range(i+1,nbc):#matrice TSif m[i,j]==1:# 0 ou 1 interprétés en false ou true

    aretes.append(subsegment(coords[i],coords[j],\r,"blue"))

    return cercles,annotations,aretes# ******************

    [28]: fig,ax=plt.subplots()A=np.array([0,0])B=np.array([0,4])C=np.array([4,4])D=np.array([4,0])E=np.array([5,2])coords=[A,B,C,D,E]noms=["A","B","C","D","E"]m=np.zeros((len(coords),len(coords)))m[0,1]=m[1,0]=m[0,3]=m[3,0]=1m[1,2]=m[2,1]=1m[2,3]=m[3,2]=m[2,4]=m[4,2]=m[3,4]=m[4,3]=1ce,an,ar=trace(m,coords,noms)#ajouter les cerclesfor c in ce:

    ax.add_patch(c)#les limites du graphiquexmin,xmax,ymin,ymax=limites(centres)ax.set_xbound(xmin-2,xmax+2)ax.set_ybound(ymin-2,ymax+2)

    ax.axis("equal")#orthonorméax.set_title("Graphe associé à la matrice $M$")plt.show()

    17

  • 4.2 Graphes orientés

    Cette fois-ci la matrice n’est plus symétrique. Et il faut ajouter des flèches à nos arêtes quideviennent donc des arcs.

    4.2.1 Flèche

    Ecrire une fonction

    def arrow(A,B,lg,alpha)

    qui prend en paramètres deux points A,B et retourne les points C,D tels que

    • ÂBC = ÂBD = alpha

    • C et D sont symétriques orthogonaux par rapport à (AB)

    • CD = lg

    [29]: from numpy import cos, sin, pi, arrayfrom numpy.linalg import norm #norme euclidienne (par défaut)

    [30]: np.linalg.norm(np.array([3,4]))#exemple

    [30]: 5.0

    18

  • [31]: np.linalg.norm(np.array([1,1])),2**0.5#exemple

    [31]: (1.4142135623730951, 1.4142135623730951)

    [32]: #*******************************def arrow(A,B,lg,alpha):

    BA=(A-B)/norm(B-A)#vecteur unitaire de même direction que BAxC=B[0]+lg*(cos(alpha)*BA[0]-sin(alpha)*BA[1])yC=B[1]+lg*(sin(alpha)*BA[0]+cos(alpha)*BA[1])C=array([xC,yC])alpha=-alphaxD=B[0]+lg*(cos(alpha)*BA[0]-sin(alpha)*BA[1])yD=B[1]+lg*(sin(alpha)*BA[0]+cos(alpha)*BA[1])D= array([xD,yD])return C,D

    # ***************

    [33]: A=np.array([0,0])B=np.array([4,4])C,D=arrow(A,B,0.5,pi/6)E,F=arrow(B,A,0.5,pi/6)print(C,D)

    [3.87059048 3.51703709] [3.51703709 3.87059048]

    [34]: fig,ax=plt.subplots()A=np.array([0,0])B=np.array([4,4])C,D=arrow(A,B,0.5,pi/6)

    subsegment(A,B,0,"blue")subsegment(C,B,0,"red")subsegment(D,B,0,"red")

    plt.annotate(xy=C,s='C')plt.annotate(xy=D,s='D')

    plt.annotate(xy=A-np.array([-0.1,0.1]),s='A')plt.annotate(xy=B,s='B')ax.axis("equal")plt.show()

    19

  • 4.2.2 Tracé

    Reprendre la fonction trace pour qu’elle représente maintenant un graphe orienté.

    def trace_oriente(m,coords,noms, alpha=pi/6,lg=0.5)

    On ajoute l’angle que doit respecter l’extrêmité de la flèche (par défaut π6

    ) et la longueur des petitsaxes (par défaut 0.5).

    Dans ce qui suit, le code choisit de représenter les extrêmités de flèches en rouge, mais vous pouvezchoisir une autre couleur.

    [35]: # ****************def trace_oriente(m,coords,noms, alpha=pi/6,lg=0.5):

    nbl,nbc=m.shapearetes,r=[],0.5cercles=trace_cercles(coords,[r]*len(coords))annotations=trace_annotations(coords,noms)for i in range(nbl):

    for j in range(nbc):if m[i,j]:# 1 ou 0 valent false ou true

    A,B=arete(coords[i],coords[j],r/distance(coords[i],coords[j]))C,D=arrow(A,B,lg,alpha)aretes.append(subsegment(A,B,0,"blue"))aretes.append(subsegment(C,B,0,"red"))aretes.append(subsegment(D,B,0,"red"))

    20

  • return cercles,annotations,aretes# ******************

    [36]: fig,ax=plt.subplots()A=np.array([0,0])B=np.array([0,4])C=np.array([4,4])D=np.array([4,0])E=np.array([8,4])F=np.array([8,0])coords=[A,B,C,D,E,F]noms=["A","B","C","D","E","F"]m=np.zeros((len(coords),len(coords)))m[0,1]=m[0,2]=1m[1,2]=m[2,3]=m[2,4]=1m[4,3]=m[4,0]=m[5,3]=1ce,an,ar=trace_oriente(m,coords,noms)#ajouter les cerclesfor c in ce:

    ax.add_patch(c)#les limites du graphiquexmin,xmax,ymin,ymax=limites(centres)ax.set_xlim(xmin-2,xmax+2)ax.set_ylim(ymin-2,ymax+2)

    ax.axis("equal")#orthonorméax.set_title("Graphe $G$ associé à la matrice $M$")plt.show()

    21

  • [37]: print(m)

    [[0. 1. 1. 0. 0. 0.][0. 0. 1. 0. 0. 0.][0. 0. 0. 1. 1. 0.][0. 0. 0. 0. 0. 0.][1. 0. 0. 1. 0. 0.][0. 0. 0. 1. 0. 0.]]

    5 Partie réservée aux Kadors

    Dans cette partie les graphes sont simples, non orienté et donnés par leurs matrices d’adjacence.

    Non fournie avec le corrigé.

    22

    Représentation de graphesBref tuto matplotlibLigne briséeCerclesLimites vs Bound

    Exercices préliminairesTracé d'un segmentArêteDistance euclidienneLimites du graphiqueTracé de cerclesSous-segmentsAnnotations

    Graphes non orientésTracer le grapheGraphes orientésFlècheTracé

    Partie réservée aux Kadors