CentraleSupélec LMF, UMR CNRS 9021
Département informatique Laboratoire Méthodes Formelles
Bât Breguet, 3 rue Joliot-Curie Bât 650 Ada Lovelace, Université Paris Sud
91190 Gif-sur-Yvette, France Rue Noetzlin, 91190 Gif-sur-Yvette, France
TD n°12 et 13 SIP

Le sujet SIP-TD12-13.pdf

Éléments de corrigé

import random
import math
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import matplotlib.colors as colors

def approx_pi(n) :
    inside = 0
    total = 0
    while total < n :
        x = random.uniform(-1, 1)
        y = random.uniform(-1, 1)
        total += 1
        if math.hypot(x, y) < 1 :
            inside += 1
    almost_pi = 4 * (inside / total)
    rel_error = math.fabs(almost_pi - math.pi) / math.pi
    return (almost_pi, rel_error)

# approx_pi(1000)
# approx_pi(100000)

def plot_monte_carlo() :
    fig = plt.figure()         # Create a figure
    fig.patch.set_facecolor('white') # Set its background to white
    axes = plt.axes()          # Create the axes of the figure
    axes.set_aspect('equal')   # Set their aspect ratio to 1
    axes.set_axis_off()        # Do not display the axes
    axes.set_xlim(left=-1, right=1.1)  # The .1 is for avoiding to clip the rectangle
    axes.set_ylim(bottom=-1.1, top=1)
    # Add the rectangle and the circle
    axes.add_patch(patches.Circle((0, 0), 1, linewidth=1, fill=False, edgecolor='blue'))
    axes.add_patch(patches.Rectangle((-1, -1), 2, 2, linewidth=1, fill=False))

def approx_pi_plot(n) :
    plot_monte_carlo()
    inside = 0
    total = 0
    while total < n :
        x = random.uniform(-1, 1)
        y = random.uniform(-1, 1)
        total += 1
        if math.hypot(x, y) < 1 :
            inside += 1
            plt.plot(x, y, 'ro', markersize=2)
        else:
            plt.plot(x, y, 'go', markersize=2)
        plt.pause(0.05)  # Pause for animation
    plt.show()
    almost_pi = 4 * (inside / total)
    rel_error = math.fabs(almost_pi - math.pi) / math.pi
    return (almost_pi, rel_error)

##
# Mandelbrot set
##
def module_real_img(z) :
    return math.hypot(z.real, z.imag)

def module_conj(z) :
    return math.sqrt((z.conjugate()*z).real)

def mandelfunc(c, z) :
    return z*z + c

def mandelbrot(c, n_max) :
    z = 0
    n = 0
    while n < n_max and abs(z) < 2 :
        n += 1
        z = mandelfunc(c, z)
    return n

def mandelbrot_set(xmin, xmax, ymin, ymax, xnum, ynum, n_max) :
    x = [xmin + i * (xmax - xmin)/xnum for i in range(xnum+1)]
    y = [ymin + i * (ymax - ymin)/ynum for i in range(ynum+1)]
    z = [[mandelbrot(complex(x[i], y[j]), n_max) for i in range(xnum)] for j in range(ynum)]
    return z

def plot_mandelbrot(xmin, xmax, ymin, ymax, xnum, ynum, n_max) :
    z = mandelbrot_set(xmin, xmax, ymin, ymax, xnum, ynum, n_max)
    mycolors = [(1,0,0), (0,1,0), (0,0,1), (0,0,0)]
    colmap = colors.LinearSegmentedColormap.from_list("mandelbrot", mycolors, 16)
    plt.imshow(z, cmap=colmap, interpolation='bicubic')
    plt.show()

# plot_mandelbrot(-2.25, 0.75, -1.25, 1.25, 1500, 1250, 64)

##
# PageRank
##
def subdiv_one(n):
    elems = [random.random() for _  in range(n)]
    norm = sum(elems)
    return [elem / norm for elem in elems]

import numpy as np
def create_transition_matrix(size) :
    # First, we create a matrix whose lines sum up to 1
    m = np.matrix([subdiv_one(size) for i in range(size)])
    # and we transpose it to have columns that sum up to 1
    return m.transpose()

# https://en.wikipedia.org/wiki/Matrix_norm
import numpy.linalg as la

def page_rank(size, epsilon) :
    m = create_transition_matrix(size)
    s0 = [[1/size] for _ in range(size)]  # 1 column matrix
    rank = 0
    norm = la.norm((m ** (rank + 1) - m ** rank), np.inf)
    while (norm/size > epsilon) :
        rank += 1
        norm = la.norm((m ** (rank + 1) - m ** rank), np.inf)
    return (m ** rank) * s0

# More efficient version, which does not recompute m**k at
# each iteration. It also compare the norm directly to epsilon,
# without dividing by the number of pages
def page_rank_lowcost(size, epsilon) :
    m = create_transition_matrix(size)
    mk = m
    s0 = [[1/size] for _ in range(size)]
    rank = 0
    norm = la.norm(m, np.inf)
    while (norm > epsilon) :
        rank += 1
        mk2 = mk * m
        norm = la.norm((mk2 - mk), np.inf)
        mk = mk2
    return mk * s0

##
# Prey-predator system
##
# The function that gives the derivative from the current values
def f(x, y, a, b) :
    return x * (a - b * y)

# The function that gives the next value of z (which is either x or y)
# from the current value of z, of the other variable (t), the parameters
# of the problem (a and b) and the integration step (Euler explicit scheme).
def next_step(zn, tn, a, b, step) :
    return zn + step * f(zn, tn, a, b)

def populations(x0, y0, alpha, beta, delta, gamma, step, n) :
    x, y = x0, y0
    lx, ly = [x0], [y0]
    for _ in range(n) :
        # We have dx/dt =  alpha*x - beta*x*y
        # and     dy/dt = -gamma*y + delta*y*x
        # hence the parameters of next_step
        x, y = next_step(x, y, alpha, beta, step), \
               next_step(y, x, -gamma, -delta, step)
        lx.append(x)
        ly.append(y)
    return lx, ly

def display_populations() :
    # Initial populations
    x0, y0 = 0.9, 0.9
    # Parameters
    alpha, beta, delta, gamma = 2/3, 4/3, 1, 1
    # Temporal resolution
    resolution = 1000
    # Compute until that time
    time_max = 20
    # Time step size
    step = 1 / resolution
    # Total number of steps
    n = time_max * resolution
    ## Compute the populations
    prey, pred = populations(x0, y0, alpha, beta, delta, gamma, step, n)
    # Plot the result
    time = [step * i for i in range(n+1)]
    plt.subplot(121)
    # First subplot for the evolution of populations through time
    plt.title("Population versus time")
    plt.plot(time, prey, label="Preys")
    plt.plot(time, pred, label="Predators")
    plt.xlabel("Time")
    plt.ylabel("Population")
    plt.legend(loc='upper left')
    # Second subplot for the phase diagram
    plt.subplot(122)
    plt.title("Predators versus preys")
    plt.plot(prey, pred)
    plt.xlabel("Preys")
    plt.ylabel("Predators")
    plt.show()