optim - non-linear optimization routine
min costf(x) w.r.t x.
costf is an "external" i.e a Scilab function, a list or a string giving the name of a C or Fortran routine (see "external"). This external must return the value f of the cost function at the point x and the gradient g of the cost function at the point x .
If costf is a Scilab function, the calling sequence for costf must be: [f,g,ind]=costf(x,ind)
Here, costf is a function which returns f , value (real number) of cost function at x , and g , gradient vector of cost function at x . The variable ind is described below.If costf is a list, it should be of the form: list(real_costf, arg1,...,argn) with real_costf a Scilab function with calling sequence : [f,g,ind]=costf(x,ind,arg1,... argn) . The x , f , g , ind arguments have the same meaning that above. argi arguments can be used to pass function parameters.
If costf is a character string, it refers to the name of a C or Fortran routine which must be linked to Scilab
The generic calling sequence for the Fortran subroutine is: subroutine costf(ind,n,x,f,g,ti,tr,td) with the following declarations:
integer ind,n ti(*) double precision x(n),f,g(n),td(*) real tr(*)The argument ind is described below.
The Fortran subroutine costf must return f and the vector g , given x, ind, n, ti, tr,td .
ti,tr,td can be used to initialize parameters. In the calling sequence of optim , the keyword <params>' can be replaced by 'ti', valti ,'td', valtd . Then, the routine costf is evaluated with ti=valti and td=valtd whatever the value of ind . Thus, the Scilab variables valti and valtd (integer vector and real vector) are sent to the routine costf .
The generic calling sequence for the C procedure is: void costf(int *ind, int *n, double *x, double *f, double *g, int *ti, float *tr, double *td) with the following declarations:
The argument ind is described below.
The C procedure costf must return f and the vector g , given x, ind, n, ti, tr, td .
ti,tr,td can be used to initialize parameters. In the calling sequence of optim , the string 'in' can be replaced by 'ti', valti ,'td', valtd . Then, the procedure costf is evaluated with ti=valti and td=valtd whatever the value of ind . Thus, the Scilab variables valti and valtd (integer vector and real vector) are sent to the procedure costf .
If ind=2 (resp. 3, 4 ), costf must provide f (resp. g, f and g ).
If ind=1 nothing is computed (used for display purposes only).
On output, ind<0 means that f cannot be evaluated at x and ind=0 interrupts the optimization.
// External function written in Scilab
xref=[1;2;3];x0=[1;-1;1]
deff('[f,g,ind]=cost(x,ind)','f=0.5*norm(x-xref)^2,g=x-xref');
[f,xopt]=optim(cost,x0) //Simplest call
[f,xopt,gopt]=optim(cost,x0,'gc') // By conjugate gradient
[f,xopt,gopt]=optim(cost,x0,'nd') //Seen as non differentiable
[f,xopt,gopt]=optim(cost,'b',[-1;0;2],[0.5;1;4],x0) // Bounds on x
[f,xopt,gopt]=optim(cost,'b',[-1;0;2],[0.5;1;4],x0,'gc') // Bounds on x
[f,xopt,gopt]=optim(cost,'b',[-1;0;2],[0.5;1;4],x0,'gc','ar',3)
// External function written in C (C compiler required)
// write down the C code (Rosenbrock problem)
C=['#include <math.h>'
'double sq(double x)'
'{ return x*x;}'
'void rosenc(int *ind, int *n, double *x, double *f, double *g, '
' int *ti, float *tr, double *td)'
'{'
' double p;'
' int i;'
' p=td[0];'
' if (*ind==2||*ind==4) {'
' *f=1.0;'
' for (i=1;i<*n;i++)'
' *f+=p*sq(x[i]-sq(x[i-1]))+sq(1.0-x[i]);'
' }'
' if (*ind==3||*ind==4) {'
' g[0]=-4.0*p*(x[1]-sq(x[0]))*x[0];'
' for (i=1;i<*n-1;i++)'
' g[i]=2.0*p*(x[i]-sq(x[i-1]))-4.0*p*(x[i+1]-sq(x[i]))*x[i]-2.0*(1.0-x[i]);'
' g[*n-1]=2.0*p*(x[*n-1]-sq(x[*n-2]))-2.0*(1.0-x[*n-1]);'
' }'
'}'];
mputl(C,TMPDIR+'/rosenc.c')
// compile the C code
l=ilib_for_link('rosenc','rosenc.o',[],'c',TMPDIR+'/Makefile');
// incremental linking
link(l,'rosenc','c')
//solve the problem
x0=[40;10;50];
p=100;
[f,xo,go]=optim('rosenc',x0,'td',p)
// External function written in Fortran (Fortran compiler required)
// write down the Fortran code (Rosenbrock problem)
F=[ ' subroutine rosenf(ind, n, x, f, g, ti, tr, td)'
' integer ind,n,ti(*)'
' double precision x(n),f,g(n),td(*)'
' real tr(*)'
'c'
' double precision y,p'
' p=td(1)'
' if (ind.eq.2.or.ind.eq.4) then'
' f=1.0d0'
' do i=2,n'
' f=f+p*(x(i)-x(i-1)**2)**2+(1.0d0-x(i))**2'
' enddo'
' endif'
' if (ind.eq.3.or.ind.eq.4) then'
' g(1)=-4.0d0*p*(x(2)-x(1)**2)*x(1)'
' if(n.gt.2) then'
' do i=2,n-1'
' g(i)=2.0d0*p*(x(i)-x(i-1)**2)-4.0d0*p*(x(i+1)-x(i)**2)*x(i)'
' & -2.0d0*(1.0d0-x(i))'
' enddo'
' endif'
' g(n)=2.0d0*p*(x(n)-x(n-1)**2)-2.0d0*(1.0d0-x(n))'
' endif'
' return'
' end'];
mputl(F,TMPDIR+'/rosenf.f')
// compile the Fortran code
l=ilib_for_link('rosenf','rosenf.o',[],'f',TMPDIR+'/Makefile');
// incremental linking
link(l,'rosenf','f')
//solve the problem
x0=[40;10;50];
p=100;
[f,xo,go]=optim('rosenf',x0,'td',p)
external , quapro , linpro , datafit , leastsq , numdiff , derivative , NDcost ,