OCamlgraph est une librairie d'algorithmes de graphes. Son principe est de proposer des foncteurs, qui prennent une interface représentant des graphes et produisent un module définissant un algorithme. On se propose d'écrire un mini OCamlgraph.
Voici l'interface d'une monade d'état :
Il faut comprendre que 'value t est une action produisant une valeur de type 'value. Par ailleurs, cette action a accès à un état qu'elle peut lire ou modifier. De même, une valeur de type 'arg -> 'res t peut se comprendre comme une fonction de type 'arg -> 'res, mais pouvant utiliser ou modifier l'état.
On suppose disposer d'une monade d'état dont le type stateest int.
Écrivez l'action permettant de calculer la factorielle d'un entier $n$ à l'aide de la question précédente. Vous pouvez modifier l'état arbitrairement.
Nous avons vu en cours d'algorithmique qu'un programme dynamique est un algorithme récursif auquel on ajoute un mécanisme qui permet de mémoriser pour chaque instance quelle est la solution associée. Ainsi, sur les récursions exigent le calcul de la solution d'une même instance plusieurs fois, seul le premier calcul prend du temps.
La technique étant toujours la même, il doit être possible de la factoriser. Nous allons le faire en utilisant un foncteur. Pour cela, nous allons définir ce qu'est un problème typique de programmation dynamique, ce qui nous définit une interface, puis comment depuis une telle interface on peut dériver automatiquement le programme dynamique. Il est nécessaire d'avoir fait l'exercice sur les monades d'états pour faire cet exercice.
Voici l'interface d'un problème solvable par programmation dynamique :
resolve prend une fonction en argument, qui est en fait la fonction à utiliser pour les appels récursifs. Comme ceux-ci ultimement auront à utiliser la mémoire, nous les définissons dans une monade d'état.
Créer un module de signature Problem pour le calcul des termes de la suite de Fibonacci.
Voici le foncteur créant le programme dynamique.
La fonction solve se programme en récupérant l'état de la mémoire, et en y cherchant l'instance. Si l'instance n'y est pas, on utilise la fonction de résolution du problème et on ajoute la solution en mémoire. Ajoutez une fonction enregistrant une solution en mémoire