Scilab Function
Last update : 3/8/39972196

optim - non-linear optimization routine

Calling Sequence

[f,xopt]=optim(costf,x0)
[f [,xopt [,gradopt [,work]]]]=optim(costf [,<contr>],x0 [,algo] [,df0 [,mem]] [,work] [,<stop>] [,<params>] [,imp=iflag])

Parameters

Description

Non-linear optimization routine for programs without constraints or with bound constraints:
      
      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.

- Scilab function case

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.
- List case

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.

- String case

If costf is a character string, it refers to the name of a C or Fortran routine which must be linked to Scilab

* Fortran case

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.

* C case

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.

Examples

    
    // 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)

 
    
  

See Also

external,  quapro,  linpro,  datafit,  leastsq,  numdiff,  derivative,  NDcost,