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 :

[Debutant] Problème avec les Bigarray


Sujet :

Caml

  1. #1
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2009
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2009
    Messages : 5
    Points : 1
    Points
    1
    Par défaut [Debutant] Problème avec les Bigarray
    Bonjour à toutes et tous.

    Je dois réaliser dans le cadre d'un cours un programme en OCaml qui doit travailler sur des matrices de grandes tailles. On m'a conseillé d'utiliser le module Bigarray, mais je ne parviens pas à créer le moindre Bigarray, même un qui me semble tout simple.

    Pour m'entrainer je voulais créer une matrice de float, puis dire que l'élément (1,1) valait 2.
    J'ai donc écrit cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    open Bigarray
    let a = Array2.create float64 fortran_layout 3 3 
    a.{1,1} <- 2.;
    Mais à la compilation, il me dit qu'il y a une erreur de syntaxe à la ligne 3, caractères 8-10.
    J'ai pensé qu'il manquait un 'in' à la ligne 2, mais ce n'est pas cela (il me dit à la compilation qu'il y a erreur à la ligne 2, caractère 49-51 ce qui correspond au 'in')

    Quelqu'un aurait-il une idée pour m'aider, s'il vous plait?

    D'avance, merci!

  2. #2
    Membre éprouvé
    Avatar de InOCamlWeTrust
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    1 036
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 1 036
    Points : 1 284
    Points
    1 284
    Par défaut
    Il te manque le in du let ... = ... in ....

  3. #3
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2009
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2009
    Messages : 5
    Points : 1
    Points
    1
    Par défaut
    J'ai aussi essayé le code en ajoutant le "in" à la fin de la deuxième ligne, mais alors l'erreur à la compilation est une erreur de syntaxe, ligne 2, caractères 49-51, cad le "in" justement...

  4. #4
    Membre éprouvé
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    832
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 832
    Points : 1 104
    Points
    1 104
    Par défaut
    L'erreur est liée à l'utilisation d'une simple expression au top-level. Pour la corriger, il suffit de remplacer l'expression par une déclaration, c'est à dire utiliser l'un des deux codes suivant :

    Code ocaml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    open Bigarray
    let a = Array2.create float64 fortran_layout 3 3
    let () = a.{1,1} <- 2.


    Code ocaml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    open Bigarray
    let () =
      let a = Array2.create float64 fortran_layout 3 3 in
      a.{1,1} <- 2.

    Cela vient d'une ambiguité syntaxique entre le début d'une phrase et la fin de la précédente, dans le cas d'une phrase qui est une expression. Tu peux aussi la corriger en ajoutant des fins de phrases explicites ";;" :
    Code ocaml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    open Bigarray
    let a = Array2.create float64 fortran_layout 3 3;;
    a.{1,1} <- 2.
    Code ocaml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    open Bigarray;;
    let a = Array2.create float64 fortran_layout 3 3 in
    a.{1,1} <- 2.

    Quand tu as une erreur de syntaxe étrange, pense à utiliser le préprocesseur camlp4 : il donne souvent des messages d'erreur plus détaillés :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    open Bigarray
    let a = Array2.create float64 fortran_layout 3 3
    a.{1,1} <- 2.
    $ ocamlc -pp camlp4o bigarray.cma test.ml -c
    File "test.ml", line 2, characters 8-62 (end at line 3, character 13):
    Failure: "bad left part of assignment"
    File "test.ml", line 1, characters 0-1:
    Error: Preprocessor error
    $ camlp4o test.ml
    open Bigarray
    let a =
    (Array2.create float64 fortran_layout 3 3 (Bigarray.Array2.get a 1 1)) <-
    2.
    Remarque : De plus, camlp4o n'utilise pas le même parseur qu'ocaml par défaut, donc les programmes qu'ils rejettent sont parfois différents : camlp4o accepte la forme "let .. in" sans ";;".

  5. #5
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2009
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2009
    Messages : 5
    Points : 1
    Points
    1
    Par défaut
    Merci beaucoup pour cette réponse très détaillée, bluestorm.

    J'ai donc essayé la correction suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Open Bigarray
    let a = Array2.create float64 fortran_layout 3 3
    let () =  a.{1,1} <- 2.
    Le nouveau problème qui surgit, c'est que j'ai cette erreur maintenant :
    $ ocamlc essaiM.ml -o essaiM.exe
    File "essaiM.ml", line 1, characters 0-1:
    Error : Error while linking essaiM.cmo:
    Reference to undefined global 'Bigarray'
    (il donne la même chose lorsque j'utilise "-pp camlp4o".
    J'ai remarqué que si j'utilisais
    $ ocamlc bigarray.cma essaiM.ml -o essaiM.exe
    tout se passais bien.
    Je ne comprends pas pourquoi je dois lui préciser "bigarray.cma" lors de la compilation. Manque-t-il quelque chose dans mon code source qui pourrait me permettre de me passer du "bigarray.cma" dans l'ordre de compilation?


    Sinon, ce bout de code fonctionne.
    J'ai voulu tester qu'il faisait ce que je lui demandais, et j'ai donc ajouté
    Ce code me renvoyant une erreur, je l'ai modifié en :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    let b = a.{1,1} in
    print_float (b);
    Et là, miracle il imprime bien "2.".
    J'ai essayé de comprendre quelle erreur je faisais quand je demandais d'imprimer directement a.{1,1}, et je me demande si c'est lié au fait que je travaille avec des Bigarray (j'ai lu la documentation à leur sujet, mais j'avoue ne pas être très doué en programmation, et n'y avoir compris que le minimum...)

  6. #6
    Membre éprouvé
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    832
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 832
    Points : 1 104
    Points
    1 104
    Par défaut
    Ça dépend de ton code complet. Mais si tu as écrit
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    let () = a.{1,1} <- b
    print_float ...
    C'est normal que ça ne marche pas.

    Ce ne sont pas des problèmes liés à Bigarray, mais uniquement des problèmes syntaxiques. Si tu n'es pas très sûr de ce que tu fais, met systématiquement les délimiteurs ";;" à la fin de chaque phrase, et raisonne sur chaque phrase en isolation.

    Je ne comprends pas pourquoi je dois lui préciser "bigarray.cma" lors de la compilation. Manque-t-il quelque chose dans mon code source qui pourrait me permettre de me passer du "bigarray.cma" dans l'ordre de compilation?
    Non, il ne manque rien. C'est tout simplement le fait que le compilateur ne peut pas deviner à priori de quel module "Bigarray" tu parles, il faut lui préciser la place de la bibliothèque Bigarray sur ton ordinateur, ce que fait l'option "bigarray.cma" (ça lui dit d'aller chercher le fichier bigarray.cma à son emplacement par défaut, donc dans le répertoire des bibliothèques de caml).

    Si tu n'as pas besoin de le faire pour les autres modules que tu connais (List, Array, Printf, etc.), c'est parce que ces modules sont automatiquement chargés par OCaml, c'est un "noyau de base" que tu peux utiliser sans le préciser. Ces différences sont précisées dans le manuel :
    - http://caml.inria.fr/pub/docs/manual-ocaml/index.html , partie 4

    Les modules chargés automatiquement sont ceux de la "standard library", http://caml.inria.fr/pub/docs/manual...manual034.html . Les autres de cette partie ( Num, Str, Bigarray, Graphics, Dynlink, etc. ) doivent être chargées explicitement (c'est précisé dans la documentation), de même que toutes les bibliothèques tierces, codées par d'autres gens, qui ne font pas partie de la distribution caml de base.

  7. #7
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2009
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2009
    Messages : 5
    Points : 1
    Points
    1
    Par défaut
    Ok, merci beaucoup



    Maintenant, je me pose une autre question, toujours liée à ces Bigarray.
    Je dois écrire un code donc qui doit résoudre un système du type AX=B où A est une matrice et X et B deux vecteurs.
    J'ai donc créé ma matrice A en utilisant un Bigarray,

    Code : 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
    open Bigarray
      
    let c = 0. in
    let d = 1. in
    let f argument = 0. in 
    let n = 10 in (* Nombre de noeuds du maillage, sans compter les bornes*)
    let potentiel arg = arg in 
    let h = (d -. c) /. (float_of_int (n+1)) in
    let x = Array.create (n+2) 0. in (*tableau contenant le maillage *)
    (*Initialisation du tableau contenant le maillage *)
    for i=0 to (n+1) do
      x.(i) <- c +. float_of_int i *. h;
    done; 
    (*Calcul de la matrice de rigidité encodée dans un Bigarray de dimension 2 *)
    let () =
      let matriceRigidite = Array2.create float64 fortran_layout n 2 in
      for i=1 to (n-1) do
        matriceRigidite.{i,1} <-  2. /.h +. h/.3. *. (potentiel ((x.(i-1) +. x.(i)) /.2. ) +. potentiel (x.(i)) +. potentiel ((x.(i) +. x.(i+1)) /. 2.) )
        matriceRigidite.{i,2} <- 1. /.h +. h/.6. *. (potentiel (x.(i) +. x.(i+1) ) /. 2.  )
      done;
      matriceRigidite.{n,1}<- 2. /.h +. h/.3. *. (potentiel ((x.(n-1) +. x.(n)) /.2. ) +. potentiel (x.(n)) +. potentiel ((x.(n) +. x.(n+1)) /. 2.) );

    Lorsque je compile j'ai une erreur, ligne 21, caractère 145-146 :
    Parse error: 'in' expected after [binding] (in [expr])

    Si je mets la partie "let () ..." jusque la fin du code en commentaire, le programme compile.
    Je ne comprends pas ce que le message d'erreur veut dire. Je en vois pas non plus quelle erreur je fais, même si je me doute que j'ai encore mal utilisé mon expression de déclaration...

  8. #8
    Membre éprouvé
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    832
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 832
    Points : 1 104
    Points
    1 104
    Par défaut
    Bon, je reviens sur les bases de la syntaxe :

    Un fichier de code OCaml (ou un module) est constitué de phrases. Les phrases peuvent être entre autres des déclarations de type "type .. = ..", des directives "open", "include", etc., des déclarations top-level ("let .. = .."), ou des expressions simples.

    Les phrases sont séparées par le délimiteur ";;", que l'on peut omettre quand il n'y a pas d'ambiguité : toutes les phrases, à part les expressions simples, commencent par un mot-clé caractéristique qui permet de détecter le début de phrase même en absence de délimiteur.

    Les déclarations locales ("let .. = .. in .."), les boucles, les modifications (.. := .., .. <- ..) sont des expressions. On peut aussi mettre bout à bout des expressions en les séparant par des ";", l'ensemble forme alors une expression.

    Dans ton code :
    - les déclarations de départ sont sous la forme "let .. in", donc désignent des expressions et non des phrases (et ce qui est après le "in" doit donc être une expression)
    - la boucle "for .. do .. done" est une expression. Elle est suivie d'un simple ";", donc on attend une expression ensuite
    - la déclaration "let () = .." suivante n'est pas suivie d'un "in expression", c'est une phrase

    Il y a donc un problème.

    Par ailleurs, si tu dois résoudre des systèmes linéaires, est-ce que tu es sûr que tu dois coder l'algorithme de résolution toi-même ? Il existe des bibliothèques qui permettent de faire ça, tu pourrais réutiliser l'une d'entre elles ? Si tu dois manipuler de très grosses données, les gains de performance par rapport à une implémentation perso non optimisée seraient sensibles.

  9. #9
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2009
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2009
    Messages : 5
    Points : 1
    Points
    1
    Par défaut
    Encore une fois, merci bluestorm.

    J'ai donc réécrit le code (correctement cette fois, j'espère). En tout cas il fait ce que je veux. Cela résout bien -u''(x) + V(x) u(x) = f(x) par la méthode des éléments finis.

    Code : 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
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    open Bigarray
     
    let schrodinger1D c d n = 
     
      let f argument = 0.
      and potentiel arg = arg
      and h = (d -. c) /. (float_of_int (n+1))
      and x = Array.create (n+2) 0.
      and matriceRigidite = Array2.create float64 fortran_layout n 2
      and vecteurColonne = Array.make n 0.
      and z = Array.make n 0.
      and u = Array.make (n-1) 0.
      and d = Array.make n 0. 
      and v = Array.make n 0. in
      for i=0 to (n+1) do
        x.(i) <- c +. float_of_int i *. h;
      done;
      for i=1 to (n-1) do
        matriceRigidite.{i,1} <- (2. /.h +. h/.3. *. (potentiel ((x.(i-1) +. x.(i)) /.2. ) +. potentiel (x.(i)) +. potentiel ((x.(i) +. x.(i+1)) /. 2.) ));
        matriceRigidite.{i,2} <- 1. /.h +. h/.6. *. (potentiel (x.(i) +. x.(i+1) ) /. 2.  );
      done;
      matriceRigidite.{n,1}<- 2. /.h +. h/.3. *. (potentiel ((x.(n-1) +. x.(n)) /.2. ) +. potentiel (x.(n)) +. potentiel ((x.(n) +. x.(n+1)) /. 2.) );
      for i=0 to n-1 do
      vecteurColonne.(i) <- h /. 3. *. (f (( x.(i) +. x.(i+1) ) /. 2.) +. f (x.(i+1)) +. f (( x.(i+1) +. x.(i+2) ) /. 2.) );
      done;
      d.(0) <- matriceRigidite.{1,1};
      z.(0) <- (vecteurColonne.(0) /. d.(0));
      u.(0) <- (matriceRigidite.{1,2} /. d.(0));
      for i=1 to (n-2) do
        d.(i) <- (matriceRigidite.{i+1,1} -. matriceRigidite.{i,2} *. u.(i-1));
        u.(i) <- (matriceRigidite.{i+1,2} /. d.(i));
        z.(i) <- ((vecteurColonne.(i) -. matriceRigidite.{i,2} *. z.(i-1)) /. (d.(i)));
      done;
      d.(n-1) <- matriceRigidite.{n,1} -. matriceRigidite.{n-1,2} *. u.(n-2);
      z.(n-1) <- ((vecteurColonne.(n-1) -. matriceRigidite.{n-1,2} *. z.(n-1)) /. (d.(n-1)));
      v.(n-1) <- z.(n-1);
     
      for i=(n-2) downto 0 do
        v.(i) <- z.(i) -. u.(i) *. v.(i+1);
      done;
      v;;

    Ce que je me demande, c'est comment faire pour appeler ma fonction schrodinger1D quand je suis dans un autre fichier (le fichier test.ml).
    J'ai essayé en mettant "open essai" dans le fichier test, mais il n'est pas content. Et ma foi je n'ai pas trouvé comment le faire (surement mal cherché ou pas compris les explications des tutoriels que j'ai parcouru).


    Sinon,
    Par ailleurs, si tu dois résoudre des systèmes linéaires, est-ce que tu es sûr que tu dois coder l'algorithme de résolution toi-même ? Il existe des bibliothèques qui permettent de faire ça, tu pourrais réutiliser l'une d'entre elles ? Si tu dois manipuler de très grosses données, les gains de performance par rapport à une implémentation perso non optimisée seraient sensibles.
    Oui, je suis sensé utilisé Lapack. Mais cela me semble d'une part compliqué de prime abord (cela doit être surement bien plus simple que j'ai fait, si je comprenais ce que Lapack fait je suppose), et de plus je voulais vraiment essayer de réaliser un programme qui tourne sans utiliser de libraire. Mais comme je ne vais pas avoir le choix je vais, c'est sur, devoir m'y mettre...

  10. #10
    Membre éprouvé
    Avatar de Cacophrene
    Homme Profil pro
    Biologiste
    Inscrit en
    Janvier 2009
    Messages
    535
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Biologiste

    Informations forums :
    Inscription : Janvier 2009
    Messages : 535
    Points : 1 125
    Points
    1 125
    Par défaut
    Bonjour !

    Je prends la discussion en cours donc peut-être que je ne serai pas aussi précis qu'il faudrait.

    Citation Envoyé par Webkev
    Ce que je me demande, c'est comment faire pour appeler ma fonction schrodinger1D quand je suis dans un autre fichier (le fichier test.ml). J'ai essayé en mettant "open essai" dans le fichier test, mais il n'est pas content. Et ma foi je n'ai pas trouvé comment le faire (surement mal cherché ou pas compris les explications des tutoriels que j'ai parcouru).
    OCaml considère qu'un fichier .ml (et son interface éventuelle en .mli) forment un module (et donc aussi un espace de nom). Donc tu peux appeler ta fonction avec Essai.schrodinger1D ou écrire open Essai (très peu recommandé parce que ça pollue l'espace de nom du module Test). Pour compiler tes deux fichiers et produire un exécutable :

    • Compiler le module Essai : ocamlc -c essai.mli essai.ml
    • Compiler le module Test : ocamlc -c test.mli test.ml
    • Édition de liens et exécutable : ocamlc essai.cmo test.cmo -o test

    C'est le même principe en natif. Et, comme dit plus haut, le fichier d'interface .mli n'est pas indispensable. Les commandes telles que #open ou #load ne sont comprises que par l'interpréteur.

    Règle de base : le fichier foo.ml donne le module Foo.
    Fichier d'interface : le fichier foo.mli permet de restreindre les fonctions accessibles hors du module Foo. Accessoirement, il sert aussi à documenter les fonctions disponibles.

    Cordialement,
    Cacophrène

Discussions similaires

  1. [debutant] Problème avec les formulaires et le SQL
    Par Bistru dans le forum Langage SQL
    Réponses: 3
    Dernier message: 30/01/2010, 23h53
  2. [Debutant], probléme avec les structures
    Par BobLunique dans le forum C
    Réponses: 5
    Dernier message: 27/03/2008, 19h19
  3. [Debutant] problème avec les vectors
    Par julien.63 dans le forum Langage
    Réponses: 6
    Dernier message: 21/12/2007, 22h53
  4. []Problème avec les formulaires Outlook
    Par davidinfo dans le forum Outlook
    Réponses: 6
    Dernier message: 05/12/2002, 09h59

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