Function - str2func gives unusual error

[EDIT: 20110523 11:28 CDT - reformat - WDR]
Background:
I have written a script that takes user input for a fit of a sum of functions. Using this, the fit is performed using separable least squares. The fit is obtained flawlessly. The problem arises in the determination of parameter error.
Problem:
Shown below is the section of the program wherein the issue occurs. nfunct is defined previously in the script and corresponds to the user inputted number functions in the sum of functions for the overall fit. ppm.B11 is a matrix of values that resulted from data collection. For the sake of example, let ppm.B11=[0;1;2;3;4;5;6;7;8;9;10]
FUN='@(c)(';
for s=1:1:nfunct-1
FUN=[FUN 'c(' num2str(3.*(s-1)+1) ').*(c(' num2str(3.*(s-1)+2) ').^2)./((ppm.B11(:,' num2str(specnum) ')-c(' num2str(3.*(s-1)+3) '))+c(' num2str(3.*(s-1)+2) '))+'];
end
FUN=[FUN 'c(' num2str(3.*(nfunct-1)+1) ').*(c(' num2str(3.*(nfunct-1)+2) ').^2)./((ppm.B11(:,' num2str(specnum) ')-c(' num2str(3.*(nfunct-1)+3) '))+c(' num2str(3.*(nfunct-1)+2) '))'];
FUN=[FUN ')'];
pdefun=str2func(FUN);
When I ask MatLab to output pdefun, I get the following:
pdefun =
@(c)(c(1).*(c(2).^2)./((ppm.B11(:,1)-c(3))+c(2)))
This looks as I would have expected. However, when I type in pdefun([1 1 1]), I get the following error:
??? The class "ppm" is undefined.
Perhaps Java is not running.
Error in ==>
@(c)(c(1).*(c(2).^2)./((ppm.B11(:,1)-c(3))+c(2)))
Interestingly, if I type out (or copy and paste from the output when I type "pdefun" alone) in the following manner:
pdefun=@(c)(c(1).*(c(2).^2)./((ppm.B11(:,1)-c(3))+c(2)))
followed by: pdefun([1 1 1]), I get:
ans =
Inf
1.0000
0.5000
0.3333
0.2500
0.2000
0.1667
0.1429
0.1250
0.1111
0.1000
Any ideas why this might be the case?? Thanks.

1 comentario

Tazmusica
Tazmusica el 23 de Mayo de 2011
Also, for this example, assume that nfunct=1 and specnum=1
Since there is this difference, pdefun cannot be fed to jacobianest to determine parameter error in the case where the function is created by conversion from a string. In the second case it works fine with jacobianest.

Iniciar sesión para comentar.

 Respuesta aceptada

Matt Fig
Matt Fig el 23 de Mayo de 2011
What version of MATLAB are you using?
As a workaround, this will produce your desired results. Instead of:
pdefun=str2func(FUN); % Not working...
use this:
eval(['pdefun = ',FUN]) % This works...
For example:
nfunct = 1;
specnum = 1;
ppm.B11=[0;1;2;3;4;5;6;7;8;9;10];
FUN='@(c)(';
for s=1:1:nfunct-1
FUN=[FUN 'c(' num2str(3.*(s-1)+1) ').*(c(' num2str(3.*(s-1)+2),...
').^2)./((ppm.B11(:,' num2str(specnum) ')-c(',...
num2str(3.*(s-1)+3) '))+c(' num2str(3.*(s-1)+2) '))+'];
end
FUN=[FUN 'c(' num2str(3.*(nfunct-1)+1) ').*(c(',...
num2str(3.*(nfunct-1)+2) ').^2)./((ppm.B11(:,',...
num2str(specnum) ')-c(' num2str(3.*(nfunct-1)+3),...
'))+c(' num2str(3.*(nfunct-1)+2) '))'];
FUN=[FUN ')'];
eval(['pdefun = ',FUN,';'])
% pdefun=str2func(FUN);
pdefun([1 1 1])
ans =
Inf
1
0.5
0.33333
0.25
0.2
0.16667
0.14286
0.125
0.11111
0.1

8 comentarios

Tazmusica
Tazmusica el 23 de Mayo de 2011
Great, thank you. This solves my problem, and furthermore allows pdefun to be used as an input for jacobianest. I greatly appreciate your suggestion!
Oleg Komarov
Oleg Komarov el 23 de Mayo de 2011
Evil...but sometimes is the only way to go.
A question, should string to fcn automaticly eval in the ppm if it exists in the base workspace?
Tazmusica
Tazmusica el 24 de Mayo de 2011
I would have thought that if ppm was in the base workspace, as long as you provided the array of values for c, it would do so. Evidently, you must explicitly tell it to eval if it is to work (see the accepted answer).
Oleg Komarov
Oleg Komarov el 24 de Mayo de 2011
I'd like to get any feedback from TMW on that.
Matt Fig
Matt Fig el 24 de Mayo de 2011
Oleg, I am not sure I understand your question. Even if I did, I couldn't check it out because 2007b doesn't allow anonymous function args to str2func. Does this work in your version?
c = 3;
fh = str2func('@(x) x.^c');
fh(4)
I would guess that, though it isn't mentioned in the doc, str2func doesn't capture local parameters the way some users (myself included) would expect.
Oleg Komarov
Oleg Komarov el 24 de Mayo de 2011
I submitted a service request to TMW asking almost exactly your example.
I would have expected it to work as it works with:
fh1 = @(x) x.^c
Matt Fig
Matt Fig el 24 de Mayo de 2011
I will do the same, in case I ever upgrade ;-). I am surprised this didn't come up in Loren's Blog post about STR2FUNC, or in the lengthy discussion that follows.
Oleg Komarov
Oleg Komarov el 24 de Mayo de 2011
The support confirms my explanation: constant are not evaluated into str2func workspace. They suggest for fcn2 defined as:
a = 1;
fcn2 = str2func('@(x) x+a');
to use instead
fcn2 = str2func(['@(x) x+' num2str(a)]);
@Matt: do you think it is worth to submit an enhancement request for an automatic check of "a" (or any constant)?

Iniciar sesión para comentar.

Más respuestas (1)

Oleg Komarov
Oleg Komarov el 23 de Mayo de 2011
Use:
FUN='@(c,ppm)(';
And call:
pdefun([1 1 1],ppm)
My interpretation of the problem is: when you call str2func(FUN), ppm.B11 is not in the private workspace of str2func and thus the anonymous functions considers ppm.B11 as an undeclared constant (bug? unexpected/expected behaviour? Dunno).
When you call pdepe(.), thus ppm.B11 has no value and it throws that error (strange error though).
In anonymous functions the constants take the value they have at the moment the @(.) is created and thus it doesn't search the workspace when executed for the actual value of the constant (this is true also if you update ppm and expect @(.) to reflect this change).

2 comentarios

Matt Fig
Matt Fig el 23 de Mayo de 2011
This does not help on my system, but I am using 2007b too...
Tazmusica
Tazmusica el 23 de Mayo de 2011
This method works to let me evaluate pdefun. However, it fails when pdefun is used as an input argument for jacobianest. Thanks for your help though, as it helps provide some insight and useful knowledge!

Iniciar sesión para comentar.

Categorías

Más información sobre Function Handles en Centro de ayuda y File Exchange.

Preguntada:

el 23 de Mayo de 2011

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by