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 ,