IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Caml Discussion :

Parser de l'AMPL


Sujet :

Caml

  1. #1
    Membre du Club
    Homme Profil pro
    Chercheur en maths appli
    Inscrit en
    Novembre 2013
    Messages
    29
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Chercheur en maths appli
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2013
    Messages : 29
    Points : 46
    Points
    46
    Par défaut Parser de l'AMPL
    Bonjour à tous,

    pendant ma thèse, j'ai développé un outil de résolution en OCaml pour la programmation mathématique.
    Afin de le distribuer, j'aimerais l'interfacer avec AMPL, un langage de description mathématique d'un problème d'optimisation.

    La question, c'est est-ce que des bibliothèques en Caml ont déjà été faits dans ce sens, ou est-ce que je vais devoir me farcir l'analyse lexicale/syntaxique ? Mes recherches à ce sujet n'ont rien donné...
    Faites-moi signe si vous en avez connaissance
    Joyeuses fêtes,

    Charlie

  2. #2
    Membre émérite
    Avatar de SpiceGuid
    Homme Profil pro
    Inscrit en
    Juin 2007
    Messages
    1 704
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2007
    Messages : 1 704
    Points : 2 990
    Points
    2 990
    Par défaut 3 solutions
    • OCamlYacc
    • Menhir
    • À la main (analyse descendante)
    Du même auteur: mon projet, le dernier article publié, le blog dvp et le jeu vidéo.
    Avant de poser une question je lis les règles du forum.

  3. #3
    Membre du Club
    Homme Profil pro
    Chercheur en maths appli
    Inscrit en
    Novembre 2013
    Messages
    29
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Chercheur en maths appli
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2013
    Messages : 29
    Points : 46
    Points
    46
    Par défaut
    Yes, je me suis commencé tranquillou une analyse syntaxique avec Menhir

  4. #4
    Membre du Club
    Homme Profil pro
    Chercheur en maths appli
    Inscrit en
    Novembre 2013
    Messages
    29
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Chercheur en maths appli
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2013
    Messages : 29
    Points : 46
    Points
    46
    Par défaut Renvoyer un foncteur
    Salut,

    j'ai pas mal avancé dans mon analyse du langage AMPL avec Menhir.
    J'ai notamment lu dans la doc qu'on peut paramétrer le parseur par des modules avec la commande %parameter.

    Ca transforme le parseur en foncteur. Mais est-il en outre possible de renvoyer un foncteur ? Je m'explique :

    Lorsque je lis une expression mathématique dans le fichier AMPL (par exemple f(x) = 3*x+1), j'utilise les opérations élémentaires donnée par le module L passé en paramètre du parseur pour construire en Caml la fonction correspondante : L.add (L.mult 3 (L.var "x")) 1 dans cet exemple.

    L'idée est ensuite d'instancier L à plusieurs modules différents (un sur les flottants, un sur les entiers, un sur les arbres syntaxiques, etc) afin d'évaluer ma fonction f de plusieurs manières différentes.
    Le "problème", c'est qu'en l'état, j'instancie le parseur en lui fournissant un module L particulier (L_entier, ou L_flottant...), puis l'analyse syntaxique est réalisée.
    Il va donc y avoir autant d'analyses syntaxiques (toutes identiques qui plus est) que de modules L.

    Ce que j'aimerais réaliser, c'est un parseur qui disposerait d'un module L abstrait en paramètre, qui ferait l'analyse syntaxique et renverrait un foncteur paramétré par L. Instancier ce foncteur par un L_entier ou un L_flottant permettrait de récupérer directement l'expression de f sans avoir à refaire l'analyse syntaxique.

    Est-ce que c'est possible ?

  5. #5
    Membre émérite
    Avatar de SpiceGuid
    Homme Profil pro
    Inscrit en
    Juin 2007
    Messages
    1 704
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2007
    Messages : 1 704
    Points : 2 990
    Points
    2 990
    Par défaut
    C'est possible depuis OCaml version 3.12.
    C'est d'ailleurs détaillé à la section 7.14 du manuel d'utilisation.

    Maintenant est-ce la meilleure solution ?
    Personnellement j'ai pris l'habitude d'utiliser le minimum d'abstraction suffisant à factoriser le maximum de code.
    Pour ton cas voilà ce que j'ai en tête :

    Créer un type numérique et l'évaluateur qui va avec :
    Code OCaml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
    module type Num
       =
    sig
       type t
       val add : t -> t -> t
       val mul : t -> t -> t 
    end
     
    module Eval (N : Num)
       = 
    struct
       type expr =
          | Var
          | Const of N.t
          | Add of expr * expr
          | Mul of expr * expr
       let rec eval x = function
          | Var -> x
          | Const c -> c
          | Add(a,b) -> N.add (eval x a) (eval x b)
          | Mul(a,b) -> N.mul (eval x a) (eval x b) 
    end

    Gérer le type int :
    Code OCaml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    module Num_int : Num with type t = int
       =
    struct
       type t = int
       let add a b = a + b
       let mul a b = a * b
    end
     
    module Eval_int = Eval(Num_int)

    Gérer le type float :
    Code OCaml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    module Num_float : Num with type t = float
       =
    struct
       type t = float
       let add a b = a +. b
       let mul a b = a *. b
    end
     
    module Eval_float = Eval(Num_float)

    Et ainsi de suite...

    EDIT: Une façon simple de créer un module paramétré à partir d'un autre c'est de faire une application partielle sur un module à 2 paramètres.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    module type Size
       =
    sig
       val n : int
    end
     
    module Matrix (W: Size) (H : Size)
       =
    struct
       let make init = Array.make_matrix W.n H.n init
    end
     
    (* les matrices de largeur 2 *)
    module Matrix2 = Matrix (struct let n = 2 end )
    Du même auteur: mon projet, le dernier article publié, le blog dvp et le jeu vidéo.
    Avant de poser une question je lis les règles du forum.

  6. #6
    Membre du Club
    Homme Profil pro
    Chercheur en maths appli
    Inscrit en
    Novembre 2013
    Messages
    29
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Chercheur en maths appli
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2013
    Messages : 29
    Points : 46
    Points
    46
    Par défaut
    Merci pour ta réponse.
    Pour les modules entiers/flottants, je voyais bien comment faire.

    Par contre, paramétrer un module par plusieurs autres, je n'avais jamais eu l'occasion de le faire. Et ça coule de source en y pensant.

    Après t'avoir lu, j'ai encore du mal à voir comment effectuer l'analyse syntaxique et renvoyer des opérations génériques sans paramétrer mon foncteur...
    Je vais potasser un peu la doc

  7. #7
    Membre émérite
    Avatar de SpiceGuid
    Homme Profil pro
    Inscrit en
    Juin 2007
    Messages
    1 704
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2007
    Messages : 1 704
    Points : 2 990
    Points
    2 990
    Par défaut
    Je suis entêté mais en insistant bien je finis par répondre à la question.

    Ce n'est pas que la doc soit mal faite c'est plutôt que quelques exemples supplémentaires ne sont pas de trop pour s'épargner quelques déconvenues. Qui surviennent souvent sous la forme de syntax error pas du tout informatifs.

    Le plus important avant de licencier renvoyer un module c'est de nommer son type.
    Ici MatrixF le type de notre module paramétré :
    Code OCaml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    module type MatrixF =
       functor (H : Size) -> sig val make : 'a -> 'a array array end

    Après quoi on peut écrire une fonction qui renvoie un élément de ce type :
    Code OCaml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    let matrix_w w =
       let module MatrixW = Matrix (struct let n = w end)
       in (module MatrixW : MatrixF)

    On obtient une valeur-module qui peut servir à créer un module statiquement :
    Code OCaml : Sélectionner tout - Visualiser dans une fenêtre à part
    module Matrix_2x2 = (val (matrix_w 2) : MatrixF)(struct let n = 2 end)

    Ou bien dynamiquement, localement à une fonction :
    Code OCaml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    let make_WxH w h init =
       let module M_WxH =
          (val (matrix_w w) : MatrixF)(struct let n = h end)
       in M_WxH.make init
    Du même auteur: mon projet, le dernier article publié, le blog dvp et le jeu vidéo.
    Avant de poser une question je lis les règles du forum.

  8. #8
    Membre du Club
    Homme Profil pro
    Chercheur en maths appli
    Inscrit en
    Novembre 2013
    Messages
    29
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Chercheur en maths appli
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2013
    Messages : 29
    Points : 46
    Points
    46
    Par défaut
    Bonjour à tous,

    je me suis remis aujourd'hui à mon parseur AMPL après l'avoir mis de côté pendant quelques mois.

    J'ai paramétré mon parseur par un module Num qui contient toutes les opérations élémentaires.
    On peut alors instancier Num à plusieurs modules différents (sur les flottants, sur les AST, etc).

    Mon parser doit récupérer des définitions de fonctions, ie par exemple :
    f(x1, x2) = 3*x1+2*x2

    Le problème est de lier les variables xi de gauche à celles de droite, pour obtenir une fonction de type Num.t array -> Num.t
    où l'array représente le vecteur des xi.

    Question : comment faire ça ? Je n'ai pas l'impression qu'il soit possible de passer des valeurs en arguments des règles (seulement des symboles).
    Une idée serait éventuellement de créer une lambda à chaque fonction élémentaire, et l'évaluer dans la règle du dessus :

    f = fun x ->
    (fun x -> 3.*.x.(0)) x
    +.
    (fun x -> 2.*.x.(1)) x

    mais ça ne me satisfait pas.
    Des idées ?

  9. #9
    Membre émérite
    Avatar de SpiceGuid
    Homme Profil pro
    Inscrit en
    Juin 2007
    Messages
    1 704
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2007
    Messages : 1 704
    Points : 2 990
    Points
    2 990
    Par défaut
    Je n'ai personnellement jamais utilisé Menhir.
    C'est toutefois un outil assez populaire parmi les ocamleurs et quelqu'un ne manquera de t'indiquer la bonne pratique qui va avec ton cas d'usage.

    Si la réponse tarde trop sur ce forum, ou bien si tu es trop pressé par le temps, n'hésite pas à consulter/requêter la liste de discussion dédiée.
    Du même auteur: mon projet, le dernier article publié, le blog dvp et le jeu vidéo.
    Avant de poser une question je lis les règles du forum.

  10. #10
    Membre du Club
    Homme Profil pro
    Chercheur en maths appli
    Inscrit en
    Novembre 2013
    Messages
    29
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Chercheur en maths appli
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2013
    Messages : 29
    Points : 46
    Points
    46
    Par défaut
    Merci SpaceGuid, je vais également aller voir du côté des forums consacrés à Menhir.

Discussions similaires

  1. [JAXP] com.sun.xml.parser.ValidatingParser
    Par yolepro dans le forum Format d'échange (XML, JSON...)
    Réponses: 7
    Dernier message: 05/11/2008, 15h36
  2. parser xml
    Par billout dans le forum C++Builder
    Réponses: 4
    Dernier message: 20/11/2003, 11h08
  3. [Servlet] parser la requete
    Par jaimepasteevy dans le forum Servlets/JSP
    Réponses: 3
    Dernier message: 15/10/2003, 16h43
  4. Parser XML
    Par miloux32 dans le forum XML/XSL et SOAP
    Réponses: 4
    Dernier message: 18/07/2003, 03h17
  5. [langage] Continuer a parser une ligne
    Par D[r]eadLock dans le forum Langage
    Réponses: 5
    Dernier message: 30/09/2002, 18h49

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo