Fixed parameters for optimize
serrano
Hi all,
Is there an easy way to hold parameters when using optimize, like the /H flag of curvefit?
I'd like to do a complex optimization that depends on >10 parameters and would like to allow the user to keep selected parameters fixed. Adding penalties for deviations from the initial guess kind of works, but this doesn't feel very clean to me.
The only way to hold a parameter during Optimize is to move it from the list of X values into the parameter wave. I see the value of being able to do that, since one common use for Optimize is to implement curve fitting by means other than least squares. It would be tricky to implement... I'll think about it.
November 29, 2022 at 11:25 am - Permalink
Thanks, that worked. If anyone is interested, a possible implementation is below.
Quick follow-up question: Is there a way to access the Hessian in case I'd like to implement error estimation?
Function OptimizeWrapper(Wave xw, String holdString)
if(strlen(holdString) != numpnts(xw))
abort "strlen(holdString) must be equal to npnts(xw)"
endif
//use hold string as a mask to split xw into xw and pw, later reassemble
//pass holdString as bit mask as first parameter in pw to optimizing function.
//optfunc will reassemble
Make/O/N=0/FREE xw_split, pw_split
Variable bitmask = 0
Variable i
for(i=0;i<strlen(holdString);i+=1)
if(stringmatch(holdString[i], "0"))
InsertPoints/V=(xw[i]) numpnts(xw_split), 1, xw_split
elseif(stringmatch(holdString[i], "1"))
InsertPoints/V=(xw[i]) numpnts(pw_split), 1, pw_split
bitmask = bitmask | 2^i
else
abort "Illegal holdString"
endif
endfor
InsertPoints/V=(bitmask) 0, 1, pw_split //store bitmask in pos 0 of pw
Optimize/A/M={2,1}/D=4/X=xw_split/R=xw_split optFuncHoldWrap, pw_split //TODO: The wrapper now hard-codes the actual function that I'd like to optimize. How do I pass an optFunc FUNCREF to optFuncHoldWrap?
End
Function optFuncHoldWrap(Wave pw_split, Wave xw_split)
Variable bitmask = pw_split[0]
Variable numPar = numpnts(xw_split)+numpnts(pw_split)-1
//Reassemble xw
Make/O/FREE/N=0 xw, pw
Variable i, cx=0, cp=0
for(i=0;i<numPar;i+=1)
if(bitmask & 2^i)
InsertPoints/V=(pw_split[cp+1]) numpnts(xw), 1, xw
cp+=1
else
InsertPoints/V=(xw_split[cx]) numpnts(xw), 1, xw
cx+=1
endif
endfor
return optFunc(pw, xw) //Hard-coded
End
Function optFunc(Wave pw, Wave xw)
//(...)
End
December 1, 2022 at 06:23 am - Permalink
No, the Hessian is internal to the OPTIF9 package that we didn't write. It's pretty old FORTRAN code in the public domain. The Hessian is in there somewhere...
With a bit of effort you can write a Hessian function using finite differences if necessary. You have already shown ability to put in the effort!
December 1, 2022 at 01:09 pm - Permalink