Variabile esterna funzione

di il
8 risposte

Variabile esterna funzione

Voglio definire una variabile eserna a una funzione che risolve un'equazione differenziale.

Spiego il problema:
ho un sistema di equazioni differenziali con un certo parametro 'a' noto, ma che non voglio fissare già nell'ambiente function - per intenderci, voglio risolvere l'equazione differenziale per a=1, per dire, ma mettiamo che domani mi gira di cambiare e risolvere lo stesso sistema per a = 2

ovviamente posso entrare nella function e modificarla, ma vorrei fare qualcosa di più generale

ho pensato di entrare nella function e, prima di definire le equazioni differenziali del sistema, aggiungere
a = input('inserire valore di a')
però facendo così mi richiede il valore di a per ogni iterazione...!

Ho allora tentato di lasciare una 'a' generica nelle equazioni definite in function, poi o scritto a = 1 nel workspace, e infine ho richiamato la function, però la a risulta ancora non definita - in realtà non ci speravo molto in questo secondo caso, perchè ovviamente ho definito a esternamente



come posso fare? :/

8 Risposte

  • Re: Variabile esterna funzione

    Una possibile soluzione consiste nel definire la funzione con un numero variabile di parametri utilizzando varargin e nargin.

    La funzione viene quindi definita come:

    function output_var=function_name(varargin)

    quando la funzione viene invocata è quindi possibile definire un numero variabile di input; esempi "validi" di invocazione della funzione "function_name" possono essere:

    x=function_name
    x=function_name(x)
    x=function_name(x,y)
    x=function_name(x,y,42)
    ecc.

    Nella definizione della funzione devono essere codificati opportuni controlli per il riconoscimento degli input e per la loro validità.
    All'interno del codice della funzione si accede ai parametri tramite il cellarray varargin, il numero dei parametri inseriti è definito da nargin.

    Le modalità di definizione e gestione dei parametri sono molte, dalla semplice sequenza di valori:

    x=function_name(x,y,42)

    all'utilizzo delle coppie nome_parametro - valore:

    x=function_name('parametro_1',x,'parametro_1',y,'parametro_1',42)

    Nella funzione proposta nell'esempio che segue è stata implementata la prima modalità (semplice lista di parametri): la definizione della funzione assume che:

    [*] la funzione necessiti di due parametri in input
    [*] il primo parametro deve essere positivo
    [*] il secondo parametro deve essere negativo
    [*] di default la funzione utilizzi come valore del parametro opzionale "a" il valore "1"
    [*] l'eventuale terzo parametro specificato nell'invocazione della funzione costituisce il valore da assegnare al parametro opzionale "a" in sostituzione del valore di default (1)
    
    function res=my_equation(varargin)
    % my_equation(varargin)
    %    Esempio di funzione che accetta un numero variabile di parametri:
    %    Numero di parametri di default = 2
    %    L'eventuale terzo input specifica il valore del parametro opzionale
    %    "a"
    %
    
    % 
    % Definizione del valore di default del parametro "a"
    % 
    a=1;
    % 
    % Controllo degli input:
    % 
    % Se non viene specificato nessun valore in input: generazione di un
    % messaggio di errore
    % 
    if(nargin == 0)
       error('Nessun input specificato')
    % 
    % Se viene specificato un solo valore in input: generazione di un
    % messaggio di errore (la funzione richiede minimo 2 valori in input)
    % 
    elseif(nargin < 2)
       error('Numero di input insufficiente')
    % 
    % Se vengono specificati due valore in input: si procede al controllo della
    % loro validità (il primo deve essere positivo, il secondo negativo. Se il
    % controllo non ha esito positivo viene generato un messaggio di errore in
    % caso contrario l'esecuzione della funzione prosegue e verrà utilizzato
    % il valore di default del parametro "a"
    % 
    elseif(nargin == 2)
       if(varargin{1} < 0)
          error('Il primo parametro deve essere positivo');
       elseif(varargin{2} > 0)
          error('Il secondo parametro deve essere negativo');
       end
       disp(['Parametro opzionale "a" non specificato'])
       disp(['verrà utilizzato il valore di default a=' num2str(a)]);
    % 
    % Se vengono specificati tre valori in input si assume che i primi due
    % costituiscano gli input "base" della funzione e che il terzo rappresenti
    % il parametro opzionale. Viene quindi effettuato un controllo di validità
    % si tre parametri. Se il controllo va a buon fine l'esecuzione della
    % funzione prosegue con l'utilizzo del valore del terzo parametro come
    % parametro opzionale; in caso contrario viene generato un opportuno
    % messaggi di errore
    % 
    elseif(nargin == 3)
       if(varargin{1} < 0)
          error('Il primo parametro deve essere positivo');
       elseif(varargin{2} > 0)
          error('Il secondo parametro deve essere negativo');
       elseif(~isfloat(varargin{3}))
          error('Il parametro opzionale deve essere un "float"')
       else
          disp(['Parametro opzionale a=' num2str(varargin{3})])
          a=varargin{3};
       end
    % 
    % Se vengono specificati più di tre valori in input: generazione di un
    % messaggio di errore
    % 
    else
       error('Numero di parametri eccessivo')
    end
    % 
    % Calcoli effettuati dalla funzione con l'utilizzo del parametro opzionale "a"
    % 
    param_1=varargin{1};
    param_2=varargin{2};
    res=(param_1-param_2)*a;
    
    
    Hope this helps.
  • Re: Variabile esterna funzione

    Penso di aver capito (non del tutto, ma quasi) quello che mi hai risposto


    non so però come accoppiare nargin e varargin con il mio problema. voglio dire, il mio problema è a uno step precedente: io so già quanti sono i parametri (uno solo) ma non so come inserire un parametro in un'equazione differenziale.

    faccio un esempio proprio cretino al massimo. come devo modificare una sintassi del tipo:

    function vprime = eq(t,v)
    vprime(1,1)=15*v(2);
    vprime(2,1)=v(1);
    end


    per fare in modo che quel 15 che ho messo nella prima equazione diventi un parametro generico?

    spero di essermi spiegata meglio...
  • Re: Variabile esterna funzione

    Dunque, un passo alla volta e riusciremo a venire a capo di questo problema

    Innanzi tutto,
    penso di aver capito (non del tutto, ma quasi) quello che mi hai risposto
    cosa non era chiaro nella risposta?

    Provo a chiarire meglio il procedimento partendo dalla funzione "eq" dell'esempio.
    function vprime = eq(t,v)
    vprime(1,1)=15*v(2);
    vprime(2,1)=v(1);
    end
    Partendo dalla funzione "eq" ho scritto la funzione eq_1 nella quale ho utilizzato "varargin" e "nargin":

    [*] varargin è un cellarray all'interno del quale vengono inseriti i parametri di input passati alla funzione
    [*] nargin è un contatore nel quale viene settato il numero dei parametri di input (numero degli elementi di varargin)

    Ho anche modificato la definizione degli output della funzione, aggiungendo la variabile "err_msg" che verrà utilizzata per memorizzare eventuali messaggi di errore generati dalla funzione.
    La funzione "eq_1" è quindi definita come:

    function [vprime,err_msg] = eq_1(varargin)

    gli input (t,v) della funzione "eq" sono stati quindi sostituiti da "varargin"

    La funzione "eq_1" è strutturata più o meno allo stesso modo rispetto a quella della risposta precedente, con l'esclusione del controllo sulla validità degli input.

    il primo "if" ed il successivo "elseif" effettuano un controllo sul numero dei parametri di input (nargin).

    Il set di istruzione contenute nel secondo "elseif" corrispondono alla definizione della funzione "eq":

    [*] alle variabili "t" e "v" vengono assegnati i valori dei primi due elementi del cellarray varargin
    [*] viene poi utilizzata la variabile "param_esterno" alla quale viene assegnato il valore "15" (così come nella funzione "eq" il valore 15 era "hard coded").

    Se la funzione "eq_1" viene chiamata nel modo seguente:

    [vprime,err_msg]=eq_1(t,v)

    la condizione del secondo "elseif" sarà verificata, verranno settate le variabili come descritto sopra e l'esecuzione della funzione "salterà" fino al blocco "if"

    if(go_flg)

    dove verranno effettuati i calcoli utilizzando il valore "15" (memorizzato nella variabile "param_esterno" - in questo caso, il funzionamento di "eq" e "eq_1" è identico)

    Se la funzione "eq_1" viene chiamata nel modo seguente:

    [vprime,err_msg]=eq_1(t,v,ext_param)

    e se, in precedenza alla variabile "ext_param"è stato assegnato, ad esempio il valore "33" (o se, in alternativa, la funzione viene chiamata inserendo il valore "33" direttamente nella chiamata: [vprime,err_msg]=eq_1(t,v,33)), sarà la condizione del terzo "elseif" ad essere verifica.
    Questo comporterà che, come per il caso precedente:

    [*] alle variabili "t" e "v" vengono assegnati i valori dei primi due elementi del cellarray varargin
    [*] alla variabile "param_esterno" verrà assegnato il valore contenuto nel terzo elemento di "varargin" (terzo parametro di input nella chiamata)

    Anche in questo caso l'esecuzione della funzione "salterà fino al blocco "if"

    if(go_flg)

    ma, a differenza del caso precedente, la variabile "param_esterno" non conterrà più il valore "15", ma il valore definito dall'utente.

    L'ultimo "else" della funzione "eq_1" è stato inserito solo per illustrare come accedere ad eventuali altri parametri di input contenuti in "varargin", ma dal punto di vista dell'esecuzione dei calcoli, non si differenzia dal caso precedente.

    All'interno della definizione della funzione "eq_1" sono state inserite delle istruzioni "disp " le quali scriveranno dei messaggi di stato nella Command Window.

    Il codice della funzione "eq_1" è riportato di seguito; dopo di esso ho inserito il codice di uno script che chiama la funzione "eq" e, poi, la funzione "eq_1" nelle diverse modalità descritte in precedenza.

    Se questo script viene eseguito in "modalità debug" e se si effettuerà uno step alla volta ("entrando nella funzioni "eq" e "eq_1" - F11) dovrebbe essere abbastanza chiaro il funzionamento delle funzione "eq_1".

    Inoltre, i messaggi di stato che vengono scritti nella Command Window, dovrebbero ulteriormente chiarire il funzionamento della funzione "eq_1".

    Codice della funzione "eq_1"
    
    function [vprime,err_msg] = eq_1(varargin)
    %
    % Inizializzazione del vettore di output "vprime", del messaggio di errore
    % e del flag per l'interruzione dell'esecuzione della funzione in caso di
    % errore
    %
    vprime=zeros(2,1)*NaN;
    err_msg='Nessun errore nella definizione dei parametri di input';
    go_flg=1;
    %
    % Se la funzione viene chiamata senza specificare alcun parametro, viene
    % generato un messaggio di errore ed il flag di controllo viene settato a
    % "0" il che impedirà l'esecuzione dei calcoli
    %
    if(nargin == 0)
       err_msg='Function eq_1 - ERROR #1: Nessun input specificato';
       go_flg=0;
       %
       %    Se la funzione viene chiamata specificando solo un parametro, viene
       %    generato un messaggio di errore ed il flag di controllo viene
       %    settato a "0" il che impedirà l'esecuzione dei calcoli
       %
    elseif(nargin < 2)
       err_msg='Function eq_1 - ERROR #2: Numero di input insufficiente';
       go_flg=0;
    elseif(nargin == 2)
       %
       %    Se la funzione viene chiamata specificando 2 parametri, questi
       %    vengono assegnati alle variabili "t" e "v" ed il valore "15" viene
       %    assegnato alla variabile (interna alla funzione) "param_esterno
       %
       t=varargin{1};
       v=varargin{2};
       param_esterno=15;
    elseif(nargin == 3)
       %
       %    Se la funzione viene chiamata specificando 3 parametri, i primi due
       %    vengono assegnati alle variabili "t" e "v", il terzo viene
       %    assegnato alla variabile (interna alla funzione) "param_esterno"
       %
       t=varargin{1};
       v=varargin{2};
       param_esterno=varargin{3};
    else
       %
       %    Se la funzione viene chiamata specificando più di tre parametri, i
       %    primi due vengono assegnati alle variabili "t" e "v", il terzo
       %    viene assegnato alla variabile (interna alla funzione)
       %    "param_esterno". Gli altri parametri vengono ignorati
       %
       t=varargin{1};
       v=varargin{2};
       param_esterno=varargin{3};
       disp('Numero di parametri eccessivo')
       disp(['Il terzo parametro ' num2str(varargin{3}) ' verrà utilizzato come parametro esterno'])
       disp('gli altri parametri ')
       for i=4:nargin
          disp(['   Parametro #' num2str(i) '=' num2str(varargin{i})])
       end
       disp('non verranno utilizzati');
    end
    %
    % Il valore "15" viene sostituito dalla variabile "param_esterno" che, a
    % seconda del numero dei parametri con i quali la funzione è stata chiamata
    % assumerà il valore "15" (valore di default) od il valore specificato
    % nelle chiamata alla funzione
    %
    % L'esecuzioe dei calcoli della funzione è condizionato all'assenza di
    % errori nella definizione dei parametri di input
    %
    if(go_flg)
       vprime(1,1)=param_esterno*v(2);
       %
       %    Stampa a video del valore utilizzato come parametro
       %
       disp(['Calcolo effettuato utilizzando come "parametro" il valore ' num2str(param_esterno)])
       vprime(2,1)=v(1);
    end
    % end
    
    Codice dello script per le diverse chiamate delle funzioni "eq" e "eq_1"
    %
    % Definizione del parametro "t"
    % Definizione del vettore "v" utilizzato % all'interno della funzione
    %
    t=42;
    v=[10 20];
    %
    % Chiamata della funzione "eq" (come scritta nella dimanda); la funzione
    % utilizxa il valore "15" "hard coded" nella funzione
    %
    disp('Chiamata: vprime=eq(t,v)')
    vprime=eq(t,v);
    vprime
    disp(' ')
    disp('**************************')
    disp(' ')
    %
    % Chiamata alla funzione "eq_1" modificata (rispetto alla "eq") con
    % l'inserimento delle istruzioni per la gestioine dinamica dei parametri.
    % La funzione viene chiamata con due soli parametri ed utilizza, di default
    % il valore "15". Il risultato è lo stesso che si ottiene chiamado la
    % funzione "eq"
    %
    disp('Chiamata: vprime=eq_1(t,v)')
    [vprime,err_msg]=eq_1(t,v);
    vprime
    disp(err_msg)
    disp(' ')
    disp('**************************')
    disp(' ')
    %
    % Definizione del parametro esterno "ext_param": il valore 33 sostituirà il
    % valore di default "15" all'interno della funzione senza che si debba
    % modificare il codice della funzione "eq_1". La chiamata della funzione
    % "eq_1" è diversa da quella precedente, per l'aggiunta del terzo parametro
    %
    disp('Chiamata: vprime=eq_1(t,v,ext_param)')
    ext_param=33;
    [vprime,err_msg]=eq_1(t,v,ext_param);
    vprime
    disp(err_msg)
    disp(' ')
    disp('**************************')
    disp(' ')
    %
    % Per verifica della correttezza dell'implementazine della la funzione "eq_1", la stessa viene chiamata:
    %  - senza parametri ==> ci si aspetta un messaggio di errore
    %  - con un solo parametro ==> ci si aspetta un messaggio di errore
    %  - con 7 parametri ==> ==> ci si aspetta un messaggio di warning, ma il
    %    risultato deve essere uguale a quello ottenuto chiamado la funzione
    %    con tre parametri, l'ultimo dei quali deve essere "ext_param". In
    %    questa chiamata il valore del parametro "ext_param" è stato modificato
    %    da "33" (chiamata precedente) a 369, per illustrare la possibilità di
    %    cambiarlo "a piacere" (ad esempio all'interno di un loop)
    %
    disp('Chiamata: vprime=eq_1()')
    [vprime,err_msg]=eq_1();
    vprime
    disp(err_msg)
    disp(' ')
    disp('**************************')
    disp(' ')
    %
    disp('Chiamata: vprime=eq_1(t)')
    [vprime,err_msg]=eq_1(t);
    vprime
    disp(err_msg)
    disp(' ')
    disp('**************************')
    disp(' ')
    %
    disp('Chiamata: vprime=eq_1(t,v,ext_param,1.2,3.3,42,69)')
    ext_param=369;
    [vprime,err_msg]=eq_1(t,v,ext_param,1.2,3.3,42,69);
    vprime
    disp(err_msg)
    
    Spero che questo esempio sia più chiaro e, soprattutto, aiuti a risolvere il problema.
    Let me know
  • Re: Variabile esterna funzione

    Ora ho capito di più

    il mio dubbio è sempre sull'equazione differenziale.

    io vorrei usare un comando (ovviamente nella command window) del tipo
    [t,n]=ode45(eq_1,[0,1],[0,1],1)

    con il richiamo che fai tu risolve l'equazione differenziale?

    per cui avevo pensato di sfruttare quello che mi hai scritto, e di scrivere qualcosa del tipo (salto l'interno degli if, considera che è quello che hai scritto tu)

    function nprime = eq (varargin)
    if(nargin == 0)
    ...
    elseif(nargin < 2)
    ...
    elseif(nargin == 2)
    ...
    elseif(nargin == 3)
    ...
    else
    ...
    end
    vprime(1,1) = ...
    vprime(2,1) = ...
    end



    ma, richiamando questa funzione con (numeri a caso)
    [t,n]=ode45(@eq_1,[0,1],[0,1],1)
    oppure
    [t,n]=ode45(@eq_1,[0,1],[0,1])

    mi restituisce in entrambi i casi errore. Ho anche spostato la definizione di vprime(1,1) e vprime(2,1) all'interno dei cicli per cui non restituisce errore, ma niente


    C'è un'incompatibilità tra nargin/varargin e la sintassi di ode45?



    Stavo pensando di fare due funzioni, una per l'assegnazione del parametro, e una per la risoluzione dell'equazione differenziale, e poi fare in modo che una richiama l'altra... però mi sembra eccessivo, penso esista una soluzione più semplice
  • Re: Variabile esterna funzione

    Per cominciare, mi devo scusare due volte.
    La prima per non aver capito la domanda originale; pensavo che l'equazione "eq" fosse quella che risolveva l'equazione differenziale mentre invece (spero di avere capito) è l'equazione differenziale.
    La seconda perchè la mia conoscenza delle equazioni differenziali si limita ... a sapere che esistono.

    Ad ogni modo, forse ho trovato una soluzione anche se probabilmente poco elegante ed un po' contorta (ormai, però, era diventata una sfida)

    Dunque.
    Come base ho preso il sistema di equazioni differenziali definito nell'help di MatLab per "ode45" (rigid); ho eliminato l'istruzione "options = odeset('RelTol',1e-4,'AbsTol',[1e-4 1e-4 1e-5]); ed ho modificato le tre equazioni aggiungendo, ad ognuna un fattore moltiplicativo.
    Questo fattore sarà il parametro "opzionale" che dovrà essere passato alla funzione.
    Lo script di questa funzione è riportato in calce (file rigid.m).

    La soluzione (ammesso che lo sia) è codificata nel file "my_rigid_varargin.m" (lo script è in calce ed è basata su "Parameterizing Functions (descritto nell'help di MatLab).

    La funzione "my_rigid_varargin" si compone di due sezioni principali: nella prima vengono processati i parametri opzionali e viene invocata la funzione "ode45" alla quale viene passato, come input la funzione "rigid" che corrisponde al sistema di equazioni originale.

    La stessa funzione "rigid" viene "ridefinita" all'interno della funzione "my_rigid_varargin".

    La funzione "my_rigid_varargin" riceve tre parametri in input:

    [*] t0_tf: un vettore di due elementi che definiscono l'intervallo di integrazione (usato da "ode45")
    [*] y0: un vettore di "n" elementi (tanti quante le equazione del sistema) che definisce le condizioni iniziali
    [*] varargin: i parametri opzionali

    I parametri opzionali sono definiti a coppie: nome del parametro, valore.

    Il processo di gestione dei parametri opzionali (blocco switrch nel codice) assegna alla variabile parametrica il corrispondente valore; se uno o più di uno dei parametri opzionali non vengono definiti in input, un valore di default viene loro assegnato.

    Lo script "call_my_rigid.m" (il codice è riportato in calce) viene utilizzato per testare la soluzione proposta e confrontare il risultato con quella "originale".

    Nella prima parte di "call_my_rigid.m" viene invocata la funzione "ode45" alla quale viene dato in input il sistema originale (rigid.m)

    Nella seconda parte, viene invocata la funzione "my_rigid_varargin" alla quale vengono passati in input:

    [*] il vettore "intervallo di integrazione"
    [*] il vettore con le condizioni iniziali
    [*] tre coppie di parametri opzionali (grazie al meccanismo di gestione dei parametri opzionali, se ne possono indicare anche solo 2 o 1)

    la chiamata a "ode45" è all'interno della funzione "my_rigid_varargin".

    Negli script riportati in calce, sono stati definiti gli stessi valori per i parametri "hard coded" in "regid.m" e per i parametri opzionali in "my_rigid_varargin".
    Volendo fare ulteriori prove per testare la soluzione proposta occorre modificare la funzione "rigid" ed, in accordo, i parametri opzionali in "my_rigid_varargin"
    In particolare, se si vogliono specificare in "my_rigid_varargin" solo 1 o 2 parametri, occorre eliminare (o settare a 1) i corrispondenti fattori in "rigid".

    rigid.m
    
    % 
    % Sistema di equazioni tratto dalla pagina "ode45" della documentazine di
    % MatLab (doc ode45)
    % Le equazioni sono state modificate inserendo i fattori "2", "3" e "4"
    % 
    function dy = rigid(t,y)
    dy = zeros(3,1);
    % 
    % Equazione modificata: inserito "2*"
    % 
    dy(1) = y(2) * 2 * y(3);
    % 
    % Equazione modificata: inserito "3*"
    % 
    dy(2) = -y(1) * 3 * y(3);
    % 
    % Equazione modificata: inserito "4*"
    % 
    dy(3) = -0.51 * y(1) * 4 * y(2);
    
    my_rigid_varargin.m
    
    %
    % Sistema di equazioni geenrato a partire dal sistema "rigid"
    %
    function dy=my_rigid(t0_tf,y0,varargin)
    %
    % Gestione dei parametri opzionali: Definizione dei valori di default
    %
    a=1;
    b=1;
    c=1;
    %
    % Gestione dei parametri opzionali: controllo numro dei parametri opzionali
    %
    if(nargin ~= 0)
       if(floor(nargin/2)*2 ~= nargin)
          disp('Il numero dei parametri opzionali deve essere pari:');
          disp('Formato: coppia ''nome_parametro'' , valore');
       else
    %
    % Gestione dei parametri opzionali: loop sui paraemtri opzionali
    % "nargin" contiene il numero totale dei parametri di input: i primi due
    % vettori ed i parametri opzionali. I primi vanno esclusi, quindi il numero
    % di parametri sui quali lavorare è "nargin - 2"
    %
          for i=1:2:nargin-2
             switch(lower(varargin{i}))
                case 'param_a'
                   a=varargin{i+1};
                case 'param_b'
                   b=varargin{i+1};
                case 'param_c'
                   c=varargin{i+1};
             end
          end
       end
    end
       %
       % Chiamata della funzione "ode45"
       %
       [T,Y] = ode45(@rigid,t0_tf,y0);
       %
       % Ridefinizione della funzione originale
       % Sistema di equazioni originale con inserimento delle variabili "a" e "b"
       % passate attraverso la funzione "my_rigid"
       %
       function dy = rigid(t,y)
       dy = zeros(3,1);
       %
       %       Equazione modificata con l'inserimento della variabile "a"
       %
       dy(1) = y(2) * a *y (3);
       %
       %       Equazione modificata con l'inserimento della variabile "b"
       %
       dy(2) = -y(1) * b * y(3);
       %
       %       Equazione non modificata
       %
       dy(3) = -0.51 * y(1) * c * y(2);
       end
       %
       % Per poter essere estratti dalla funzione "my_rigid", i vettori calcolati
       % dalla funzione "ode45" vengono assegnati alla variabile di output "dy"
       %
       dy=[T,Y];
    end
    
    call_my_rigid.m
    
    % 
    % Utilizzo standard della funzione passata a "ode45"
    % 
    [T,Y] = ode45(@rigid,[0 12],[0 1 1]);
    figure
    subplot(2,1,1)
    plot(T,Y(:,1),'-',T,Y(:,2),'-',T,Y(:,3),'-','linewidth',2)
    title('ORIGINALE')
    grid on
    % 
    % Utilizzo modificato della funzione passata a "ode45"
    % 
    dy=my_rigid_varargin([0 12],[0 1 1],'param_a',2,'param_b',3,'param_c',4);
    T1=dy(:,1);
    Y1=dy(:,2:end);
    subplot(2,1,2)
    plot(T1,Y1(:,1),'-',T1,Y1(:,2),'-',T1,Y1(:,3),'-','linewidth',2)
    title('MODIFICATO')
    grid on
    % 
    % Controllo della differenza tra i risultati ottenuti con i due metodi
    % 
    if(sum(sum(Y-Y1) ~= 0.0))
       disp('Error')
    else
       disp('OK')
    end
    
    la soluzione è effettivamente un po' complicata, ma ...

    Hope this helps
    Allegati:
    16082_ee998e0f1b2bde16c1c1c9e9300f58fd.jpg
    16082_ee998e0f1b2bde16c1c1c9e9300f58fd.jpg
  • Re: Variabile esterna funzione

    Esattamente! mi serviva qualcosa del genere ottimo

    ps: sì, anche per me in realtà era più un sfida che altro. voglio dire, mi serve effettivamente, ma potevo scrivere una funzione che lanciava un warning dicendo 'c'è questo parametro fissato pari a 100 (per dire) se il tuo parametro è diverso, entra nella funzione e cambialo'... però non mi soddisfaceva affatto

    comunque grazie mille
  • Re: Variabile esterna funzione

    Grazie!
    E' stato divertente.
    Buon tutto!
  • Re: Variabile esterna funzione

    Sono stato proprio un asino

    C'è un modo MOLTO più semplice per passare delle variabili: basta definire le variabili che si vogliono passare come "global" come negli script che seguono.

    Script per invocare la funzione ode45 nei due modi
    
    % 
    % Utilizzo standard della funzione passata a "ode45"
    % 
    [T,Y] = ode45(@rigid,[0 12],[0 1 1]);
    figure
    subplot(2,1,1)
    plot(T,Y(:,1),'-',T,Y(:,2),'-',T,Y(:,3),'-','linewidth',2)
    title('ORIGINALE')
    grid on
    % 
    % Utilizzo modificato delle variabili globali
    % 
    % Definizione delle variabili globali
    % 
    global global_var_1 global_var_2 global_var_3
    % 
    % Inizializzazione delle variabili globali
    % 
    global_var_1=2;
    global_var_2=3;
    global_var_3=4;
    % 
    % Alla funzine "ode45" viene passata la funzione "rigid_global" modificata
    % per mezzo dell'iserimento delle variabili globali
    % 
    [T,Y1] = ode45(@rigid_global,[0 12],[0 1 1]);
    subplot(2,1,2)
    plot(T,Y1(:,1),'-',T,Y1(:,2),'-',T,Y1(:,3),'-','linewidth',2)
    title(' MODIFICATO')
    grid on
    % 
    % Controllo della differenza tra i risultati ottenuti con i due metodi
    % 
    if(sum(sum(Y-Y1) ~= 0.0))
       disp('Error')
    else
       disp('OK')
    end
    
    Script della funzione "rigid" (non è stata modificata rispetto alla "risposta precedente")
    
    % 
    % Sistema di equazioni tratto dalla pagina "ode45" della documentazine di
    % MatLab (doc ode45)
    % Le equazioni sono state modificate inserendo i fattori "2", "3" e "4"
    % 
    function dy = rigid(t,y)
    dy = zeros(3,1);
    % 
    % Equazione modificata: inserito "2*"
    % 
    dy(1) = y(2) * 2 * y(3);
    % 
    % Equazione modificata: inserito "3*"
    % 
    dy(2) = -y(1) * 3 * y(3);
    % 
    % Equazione modificata: inserito "4*"
    % 
    dy(3) = -0.51 * y(1) * 4 * y(2);
    
    Script della funzione "rigid_global" con l'utilizzo delle "variabili globali"
    %
    % Sistema di equazioni tratto dalla pagina "ode45" della documentazine di
    % MatLab (doc ode45)
    % Le equazioni sono state modificate inserendo i fattori "2", "3" e "4"
    %
    function dy = rigid(t,y)
    %
    % Dichiarazione delle variabili globali
    %
    global global_var_1 global_var_2 global_var_3 once_1 once_2 once_3
    %
    % Controllo delle variabili globali "once" utilizzate solo per controllare
    % la stampa a video del messaggio di warning
    %
    if(isempty(once_1))
       once_1=1;
    end
    if(isempty(once_2))
       once_2=1;
    end
    if(isempty(once_3))
       once_3=1;
    end
    %
    % Controllo delle variabili globali: se non sono state definite prima
    % dell'invocazione della funzione viene loro assegnato un valore di default
    %
    if(isempty(global_var_1))
       global_var_1=1;
       if(once_1)
          once_1=0;
          disp('Global variable "global_var_1" not initialized')
          disp(['   Default value "' num2str(global_var_1) '" will be assigned'])
       end
    else
       if(once_1)
          once_1=0;
          disp(['Global variable "global_var_1"=' num2str(global_var_1)])
       end
    end
    if(isempty(global_var_2))
       global_var_2=1;
       if(once_2)
          once_2=0;
          disp('Global variable "global_var_1" not initialized')
          disp(['   Default value "' num2str(global_var_2) '" will be assigned'])
       end
    else
       if(once_2)
          once_2=0;
          disp(['Global variable "global_var_2"=' num2str(global_var_2)])
       end
    end
    if(isempty(global_var_3))
       global_var_3=1;
       if(once_3)
          once_3=0;
       end
       disp('Global variable "global_var_3" not initialized')
       disp(['   Default value "' num2str(global_var_3) '" will be assigned'])
    else
       if(once_3)
          once_3=0;
          disp(['Global variable "global_var_3"=' num2str(global_var_3)])
       end
    end
    
    dy = zeros(3,1);
    %
    % Equazione modificata: inserita variabile "global_var_1
    %
    dy(1) = y(2) * global_var_1 * y(3);
    %
    % Equazione modificata: inserita variabile "global_var_2
    %
    dy(2) = -y(1) * global_var_2 * y(3);
    %
    % Equazione modificata: inserita variabile "global_var_3
    %
    dy(3) = -0.51 * y(1) * global_var_3 * y(2);
    
    Hope this helps.
Devi accedere o registrarti per scrivere nel forum
8 risposte