support de cours algo avancée

This commit is contained in:
gwen 2017-10-16 15:35:34 +02:00 committed by Benjamin Bohard
parent 07b57d4515
commit a04519ca4a
8 changed files with 202 additions and 357 deletions

View File

@ -1,13 +1,8 @@
les cycle écriture-compilation-exécution
d ́efinitions r ́ecursives
définitions récursives
une fonction est
r ́ecursive
si elle fait appel `a elle mˆeme dans sa propre
d ́efinition
définition par cas
(match-with)
récursive
si elle fait appel à elle même dans sa propre
définition
récursivité mutuelle
@ -31,6 +26,9 @@ type couleur = Pique | Coeur | Carreau | Trefle
# let a = Trefle ;;
val a : couleur = Trefle
définition par cas
(match-with)
let points v =
match v with
Pique -> 1

View File

@ -4,11 +4,17 @@ Aperçu des algorithmes fondamentaux
Les algorithmes sont partout. Absolument partout aujourd'hui.
Il n'est pas un domaine de nos activités qui ne soit liés à tel ou tel algorithme.
Quelques grands thèmes: systèmes cryptographiques, géométrie algorithmique, reconnaissance de motifs, mais aussi les problèmes posés par lalgorithmique parallèle, etc...
En mathématiques
-----------------
- l'algèbre (étude des structures de données)
- l'arithmétique modulaire (théorie des nombres)
En mathématiques et plus précisément en théorie algébrique des nombres,
larithmétique modulaire est un ensemble de méthodes permettant la résolution de problèmes
sur les nombres entiers.
Ces méthodes dérivent de létude du reste obtenu par une division euclidienne.
- la géométrie (affine, algébrique, invariants topologiques...)
- les diagrammes (diagrammes de Venn...)
- les colorisation d'une carte
@ -77,3 +83,14 @@ Exemple de résolution
\end{algorithmic}
\end{algorithm}
Algorithmes gloutons
--------------------
Les algorithmes servant à résoudre les problèmes doptimisation parcourent en général une
série détapes, au cours desquelles ils sont confrontés à un ensemble de possibilités. Un
algorithme glouton fait toujours le choix qui semble le meilleur sur le moment, dans lespoir
quil mènera à la solution optimale globalement.

View File

@ -0,0 +1,50 @@
Notion de complexité d'un algorithme
====================================
définition
-----------
lanalyse de la complexité dun algorithme consiste à évaluer les ressources
consommées par lalgorithme lors de lexécution
deux critères dévaluation
- le coût en temps (nombre dopérations)
- le coût en espace, (quantité de mémoire)
principes de base
-----------------
Caractériser la quantité de ressources consommées en fonction de la
taille des données sur lesquelles lalgorithme est appliqué.
Evaluer le coût exact est difficile, on exprimera donc seulement un
ordre de grandeur
définition mathématique
-----------------------
- si f est la fonction caractérisant exactement le coût dun algorithme
- et n la taille des données
- on sintéresse à la façon dont croı̂t f(n) lorsque n croı̂t
- on va montrer que f (n) ne croı̂t pas plus vite quune autre fonction g(n)
Du point de vue mathématique, on dit que la fonction f est dominée
asymptotiquement par la fonction g ce qui se note f= O(g)
::
f = O(g) ssi ∃k, ∃n 0 , ∀n, n > n 0 ⇒ f (n) ≤ k.g (n)
exemples
---------
- O(n) : progression linéaire
- O(n^2) : progression quadratique
- O(n^p) : progression polynomiale
- O(p^n ) : progression exponentielle
- O(log(n)): progression logarithmique

View File

@ -1,2 +1,82 @@
.. include:: ../../tronCommun/fonctions.txt
Définitions par filtrage
--------------------------
Lorsqu'un argument est passé à un ensemble de clauses::
p1 -> e1 pn -> en
- la première clause qui filtre l'argument est exécutée, les autres sont
ignorées.
- si aucune clause ne filtre l'argument, une exception est levée.
Définitions récursives
-----------------------
En ocaml, `let rec` définit une variable récursive, ie qui utilise la (les) valeur(s) en cours de définition.
Exemples
--------
::
let rec f (x) = if x <= 1 then 1 else f(x-1) + f(x-2) ;;
let rec g (x) = if x = 0 then 1 else x * g (x-1) ;;
let rec h (x, y) = if x = 0 then 1 else h (x-1, h(x,y)) ;;
let rec m (x) = if x > 100 then x - 10 else m (m (x+11)) ;;
On peut imprimer leur valeurs pour qques valeurs::
begin
for i = 1 to 15 do
printf "%d " (f (i)) done;
printf "\n"
end ;;
f, g sont les fonctions de Fibonacci et factorielles. C'est la même notation que pour les suites récurrentes. Que valent h et m?
La récursivité est très puissante. Invention de Kleene (1935). Théorie des fonctions récursives, comme moyen général de calcul. On peut montrer qu'il existe toujours des fonctions récursives partielles (qui ne terminent pas pour tte valeur de leurs arguments), si on veut un modèle général. La sous théorie des fonctions récursives primitives correspond aux programmes sans boucles, sans appels récursifs, et l'instruction for. Ces programmes terminent toujours. (cf Introduction to Metamathematics, S. Kleene; Recursive Functions Theory and Logic, A. Yasuhara).
Church et les autres logiciens des années 30 ont montré que systèmes de Post, les fonctions récursives de Kleene, les machines de Turing, sont tous équivalentes. Il a émis la thèse suivante: tous les modèles de la calculabilité sont équivalents.
Fonctions récursives
---------------------
::
let rec fact n = if n > 1 then n * fact (n -1) else 1;;
dans le prompt::
utop # let rec fact n = if n > 1 then n * fact (n -1) else 1;;
val fact : int -> int = <fun>
counter: 0 }─utop # fact 5;;
- : int = 120
et mutuellement récursives::
let rec ping n = if n > 0 then pong (n - 1) else "ping"
and pong n = if n > 0 then ping (n - 1) else "pong";;
# ping 8 ;;
- : bytes = "ping"
# ping 15 ;;
- : bytes = "pong"
types récursif
---------------
::
type 'a liste =
Vide
| Cellule of 'a * 'a liste;;

View File

@ -1,6 +1,7 @@
Algorithmique Approfondie
=========================
.. toctree::
:maxdepth: 2
@ -13,6 +14,7 @@ Algorithmique Approfondie
control
donnees
apercu
complexite
modularite
modules
tp

View File

@ -1,15 +1,26 @@
Avant propos
============
.. include:: ../../tronCommun/presentation.txt
.. image:: _static/pascal.jpg
Objectifs de ce cours
~~~~~~~~~~~~~~~~~~~~~
Il s'agit de :
.. FIXME définir les objectifs
- choisir une représentation appropriée des données,
- décomposer en sous-problèmes et affinements successifs,
- choisir une représentation appropriée des données
- décomposer en sous-problèmes et affinements successifs (programmation dynamique)
- approfondir les connaissances des structures de données et des algorithmes
- les appliquer à la résolution de problèmes
- rappels sur les types abstraits de données
- rappels sur la complexité des algorithmes
- abstractions de données et de contrôle
- utilisation de librairies de bases implémentant quelques algorithmes (tri, itérateur...)
- choix de collections et structures de données adaptée au design d'un programme
- structures de données complexes arbres, tables, graphes

View File

@ -36,10 +36,10 @@
%%\setbeamertemplate{background}{\includegraphics[width=128mm]{beamer-skel/img/banner01.png}}
\title[]{Algorithmique}
\title[]{Algorithmique Approfondie}
\subtitle{CESI alternance}
\subtitle{promotion GMSI B3}
\subtitle{INFAL24}
\author[Gwenaël Rémond]{}
@ -168,25 +168,39 @@ Une vision esthétique, littéraire, mathématique du codage}
\end{frame}
\begin{frame}
\frametitle{L'état de l'art de l'agorithmique}
\frametitle{L'état de l'art de l'algorithmique}
\begin{itemize}
\item en mathématiques
\begin{itemize}
\item algorithmique algébrique,
\item arithmétique modulaire,
\item en mathématiques, quelques grands thèmes
\begin{itemize}
\item géométrie algorithmique
\item algorithmique algébrique
\item arithmétique modulaire
\item \dots
\end{itemize}
\item en informatique
\begin{itemize}
\item en informatique fondamentale
\item en langages de programmation
\item dans touts les domaines où l'informatique intervient\dots
\item systèmes cryptographiques
\item reconnaissance de motifs
\item mais aussi les problèmes posés par lalgorithmique parallèle \dots
\item
\end{itemize}
\item en sciences physique, en biologie
\item en sciences sociales (réseaux sociaux, auto-organisation\dots)
\end{itemize}
\end{frame}
\section{Complexité d'un algorithme}
\begin{frame}
\frametitle{Complexité d'un algorithme}
\begin{itemize}
\item coût d'un algorithme
\item évaluation du coût
\item définition mathématique
\end{itemize}
\end{frame}
\section{Programmation modulaire}
\begin{frame}
\frametitle{La programmation modulaire}
@ -198,6 +212,15 @@ Une vision esthétique, littéraire, mathématique du codage}
\end{frame}
\section{Programmation modulaire avancée}
\begin{frame}
\frametitle{Les modules sont comme les classes}
\begin{itemize}
\item L'encapsulation
\item Le typage et la signature, l'héritage
\item Catégories et foncteurs
\end{itemize}
\end{frame}
% Not present in TOC

View File

@ -1,336 +0,0 @@
Les langages de programmation
=============================
langage
Un langage de
programmation
doit permettre d'écrire des
programmes de bonne qualité
Un programme doit être :
- correct
- robuste
- lisible, bien documenté
- facile à modifier, extensible
Un langage de programmation doit permettre :
- la programmation structurée
- la structuration avec les types
- proposer un mécanisme dexceptions
- présenter des caractères de généricité, de polymorphisme et de surcharge
.. important:: La structuration et l'organisation modulaire sert à maintenir de grands programmes,
Elles sont une nécessité
Approche historique et chronologique
-------------------------------------
- Lambda calcul (1930)
- machines de Turing (1936)
- début des langages vers les années 1950 (A0, Fortran(impératif),
Lisp(impératif et fonctionnel), Cobol)
- années 60 : Simula (classes), CPL (compilation séparée)
- années 70 : C (référence du langage impératif de bas niveau), Pascal
(procédures), Smalltalk (programmation orientée objects), Prolog
(programmation logique), Scheme (programmation fonctionnelle pure), Modula,
C++, Ada, Turbo Pascal, Common Lisp, Eiffel (programmation par contrats)
- années 80 : ML, CAML (langages fonctionnels)
- années 90 : Perl, Python, Ruby (languages de scripting multi-paradigmes)
Haskell (fonctionnel pur), Lua, Delphi, Java (orienté objet, machine
virtuelle), PHP (impératif, dédié au web), Erlang (fonctionnel+
programmation concurrente), javascript (orienté web, objets par
prototypage), OCaml (multi-paradigme, fortement typé, orienté sécurité,
programmation générique, fonctionnelle et objets, modulaire et fonctorielle)
- 2009 : go (google, compilé, typage statique, objets par prototypage,
prgrammation concurrente), Rust (fondation mozilla, multiparadigme, programmation concurrente)
Les langages actuellement les plus utilisés dans le monde de l'entreprise sont :
- javascript/NodeJS (70% du code dans le dépôt github) mais victime de son
succès (chaos complet des librairies)
- le go est de plus en plus utilisé, c'est **le** langage qui monte
actuellement
- Python, Ruby, lua, autres langages de scripting (de plus en plus utilisés)
- PHP, Java (stagnants)
- C, C++ (de moins en moins utilisés)
Approche par typologie des langages
-----------------------------------
- **A0 (1954)** : possibilité de découpage de programmes en
sous-programmes ;
- **ALGOL (1958)** : concept de bloc de code (pas forcément nommé) et d'imbrication
de blocs de code ;
- **C (1971)** : syntaxe claire et simple, programme fortement structuré ;
- **C (1980)** : le **code objet**, qui consiste à essayer de faire fonctionner
un seul jeu d'instructions sur des machines différentes. Avant, le code
d'assemblage dépendait du processeur, donc il n'y avait pas un seul et unique
jeu d'instructions ;
- **1980** : déploiement et succès des langages à objets ;
- **1983** : turbo pascal (Borland) qui fut le tournant du C,
propose un IDE (Environnement de Développement Intégré).
aujourd'hui le turbo pascal a pratiquement disparu mais pas totalement,
il est soutenu par une communauté open source autour de **Lazarus** ;
- **depuis les années 90** : deux grands groupes de langages. Les langages à
objets, et les langages fonctionnels. Les deux mondes s'interpénètrent (les
avancées actuelles du web, les microservices (Erlang, Haskell),
viennent du monde fonctionnel, le NoSQL, etc).
Les grandes avancées architecturales (système d'exploitation, linux, etc...)
viennent du monde de l'impératif.
Approches par modèles de programmation
--------------------------------------
- **le mécanisme d'exceptions** : il est possible de rompre l'exécution normale d'un
programme à un endroit et de la reprendre à un autre endroit du programme prévu à
cet effet. Ce mécanisme permet de gérer les situations exceptionnelles.
- **le paradigme impératif** : les entrées-sorties, les modifications physiques de
valeurs et les structures de contrôle itératives sont possibles.
- **le paradigme fonctionnel** : manipule les fonctions comme étant des valeurs du
langage. Celles-ci peuvent être utilisées en tant que paramètres d'autres fonctions
ou être retournées comme résultat d'un appel de fonction.
- **le paradigme objet** : La représentation du programme colle à la réalité en
reproduisant des entités relativement proches des objets réel. Attention, le piège
est de croire qu'il s'agit *du* paradigme universel puisqu'il reproduit en miroir le
réel. **C'est en fait un processus d'abstraction comme un autre**.
Sûreté du langage, typage
~~~~~~~~~~~~~~~~~~~~~~~~~
Tri par ordre de sûreté croissant :
0. typage très faible (presque inexistant aujourd'hui) : 42 == "42" == 42.0...
1. typage dynamique faible : (javascript) (possibilité de changer le prototype
d'un objet pendant l'éxécution du programme, c'est la fête on peut faire
n'importe quoi)
2. typage dynamique fort inféré par le comportement (behavior, duck typing)
(python, ruby, PHP) Le contenu de la variable détermine le choix du typage
`var = 0 -> type int`
3. typage statique déclaré fort (Java)
`int var = 0 ;` (pas mal mais super lourd, pas **agile** du tout)
4. langages à types statiques muni d'un moteur d'inférence de types (Ocaml)
sûreté d'exécution, agilité, sécurité.
La syntaxe, la lisibilité
~~~~~~~~~~~~~~~~~~~~~~~~~
Importance de la lisibilité (notamment par rapport aux méthodes agiles).
- courte (python)
- verbeuse (C)
- l'importance des mots clef du langage
- délimiteur de phrase, de blocs (parenthèses, accolades, tabulations, blocs...)
Langages compilés ou interprétés ?
-----------------------------------
.. glossary::
langage compilé
une première passe est faite, des validations son effectuées **avant**
la génération du code objet, cette phase est faite par le compilateur.
compilateur
programme qui transforme un langage de haut niveau en un langage de base
niveau
- phase danalyse syntaxique (source -> syntaxe abstraite)
- phase de synthèse (syntaxe abstraite -> code objet)
scripting (langage de scripting)
langage interprèté
générique (langage)
Langage à usage générique, qui peut être utilisé dans n'importe quel
domaine (par opposition au DSL)
domain specific
Domain Specific Language, langage destiné à être utilisé dans un
domaine prédéfini.
paradigmes
représentation d'une vision particulière à partir d'un modèle théorique
impératif
l'algorithme ressemble à une recette de cuisine,
c'est-à-dire à une succession d'instructions à exécuter
les unes à la suite des autres
fonctionnel
l'algorithme ne dépend plus de l'ordre d'exécution d'instructions
pas de mélange entre les données et les traitements
objets (programmation)
le monde est découpé en catégories
qui permettent de créer des objets
**développement par composants**
les objets sont organisés entre eux par composants suivant des designs patterns,
(patrons de conception)
garbage collector (ramasse miettes)
la gestion automatique de la mémoire apparaît en 1989
machine virtuelle
portabilité du code (mais diminution en optimisation et performances)
JIT (just in time compiler)
code objet, programmes fonctionnant autour de machines virtuelles
- **le typage statique** : la vérification de la compatibilité entre les types des
paramètres formels et des paramètres d'appel est effectuée au moment de la
compilation du programme. Dès lors, il n'est pas nécessaire de faire ces
vérifications durant l'exécution du programme ce qui accroît son efficacité. En
outre, la vérification de type permet d'éliminer la plupart des erreurs introduites
par maladresse ou étourderie et contribue à la sûreté de l'exécution.
- **le typage dynamique** : la vérification de la compatibilité entre les types des
paramètres formels et des paramètres d'appel est effectuée au moment de l'exécution
ou de l'appel à certaines parties de codes du programme.
- **le polymorphisme paramétrique** : une fonction ou un objet qui n'explore pas la
totalité de la structure d'un de ses arguments accepte que celui-ci ait un type non
entièrement déterminé. Ce paramètre est alors dit polymorphe. Cette particularité
permet de développer un code générique utilisable pour des structures de données
différentes tant que la représentation exacte de cette structure n'a pas besoin
d'être connue par le code en question. L'algorithme de typage est à même de faire
cette distinction.
- **l'inférence de types** : le programmeur n'a besoin de donner aucune information
de type à l'intérieur de son programme. Le langage se charge seul de déduire du code
le type le plus général des expressions et des déclarations qui y figurent. Cette
inférence est effectuée conjointement à la vérification, lors de la compilation du
programme.
Les grands paradigmes de programmation
---------------------------------------
Le paradigme des objets
~~~~~~~~~~~~~~~~~~~~~~~
- 1962 (SIMULA) : premières notions de classes ;
Pui, une dizaine d'années plus tard :
- C++ : intégration des classes pour le C ;
- turbo pascal : intégration des classes pour le pascal ;
Tous les langages actuels ont intégré des traits objets mais de manière très
différentes :
- perl (1987)
- python (1991)
- Ruby (1993)
- L'implémentation des objets en python est très proche des notions initiales de
classes issues du Smaltalk et présente une tentative très intéressante
d'unification des objets et des types depuis python 2.2 ;
- Java (1995) : très grosse réussite industrielle en surfant sur la vague de la
programmation objet, et des machines virtuelles, mais en fait et avec le recul,
doté d'un support objet lourd et alambiqué.
Le monde Java est lourd, avec des outils consommant beaucoup de mémoire et
qui ne satisfont pas à la règle du KISS (Keep It Simple, Stupid) ;
Il n'y a pas **une** POO (Programmation Objet), il y a des POO.
Les implémentations objets dans les langages sont riches et variées :
- objets obligatoirement construits pas des classes (Java, C++, ...)
- objets sans définition de classes (javascript, Ocaml, go, rust)
- langages à attributs (python)
- langages ou le type des objets est défini par leur classe (python, ruby)
- langages ou le type des objets est différent du type de leur classe (Ocaml)
- objets sans classes mais construits par des prototypes (javascript)
- construction d'objets possibles objets sans classe du tout (Ocaml)
- encapsulation des attributs des objets (Java, Ocaml, C++, PHP)
- pas d'encapsulation des attributs (python, ruby, javascript...)
Le paradigme impératif
~~~~~~~~~~~~~~~~~~~~~~
Un programme est une suite d'états de la mémoire de l'ordinateur,
c'est la suite logique des machines de Turing.
La plupart des programmeur aujourd'hui raisonnent suivant ce paradigme,
et ont une très faible visibilité par rapport aux autres paradigmes existants.
Seuls les programmeurs cultivés sont aujourd'hui capable de raisonner
suivant différents paradigmes, ce sont des programmeurs chevronnés et
cultivés.
Le paradigme fonctionnel
~~~~~~~~~~~~~~~~~~~~~~~~
La notion de fonction que possède sous une forme ou une autre la plupart des
langages est empruntée aux mathématiques et non à l'électronique. D'une manière
générale, les langages substituent des modèles formels aux conceptions purement
calculatoires. Ils y gagnent en expressivité. Certains langages fondent leur
paradigme de programmation sur l'abstraction entrée-traitement-sortie, donc sur le
**mathème fonctionnel** et pas sur la boite noire électronique. La fonction
mathématique apporte un niveau opératoire dans le traitement de l'information.
Approche par fonctionnalités
----------------------------
Plusieurs domaines de l'informatique on proposé/imposé des méthodologies,
des manières de faire. Ces modèles de programmation on fortement influencé
en retour les langages. On reconnaît aujourd'hui :
- Le modèle client-serveur
- Le modèle de programmation concurrente (exécution de processus légers, threads) :
- Le modèle de développement d'une application de bureau (MVC, ergonomie d'interface)
- Le modèle de développement web (communiquer sur le réseau Internet, API
REST, microservices...)
- Le modèle de programmation système et réseau
- le modèle **Dev Ops** et les méthodes de développement virtualisés
- les langages présentant des **fonctionnalités agiles**
Conclusion
-----------
Les langages de haut niveau sont caractérisés par
des concepts tels que :
- déclaration de valeurs, types, expressions, portée
- expressions, variables, instructions, structures de contrôle
- fonctions, procédures, fermetures
- encapsulation, modules, objets
=========== ============
Paradigmes Concepts
=========== ============
impératif variables, procédures, modules
objets classes, méthodes, héritage, surcharge
fonctionnel fonctions, fermetures, modules
logique prédicats, modules
concurrent tâche/processus, communication
=========== ============