Example #1
0
def Newton_algoritmo(F, J, x, eps):
    """
    Resuelve un sistema no linear Rn-Rn F(x)=0, ambos F y J deben ser funciones de x
    x es el valor de las coordenadas iniciales, y sigue hasta que ||F|| < eps que es una tolerancia
    """
    F_value = F(x)
    #display(Latex('$$ F(x) = '+ latex(simplify(F_value)) + '$$'))
    F_norm = np.linalg.norm(F_value, ord=2)  # l2 norm of vector
    contador_iteraciones = 0
    while abs(F_norm) > eps and   contador_iteraciones < 100:
        delta = np.linalg.solve(J(x), -F_value)
       # display(Latex('$$ F(x) = '+ latex(simplify(F_value)) + '$$'))
       # display(Latex('$$ J(x) = '+ latex(simplify(J(x))) + '$$'))
       # display(Latex('$$ SEL = '+ latex(simplify(delta)) + '$$'))
        x = x + delta
        display(Latex('$$ Iteracion = '+ latex(simplify(contador_iteraciones)) + '$$'))
        display(Latex('$$ SolucionSistema = '+ latex(simplify(x)) + '$$'))
        F_value = F(x) #test
        F_norm = np.linalg.norm(F_value, ord=2)
        contador_iteraciones += 1

    # Hasta que una solucion es encontrada o muchas iteraciones 
    if abs(F_norm) > eps:
        contador_iteraciones = -1
    return x, contador_iteraciones
def Ex4Chapitre2_11(A1_inv, A2_inv):
    """Provides the correction to exercise 4 of notebook 2_11

    :param A1_inv: inverse of matrix A1
    :type A1_inv: list[list]
    :param A2_inv: inverse of matrix A2
    :type A2_inv: list[list]
    """

    A1 = np.array([[1, 2, 0, 1, 0], [0, -2, 1, -1, 0], [-2, -1, 1, 0, 1],
                   [0, 0, 0, 2, 0], [0, 0, 0, 0, 1]])
    A1_inv_true = np.linalg.inv(A1)
    A1_inv = np.array(A1_inv)

    A2_inv_true = [[]]

    A_inv_bool = np.zeros(3).astype(bool)
    A_inv_bool[0] = A1_inv.shape == A1_inv_true.shape and np.linalg.norm(
        A1_inv - A1_inv_true) < 1e-6
    A_inv_bool[1] = A2_inv == A2_inv_true

    correct = set(np.where(A_inv_bool)[0] + 1)
    wrong = set(np.arange(1, 3)) - correct

    if wrong:
        display(Latex("C'est faux."))
        if correct:
            display(Latex(f"Corrects: {correct}"))
        else:
            display((Latex("Corrects: {}")))
        display(Latex(f"Manqué: {wrong}"))
    else:
        display(Latex("C'est correct."))

    return
Example #3
0
def question7_2c(reponse):
    c = sp.Matrix([[4, 6, -3], [-4, 8, 12], [-4, 5, -1]])

    if np.abs(reponse - sp.det(c)) != 0:
        display(
            "Dans ce cas, la deuxième rangée a été multiplié par 4 et la troisième par -1"
        )
        display(
            Latex(
                "$ Soit: 4 \\times R_2 \\rightarrow R_2, -1 \\times R_3 \\rightarrow R_3  $"
            ))
        display("Le déterminant est donc:")
        display(
            Latex(
                '$ det|c| = (-1) \cdot (4) \cdot det|A| = -4 \cdot 155 = - 620 $'
            ))

        button = widgets.Button(description='Solution', disabled=False)
        box = HBox(children=[button])
        out = widgets.Output()

        @out.capture()
        def solution(e):
            out.clear_output()
            Determinant_3x3(c, step_by_step=True)

        button.on_click(solution)

        display(box)
        display(out)
    else:
        display("Bravo! Vous avez trouvé la réponse")
Example #4
0
def ch8_8_ex_1(A, prop_answer):
    """
    Check if a matrix is diagonalisable.
    @param A: sympy square matrix
    @param prop_answer: boolean, answer given by the student
    @return:
    """
    if not A.is_Matrix:
        raise ValueError("A should be a sympy Matrix.")
    n = A.shape[0]
    if n != A.shape[1]:
        raise ValueError('A should be a square matrix.')

    eig = A.eigenvects()
    dim_geom = 0

    for x in eig:
        dim_geom += len(x[2])
    answer = dim_geom == n

    if answer:
        display(Latex("Oui la matrice $A = " + latexp(A) + "$ est diagonalisable."))
    else:
        display(Latex("Non la matrice $A = " + latexp(A) + "$ n'est pas diagonalisable."))

    if answer == prop_answer:
        display(Latex("Votre réponse est correcte !"))
    else:
        display(Latex("Votre réponse est incorrecte."))
Example #5
0
def show_limit_analysis(f, r):
    display(Markdown("We have set: "))
    display(Latex("$f(x)= " + sp.latex(f(x)) + "$"))
    display(Latex("$r =  " + sp.latex(r) + "$"))

    display(Markdown("<br>"))
    display(Markdown("**Problem**: *Estimate*  "))
    display(Latex("$\large \lim_{x \\to r} f(x)$"))
    display(Markdown("---"))

    display(
        Markdown(
            "We generate a table of values of f around (but *not exactly at*) r"
        ))

    display(
        show_table(
            f, [r - 0.1, r - 0.01, r - 0.001, r + 0.001, r + 0.01, r + 0.1]))

    display(Markdown("<br>"))

    display(
        Markdown(
            "What do the values suggest a reasonable estimate for the limit would be?"
        ))
Example #6
0
def question7_2e(reponse):
    e = sp.Matrix([[-1, 2, 3], [4, 6, -3], [0, -11, 4]])

    if np.abs(reponse - sp.det(e)) != 0:
        display(
            "Dans ce cas, deux fois la première rangée a été ajouté à la troisième rangée."
        )
        display("Aussi les premières deux rangées sont échangées.")
        display(
            Latex(
                "$ Soit: 2 \\times R_1 + R_3 \\rightarrow R_3, R_1 \\leftrightarrow R_2 $"
            ))
        display("Le déterminant est donc:")
        display(
            Latex("$ det|e| = (-1) \cdot det|A| = (-1) \cdot 155 = - 155 $"))

        button = widgets.Button(description='Solution', disabled=False)
        box = HBox(children=[button])
        out = widgets.Output()

        @out.capture()
        def solution(k):
            out.clear_output()
            Determinant_3x3(e, step_by_step=True)

        button.on_click(solution)

        display(box)
        display(out)
    else:
        display("Bravo! Vous avez trouvé la réponse.")
def printEquMatrices(*args):
    """Method which prints the list of input matrices.

    .. note:: if two inputs are passed, they represent the list of coefficient matrices A and the list of rhs b
      respectively; as a result the augmented matrices A|B are plotted. Otherwise, if the input is unique, just the
      matrices A are plotted

    :param args: input arguments; they could be either a list of matrices and a list of vectors or
        a single list of matrices
    :type args: list
    """

    # list of matrices is M=[M1, M2, ..., Mn] where Mi=(Mi|b)
    if len(args) == 2:
        listOfMatrices = args[0]
        listOfRhS = args[1]
        texEqu = '$' + texMatrix(listOfMatrices[0], listOfRhS[0])
        for i in range(1, len(listOfMatrices)):
            texEqu = texEqu + '\\quad \\sim \\quad' + texMatrix(
                listOfMatrices[i], listOfRhS[i])
        texEqu = texEqu + '$'
        display(Latex(texEqu))
    else:
        listOfMatrices = args[0]
        texEqu = '$' + texMatrix(listOfMatrices[0])
        for i in range(1, len(listOfMatrices)):
            texEqu = texEqu + '\\quad \\sim \\quad' + texMatrix(
                listOfMatrices[i])
        texEqu = texEqu + '$'
        display(Latex(texEqu))
    return
Example #8
0
def question7_2f(reponse):
    f = sp.Matrix([[4, -5, 8], [6, 10, 1], [-3, 15, -2]])

    if np.abs(reponse - sp.det(f)) != 0:
        display("Dans ce cas, la deuxième rangée a été multiplié par cinq.")
        display("Après ça, c''est la transposée de la matrice.")
        display(
            Latex(
                "$ Soit: 5 \\times R_2 \\rightarrow R_2, \: et \: transposée $"
            ))
        display("Le déterminant est donc:")
        display(
            Latex(
                "$ det|f| = 5 \cdot det|A|^T = 5 \cdot det|A| = 5 \cdot 155 = 755 $"
            ))

        button = widgets.Button(description='Solution', disabled=False)
        box = HBox(children=[button])
        out = widgets.Output()

        @out.capture()
        def solution(e):
            out.clear_output()
            Determinant_3x3(f, step_by_step=True)

        button.on_click(solution)

        display(box)
        display(out)
    else:
        display("Bravo! Vous avez trouvé la réponse.")
 def correction(a, b, c, d):
     if c and not a and not b and not d:
         display(Latex("C'est correct! La matrice C vaut:"))
         C = [[-6, 64], [-32, -22], [28, -10], [-2, 6]]
         printA(C)
     else:
         display(Latex("C'est faux."))
 def correction(a, b, c, d):
     if c and not a and not b and not d:
         A = [[14], [6]]
         texA = '$' + texMatrix(A) + '$'
         display(
             Latex(r"C'est correct! Le produit $ AB$ vaut: $AB$ = " + texA))
     else:
         display(Latex("C'est faux."))
 def correction(a_1, a_2, a_3):
     if not a_1 and a_2 and not a_3:
         display(
             Latex(
                 "C'est correct! Plus précisément, la matrice $A_1$ n'admet pas de décomposition LU car elle n'est pas inversible, la matrice $A_2$ admet décomposition LU et la matrice $A_3$ n'admet pas décomposition LU car elle ne peut pas être réduite sans échanger deux lignes pendant la méthode d'élimination de Gauss"
             ))
     else:
         display(Latex("C'est faux."))
def lin_or_non2(val):
    if val == "Linear":
        display(Latex("Try Again!"))
    elif val == "Non-Linear":
        display(Latex("Right on!"))
        display(
            Latex(
                "Because $x$ is raised to the power of 2, this function is not linear."
            ))
def wage(val):
    if val == "W (Wage)":
        display(Latex("Correct!"))
        display(
            Latex(
                "The amount of money you make depends on your wage, and your wage is free to change. It is therefore the independent variable."
            ))
    elif val == "M (Money Made)":
        display(Latex("Try Again!"))
def lin_or_non4(val):
    if val == "Linear":
        display(Latex("Good job!"))
        display(
            Latex("This graph is a straight line, and is therefore linear."))
        display(Latex("The equation for this function is:"))
        display(Math("y = -x - 6"))
    elif val == "Non-Linear":
        display(Latex("Try Again!"))
def lin_or_non1(val):
    if val == "Linear":
        display(Latex("Correct!"))
        display(
            Latex(
                "This equation has no exponent on either variable, and is therefore linear."
            ))
    elif val == "Non-Linear":
        display(Latex("Try Again!"))
 def correction(a, b, c, d):
     if d and not a and not c and not b:
         A = np.array(([-1, 0, 0], [3, 1 / 2, 0], [1, 2, 1]))
         res = np.transpose(np.linalg.inv(A))
         texAres = '$' + texMatrix(res) + '$'
         display(
             Latex("C'est correct! $(A^T)^{-1}$ est donnée par: $\quad$" +
                   texAres))
     else:
         display(Latex("C'est faux."))
 def correction(a, b, c):
     if a and not c and not b:
         display(
             Latex(
                 "C'est correct! Pour $\lambda=-3$ La matrice échelonnée réduite est:"
             ))
         A = [[1, 0, -2, 3], [0, 1, -1, 7]]
         printA(A)
     else:
         display(Latex("C'est faux."))
Example #18
0
def grid(items_and_weights):
    print(Latex("\n\\begin{Row}%\n"))
    for val, width in items_and_weights:
        print(Latex("\n\\begin{Cell}{" + str(width) + "}\n"))

        if not isinstance(val, str):
            print(Latex("\\vspace*{-.4cm}\n"))
        print(val)
        print(Latex("\n\n\\end{Cell}\n"))
    print(Latex("\n\\end{Row}\n"))
    def classify(self,trainData,labels,features):
        
        
        labels =list(labels)
        probability_y={}#概率集合
        

        Latex('''  $p(A)$  :事件A发生的概率  ''')
        #每一个标签数量除以总数
        for label in labels:
            probability_y[label] = labels.count(label)/float(len(labels))

        Latex('''  $p(A\cap\;B)$  :事件A 和事件B同时发生的概率   ''')
        #求label与feature同时发生的概率
        probability_xy={}
        for y in probability_y.keys():
            #labels 放入枚举函数中,形成(序号,值)这一数据结构
            y_index = [i for i,label in enumerate(labels) if label == y]
            #y_index 对应标签的一行值 的 所有位置

            for j in range(len(features)):
                x_index = [i for i,feature in enumerate(trainData[:,j]) if feature == features[j]]
                #set 是集合,& 交集,| 并集,- 差集 ,in 属于,not in 不属于
                #求 x_index 和 y_index的 两个集合的交集。也就是同时发生的次数
                xy_count = len(set(x_index)&set(y_index))
                

                probaility_key = str(features[j])+'*'+str(y)
                print(probaility_key)
                probability_xy[probaility_key] = xy_count/float(len(labels))

        #条件概率
        Latex('''  $p(A|B)$  :表示事件A在事件B发生的条件下发生的概率  ''')
         #P[X1/Y] = P[X1Y]/P[Y]
        Latex(''' $P[X|Y] = P[X\cap\;Y]/P[Y] $''')
        probability={}
        for y in probability_y.keys():
            for x in features:
                pkey = str(x)+'|'+str(y)

                
                probability[pkey] = probability_xy[str(x)+'*'+str(y)]/float(probability_y[y])
        

        #求各个类别的概率
        Class_each={}
        for y in probability_y:
            Class_each[y]=probability_y[y]
            for x in features:
                print(Class_each[y])
                print(probability[str(x)+'|'+str(y)])
                Class_each[y] =Class_each[y]*probability[str(x)+'|'+str(y)]

        features_label =max(Class_each,key=Class_each.get)
        return features_label
Example #20
0
def polezero_gen4_demo1_plot(zeta1=0.5, omega01=10, kind1=kinds[0],
                             zeta2=0.5, omega02=20, kind2=kinds[0],
                             mode=response_modes[0]):

    t = np.linspace(-0.1, 3, 201)
    t2 = np.linspace(0, 3, 201)    
    w = np.logspace(-1, 3, 201)    
    s = 1j * w

    if kind1 == 'Low-pass':
        obj1 = Lowpass2(zeta1, omega01)
    elif kind1 == 'Band-pass':
        obj1 = Bandpass2(zeta1, omega01)        
    elif kind1 == 'High-pass':
        obj1 = Highpass2(zeta1, omega01)        
    elif kind1 == 'Band-stop':
        obj1 = Bandstop2(zeta1, omega01)

    if kind2 == 'Low-pass':
        obj2 = Lowpass2(zeta2, omega02)
    elif kind2 == 'Band-pass':
        obj2 = Bandpass2(zeta2, omega02)        
    elif kind2 == 'High-pass':
        obj2 = Highpass2(zeta2, omega02)        
    elif kind2 == 'Band-stop':
        obj2 = Bandstop2(zeta2, omega02)        

    if mode == 'Step response':
        h1 = obj1.step_response(t)
        h2 = obj2.step_response(t2)
        h = np.convolve(h1, h2)[0:len(t)] * (t[1] - t[0])
        ylim = (-0.5, 2.1)        
    elif mode == 'Impulse response':
        h1 = obj1.impulse_response(t)
        h2 = obj2.impulse_response(t2)        
        if h1 is None:
            return Latex('Cannot compute Dirac delta for %s' % mode)
        if h2 is None:
            return Latex('Cannot compute Dirac delta for %s' % mode)
        h = np.convolve(h1, h2)[0:len(t)] * (t[1] - t[0])
        ylim = (-5, 10)                    
    elif mode == 'Frequency response':
        H1 = obj1.frequency_response(s)
        H2 = obj2.frequency_response(s)
        h = H1 * H2
        ylim = (-40, 20)
        t = w
    else:
        raise ValueError('Unknown mode=%s', mode)        

    poles = np.array(obj1.poles + obj2.poles)
    zeros = np.array(obj1.zeros + obj2.zeros)    

    axes = polezero_plot_with_time(t, h, poles, zeros, ylim=ylim, mode=mode)
Example #21
0
def question7_2d(reponse):
    d = sp.Matrix([[4, 6, -3], [-1, 2, 3], [-8, 10, -2]])

    if np.abs(reponse - sp.det(d)) != 0:
        display("Dans ce cas, la troisième rangée est multipliée par -2 ")
        display(Latex("$ Soit: -2 \\times R_3 \\rightarrow R_3 $"))
        display("Le déterminant est donc:")
        display(Latex("$ det|d| = (-2) \cdot det|A| = -2 \cdot 155 = - 310 $"))
        Determinant_3x3(d, step_by_step=True)
    else:
        display("Bravo! Vous avez trouvé la réponse.")
def lin_or_non3(val):
    if val == "Linear":
        display(Latex("Try Again!"))
    elif val == "Non-Linear":
        display(Latex("Way to go!"))
        display(
            Latex(
                "This graph does not resemble a straight line, therefore, it is not linear."
            ))
        display(Latex("The equation for this function is:"))
        display(Math("y = x^2"))
 def correction(a, b, c):
     if a and not b and not c:
         A1 = np.array([[2, 0, 1], [0, 6, 4], [2, 2, 1]])
         A1_inv = np.linalg.inv(A1)
         texA1inv = '$' + texMatrix(A1_inv) + '$'
         display(
             Latex(
                 "C'est correct! $A_1$ est la seule matrice inversible et son inverse est: $\quad A_1^{-1} = $"
                 + texA1inv))
     else:
         display(Latex("C'est faux."))
Example #24
0
 def solution(e):
     out.clear_output()
     display(Latex(line0))
     display(Latex(line1))
     display(Latex(line2))
     display(Latex(line3))
     display(Latex(line4))
     display(Latex(line5))
     display(Latex(line6))
     display(Latex(line7))
     display(Latex(line8))
     display(Latex(line9))
 def correction(a, b, c, d, e, f, g, h):
     if c and e and g and h and not a and not b and not d and not f:
         display(
             Latex(
                 r"C'est correct! En effet $A$ n'est pas inversible si $\alpha = \dfrac{8}{\beta}$ (résultat "
                 r"obtenu en divisant par élément les lignes de A les unes par les autres et en imposant que "
                 r"les résultats des divisions soient les mêmes). Si $\alpha = -2$ et $\beta = -4$, "
                 r"alors le système admet une infinité de solutions, puisque les rapports obtenus par la "
                 r"division est $-\dfrac{1}{2}$, qui est égal au rapport entre les éléments du vecteur de droite "
                 r"$b$."))
     else:
         display(Latex("C'est faux."))
 def correction(a, b, c, d, e, f, g, h):
     if not a and not b and not c and d and not e and not f and g and not h:
         display(
             Latex(
                 "C'est correct. En effet, $A$ n'est clairement pas inversible, car la dernière ligne est "
                 "égale à la seconde moins la première, et il en va de même pour le vecteur de droite $b$. "
                 "Par conséquent, la dernière ligne de $U$ est entièrement composée de zéros (réponse 7) et la "
                 "dernière entrée du vecteur de droite $b$, après l'application de la méthode d'élimination de "
                 "Gauss, est également égale à 0. Ainsi, la dernière équation du système linéaire résultant a "
                 "tous les coefficients égaux à 0, ce qui donne lieu à une infinité de solutions "
                 "(réponse 4)."))
     else:
         display(Latex("C'est faux."))
 def correction(a, b, c, d, e, f, g, h):
     if a and not b and not c and d and not e and not f and g and h:
         display(
             Latex(
                 "C'est correct. En effet, l'ensemble des solutions peut être écrit comme "
                 "$x = [1-4a, 2.5a, 3a-1, a]$. On en déduit que la deuxième entrée est 2.5 fois la 4ème (réponse 4),"
                 " que la somme de toutes les entrée sauf la 2ème vaut 0 (réponse 7) "
                 "et que $\hat{x} = [1,0,-1,0]$ est une solution, c'est le cas $a=0$ (réponse 8). "
                 "Alors, si L est calculée de manière à obtenir des 1 sur sa diagonale, on peut déduire que "
                 "le vecteur $\vec{y}$ qui résout $L\vec{y}=\vec{b}$ n'est fait que de 1."
             ))
     else:
         display(Latex("C'est faux."))
def Ex2bChapitre2_5(inv):
    """Provides the correction to exercise 2b of notebook 2_5

    :param inv: inverse of the matrix to be calculated
    :type inv: list[list]
    """

    if inv == [[0, 0, 1 / 5], [4, 1, 0], [1, 0, 0]]:
        display(Latex("C'est correct!"))
    else:
        display(Latex("C'est faux."))

    return
Example #29
0
    def correction(res):
        if 'a)' in res and 'c)' in res :
            print("C'est correct!")
            print('Pour le système a), on peut par exemple faire\n')
            sola= '$\\left(\\begin{array}{cc|c} 1 & 1 & 3\\\\ -1& 4 & -1 \\end{array}\\right) \\stackrel{E_{12}}{\sim}\\left(\\begin{array}{cc|c} -1& 4 & -1\\\\ 1 & 1 & 3 \\end{array}\\right)\\stackrel{E_{1}(-2)}{\sim}\\left(\\begin{array}{cc|c} 2& -8 & 2\\\\ 1 & 1 & 3 \\end{array}\\right)$'
            display(Latex(sola))

            print("Pour le système b), les systèmes ne sont pas équivalents. Comme solution on peut exprimer x1 en fonction de x2 et on obtient deux droites (parallèles) de pente 1 mais de hauteurs -2 et 2.$")
            print('Pour le système c), on peut par exemple faire\n')
            sola= '$\\left(\\begin{array}{ccc|c} \dfrac{1}{4} & -2 & 1& 5\\\\ 0& 1 & -1 & 0\\\\ 1 & 2 & -1 & 0 \\end{array}\\right) \\stackrel{E_{1}(4)}{\sim}\\left(\\begin{array}{ccc|c} 1 & -8 & 4& 20\\\\ 0& 1 & -1 & 0\\\\ 1 & 2 & -1 & 0\\end{array}\\right)\\stackrel{E_{31}(-1)}{\sim}\\left(\\begin{array}{ccc|c} 1& -8 & 4&20\\\\ 0 & 1 & -1&0\\\\ 0&10 &-5 & -20\\end{array}\\right)\\stackrel{E_{3}\\big({\\tiny\dfrac{1}{5}}\\big)}{\sim}\\left(\\begin{array}{ccc|c}1& -8 & 4&20\\\\ 0 & 1 & -1&0\\\\ 0&2&-1 & -4\\end{array}\\right)$'
            display(Latex(sola))
            
        else:
            print("C'est faux. Veuillez rentrer d'autres valeurs")
def Ex1Chapitre2_8_9(E1, E2, E3, E4):
    """Provides the correction of exercise 2 of notebook 2_8_9

    :param E1:
    :type E1:
    :param E2:
    :type E2:
    :param E3:
    :type E3:
    :param E4:
    :type E4:
    :return:
    :rtype:
    """

    # MATRIX A1
    E_pre_1 = [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]
    E_post_1 = [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [1, 0, 0, 1]]

    # MATRIX A2
    E_pre_2 = [[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]]
    E_post_2 = [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1 / 2, 0], [0, 0, 0, -1]]

    # MATRIX A3
    E_pre_3 = [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, -1]]
    E_post_3 = [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, -2], [0, 0, 0, 1]]

    # MATRIX A4
    E_pre_4 = [[1 / 2, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]
    E_post_4 = [[1, 0, 0, 0], [0, 1, 1, 0], [0, 0, 1, 0], [0, 0, 0, -1]]

    E_bool = np.zeros(4).astype(bool)
    E_bool[0] = E1[0] == E_pre_1 and E1[1] == E_post_1
    E_bool[1] = E2[0] == E_pre_2 and E2[1] == E_post_2
    E_bool[2] = E3[0] == E_pre_3 and E3[1] == E_post_3
    E_bool[3] = E4[0] == E_pre_4 and E4[1] == E_post_4

    correct = set(np.where(E_bool)[0] + 1)
    wrong = set(np.arange(1, 5)) - correct

    if wrong:
        if correct:
            display(Latex(f"Corrects: {correct}"))
        else:
            display((Latex("Corrects: {}")))
        display(Latex(f"Manqué: {wrong}"))
    else:
        display(Latex("C'est correct."))

    return