UP | HOME

Test 3 - Lundi 22 juin - 35 minutes

Table of Contents

Nom : …………………….. - Prénom : ………………………

Les réponses sont à donner directement sur l'énoncé, en complétant les espaces libres en pointillé. Pour les questions fermées (à choix simple), cocher la case correspondant à sa réponse.

  • Le langage de programmation utilisé est Java (version au moins 5). On utilise la bibliothèque java.util de l'API ("Application Programming Interface") de Java. On suppose qu'elle est toujours importée par les classes l'utilisant, ce qui permet de recourir aux noms simples pour nommer ses types.
  • Dans la suite, l'expression (trois points) représente du code supposé connu.

Partie 1 - Agrégation avec délégation

Considérons les interfaces suivantes.

interface Fonction {
        double valeur(double x);
}
interface FonctionAvecZero extends Fonction {
        double unZero();
}

Un objet f de type Fonction représente une fonction à valeurs réelles, les réels étant représentés par des double : l'image du double x par f est donnée par f.valeur(x). Un objet f de type FonctionAvecZero est aussi de type Fonction et possède une méthode double unZero() donnant un point d'annulation de la fonction associée (un x tel que f.valeur(x) vaut 0, à une approximation près).

On s'intéresse à des fonctions ayant un zéro sur un intervalle fermé fixé, par exemple entre 0 et 1. On considère des implémentations de la méthode unZero pouvant s'exprimer en utilisant la seule méthode valeur. Précisément, on considère deux classes de fonctions

  • une classe de polynômes et
  • une classe de séries de Fourier,

et deux algorithmes de recherche d'un zéro d'une fonction

  • la méthode par dichotomie et
  • la méthode de Newton.
Algorithme
Dichotomie Newton
Fonction Polynôme
Série de Fourier

Architecture

L'architecture précédente possède deux couches.

Quelle est la méthode appartenant à la couche basse ?

\[ \begin{array}{llcll} \Box & \mathtt{valeur} & \quad \quad & \Box & \mathtt{unZero} \\ \end{array} \]

Quelle est la méthode appartenant à la couche haute ?

\[ \begin{array}{llcll} \Box & \mathtt{valeur} & \quad \quad & \Box & \mathtt{unZero} \\ \end{array} \]

Au total, avec deux sortes de fonctions, les polynômes et les séries de Fourier, et deux algorithmes de recherche d'un zéro, la dichotomie et Newton, on obtient quatre combinaisons possibles pour l'implémentation de l'interface FonctionAvecZero. On développe une solution par agrégation avec délégation permettant d'obtenir ces quatre combinaisons. On se donne deux classes Polynome et SerieFourier implémentant l'interface Fonction.

Factorisation de la délégation

Compléter la définition de la classe FonctionAvecZeroDeleguantEvaluation en suivant les commentaires et les indications suivantes. Cette classe implémente partiellement l'interface FonctionAvecZero ; elle réalise une délégation à la fonction de type Fonction qu'elle agrège.

........................................................................ 
  class FonctionAvecZeroDeleguantEvaluation implements 
    ....................................................................
{
  // Attribut de type Fonction.
  ......................................................................
  // Constructeur initialisant l'attribut avec son argument.
  public FonctionAvecZeroDeleguantEvaluation(Fonction f) {
    ....................................................................
  }
  // Délégation à la fonction agrégée.
  public double valeur(double x) {
    ....................................................................
  }
}

Implémentation de la couche haute

Compléter la définition de la classe concrète ZeroParDichotomie héritant de FonctionAvecZeroDeleguantEvaluation et implémentant FonctionAvecZero. On note DICHOTOMIE le code de la méthode unZero, une implémentation de l'algorithme par dichotomie. On rappelle qu'il est possible d'appeler le constructeur d'une classe parente en utilisant l'instruction super(x);, où x est l'argument à transmettre.

class ZeroParDichotomie 
........................................................................
........................................................................
{
  public ZeroParDichotomie(Fonction f) {
    ....................................................................
  }
  public double unZero() {
    DICHOTOMIE
  }
}

A l'intérieur du code DICHOTOMIE, comment appeler la méthode valeur de la fonction agrégée ? On qualifiera l'appel en utilisant une notation pointée cible.valeur(…).

....................................................................

On suppose que la classe concrète ZeroParNewton a été définie comme la classe concrète ZeroParDichotomie, à la différence qu'elle implémente la méthode unZero en utilisant l'algorithme de Newton.

Injection de dépendance

En utilisant les classes ZeroParDichotomie et ZeroParNewton, définir quatre fonctions de type FonctionAvecZero correspondant aux quatre combinaisons possibles entre les couches haute et basse. On utilisera les constructeurs sans argument des classes Polynome et SerieFourier.

FonctionAvecZero f1 = ...............................................
  ..................................................................;
FonctionAvecZero f2 = ...............................................
  ..................................................................;
FonctionAvecZero f3 = ...............................................
  ..................................................................;
FonctionAvecZero f4 = ...............................................
  ..................................................................;

Analyse

Notons \(|P|\), \(|S|\), \(|D|\) et \(|N|\) les quantités de code respectivement associées aux implémentations des polynômes et des séries de Fourier et à celles des méthodes unZero par dichotomie et suivant Newton. Pour la solution utilisant l'agrégation avec délégation, donner la quantité de code nécessaire pour réaliser les quatre combinaisons (en négligeant le code pour réaliser la délégation). Par exemple, en l'absence de factorisation, la quantité nécessaire est : \[ 2.(|P| + |S| + |D| + |N|). \] Agrégation avec délégation

........................................................................

Partie 2 - Généricité

On se donne les interfaces suivantes, correspondant à des structures algébriques classiques.

interface SemiGroupeAdditif<T> {
        T somme(T x);
}
interface UnifereAddition<T> {
        T zero();
}
interface SymetriqueAddition<T> {
        T oppose();
}
interface MonoideAdditif<T> 
  extends SemiGroupeAdditif<T>, UnifereAddition<T> {}
interface GroupeAdditif<T> 
  extends MonoideAdditif<T>, SymetriqueAddition<T> {}
interface SemiGroupeMultiplicatif<T> {
        T produit(T x);
}
interface UnifereMultiplication<T> {
        T un();
}
interface MonoideMultiplicatif<T> 
  extends SemiGroupeMultiplicatif<T>, UnifereMultiplication<T> {}
interface BiUnifere<T> 
  extends UnifereAddition<T>, UnifereMultiplication<T> {}
interface SemiAnneau<T> 
  extends MonoideAdditif<T>, SemiGroupeMultiplicatif<T> {}
interface Anneau<T> 
  extends SemiAnneau<T>, GroupeAdditif<T> {}
interface SemiAnneauUnitaire<T> 
  extends SemiAnneau<T>, MonoideMultiplicatif<T>, BiUnifere<T>{}
interface AnneauUnitaire<T> extends SemiAnneauUnitaire<T>, Anneau<T> {}

Voici un récapitulatif, avec des abréviations évidentes pour les interfaces.

SG+U+S+M+G+SG*U*M*BUSAASAUAU
sommeXXXXXXX
zeroXXXXXXXX
opposeXXXX
produitXXXXXX
unXXXXX

Des calculs génériques

Dans un module de calculs, on développe des fonctions génériques de calculs opérant sur les interfaces précédentes.

Définir une fonction T soustraction(T x, T y) calculant la soustraction de y à x (autrement dit, x moins y). On veillera à donner au paramètre T le majorant le plus grand possible (relativement à la relation de sous-typage), afin de rendre la fonction soustraction la plus générale possible.

public static ........................................................
T soustraction(T x, T y) {
  ....................................................................
  ....................................................................
}

Généraliser l'opération somme en définissant une fonction générique spécifiée ainsi :

  • signature : T sommeNAire(UnifereAddition<T> genZero, List<T> l),
  • si la liste l est vide, la fonction renvoie l'élément neutre (zéro) de l'addition,
  • sinon, la fonction renvoie la somme de tous les éléments présents dans la liste l.

Pour itérer sur la liste, procéder ainsi.

for(T e : l){ // Pour tout élément e de la liste l
  ... // Code utilisant e
}

On veillera à donner au paramètre T le majorant le plus grand possible (relativement à la relation de sous-typage), afin de rendre la fonction sommeNAire la plus générale possible.

public static ........................................................
T sommeNAire(UnifereAddition<T> genZero, List<T> l) {
  ....................................................................
  ....................................................................
  ....................................................................        
  ....................................................................
  ....................................................................
}

Le symétrisé d'un semi-anneau unitaire – Interface

On peut définir l'ensemble des entiers relatifs par symétrisation : un entier relatif est représenté par deux entiers naturels, interprétés comme le diminuende et le diminuteur d'une différence (soustraction). Cette construction peut être généralisée : à partir d'un semi-anneau unitaire, il est possible de construire un anneau unitaire par symétrisation. Pour ce faire, nous définissons une interface générique Symetrise<T> par héritage de trois interfaces génériques.

La première interface parente permet de décrire la structure d'une différence.

interface Relatif<T> {
  T diminuende();
  T diminuteur();
}

La seconde interface parente, paramétée par deux types S et T, permet de créer une différence de type S à partir de deux T.

interface FabriqueDifferences<S, T> {
  S creer(T diminuende, T diminuteur);
}

Compléter la définition de l'interface générique Symetrise<T> de manière à garantir que

  • le paramètre T de type est un semi-anneau unitaire,
  • l'interface Symetrise<T> hérite des interfaces FabriqueDifferences et Relatif, instanciées correctement, et
  • l'interface Symetrise<T> est un anneau unitaire.
interface Symetrise<T ................................................ >
  ......................................................................
  ......................................................................
  ......................................................................
  ......................................................................
  ......................................................................
{}

Last Updated 2015-06-22T18:53+0200. Comments or questions: Send a mail.