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

MATLAB Discussion :

Transformer une String en fonction


Sujet :

MATLAB

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7
    Points : 2
    Points
    2
    Par défaut Transformer une String en fonction
    Bonjour,

    Je souhaite transformer une String du genre 'x+1' en fonction.

    Pour être plus clair, voici le contexte :
    J'ai une interface dans laquelle l'utilisateur saisit une formule ('x+1') que je récupère donc dans une variable formule de type String. Je souhaite ensuite appliquer cette formule à une variable y en fonction de x. J'ai d'abord penser utiliser la fonction eval de Matlab :
    mais étant donné que j'appelle cette fonction dans une boucle et que la formule peut être complexe, le temps de traitement est très long (à cause de eval()).

    Pour résumer différemment, est-il possible de créer une variable f de type function_handle et de valeur @(x)x+1 à partir de la String 'x+1' ?

    En espérant avoir été assez clair, merci pour vos réponses.

  2. #2
    Rédacteur/Modérateur

    Avatar de Jerome Briot
    Homme Profil pro
    Freelance mécatronique - Conseil, conception et formation
    Inscrit en
    Novembre 2006
    Messages
    20 318
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Freelance mécatronique - Conseil, conception et formation

    Informations forums :
    Inscription : Novembre 2006
    Messages : 20 318
    Points : 52 956
    Points
    52 956
    Par défaut
    Tu peux peut être utiliser INLINE :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    str='x+1';
    f=inline(str,'x');

  3. #3
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7
    Points : 2
    Points
    2
    Par défaut
    Merci je ne connaissais pas,
    mais le temps de traitement est aussi long qu'avec la fonction eval (et beaucoup plus long que lorsque l'on rentre la formule en dur).

  4. #4
    Rédacteur/Modérateur

    Avatar de Jerome Briot
    Homme Profil pro
    Freelance mécatronique - Conseil, conception et formation
    Inscrit en
    Novembre 2006
    Messages
    20 318
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Freelance mécatronique - Conseil, conception et formation

    Informations forums :
    Inscription : Novembre 2006
    Messages : 20 318
    Points : 52 956
    Points
    52 956
    Par défaut
    Peut être quelque chose comme ceci ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    f='x+1';
     
    g=eval(['@(x) ' f]);
     
    for n=1:3
     
       g(n)
     
    end
    (merci Caro pour l'idée)

  5. #5
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7
    Points : 2
    Points
    2
    Par défaut
    Ca fontionne et c'est plus rapide que le inline.
    En revanche ça reste toujours un peu long et dans ce cas je ne comprends pas pourquoi le traitement est plus long que si on rentrait directement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    g=@(x) x+1;
     
    for n=1:3
     
       g(n)
     
    end
    puisque des deux manières, on a bien @(x) x+1 dans g.

  6. #6
    Expert éminent sénior
    Avatar de Caro-Line
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    9 458
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 9 458
    Points : 14 828
    Points
    14 828
    Par défaut
    Ca dépend à quel niveau tu regardes le temps.
    Petit test tout bête :
    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
    clear all
    g=@(x) x+1;
    tic
    for n=1:30
       g(n);
    end
    toc
     
    clear all
    f='x+1';
    g=eval(['@(x) ' f]);
    tic
    for n=1:30
       g(n);
    end
    toc
    Moi j'obtiens :
    Elapsed time is 0.002189 seconds.
    Elapsed time is 0.002059 seconds.
    (en le faisant plusieurs fois bien sûr)
    Donc à peu près équivalent.

    Tu n'as pas d'autres choses dans ta boucle qui pourraient être optimisées ?

  7. #7
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7
    Points : 2
    Points
    2
    Par défaut
    En essayant la même manipulation avec mon code :
    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
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    clear all
    sizeX = 400;
    sizeY = 400;
    im = zeros(sizeX,sizeY);
    im = im2double(im);
     
    f='z+1';
    formule=eval(['@(z) ' f]);
    tic
    for k=-sizeX/2+1:sizeX/2
       for l=-sizeY/2+1:sizeY/2  
           a = k/(sizeX/4);
           b = l/(sizeY/4);
           r = sqrt(a*a+b*b);
           z = a + i*b;
           n = 0;  
           while r < 10 && n <= 10
              z = formule(z);
              a = real(z);
              b = imag(z);
              r = sqrt(a*a + b*b);
              n = n+1; 
           end
           im(k+sizeX/2,l+sizeY/2) = min( abs(a) , abs(b));
       end
    end
    toc
     
    clear all
    sizeX = 400;
    sizeY = 400;
    im = zeros(sizeX,sizeY);
    im = im2double(im);
     
    formule=@(z)z+1;
    tic
    for k=-sizeX/2+1:sizeX/2
       for l=-sizeY/2+1:sizeY/2  
           a = k/(sizeX/4);
           b = l/(sizeY/4);
           r = sqrt(a*a+b*b);
           z = a + i*b;
           n = 0;  
           while r < 10 && n <= 10
              z = formule(z);
              a = real(z);
              b = imag(z);
              r = sqrt(a*a + b*b);
              n = n+1; 
           end
           im(k+sizeX/2,l+sizeY/2) = min( abs(a) , abs(b));
       end
    end
    toc
    J'obtiens :
    Elapsed time is 43.046651 seconds.
    Elapsed time is 1.463195 seconds.
    Ca donne une grosse différence sur une boucle plus importante.

  8. #8
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7
    Points : 2
    Points
    2
    Par défaut
    C'est bizarre, quand je place ce morceau de code dans une fonction et que je l'appelle, j'obtiens :
    Elapsed time is 42.617504 seconds.
    Elapsed time is 1.298563 seconds.
    Et quand j'en fait un script (ou que je l'appelle directement dans la Command Window), j'obtiens :
    Elapsed time is 25.860350 seconds.
    Elapsed time is 25.854857 seconds.
    Je ne comprends pas à quoi c'est dû.

  9. #9
    Rédacteur/Modérateur

    Avatar de Jerome Briot
    Homme Profil pro
    Freelance mécatronique - Conseil, conception et formation
    Inscrit en
    Novembre 2006
    Messages
    20 318
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Freelance mécatronique - Conseil, conception et formation

    Informations forums :
    Inscription : Novembre 2006
    Messages : 20 318
    Points : 52 956
    Points
    52 956
    Par défaut
    Le problème semble bien provenir de EVAL (encore une fois)

    En testant les deux codes suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    function testA
     
    formule=@(x)x+1;
     
    y=0;
    for n=1:1E15
        y=y+formule(n);
    end
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    function testB
     
    formule=eval('@(x)x+1;');
     
    y=0;
    for n=1:1E6
        y=y+formule(n);
    end
    Et en les interrompant pendant leur exécution avec un CTRL+C, on obtient :

    Pour testA :

    ??? Operation terminated by user during ==> testA at 7
    Et pour testB :
    ??? Operation terminated by user during ==> testB>@(x)x+1

    In ==> testB at 7
    y=y+formule(n);
    Il semble qu'il y ait comme une sorte de récursivité autour de EVAL, même dans ce cas particulier. La fonction testB serait donc appelée plusieurs fois afin d'évaluer "formule"

    C'est d'ailleurs le fonctionnement normal de EVAL. Son argument pouvant être modifié entre deux appels, MATLAB ne peut le précompilé. D'où un temps d'exécution plus important.

  10. #10
    Rédacteur/Modérateur

    Avatar de Jerome Briot
    Homme Profil pro
    Freelance mécatronique - Conseil, conception et formation
    Inscrit en
    Novembre 2006
    Messages
    20 318
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Freelance mécatronique - Conseil, conception et formation

    Informations forums :
    Inscription : Novembre 2006
    Messages : 20 318
    Points : 52 956
    Points
    52 956
    Par défaut
    Essaie ceci :

    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
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    function test
    
    sizeX = 400;
    sizeY = 400;
    im = zeros(sizeX,sizeY);
    im = im2double(im);
    
    formule='z+1';
    fid=fopen('subtest.m','wt');
        fprintf(fid,'function z=subtest(z)\nz=%s;',formule);
    fclose(fid);
    
    tic
    for k=-sizeX/2+1:sizeX/2
       for l=-sizeY/2+1:sizeY/2  
           a = k/(sizeX/4);
           b = l/(sizeY/4);
           r = sqrt(a*a+b*b);
           z = a + i*b;
           n = 0;  
           while r < 10 && n <= 10
              z = subtest(z);
              a = real(z);
              b = imag(z);
              r = sqrt(a*a + b*b);
              n = n+1; 
           end
           im(k+sizeX/2,l+sizeY/2) = min( abs(a) , abs(b));
       end
    end
    toc
    
    clear all
    
    sizeX = 400;
    sizeY = 400;
    im = zeros(sizeX,sizeY);
    im = im2double(im);
    
    formule=@(z)z+1;
    tic
    for k=-sizeX/2+1:sizeX/2
       for l=-sizeY/2+1:sizeY/2  
           a = k/(sizeX/4);
           b = l/(sizeY/4);
           r = sqrt(a*a+b*b);
           z = a + i*b;
           n = 0;  
           while r < 10 && n <= 10
              z = formule(z);
              a = real(z);
              b = imag(z);
              r = sqrt(a*a + b*b);
              n = n+1; 
           end
           im(k+sizeX/2,l+sizeY/2) = min( abs(a) , abs(b));
       end
    end
    toc
    ça commence à être tiré par les cheveux

  11. #11
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7
    Points : 2
    Points
    2
    Par défaut
    Oui j'avais déjà essayer cette astuce, elle fonctionne mais le problème est que j'aimerais pouvoir modifier ma formule pendant l'exécution du programme. Or une fois que le fichier subset.m, et donc la fonction subset, sont créés, le fait de remodifier le fichier ne modifie pas la fonction : la première fonction subset en fonction de la première formule saisie est conservée pendant toute la durée de l'exécution.

    Y aurait-il moyen de réinitialiser le programme pour que la fonction subset soit "effacée" lorsque l'on saisit une nouvelle formule ?

  12. #12
    Rédacteur/Modérateur

    Avatar de Jerome Briot
    Homme Profil pro
    Freelance mécatronique - Conseil, conception et formation
    Inscrit en
    Novembre 2006
    Messages
    20 318
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Freelance mécatronique - Conseil, conception et formation

    Informations forums :
    Inscription : Novembre 2006
    Messages : 20 318
    Points : 52 956
    Points
    52 956
    Par défaut
    Citation Envoyé par Jevil Voir le message
    Y aurait-il moyen de réinitialiser le programme pour que la fonction subset soit "effacée" lorsque l'on saisit une nouvelle formule ?
    Essaie ceci :


  13. #13
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7
    Points : 2
    Points
    2
    Par défaut
    Ca fonctionne !

    Merci beaucoup à toi et à Caro !

    Bonne soirée !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Transformer une string en int
    Par blueice dans le forum AppleScript
    Réponses: 1
    Dernier message: 28/09/2014, 19h55
  2. Réponses: 3
    Dernier message: 18/02/2013, 06h15
  3. transformer une string en tableau
    Par alexis.gruet dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 06/04/2007, 00h12
  4. Transformer une String en Unicode
    Par annemarie dans le forum Delphi
    Réponses: 3
    Dernier message: 28/02/2007, 18h43
  5. Transformer une string en un dictionnaire
    Par nabix dans le forum Général Python
    Réponses: 5
    Dernier message: 24/11/2005, 18h34

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