예제 #1
0
        /*************************************************************************

        NOTES:

        1. This function has two different implementations: one which  uses  exact
           (analytical) user-supplied Jacobian, and one which uses  only  function
           vector and numerically  differentiates  function  in  order  to  obtain
           gradient.

           Depending  on  the  specific  function  used to create optimizer object
           you should choose appropriate variant of MinNLCOptimize() -  one  which
           accepts function AND Jacobian or one which accepts ONLY function.

           Be careful to choose variant of MinNLCOptimize()  which  corresponds to
           your optimization scheme! Table below lists different  combinations  of
           callback (function/gradient) passed to MinNLCOptimize()   and  specific
           function used to create optimizer.


                             |         USER PASSED TO MinNLCOptimize()
           CREATED WITH      |  function only   |  function and gradient
           ------------------------------------------------------------
           MinNLCCreateF()   |     works               FAILS
           MinNLCCreate()    |     FAILS               works

           Here "FAILS" denotes inappropriate combinations  of  optimizer creation
           function  and  MinNLCOptimize()  version.   Attemps   to    use    such
           combination will lead to exception. Either  you  did  not pass gradient
           when it WAS needed or you passed gradient when it was NOT needed.

          -- ALGLIB --
             Copyright 06.06.2014 by Bochkanov Sergey
        *************************************************************************/
        public static bool minnlciteration(minnlcstate state)
        {
            bool result = new bool();
            int i = 0;
            int k = 0;
            int n = 0;
            int ng = 0;
            int nh = 0;
            int i_ = 0;

            
            //
            // Reverse communication preparations
            // I know it looks ugly, but it works the same way
            // anywhere from C++ to Python.
            //
            // This code initializes locals by:
            // * random values determined during code
            //   generation - on first subroutine call
            // * values from previous call - on subsequent calls
            //
            if( state.rstate.stage>=0 )
            {
                i = state.rstate.ia[0];
                k = state.rstate.ia[1];
                n = state.rstate.ia[2];
                ng = state.rstate.ia[3];
                nh = state.rstate.ia[4];
            }
            else
            {
                i = -983;
                k = -989;
                n = -834;
                ng = 900;
                nh = -287;
            }
            if( state.rstate.stage==0 )
            {
                goto lbl_0;
            }
            if( state.rstate.stage==1 )
            {
                goto lbl_1;
            }
            if( state.rstate.stage==2 )
            {
                goto lbl_2;
            }
            if( state.rstate.stage==3 )
            {
                goto lbl_3;
            }
            if( state.rstate.stage==4 )
            {
                goto lbl_4;
            }
            if( state.rstate.stage==5 )
            {
                goto lbl_5;
            }
            if( state.rstate.stage==6 )
            {
                goto lbl_6;
            }
            if( state.rstate.stage==7 )
            {
                goto lbl_7;
            }
            if( state.rstate.stage==8 )
            {
                goto lbl_8;
            }
            
            //
            // Routine body
            //
            
            //
            // Init
            //
            state.repterminationtype = 0;
            state.repinneriterationscount = 0;
            state.repouteriterationscount = 0;
            state.repnfev = 0;
            state.repvaridx = 0;
            state.repfuncidx = 0;
            state.repdbgphase0its = 0;
            n = state.n;
            ng = state.ng;
            nh = state.nh;
            clearrequestfields(state);
            
            //
            // Test gradient
            //
            if( !((double)(state.diffstep)==(double)(0) && (double)(state.teststep)>(double)(0)) )
            {
                goto lbl_9;
            }
            apserv.rvectorsetlengthatleast(ref state.xbase, n);
            apserv.rvectorsetlengthatleast(ref state.fbase, 1+ng+nh);
            apserv.rvectorsetlengthatleast(ref state.dfbase, 1+ng+nh);
            apserv.rvectorsetlengthatleast(ref state.fm1, 1+ng+nh);
            apserv.rvectorsetlengthatleast(ref state.fp1, 1+ng+nh);
            apserv.rvectorsetlengthatleast(ref state.dfm1, 1+ng+nh);
            apserv.rvectorsetlengthatleast(ref state.dfp1, 1+ng+nh);
            state.needfij = true;
            for(i_=0; i_<=n-1;i_++)
            {
                state.xbase[i_] = state.xstart[i_];
            }
            k = 0;
        lbl_11:
            if( k>n-1 )
            {
                goto lbl_13;
            }
            for(i_=0; i_<=n-1;i_++)
            {
                state.x[i_] = state.xbase[i_];
            }
            state.rstate.stage = 0;
            goto lbl_rcomm;
        lbl_0:
            for(i_=0; i_<=ng+nh;i_++)
            {
                state.fbase[i_] = state.fi[i_];
            }
            for(i_=0; i_<=ng+nh;i_++)
            {
                state.dfbase[i_] = state.j[i_,k];
            }
            for(i_=0; i_<=n-1;i_++)
            {
                state.x[i_] = state.xbase[i_];
            }
            state.x[k] = state.x[k]-state.s[k]*state.teststep;
            state.rstate.stage = 1;
            goto lbl_rcomm;
        lbl_1:
            for(i_=0; i_<=ng+nh;i_++)
            {
                state.fm1[i_] = state.fi[i_];
            }
            for(i_=0; i_<=ng+nh;i_++)
            {
                state.dfm1[i_] = state.j[i_,k];
            }
            for(i_=0; i_<=n-1;i_++)
            {
                state.x[i_] = state.xbase[i_];
            }
            state.x[k] = state.x[k]+state.s[k]*state.teststep;
            state.rstate.stage = 2;
            goto lbl_rcomm;
        lbl_2:
            for(i_=0; i_<=ng+nh;i_++)
            {
                state.fp1[i_] = state.fi[i_];
            }
            for(i_=0; i_<=ng+nh;i_++)
            {
                state.dfp1[i_] = state.j[i_,k];
            }
            for(i=0; i<=ng+nh; i++)
            {
                if( !optserv.derivativecheck(state.fm1[i], state.dfm1[i], state.fp1[i], state.dfp1[i], state.fbase[i], state.dfbase[i], 2*state.s[k]*state.teststep) )
                {
                    state.repfuncidx = i;
                    state.repvaridx = k;
                    state.repterminationtype = -7;
                    result = false;
                    return result;
                }
            }
            k = k+1;
            goto lbl_11;
        lbl_13:
            state.needfij = false;
        lbl_9:
            
            //
            // AUL solver
            //
            if( state.solvertype!=0 )
            {
                goto lbl_14;
            }
            if( (double)(state.diffstep)!=(double)(0) )
            {
                apserv.rvectorsetlengthatleast(ref state.xbase, n);
                apserv.rvectorsetlengthatleast(ref state.fbase, 1+ng+nh);
                apserv.rvectorsetlengthatleast(ref state.fm2, 1+ng+nh);
                apserv.rvectorsetlengthatleast(ref state.fm1, 1+ng+nh);
                apserv.rvectorsetlengthatleast(ref state.fp1, 1+ng+nh);
                apserv.rvectorsetlengthatleast(ref state.fp2, 1+ng+nh);
            }
            state.rstateaul.ia = new int[8+1];
            state.rstateaul.ra = new double[7+1];
            state.rstateaul.stage = -1;
        lbl_16:
            if( !auliteration(state) )
            {
                goto lbl_17;
            }
            
            //
            // Numerical differentiation (if needed) - intercept NeedFiJ
            // request and replace it by sequence of NeedFi requests
            //
            if( !((double)(state.diffstep)!=(double)(0) && state.needfij) )
            {
                goto lbl_18;
            }
            state.needfij = false;
            state.needfi = true;
            for(i_=0; i_<=n-1;i_++)
            {
                state.xbase[i_] = state.x[i_];
            }
            k = 0;
        lbl_20:
            if( k>n-1 )
            {
                goto lbl_22;
            }
            for(i_=0; i_<=n-1;i_++)
            {
                state.x[i_] = state.xbase[i_];
            }
            state.x[k] = state.x[k]-state.s[k]*state.diffstep;
            state.rstate.stage = 3;
            goto lbl_rcomm;
        lbl_3:
            for(i_=0; i_<=ng+nh;i_++)
            {
                state.fm2[i_] = state.fi[i_];
            }
            for(i_=0; i_<=n-1;i_++)
            {
                state.x[i_] = state.xbase[i_];
            }
            state.x[k] = state.x[k]-0.5*state.s[k]*state.diffstep;
            state.rstate.stage = 4;
            goto lbl_rcomm;
        lbl_4:
            for(i_=0; i_<=ng+nh;i_++)
            {
                state.fm1[i_] = state.fi[i_];
            }
            for(i_=0; i_<=n-1;i_++)
            {
                state.x[i_] = state.xbase[i_];
            }
            state.x[k] = state.x[k]+0.5*state.s[k]*state.diffstep;
            state.rstate.stage = 5;
            goto lbl_rcomm;
        lbl_5:
            for(i_=0; i_<=ng+nh;i_++)
            {
                state.fp1[i_] = state.fi[i_];
            }
            for(i_=0; i_<=n-1;i_++)
            {
                state.x[i_] = state.xbase[i_];
            }
            state.x[k] = state.x[k]+state.s[k]*state.diffstep;
            state.rstate.stage = 6;
            goto lbl_rcomm;
        lbl_6:
            for(i_=0; i_<=ng+nh;i_++)
            {
                state.fp2[i_] = state.fi[i_];
            }
            for(i=0; i<=ng+nh; i++)
            {
                state.j[i,k] = (8*(state.fp1[i]-state.fm1[i])-(state.fp2[i]-state.fm2[i]))/(6*state.diffstep*state.s[i]);
            }
            k = k+1;
            goto lbl_20;
        lbl_22:
            for(i_=0; i_<=n-1;i_++)
            {
                state.x[i_] = state.xbase[i_];
            }
            state.rstate.stage = 7;
            goto lbl_rcomm;
        lbl_7:
            
            //
            // Restore previous values of fields and continue
            //
            state.needfi = false;
            state.needfij = true;
            goto lbl_16;
        lbl_18:
            
            //
            // Forward request to caller
            //
            state.rstate.stage = 8;
            goto lbl_rcomm;
        lbl_8:
            goto lbl_16;
        lbl_17:
            result = false;
            return result;
        lbl_14:
            result = false;
            return result;
            
            //
            // Saving state
            //
        lbl_rcomm:
            result = true;
            state.rstate.ia[0] = i;
            state.rstate.ia[1] = k;
            state.rstate.ia[2] = n;
            state.rstate.ia[3] = ng;
            state.rstate.ia[4] = nh;
            return result;
        }
예제 #2
0
        /*************************************************************************
        MinNLC results

        INPUT PARAMETERS:
            State   -   algorithm state

        OUTPUT PARAMETERS:
            X       -   array[0..N-1], solution
            Rep     -   optimization report. You should check Rep.TerminationType
                        in  order  to  distinguish  successful  termination  from
                        unsuccessful one:
                        * -8    internal integrity control  detected  infinite or
                                NAN   values   in   function/gradient.   Abnormal
                                termination signalled.
                        * -7   gradient verification failed.
                               See MinNLCSetGradientCheck() for more information.
                        *  1   relative function improvement is no more than EpsF.
                        *  2   scaled step is no more than EpsX.
                        *  4   scaled gradient norm is no more than EpsG.
                        *  5   MaxIts steps was taken
                        More information about fields of this  structure  can  be
                        found in the comments on MinNLCReport datatype.
           
          -- ALGLIB --
             Copyright 06.06.2014 by Bochkanov Sergey
        *************************************************************************/
        public static void minnlcresults(minnlcstate state,
            ref double[] x,
            minnlcreport rep)
        {
            x = new double[0];

            minnlcresultsbuf(state, ref x, rep);
        }
예제 #3
0
        /*************************************************************************
        This  function  tells MinNLC unit to use  Augmented  Lagrangian  algorithm
        for nonlinearly constrained  optimization.  This  algorithm  is  a  slight
        modification of one described in "A Modified Barrier-Augmented  Lagrangian
        Method for  Constrained  Minimization  (1999)"  by  D.GOLDFARB,  R.POLYAK,
        K. SCHEINBERG, I.YUZEFOVICH.

        Augmented Lagrangian algorithm works by converting problem  of  minimizing
        F(x) subject to equality/inequality constraints   to unconstrained problem
        of the form

            min[ f(x) + 
                + Rho*PENALTY_EQ(x)   + SHIFT_EQ(x,Nu1) + 
                + Rho*PENALTY_INEQ(x) + SHIFT_INEQ(x,Nu2) ]
            
        where:
        * Rho is a fixed penalization coefficient
        * PENALTY_EQ(x) is a penalty term, which is used to APPROXIMATELY  enforce
          equality constraints
        * SHIFT_EQ(x) is a special "shift"  term  which  is  used  to  "fine-tune"
          equality constraints, greatly increasing precision
        * PENALTY_INEQ(x) is a penalty term which is used to approximately enforce
          inequality constraints
        * SHIFT_INEQ(x) is a special "shift"  term  which  is  used to "fine-tune"
          inequality constraints, greatly increasing precision
        * Nu1/Nu2 are vectors of Lagrange coefficients which are fine-tuned during
          outer iterations of algorithm

        This  version  of  AUL  algorithm  uses   preconditioner,  which   greatly
        accelerates convergence. Because this  algorithm  is  similar  to  penalty
        methods,  it  may  perform  steps  into  infeasible  area.  All  kinds  of
        constraints (boundary, linear and nonlinear ones) may   be   violated   in
        intermediate points - and in the solution.  However,  properly  configured
        AUL method is significantly better at handling  constraints  than  barrier
        and/or penalty methods.

        The very basic outline of algorithm is given below:
        1) first outer iteration is performed with "default"  values  of  Lagrange
           multipliers Nu1/Nu2. Solution quality is low (candidate  point  can  be
           too  far  away  from  true  solution; large violation of constraints is
           possible) and is comparable with that of penalty methods.
        2) subsequent outer iterations  refine  Lagrange  multipliers  and improve
           quality of the solution.

        INPUT PARAMETERS:
            State   -   structure which stores algorithm state
            Rho     -   penalty coefficient, Rho>0:
                        * large enough  that  algorithm  converges  with   desired
                          precision. Minimum value is 10*max(S'*diag(H)*S),  where
                          S is a scale matrix (set by MinNLCSetScale) and H  is  a
                          Hessian of the function being minimized. If you can  not
                          easily estimate Hessian norm,  see  our  recommendations
                          below.
                        * not TOO large to prevent ill-conditioning
                        * for unit-scale problems (variables and Hessian have unit
                          magnitude), Rho=100 or Rho=1000 can be used.
                        * it is important to note that Rho is internally multiplied
                          by scaling matrix, i.e. optimum value of Rho depends  on
                          scale of variables specified  by  MinNLCSetScale().
            ItsCnt  -   number of outer iterations:
                        * ItsCnt=0 means that small number of outer iterations  is
                          automatically chosen (10 iterations in current version).
                        * ItsCnt=1 means that AUL algorithm performs just as usual
                          barrier method.
                        * ItsCnt>1 means that  AUL  algorithm  performs  specified
                          number of outer iterations
                        
        HOW TO CHOOSE PARAMETERS

        Nonlinear optimization is a tricky area and Augmented Lagrangian algorithm
        is sometimes hard to tune. Good values of  Rho  and  ItsCnt  are  problem-
        specific.  In  order  to  help  you   we   prepared   following   set   of
        recommendations:

        * for  unit-scale  problems  (variables  and Hessian have unit magnitude),
          Rho=100 or Rho=1000 can be used.

        * start from  some  small  value of Rho and solve problem  with  just  one
          outer iteration (ItcCnt=1). In this case algorithm behaves like  penalty
          method. Increase Rho in 2x or 10x steps until you  see  that  one  outer
          iteration returns point which is "rough approximation to solution".
          
          It is very important to have Rho so  large  that  penalty  term  becomes
          constraining i.e. modified function becomes highly convex in constrained
          directions.
          
          From the other side, too large Rho may prevent you  from  converging  to
          the solution. You can diagnose it by studying number of inner iterations
          performed by algorithm: too few (5-10 on  1000-dimensional  problem)  or
          too many (orders of magnitude more than  dimensionality)  usually  means
          that Rho is too large.

        * with just one outer iteration you  usually  have  low-quality  solution.
          Some constraints can be violated with very  large  margin,  while  other
          ones (which are NOT violated in the true solution) can push final  point
          too far in the inner area of the feasible set.
          
          For example, if you have constraint x0>=0 and true solution  x0=1,  then
          merely a presence of "x0>=0" will introduce a bias towards larger values
          of x0. Say, algorithm may stop at x0=1.5 instead of 1.0.
          
        * after you found good Rho, you may increase number of  outer  iterations.
          ItsCnt=10 is a good value. Subsequent outer iteration will refine values
          of  Lagrange  multipliers.  Constraints  which  were  violated  will  be
          enforced, inactive constraints will be dropped (corresponding multipliers
          will be decreased). Ideally, you  should  see  10-1000x  improvement  in
          constraint handling (constraint violation is reduced).
          
        * if  you  see  that  algorithm  converges  to  vicinity  of solution, but
          additional outer iterations do not refine solution,  it  may  mean  that
          algorithm is unstable - it wanders around true  solution,  but  can  not
          approach it. Sometimes algorithm may be stabilized by increasing Rho one
          more time, making it 5x or 10x larger.

        SCALING OF CONSTRAINTS [IMPORTANT]

        AUL optimizer scales   variables   according   to   scale   specified   by
        MinNLCSetScale() function, so it can handle  problems  with  badly  scaled
        variables (as long as we KNOW their scales).   However,  because  function
        being optimized is a mix  of  original  function and  constraint-dependent
        penalty  functions, it  is   important  to   rescale  both  variables  AND
        constraints.

        Say,  if  you  minimize f(x)=x^2 subject to 1000000*x>=0,  then  you  have
        constraint whose scale is different from that of target  function (another
        example is 0.000001*x>=0). It is also possible to have constraints   whose
        scales  are   misaligned:   1000000*x0>=0, 0.000001*x1<=0.   Inappropriate
        scaling may ruin convergence because minimizing x^2 subject to x>=0 is NOT
        same as minimizing it subject to 1000000*x>=0.

        Because we  know  coefficients  of  boundary/linear  constraints,  we  can
        automatically rescale and normalize them. However,  there  is  no  way  to
        automatically rescale nonlinear constraints Gi(x) and  Hi(x)  -  they  are
        black boxes.

        It means that YOU are the one who is  responsible  for  correct scaling of
        nonlinear constraints  Gi(x)  and  Hi(x).  We  recommend  you  to  rescale
        nonlinear constraints in such way that I-th component of dG/dX (or  dH/dx)
        has magnitude approximately equal to 1/S[i] (where S  is  a  scale  set by
        MinNLCSetScale() function).

        WHAT IF IT DOES NOT CONVERGE?

        It is possible that AUL algorithm fails to converge to precise  values  of
        Lagrange multipliers. It stops somewhere around true solution, but candidate
        point is still too far from solution, and some constraints  are  violated.
        Such kind of failure is specific for Lagrangian algorithms -  technically,
        they stop at some point, but this point is not constrained solution.

        There are exist several reasons why algorithm may fail to converge:
        a) too loose stopping criteria for inner iteration
        b) degenerate, redundant constraints
        c) target function has unconstrained extremum exactly at the  boundary  of
           some constraint
        d) numerical noise in the target function

        In all these cases algorithm is unstable - each outer iteration results in
        large and almost random step which improves handling of some  constraints,
        but violates other ones (ideally  outer iterations should form a  sequence
        of progressively decreasing steps towards solution).
           
        First reason possible is  that  too  loose  stopping  criteria  for  inner
        iteration were specified. Augmented Lagrangian algorithm solves a sequence
        of intermediate problems, and requries each of them to be solved with high
        precision. Insufficient precision results in incorrect update of  Lagrange
        multipliers.

        Another reason is that you may have specified degenerate constraints: say,
        some constraint was repeated twice. In most cases AUL algorithm gracefully
        handles such situations, but sometimes it may spend too much time figuring
        out subtle degeneracies in constraint matrix.

        Third reason is tricky and hard to diagnose. Consider situation  when  you
        minimize  f=x^2  subject to constraint x>=0.  Unconstrained   extremum  is
        located  exactly  at  the  boundary  of  constrained  area.  In  this case
        algorithm will tend to oscillate between negative  and  positive  x.  Each
        time it stops at x<0 it "reinforces" constraint x>=0, and each time it  is
        bounced to x>0 it "relaxes" constraint (and is  attracted  to  x<0).

        Such situation  sometimes  happens  in  problems  with  hidden  symetries.
        Algorithm  is  got  caught  in  a  loop with  Lagrange  multipliers  being
        continuously increased/decreased. Luckily, such loop forms after at  least
        three iterations, so this problem can be solved by  DECREASING  number  of
        outer iterations down to 1-2 and increasing  penalty  coefficient  Rho  as
        much as possible.

        Final reason is numerical noise. AUL algorithm is robust against  moderate
        noise (more robust than, say, active set methods),  but  large  noise  may
        destabilize algorithm.

          -- ALGLIB --
             Copyright 06.06.2014 by Bochkanov Sergey
        *************************************************************************/
        public static void minnlcsetalgoaul(minnlcstate state,
            double rho,
            int itscnt)
        {
            alglib.ap.assert(itscnt>=0, "MinNLCSetAlgoAUL: negative ItsCnt");
            alglib.ap.assert(math.isfinite(rho), "MinNLCSetAlgoAUL: Rho is not finite");
            alglib.ap.assert((double)(rho)>(double)(0), "MinNLCSetAlgoAUL: Rho<=0");
            if( itscnt==0 )
            {
                itscnt = 10;
            }
            state.aulitscnt = itscnt;
            state.rho = rho;
            state.solvertype = 0;
        }
예제 #4
0
        /*************************************************************************
        This function turns on/off reporting.

        INPUT PARAMETERS:
            State   -   structure which stores algorithm state
            NeedXRep-   whether iteration reports are needed or not

        If NeedXRep is True, algorithm will call rep() callback function if  it is
        provided to MinNLCOptimize().

        NOTE: algorithm passes two parameters to rep() callback  -  current  point
              and penalized function value at current point. Important -  function
              value which is returned is NOT function being minimized. It  is  sum
              of the value of the function being minimized - and penalty term.

          -- ALGLIB --
             Copyright 28.11.2010 by Bochkanov Sergey
        *************************************************************************/
        public static void minnlcsetxrep(minnlcstate state,
            bool needxrep)
        {
            state.xrep = needxrep;
        }
예제 #5
0
        /*************************************************************************
        Internal initialization subroutine.
        Sets default NLC solver with default criteria.
        *************************************************************************/
        private static void minnlcinitinternal(int n,
            double[] x,
            double diffstep,
            minnlcstate state)
        {
            int i = 0;
            double[,] c = new double[0,0];
            int[] ct = new int[0];

            
            //
            // Default params
            //
            state.stabilizingpoint = -100.0;
            state.initialinequalitymultiplier = 1.0;
            
            //
            // Initialize other params
            //
            state.teststep = 0;
            state.n = n;
            state.diffstep = diffstep;
            state.bndl = new double[n];
            state.hasbndl = new bool[n];
            state.bndu = new double[n];
            state.hasbndu = new bool[n];
            state.s = new double[n];
            state.xstart = new double[n];
            state.xc = new double[n];
            state.x = new double[n];
            for(i=0; i<=n-1; i++)
            {
                state.bndl[i] = Double.NegativeInfinity;
                state.hasbndl[i] = false;
                state.bndu[i] = Double.PositiveInfinity;
                state.hasbndu[i] = false;
                state.s[i] = 1.0;
                state.xstart[i] = x[i];
                state.xc[i] = x[i];
            }
            minnlcsetlc(state, c, ct, 0);
            minnlcsetnlc(state, 0, 0);
            minnlcsetcond(state, 0.0, 0.0, 0.0, 0);
            minnlcsetxrep(state, false);
            minnlcsetalgoaul(state, 1.0E-3, 0);
            minnlcsetprecinexact(state);
            minlbfgs.minlbfgscreate(n, Math.Min(lbfgsfactor, n), x, state.auloptimizer);
            minnlcrestartfrom(state, x);
        }
예제 #6
0
        /*************************************************************************
                          NONLINEARLY  CONSTRAINED  OPTIMIZATION
                    WITH PRECONDITIONED AUGMENTED LAGRANGIAN ALGORITHM

        DESCRIPTION:
        The  subroutine  minimizes  function   F(x)  of N arguments subject to any
        combination of:
        * bound constraints
        * linear inequality constraints
        * linear equality constraints
        * nonlinear equality constraints Gi(x)=0
        * nonlinear inequality constraints Hi(x)<=0

        REQUIREMENTS:
        * user must provide function value and gradient for F(), H(), G()
        * starting point X0 must be feasible or not too far away from the feasible
          set
        * F(), G(), H() are twice continuously differentiable on the feasible  set
          and its neighborhood
        * nonlinear constraints G() and H() must have non-zero gradient at  G(x)=0
          and at H(x)=0. Say, constraint like x^2>=1 is supported, but x^2>=0   is
          NOT supported.

        USAGE:

        Constrained optimization if far more complex than the  unconstrained  one.
        Nonlinearly constrained optimization is one of the most esoteric numerical
        procedures.

        Here we give very brief outline  of  the  MinNLC  optimizer.  We  strongly
        recommend you to study examples in the ALGLIB Reference Manual and to read
        ALGLIB User Guide on optimization, which is available at
        http://www.alglib.net/optimization/

        1. User initializes algorithm state with MinNLCCreate() call  and  chooses
           what NLC solver to use. There is some solver which is used by  default,
           with default settings, but you should NOT rely on  default  choice.  It
           may change in future releases of ALGLIB without notice, and no one  can
           guarantee that new solver will be  able  to  solve  your  problem  with
           default settings.
           
           From the other side, if you choose solver explicitly, you can be pretty
           sure that it will work with new ALGLIB releases.
           
           In the current release following solvers can be used:
           * AUL solver (activated with MinNLCSetAlgoAUL() function)

        2. User adds boundary and/or linear and/or nonlinear constraints by  means
           of calling one of the following functions:
           a) MinNLCSetBC() for boundary constraints
           b) MinNLCSetLC() for linear constraints
           c) MinNLCSetNLC() for nonlinear constraints
           You may combine (a), (b) and (c) in one optimization problem.
           
        3. User sets scale of the variables with MinNLCSetScale() function. It  is
           VERY important to set  scale  of  the  variables,  because  nonlinearly
           constrained problems are hard to solve when variables are badly scaled.

        4. User sets  stopping  conditions  with  MinNLCSetCond(). If  NLC  solver
           uses  inner/outer  iteration  layout,  this  function   sets   stopping
           conditions for INNER iterations.
           
        5. User chooses one of the  preconditioning  methods.  Preconditioning  is
           very  important  for  efficient  handling  of boundary/linear/nonlinear
           constraints. Without preconditioning algorithm would require  thousands
           of iterations even for simple problems.  Two  preconditioners  can   be
           used:
           * approximate LBFGS-based  preconditioner  which  should  be  used  for
             problems with almost orthogonal  constraints  (activated  by  calling
             MinNLCSetPrecInexact)
           * exact low-rank preconditiner (activated by MinNLCSetPrecExactLowRank)
             which should be used for problems with moderate number of constraints
             which do not have to be orthogonal.

        6. Finally, user calls MinNLCOptimize()  function  which  takes  algorithm
           state and pointer (delegate, etc.) to callback function which calculates
           F/G/H.

        7. User calls MinNLCResults() to get solution

        8. Optionally user may call MinNLCRestartFrom() to solve  another  problem
           with same N but another starting point. MinNLCRestartFrom()  allows  to
           reuse already initialized structure.


        INPUT PARAMETERS:
            N       -   problem dimension, N>0:
                        * if given, only leading N elements of X are used
                        * if not given, automatically determined from size ofX
            X       -   starting point, array[N]:
                        * it is better to set X to a feasible point
                        * but X can be infeasible, in which case algorithm will try
                          to find feasible point first, using X as initial
                          approximation.

        OUTPUT PARAMETERS:
            State   -   structure stores algorithm state

          -- ALGLIB --
             Copyright 06.06.2014 by Bochkanov Sergey
        *************************************************************************/
        public static void minnlccreate(int n,
            double[] x,
            minnlcstate state)
        {
            alglib.ap.assert(n>=1, "MinNLCCreate: N<1");
            alglib.ap.assert(alglib.ap.len(x)>=n, "MinNLCCreate: Length(X)<N");
            alglib.ap.assert(apserv.isfinitevector(x, n), "MinNLCCreate: X contains infinite or NaN values");
            minnlcinitinternal(n, x, 0.0, state);
        }
예제 #7
0
        /*************************************************************************
        This function sets scaling coefficients for NLC optimizer.

        ALGLIB optimizers use scaling matrices to test stopping  conditions  (step
        size and gradient are scaled before comparison with tolerances).  Scale of
        the I-th variable is a translation invariant measure of:
        a) "how large" the variable is
        b) how large the step should be to make significant changes in the function

        Scaling is also used by finite difference variant of the optimizer  - step
        along I-th axis is equal to DiffStep*S[I].

        INPUT PARAMETERS:
            State   -   structure stores algorithm state
            S       -   array[N], non-zero scaling coefficients
                        S[i] may be negative, sign doesn't matter.

          -- ALGLIB --
             Copyright 06.06.2014 by Bochkanov Sergey
        *************************************************************************/
        public static void minnlcsetscale(minnlcstate state,
            double[] s)
        {
            int i = 0;

            alglib.ap.assert(alglib.ap.len(s)>=state.n, "MinNLCSetScale: Length(S)<N");
            for(i=0; i<=state.n-1; i++)
            {
                alglib.ap.assert(math.isfinite(s[i]), "MinNLCSetScale: S contains infinite or NAN elements");
                alglib.ap.assert((double)(s[i])!=(double)(0), "MinNLCSetScale: S contains zero elements");
                state.s[i] = Math.Abs(s[i]);
            }
        }
예제 #8
0
        /*************************************************************************
        This  subroutine  turns  on  verification  of  the  user-supplied analytic
        gradient:
        * user calls this subroutine before optimization begins
        * MinNLCOptimize() is called
        * prior to  actual  optimization, for each component  of  parameters being
          optimized X[i] algorithm performs following steps:
          * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i],
            where X[i] is i-th component of the initial point and S[i] is a  scale
            of i-th parameter
          * F(X) is evaluated at these trial points
          * we perform one more evaluation in the middle point of the interval
          * we  build  cubic  model using function values and derivatives at trial
            points and we compare its prediction with actual value in  the  middle
            point
          * in case difference between prediction and actual value is higher  than
            some predetermined threshold, algorithm stops with completion code -7;
            Rep.VarIdx is set to index of the parameter with incorrect derivative,
            and Rep.FuncIdx is set to index of the function.
        * after verification is over, algorithm proceeds to the actual optimization.

        NOTE 1: verification  needs  N (parameters count) gradient evaluations. It
                is very costly and you should use  it  only  for  low  dimensional
                problems,  when  you  want  to  be  sure  that  you've   correctly
                calculated  analytic  derivatives.  You  should  not use it in the
                production code (unless you want to check derivatives provided  by
                some third party).

        NOTE 2: you  should  carefully  choose  TestStep. Value which is too large
                (so large that function behaviour is significantly non-cubic) will
                lead to false alarms. You may use  different  step  for  different
                parameters by means of setting scale with MinNLCSetScale().

        NOTE 3: this function may lead to false positives. In case it reports that
                I-th  derivative was calculated incorrectly, you may decrease test
                step  and  try  one  more  time  - maybe your function changes too
                sharply  and  your  step  is  too  large for such rapidly chanding
                function.

        INPUT PARAMETERS:
            State       -   structure used to store algorithm state
            TestStep    -   verification step:
                            * TestStep=0 turns verification off
                            * TestStep>0 activates verification

          -- ALGLIB --
             Copyright 15.06.2014 by Bochkanov Sergey
        *************************************************************************/
        public static void minnlcsetgradientcheck(minnlcstate state,
            double teststep)
        {
            alglib.ap.assert(math.isfinite(teststep), "MinNLCSetGradientCheck: TestStep contains NaN or Infinite");
            alglib.ap.assert((double)(teststep)>=(double)(0), "MinNLCSetGradientCheck: invalid argument TestStep(TestStep<0)");
            state.teststep = teststep;
        }
예제 #9
0
        /*************************************************************************
        This function sets nonlinear constraints for MinNLC optimizer.

        In fact, this function sets NUMBER of nonlinear  constraints.  Constraints
        itself (constraint functions) are passed to MinNLCOptimize() method.  This
        method requires user-defined vector function F[]  and  its  Jacobian  J[],
        where:
        * first component of F[] and first row  of  Jacobian  J[]  corresponds  to
          function being minimized
        * next NLEC components of F[] (and rows  of  J)  correspond  to  nonlinear
          equality constraints G_i(x)=0
        * next NLIC components of F[] (and rows  of  J)  correspond  to  nonlinear
          inequality constraints H_i(x)<=0

        NOTE: you may combine nonlinear constraints with linear/boundary ones.  If
              your problem has mixed constraints, you  may explicitly specify some
              of them as linear ones. It may help optimizer to  handle  them  more
              efficiently.

        INPUT PARAMETERS:
            State   -   structure previously allocated with MinNLCCreate call.
            NLEC    -   number of Non-Linear Equality Constraints (NLEC), >=0
            NLIC    -   number of Non-Linear Inquality Constraints (NLIC), >=0

        NOTE 1: when you solve your problem  with  augmented  Lagrangian   solver,
                nonlinear constraints are satisfied only  approximately!   It   is
                possible   that  algorithm  will  evaluate  function  outside   of
                feasible area!
                
        NOTE 2: algorithm scales variables  according  to   scale   specified   by
                MinNLCSetScale()  function,  so  it can handle problems with badly
                scaled variables (as long as we KNOW their scales).
                   
                However,  there  is  no  way  to  automatically  scale   nonlinear
                constraints Gi(x) and Hi(x). Inappropriate scaling  of  Gi/Hi  may
                ruin convergence. Solving problem with  constraint  "1000*G0(x)=0"
                is NOT same as solving it with constraint "0.001*G0(x)=0".
                   
                It  means  that  YOU  are  the  one who is responsible for correct
                scaling of nonlinear constraints Gi(x) and Hi(x). We recommend you
                to scale nonlinear constraints in such way that I-th component  of
                dG/dX (or dH/dx) has approximately unit  magnitude  (for  problems
                with unit scale)  or  has  magnitude approximately equal to 1/S[i]
                (where S is a scale set by MinNLCSetScale() function).


          -- ALGLIB --
             Copyright 06.06.2014 by Bochkanov Sergey
        *************************************************************************/
        public static void minnlcsetnlc(minnlcstate state,
            int nlec,
            int nlic)
        {
            alglib.ap.assert(nlec>=0, "MinNLCSetNLC: NLEC<0");
            alglib.ap.assert(nlic>=0, "MinNLCSetNLC: NLIC<0");
            state.ng = nlec;
            state.nh = nlic;
            state.fi = new double[1+state.ng+state.nh];
            state.j = new double[1+state.ng+state.nh, state.n];
        }
예제 #10
0
        /*************************************************************************
        This function sets stopping conditions for inner iterations of  optimizer.

        INPUT PARAMETERS:
            State   -   structure which stores algorithm state
            EpsG    -   >=0
                        The  subroutine  finishes  its  work   if   the  condition
                        |v|<EpsG is satisfied, where:
                        * |.| means Euclidian norm
                        * v - scaled gradient vector, v[i]=g[i]*s[i]
                        * g - gradient
                        * s - scaling coefficients set by MinNLCSetScale()
            EpsF    -   >=0
                        The  subroutine  finishes  its work if on k+1-th iteration
                        the  condition  |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1}
                        is satisfied.
            EpsX    -   >=0
                        The subroutine finishes its work if  on  k+1-th  iteration
                        the condition |v|<=EpsX is fulfilled, where:
                        * |.| means Euclidian norm
                        * v - scaled step vector, v[i]=dx[i]/s[i]
                        * dx - step vector, dx=X(k+1)-X(k)
                        * s - scaling coefficients set by MinNLCSetScale()
            MaxIts  -   maximum number of iterations. If MaxIts=0, the  number  of
                        iterations is unlimited.

        Passing EpsG=0, EpsF=0 and EpsX=0 and MaxIts=0 (simultaneously) will lead
        to automatic stopping criterion selection.

          -- ALGLIB --
             Copyright 06.06.2014 by Bochkanov Sergey
        *************************************************************************/
        public static void minnlcsetcond(minnlcstate state,
            double epsg,
            double epsf,
            double epsx,
            int maxits)
        {
            alglib.ap.assert(math.isfinite(epsg), "MinNLCSetCond: EpsG is not finite number");
            alglib.ap.assert((double)(epsg)>=(double)(0), "MinNLCSetCond: negative EpsG");
            alglib.ap.assert(math.isfinite(epsf), "MinNLCSetCond: EpsF is not finite number");
            alglib.ap.assert((double)(epsf)>=(double)(0), "MinNLCSetCond: negative EpsF");
            alglib.ap.assert(math.isfinite(epsx), "MinNLCSetCond: EpsX is not finite number");
            alglib.ap.assert((double)(epsx)>=(double)(0), "MinNLCSetCond: negative EpsX");
            alglib.ap.assert(maxits>=0, "MinNLCSetCond: negative MaxIts!");
            if( (((double)(epsg)==(double)(0) && (double)(epsf)==(double)(0)) && (double)(epsx)==(double)(0)) && maxits==0 )
            {
                epsx = 1.0E-6;
            }
            state.epsg = epsg;
            state.epsf = epsf;
            state.epsx = epsx;
            state.maxits = maxits;
        }
예제 #11
0
        /*************************************************************************
        This function sets linear constraints for MinNLC optimizer.

        Linear constraints are inactive by default (after initial creation).  They
        are preserved after algorithm restart with MinNLCRestartFrom().

        You may combine linear constraints with boundary ones - and with nonlinear
        ones! If your problem has mixed constraints, you  may  explicitly  specify
        some of them as linear. It  may  help  optimizer   to   handle  them  more
        efficiently.

        INPUT PARAMETERS:
            State   -   structure previously allocated with MinNLCCreate call.
            C       -   linear constraints, array[K,N+1].
                        Each row of C represents one constraint, either equality
                        or inequality (see below):
                        * first N elements correspond to coefficients,
                        * last element corresponds to the right part.
                        All elements of C (including right part) must be finite.
            CT      -   type of constraints, array[K]:
                        * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1]
                        * if CT[i]=0, then I-th constraint is C[i,*]*x  = C[i,n+1]
                        * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1]
            K       -   number of equality/inequality constraints, K>=0:
                        * if given, only leading K elements of C/CT are used
                        * if not given, automatically determined from sizes of C/CT

        NOTE 1: when you solve your problem  with  augmented  Lagrangian   solver,
                linear constraints are  satisfied  only   approximately!   It   is
                possible   that  algorithm  will  evaluate  function  outside   of
                feasible area!

          -- ALGLIB --
             Copyright 06.06.2014 by Bochkanov Sergey
        *************************************************************************/
        public static void minnlcsetlc(minnlcstate state,
            double[,] c,
            int[] ct,
            int k)
        {
            int n = 0;
            int i = 0;
            int i_ = 0;

            n = state.n;
            
            //
            // First, check for errors in the inputs
            //
            alglib.ap.assert(k>=0, "MinNLCSetLC: K<0");
            alglib.ap.assert(alglib.ap.cols(c)>=n+1 || k==0, "MinNLCSetLC: Cols(C)<N+1");
            alglib.ap.assert(alglib.ap.rows(c)>=k, "MinNLCSetLC: Rows(C)<K");
            alglib.ap.assert(alglib.ap.len(ct)>=k, "MinNLCSetLC: Length(CT)<K");
            alglib.ap.assert(apserv.apservisfinitematrix(c, k, n+1), "MinNLCSetLC: C contains infinite or NaN values!");
            
            //
            // Handle zero K
            //
            if( k==0 )
            {
                state.nec = 0;
                state.nic = 0;
                return;
            }
            
            //
            // Equality constraints are stored first, in the upper
            // NEC rows of State.CLEIC matrix. Inequality constraints
            // are stored in the next NIC rows.
            //
            // NOTE: we convert inequality constraints to the form
            // A*x<=b before copying them.
            //
            apserv.rmatrixsetlengthatleast(ref state.cleic, k, n+1);
            state.nec = 0;
            state.nic = 0;
            for(i=0; i<=k-1; i++)
            {
                if( ct[i]==0 )
                {
                    for(i_=0; i_<=n;i_++)
                    {
                        state.cleic[state.nec,i_] = c[i,i_];
                    }
                    state.nec = state.nec+1;
                }
            }
            for(i=0; i<=k-1; i++)
            {
                if( ct[i]!=0 )
                {
                    if( ct[i]>0 )
                    {
                        for(i_=0; i_<=n;i_++)
                        {
                            state.cleic[state.nec+state.nic,i_] = -c[i,i_];
                        }
                    }
                    else
                    {
                        for(i_=0; i_<=n;i_++)
                        {
                            state.cleic[state.nec+state.nic,i_] = c[i,i_];
                        }
                    }
                    state.nic = state.nic+1;
                }
            }
        }
예제 #12
0
        /*************************************************************************
        This function sets boundary constraints for NLC optimizer.

        Boundary constraints are inactive by  default  (after  initial  creation).
        They are preserved after algorithm restart with  MinNLCRestartFrom().

        You may combine boundary constraints with  general  linear ones - and with
        nonlinear ones! Boundary constraints are  handled  more  efficiently  than
        other types.  Thus,  if  your  problem  has  mixed  constraints,  you  may
        explicitly specify some of them as boundary and save some time/space.

        INPUT PARAMETERS:
            State   -   structure stores algorithm state
            BndL    -   lower bounds, array[N].
                        If some (all) variables are unbounded, you may specify
                        very small number or -INF.
            BndU    -   upper bounds, array[N].
                        If some (all) variables are unbounded, you may specify
                        very large number or +INF.

        NOTE 1:  it is possible to specify  BndL[i]=BndU[i].  In  this  case  I-th
        variable will be "frozen" at X[i]=BndL[i]=BndU[i].

        NOTE 2:  when you solve your problem  with  augmented  Lagrangian  solver,
                 boundary constraints are  satisfied  only  approximately!  It  is
                 possible   that  algorithm  will  evaluate  function  outside  of
                 feasible area!

          -- ALGLIB --
             Copyright 06.06.2014 by Bochkanov Sergey
        *************************************************************************/
        public static void minnlcsetbc(minnlcstate state,
            double[] bndl,
            double[] bndu)
        {
            int i = 0;
            int n = 0;

            n = state.n;
            alglib.ap.assert(alglib.ap.len(bndl)>=n, "MinNLCSetBC: Length(BndL)<N");
            alglib.ap.assert(alglib.ap.len(bndu)>=n, "MinNLCSetBC: Length(BndU)<N");
            for(i=0; i<=n-1; i++)
            {
                alglib.ap.assert(math.isfinite(bndl[i]) || Double.IsNegativeInfinity(bndl[i]), "MinNLCSetBC: BndL contains NAN or +INF");
                alglib.ap.assert(math.isfinite(bndu[i]) || Double.IsPositiveInfinity(bndu[i]), "MinNLCSetBC: BndL contains NAN or -INF");
                state.bndl[i] = bndl[i];
                state.hasbndl[i] = math.isfinite(bndl[i]);
                state.bndu[i] = bndu[i];
                state.hasbndu[i] = math.isfinite(bndu[i]);
            }
        }
예제 #13
0
        /*************************************************************************
        This subroutine is a finite  difference variant of MinNLCCreate(). It uses
        finite differences in order to differentiate target function.

        Description below contains information which is specific to this  function
        only. We recommend to read comments on MinNLCCreate() in order to get more
        information about creation of NLC optimizer.

        INPUT PARAMETERS:
            N       -   problem dimension, N>0:
                        * if given, only leading N elements of X are used
                        * if not given, automatically determined from size ofX
            X       -   starting point, array[N]:
                        * it is better to set X to a feasible point
                        * but X can be infeasible, in which case algorithm will try
                          to find feasible point first, using X as initial
                          approximation.
            DiffStep-   differentiation step, >0

        OUTPUT PARAMETERS:
            State   -   structure stores algorithm state

        NOTES:
        1. algorithm uses 4-point central formula for differentiation.
        2. differentiation step along I-th axis is equal to DiffStep*S[I] where
           S[] is scaling vector which can be set by MinNLCSetScale() call.
        3. we recommend you to use moderate values of  differentiation  step.  Too
           large step will result in too large TRUNCATION  errors, while too small
           step will result in too large NUMERICAL  errors.  1.0E-4  can  be  good
           value to start from.
        4. Numerical  differentiation  is   very   inefficient  -   one   gradient
           calculation needs 4*N function evaluations. This function will work for
           any N - either small (1...10), moderate (10...100) or  large  (100...).
           However, performance penalty will be too severe for any N's except  for
           small ones.
           We should also say that code which relies on numerical  differentiation
           is  less   robust   and  precise.  Imprecise  gradient  may  slow  down
           convergence, especially on highly nonlinear problems.
           Thus  we  recommend to use this function for fast prototyping on small-
           dimensional problems only, and to implement analytical gradient as soon
           as possible.

          -- ALGLIB --
             Copyright 06.06.2014 by Bochkanov Sergey
        *************************************************************************/
        public static void minnlccreatef(int n,
            double[] x,
            double diffstep,
            minnlcstate state)
        {
            alglib.ap.assert(n>=1, "MinNLCCreateF: N<1");
            alglib.ap.assert(alglib.ap.len(x)>=n, "MinNLCCreateF: Length(X)<N");
            alglib.ap.assert(apserv.isfinitevector(x, n), "MinNLCCreateF: X contains infinite or NaN values");
            alglib.ap.assert(math.isfinite(diffstep), "MinNLCCreateF: DiffStep is infinite or NaN!");
            alglib.ap.assert((double)(diffstep)>(double)(0), "MinNLCCreateF: DiffStep is non-positive!");
            minnlcinitinternal(n, x, diffstep, state);
        }
예제 #14
0
        /*************************************************************************
        NLC results

        Buffered implementation of MinNLCResults() which uses pre-allocated buffer
        to store X[]. If buffer size is  too  small,  it  resizes  buffer.  It  is
        intended to be used in the inner cycles of performance critical algorithms
        where array reallocation penalty is too large to be ignored.

          -- ALGLIB --
             Copyright 28.11.2010 by Bochkanov Sergey
        *************************************************************************/
        public static void minnlcresultsbuf(minnlcstate state,
            ref double[] x,
            minnlcreport rep)
        {
            int i = 0;
            int i_ = 0;

            if( alglib.ap.len(x)<state.n )
            {
                x = new double[state.n];
            }
            rep.iterationscount = state.repinneriterationscount;
            rep.nfev = state.repnfev;
            rep.varidx = state.repvaridx;
            rep.funcidx = state.repfuncidx;
            rep.terminationtype = state.repterminationtype;
            rep.dbgphase0its = state.repdbgphase0its;
            if( state.repterminationtype>0 )
            {
                for(i_=0; i_<=state.n-1;i_++)
                {
                    x[i_] = state.xc[i_];
                }
            }
            else
            {
                for(i=0; i<=state.n-1; i++)
                {
                    x[i] = Double.NaN;
                }
            }
        }
예제 #15
0
        /*************************************************************************
        This function sets preconditioner to "inexact LBFGS-based" mode.

        Preconditioning is very important for convergence of  Augmented Lagrangian
        algorithm because presence of penalty term makes problem  ill-conditioned.
        Difference between  performance  of  preconditioned  and  unpreconditioned
        methods can be as large as 100x!

        MinNLC optimizer may  utilize  two  preconditioners,  each  with  its  own
        benefits and drawbacks: a) inexact LBFGS-based, and b) exact low rank one.
        It also provides special unpreconditioned mode of operation which  can  be
        used for test purposes. Comments below discuss LBFGS-based preconditioner.

        Inexact  LBFGS-based  preconditioner  uses L-BFGS  formula  combined  with
        orthogonality assumption to perform very fast updates. For a N-dimensional
        problem with K general linear or nonlinear constraints (boundary ones  are
        not counted) it has O(N*K) cost per iteration.  This   preconditioner  has
        best  quality  (less  iterations)  when   general   linear  and  nonlinear
        constraints are orthogonal to each other (orthogonality  with  respect  to
        boundary constraints is not required). Number of iterations increases when
        constraints  are  non-orthogonal, because algorithm assumes orthogonality,
        but still it is better than no preconditioner at all.

        INPUT PARAMETERS:
            State   -   structure stores algorithm state

          -- ALGLIB --
             Copyright 26.09.2014 by Bochkanov Sergey
        *************************************************************************/
        public static void minnlcsetprecinexact(minnlcstate state)
        {
            state.updatefreq = 0;
            state.prectype = 1;
        }
예제 #16
0
        /*************************************************************************
        This subroutine restarts algorithm from new point.
        All optimization parameters (including constraints) are left unchanged.

        This  function  allows  to  solve multiple  optimization  problems  (which
        must have  same number of dimensions) without object reallocation penalty.

        INPUT PARAMETERS:
            State   -   structure previously allocated with MinNLCCreate call.
            X       -   new starting point.

          -- ALGLIB --
             Copyright 28.11.2010 by Bochkanov Sergey
        *************************************************************************/
        public static void minnlcrestartfrom(minnlcstate state,
            double[] x)
        {
            int n = 0;
            int i_ = 0;

            n = state.n;
            
            //
            // First, check for errors in the inputs
            //
            alglib.ap.assert(alglib.ap.len(x)>=n, "MinNLCRestartFrom: Length(X)<N");
            alglib.ap.assert(apserv.isfinitevector(x, n), "MinNLCRestartFrom: X contains infinite or NaN values!");
            
            //
            // Set XC
            //
            for(i_=0; i_<=n-1;i_++)
            {
                state.xstart[i_] = x[i_];
            }
            
            //
            // prepare RComm facilities
            //
            state.rstate.ia = new int[4+1];
            state.rstate.stage = -1;
            clearrequestfields(state);
        }
예제 #17
0
        /*************************************************************************
        This function sets preconditioner to "exact low rank" mode.

        Preconditioning is very important for convergence of  Augmented Lagrangian
        algorithm because presence of penalty term makes problem  ill-conditioned.
        Difference between  performance  of  preconditioned  and  unpreconditioned
        methods can be as large as 100x!

        MinNLC optimizer may  utilize  two  preconditioners,  each  with  its  own
        benefits and drawbacks: a) inexact LBFGS-based, and b) exact low rank one.
        It also provides special unpreconditioned mode of operation which  can  be
        used for test purposes. Comments below discuss low rank preconditioner.

        Exact low-rank preconditioner  uses  Woodbury  matrix  identity  to  build
        quadratic model of the penalized function. It has no  special  assumptions
        about orthogonality, so it is quite general. However, for a  N-dimensional
        problem with K general linear or nonlinear constraints (boundary ones  are
        not counted) it has O(N*K^2) cost per iteration (for  comparison:  inexact
        LBFGS-based preconditioner has O(N*K) cost).

        INPUT PARAMETERS:
            State   -   structure stores algorithm state
            UpdateFreq- update frequency. Preconditioner is  rebuilt  after  every
                        UpdateFreq iterations. Recommended value: 10 or higher.
                        Zero value means that good default value will be used.

          -- ALGLIB --
             Copyright 26.09.2014 by Bochkanov Sergey
        *************************************************************************/
        public static void minnlcsetprecexactlowrank(minnlcstate state,
            int updatefreq)
        {
            alglib.ap.assert(updatefreq>=0, "MinNLCSetPrecExactLowRank: UpdateFreq<0");
            if( updatefreq==0 )
            {
                updatefreq = 10;
            }
            state.prectype = 2;
            state.updatefreq = updatefreq;
        }
예제 #18
0
 /*************************************************************************
 Clears request fileds (to be sure that we don't forget to clear something)
 *************************************************************************/
 private static void clearrequestfields(minnlcstate state)
 {
     state.needfi = false;
     state.needfij = false;
     state.xupdated = false;
 }
예제 #19
0
        /*************************************************************************
        This function sets preconditioner to "turned off" mode.

        Preconditioning is very important for convergence of  Augmented Lagrangian
        algorithm because presence of penalty term makes problem  ill-conditioned.
        Difference between  performance  of  preconditioned  and  unpreconditioned
        methods can be as large as 100x!

        MinNLC optimizer may  utilize  two  preconditioners,  each  with  its  own
        benefits and drawbacks: a) inexact LBFGS-based, and b) exact low rank one.
        It also provides special unpreconditioned mode of operation which  can  be
        used for test purposes.

        This function activates this test mode. Do not use it in  production  code
        to solve real-life problems.

        INPUT PARAMETERS:
            State   -   structure stores algorithm state

          -- ALGLIB --
             Copyright 26.09.2014 by Bochkanov Sergey
        *************************************************************************/
        public static void minnlcsetprecnone(minnlcstate state)
        {
            state.updatefreq = 0;
            state.prectype = 0;
        }
예제 #20
0
        /*************************************************************************
        This function performs actual processing for AUL algorith. It expects that
        caller redirects its reverse communication  requests  NeedFiJ/XUpdated  to
        external user who will provide analytic derivative (or handle reports about
        progress).

        In case external user does not have analytic derivative, it is responsibility
        of caller to intercept NeedFiJ request and  replace  it  with  appropriate
        numerical differentiation scheme.

          -- ALGLIB --
             Copyright 06.06.2014 by Bochkanov Sergey
        *************************************************************************/
        private static bool auliteration(minnlcstate state)
        {
            bool result = new bool();
            int n = 0;
            int nec = 0;
            int nic = 0;
            int ng = 0;
            int nh = 0;
            int i = 0;
            int j = 0;
            int outerit = 0;
            int preccounter = 0;
            double v = 0;
            double vv = 0;
            double p = 0;
            double dp = 0;
            double d2p = 0;
            double v0 = 0;
            double v1 = 0;
            double v2 = 0;
            int i_ = 0;

            
            //
            // Reverse communication preparations
            // I know it looks ugly, but it works the same way
            // anywhere from C++ to Python.
            //
            // This code initializes locals by:
            // * random values determined during code
            //   generation - on first subroutine call
            // * values from previous call - on subsequent calls
            //
            if( state.rstateaul.stage>=0 )
            {
                n = state.rstateaul.ia[0];
                nec = state.rstateaul.ia[1];
                nic = state.rstateaul.ia[2];
                ng = state.rstateaul.ia[3];
                nh = state.rstateaul.ia[4];
                i = state.rstateaul.ia[5];
                j = state.rstateaul.ia[6];
                outerit = state.rstateaul.ia[7];
                preccounter = state.rstateaul.ia[8];
                v = state.rstateaul.ra[0];
                vv = state.rstateaul.ra[1];
                p = state.rstateaul.ra[2];
                dp = state.rstateaul.ra[3];
                d2p = state.rstateaul.ra[4];
                v0 = state.rstateaul.ra[5];
                v1 = state.rstateaul.ra[6];
                v2 = state.rstateaul.ra[7];
            }
            else
            {
                n = 364;
                nec = 214;
                nic = -338;
                ng = -686;
                nh = 912;
                i = 585;
                j = 497;
                outerit = -271;
                preccounter = -581;
                v = 745;
                vv = -533;
                p = -77;
                dp = 678;
                d2p = -293;
                v0 = 316;
                v1 = 647;
                v2 = -756;
            }
            if( state.rstateaul.stage==0 )
            {
                goto lbl_0;
            }
            if( state.rstateaul.stage==1 )
            {
                goto lbl_1;
            }
            if( state.rstateaul.stage==2 )
            {
                goto lbl_2;
            }
            
            //
            // Routine body
            //
            alglib.ap.assert(state.solvertype==0, "MinNLC: internal error");
            n = state.n;
            nec = state.nec;
            nic = state.nic;
            ng = state.ng;
            nh = state.nh;
            
            //
            // Prepare scaled problem
            //
            apserv.rvectorsetlengthatleast(ref state.scaledbndl, n);
            apserv.rvectorsetlengthatleast(ref state.scaledbndu, n);
            apserv.rmatrixsetlengthatleast(ref state.scaledcleic, nec+nic, n+1);
            for(i=0; i<=n-1; i++)
            {
                if( state.hasbndl[i] )
                {
                    state.scaledbndl[i] = state.bndl[i]/state.s[i];
                }
                if( state.hasbndu[i] )
                {
                    state.scaledbndu[i] = state.bndu[i]/state.s[i];
                }
                state.xc[i] = state.xstart[i]/state.s[i];
            }
            for(i=0; i<=nec+nic-1; i++)
            {
                
                //
                // Scale and normalize linear constraints
                //
                vv = 0.0;
                for(j=0; j<=n-1; j++)
                {
                    v = state.cleic[i,j]*state.s[j];
                    state.scaledcleic[i,j] = v;
                    vv = vv+v*v;
                }
                vv = Math.Sqrt(vv);
                state.scaledcleic[i,n] = state.cleic[i,n];
                if( (double)(vv)>(double)(0) )
                {
                    for(j=0; j<=n; j++)
                    {
                        state.scaledcleic[i,j] = state.scaledcleic[i,j]/vv;
                    }
                }
            }
            
            //
            // Prepare stopping criteria
            //
            minlbfgs.minlbfgssetcond(state.auloptimizer, state.epsg, state.epsf, state.epsx, state.maxits);
            
            //
            // Main AUL cycle:
            // * prepare Lagrange multipliers NuNB/NuLC
            // * set GammaK (current estimate of Hessian norm) to 0.0 and XKPresent to False
            //
            apserv.rvectorsetlengthatleast(ref state.nubc, 2*n);
            apserv.rvectorsetlengthatleast(ref state.nulc, nec+nic);
            apserv.rvectorsetlengthatleast(ref state.nunlc, ng+nh);
            apserv.rvectorsetlengthatleast(ref state.xk, n);
            apserv.rvectorsetlengthatleast(ref state.gk, n);
            apserv.rvectorsetlengthatleast(ref state.xk1, n);
            apserv.rvectorsetlengthatleast(ref state.gk1, n);
            for(i=0; i<=n-1; i++)
            {
                state.nubc[2*i+0] = 0.0;
                state.nubc[2*i+1] = 0.0;
                if( (state.hasbndl[i] && state.hasbndu[i]) && (double)(state.bndl[i])==(double)(state.bndu[i]) )
                {
                    continue;
                }
                if( state.hasbndl[i] )
                {
                    state.nubc[2*i+0] = state.initialinequalitymultiplier;
                }
                if( state.hasbndu[i] )
                {
                    state.nubc[2*i+1] = state.initialinequalitymultiplier;
                }
            }
            for(i=0; i<=nec-1; i++)
            {
                state.nulc[i] = 0.0;
            }
            for(i=0; i<=nic-1; i++)
            {
                state.nulc[nec+i] = state.initialinequalitymultiplier;
            }
            for(i=0; i<=ng-1; i++)
            {
                state.nunlc[i] = 0.0;
            }
            for(i=0; i<=nh-1; i++)
            {
                state.nunlc[ng+i] = state.initialinequalitymultiplier;
            }
            state.gammak = 0.0;
            state.xkpresent = false;
            alglib.ap.assert(state.aulitscnt>0, "MinNLC: integrity check failed");
            clearpreconditioner(state.auloptimizer);
            outerit = 0;
        lbl_3:
            if( outerit>state.aulitscnt-1 )
            {
                goto lbl_5;
            }
            
            //
            // Optimize with current Lagrange multipliers
            //
            // NOTE: this code expects and checks that line search ends in the
            //       point which is used as beginning for the next search. Such
            //       guarantee is given by MCSRCH function.  L-BFGS  optimizer
            //       does not formally guarantee it, but it follows same rule.
            //       Below we a) rely on such property of the optimizer, and b)
            //       assert that it is true, in order to fail loudly if it is
            //       not true.
            //
            // NOTE: security check for NAN/INF in F/G is responsibility of
            //       LBFGS optimizer. AUL optimizer checks for NAN/INF only
            //       when we update Lagrange multipliers.
            //
            preccounter = 0;
            minlbfgs.minlbfgssetxrep(state.auloptimizer, true);
            minlbfgs.minlbfgsrestartfrom(state.auloptimizer, state.xc);
        lbl_6:
            if( !minlbfgs.minlbfgsiteration(state.auloptimizer) )
            {
                goto lbl_7;
            }
            if( !state.auloptimizer.needfg )
            {
                goto lbl_8;
            }
            
            //
            // Un-scale X, evaluate F/G/H, re-scale Jacobian
            //
            for(i=0; i<=n-1; i++)
            {
                state.x[i] = state.auloptimizer.x[i]*state.s[i];
            }
            state.needfij = true;
            state.rstateaul.stage = 0;
            goto lbl_rcomm;
        lbl_0:
            state.needfij = false;
            for(i=0; i<=ng+nh; i++)
            {
                for(j=0; j<=n-1; j++)
                {
                    state.j[i,j] = state.j[i,j]*state.s[j];
                }
            }
            
            //
            // Store data for estimation of Hessian norm:
            // * current point (re-scaled)
            // * gradient of the target function (re-scaled, unmodified)
            //
            for(i_=0; i_<=n-1;i_++)
            {
                state.xk1[i_] = state.auloptimizer.x[i_];
            }
            for(i_=0; i_<=n-1;i_++)
            {
                state.gk1[i_] = state.j[0,i_];
            }
            
            //
            // Function being optimized
            //
            state.auloptimizer.f = state.fi[0];
            for(i=0; i<=n-1; i++)
            {
                state.auloptimizer.g[i] = state.j[0,i];
            }
            
            //
            // Penalty for violation of boundary/linear/nonlinear constraints
            //
            penaltybc(state.auloptimizer.x, state.scaledbndl, state.hasbndl, state.scaledbndu, state.hasbndu, state.nubc, n, state.rho, state.stabilizingpoint, ref state.auloptimizer.f, state.auloptimizer.g);
            penaltylc(state.auloptimizer.x, state.scaledcleic, state.nulc, n, nec, nic, state.rho, state.stabilizingpoint, ref state.auloptimizer.f, state.auloptimizer.g);
            penaltynlc(state.fi, state.j, state.nunlc, n, ng, nh, state.rho, state.stabilizingpoint, ref state.auloptimizer.f, state.auloptimizer.g);
            
            //
            // To optimizer
            //
            goto lbl_6;
        lbl_8:
            if( !state.auloptimizer.xupdated )
            {
                goto lbl_10;
            }
            
            //
            // Report current point (if needed)
            //
            if( !state.xrep )
            {
                goto lbl_12;
            }
            for(i=0; i<=n-1; i++)
            {
                state.x[i] = state.auloptimizer.x[i]*state.s[i];
            }
            state.f = state.auloptimizer.f;
            state.xupdated = true;
            state.rstateaul.stage = 1;
            goto lbl_rcomm;
        lbl_1:
            state.xupdated = false;
        lbl_12:
            
            //
            // Update GammaK
            //
            if( state.xkpresent )
            {
                
                //
                // XK/GK store beginning of current line search, and XK1/GK1
                // store data for the end of the line search:
                // * first, we Assert() that XK1 (last point where function
                //   was evaluated) is same as AULOptimizer.X (what is
                //   reported by RComm interface
                // * calculate step length V2.
                //
                // If V2>HessEstTol, then:
                // * calculate V0 - directional derivative at XK,
                //   and V1 - directional derivative at XK1
                // * set GammaK to Max(GammaK, |V1-V0|/V2)
                //
                for(i=0; i<=n-1; i++)
                {
                    alglib.ap.assert((double)(Math.Abs(state.auloptimizer.x[i]-state.xk1[i]))<=(double)(100*math.machineepsilon), "MinNLC: integrity check failed, unexpected behavior of LBFGS optimizer");
                }
                v2 = 0.0;
                for(i=0; i<=n-1; i++)
                {
                    v2 = v2+math.sqr(state.xk[i]-state.xk1[i]);
                }
                v2 = Math.Sqrt(v2);
                if( (double)(v2)>(double)(hessesttol) )
                {
                    v0 = 0.0;
                    v1 = 0.0;
                    for(i=0; i<=n-1; i++)
                    {
                        v = (state.xk[i]-state.xk1[i])/v2;
                        v0 = v0+state.gk[i]*v;
                        v1 = v1+state.gk1[i]*v;
                    }
                    state.gammak = Math.Max(state.gammak, Math.Abs(v1-v0)/v2);
                }
            }
            else
            {
                
                //
                // Beginning of the first line search, XK is not yet initialized.
                //
                for(i_=0; i_<=n-1;i_++)
                {
                    state.xk[i_] = state.xk1[i_];
                }
                for(i_=0; i_<=n-1;i_++)
                {
                    state.gk[i_] = state.gk1[i_];
                }
                state.xkpresent = true;
            }
            
            //
            // Update preconsitioner using current GammaK
            //
            updatepreconditioner(state.prectype, state.updatefreq, ref preccounter, state.auloptimizer, state.auloptimizer.x, state.rho, state.gammak, state.scaledbndl, state.hasbndl, state.scaledbndu, state.hasbndu, state.nubc, state.scaledcleic, state.nulc, state.fi, state.j, state.nunlc, ref state.bufd, ref state.bufc, ref state.bufw, n, nec, nic, ng, nh);
            goto lbl_6;
        lbl_10:
            alglib.ap.assert(false, "MinNLC: integrity check failed");
            goto lbl_6;
        lbl_7:
            minlbfgs.minlbfgsresultsbuf(state.auloptimizer, ref state.xc, state.aulreport);
            state.repinneriterationscount = state.repinneriterationscount+state.aulreport.iterationscount;
            state.repnfev = state.repnfev+state.aulreport.nfev;
            state.repterminationtype = state.aulreport.terminationtype;
            apserv.inc(ref state.repouteriterationscount);
            if( state.repterminationtype<=0 )
            {
                goto lbl_5;
            }
            
            //
            // 1. Evaluate F/J
            // 2. Check for NAN/INF in F/J: we just calculate sum of their
            //    components, it should be enough to reduce vector/matrix to
            //    just one value which either "normal" (all summands were "normal")
            //    or NAN/INF (at least one summand was NAN/INF).
            // 3. Update Lagrange multipliers
            //
            for(i=0; i<=n-1; i++)
            {
                state.x[i] = state.xc[i]*state.s[i];
            }
            state.needfij = true;
            state.rstateaul.stage = 2;
            goto lbl_rcomm;
        lbl_2:
            state.needfij = false;
            v = 0.0;
            for(i=0; i<=ng+nh; i++)
            {
                v = 0.1*v+state.fi[i];
                for(j=0; j<=n-1; j++)
                {
                    v = 0.1*v+state.j[i,j];
                }
            }
            if( !math.isfinite(v) )
            {
                
                //
                // Abnormal termination - infinities in function/gradient
                //
                state.repterminationtype = -8;
                result = false;
                return result;
            }
            for(i=0; i<=ng+nh; i++)
            {
                for(j=0; j<=n-1; j++)
                {
                    state.j[i,j] = state.j[i,j]*state.s[j];
                }
            }
            for(i=0; i<=n-1; i++)
            {
                
                //
                // Process coefficients corresponding to equality-type
                // constraints.
                //
                if( (state.hasbndl[i] && state.hasbndu[i]) && (double)(state.bndl[i])==(double)(state.bndu[i]) )
                {
                    minnlcequalitypenaltyfunction((state.xc[i]-state.scaledbndl[i])*state.rho, ref p, ref dp, ref d2p);
                    state.nubc[2*i+0] = state.nubc[2*i+0]-dp;
                    continue;
                }
                
                //
                // Process coefficients corresponding to inequality-type
                // constraints. These coefficients have limited growth/decay
                // per iteration which helps to stabilize algorithm.
                //
                alglib.ap.assert((double)(aulmaxgrowth)>(double)(1.0), "MinNLC: integrity error");
                if( state.hasbndl[i] )
                {
                    minnlcinequalityshiftfunction((state.xc[i]-state.scaledbndl[i])*state.rho+1, ref p, ref dp, ref d2p);
                    v = Math.Abs(dp);
                    v = Math.Min(v, aulmaxgrowth);
                    v = Math.Max(v, 1/aulmaxgrowth);
                    state.nubc[2*i+0] = state.nubc[2*i+0]*v;
                }
                if( state.hasbndu[i] )
                {
                    minnlcinequalityshiftfunction((state.scaledbndu[i]-state.xc[i])*state.rho+1, ref p, ref dp, ref d2p);
                    v = Math.Abs(dp);
                    v = Math.Min(v, aulmaxgrowth);
                    v = Math.Max(v, 1/aulmaxgrowth);
                    state.nubc[2*i+1] = state.nubc[2*i+1]*v;
                }
            }
            for(i=0; i<=nec+nic-1; i++)
            {
                v = 0.0;
                for(i_=0; i_<=n-1;i_++)
                {
                    v += state.scaledcleic[i,i_]*state.xc[i_];
                }
                v = v-state.scaledcleic[i,n];
                if( i<nec )
                {
                    minnlcequalitypenaltyfunction(v*state.rho, ref p, ref dp, ref d2p);
                    state.nulc[i] = state.nulc[i]-dp;
                }
                else
                {
                    minnlcinequalityshiftfunction(-(v*state.rho)+1, ref p, ref dp, ref d2p);
                    v = Math.Abs(dp);
                    v = Math.Min(v, aulmaxgrowth);
                    v = Math.Max(v, 1/aulmaxgrowth);
                    state.nulc[i] = state.nulc[i]*v;
                }
            }
            for(i=1; i<=ng+nh; i++)
            {
                
                //
                // NOTE: loop index must start from 1, not zero!
                //
                v = state.fi[i];
                if( i<=ng )
                {
                    minnlcequalitypenaltyfunction(v*state.rho, ref p, ref dp, ref d2p);
                    state.nunlc[i-1] = state.nunlc[i-1]-dp;
                }
                else
                {
                    minnlcinequalityshiftfunction(-(v*state.rho)+1, ref p, ref dp, ref d2p);
                    v = Math.Abs(dp);
                    v = Math.Min(v, aulmaxgrowth);
                    v = Math.Max(v, 1/aulmaxgrowth);
                    state.nunlc[i-1] = state.nunlc[i-1]*v;
                }
            }
            outerit = outerit+1;
            goto lbl_3;
        lbl_5:
            for(i=0; i<=n-1; i++)
            {
                state.xc[i] = state.xc[i]*state.s[i];
            }
            result = false;
            return result;
            
            //
            // Saving state
            //
        lbl_rcomm:
            result = true;
            state.rstateaul.ia[0] = n;
            state.rstateaul.ia[1] = nec;
            state.rstateaul.ia[2] = nic;
            state.rstateaul.ia[3] = ng;
            state.rstateaul.ia[4] = nh;
            state.rstateaul.ia[5] = i;
            state.rstateaul.ia[6] = j;
            state.rstateaul.ia[7] = outerit;
            state.rstateaul.ia[8] = preccounter;
            state.rstateaul.ra[0] = v;
            state.rstateaul.ra[1] = vv;
            state.rstateaul.ra[2] = p;
            state.rstateaul.ra[3] = dp;
            state.rstateaul.ra[4] = d2p;
            state.rstateaul.ra[5] = v0;
            state.rstateaul.ra[6] = v1;
            state.rstateaul.ra[7] = v2;
            return result;
        }
예제 #21
0
 public override alglib.apobject make_copy()
 {
     minnlcstate _result = new minnlcstate();
     _result.stabilizingpoint = stabilizingpoint;
     _result.initialinequalitymultiplier = initialinequalitymultiplier;
     _result.solvertype = solvertype;
     _result.prectype = prectype;
     _result.updatefreq = updatefreq;
     _result.rho = rho;
     _result.n = n;
     _result.epsg = epsg;
     _result.epsf = epsf;
     _result.epsx = epsx;
     _result.maxits = maxits;
     _result.aulitscnt = aulitscnt;
     _result.xrep = xrep;
     _result.diffstep = diffstep;
     _result.teststep = teststep;
     _result.s = (double[])s.Clone();
     _result.bndl = (double[])bndl.Clone();
     _result.bndu = (double[])bndu.Clone();
     _result.hasbndl = (bool[])hasbndl.Clone();
     _result.hasbndu = (bool[])hasbndu.Clone();
     _result.nec = nec;
     _result.nic = nic;
     _result.cleic = (double[,])cleic.Clone();
     _result.ng = ng;
     _result.nh = nh;
     _result.x = (double[])x.Clone();
     _result.f = f;
     _result.fi = (double[])fi.Clone();
     _result.j = (double[,])j.Clone();
     _result.needfij = needfij;
     _result.needfi = needfi;
     _result.xupdated = xupdated;
     _result.rstate = (rcommstate)rstate.make_copy();
     _result.rstateaul = (rcommstate)rstateaul.make_copy();
     _result.scaledbndl = (double[])scaledbndl.Clone();
     _result.scaledbndu = (double[])scaledbndu.Clone();
     _result.scaledcleic = (double[,])scaledcleic.Clone();
     _result.xc = (double[])xc.Clone();
     _result.xstart = (double[])xstart.Clone();
     _result.xbase = (double[])xbase.Clone();
     _result.fbase = (double[])fbase.Clone();
     _result.dfbase = (double[])dfbase.Clone();
     _result.fm2 = (double[])fm2.Clone();
     _result.fm1 = (double[])fm1.Clone();
     _result.fp1 = (double[])fp1.Clone();
     _result.fp2 = (double[])fp2.Clone();
     _result.dfm1 = (double[])dfm1.Clone();
     _result.dfp1 = (double[])dfp1.Clone();
     _result.bufd = (double[])bufd.Clone();
     _result.bufc = (double[])bufc.Clone();
     _result.bufw = (double[,])bufw.Clone();
     _result.xk = (double[])xk.Clone();
     _result.xk1 = (double[])xk1.Clone();
     _result.gk = (double[])gk.Clone();
     _result.gk1 = (double[])gk1.Clone();
     _result.gammak = gammak;
     _result.xkpresent = xkpresent;
     _result.auloptimizer = (minlbfgs.minlbfgsstate)auloptimizer.make_copy();
     _result.aulreport = (minlbfgs.minlbfgsreport)aulreport.make_copy();
     _result.nubc = (double[])nubc.Clone();
     _result.nulc = (double[])nulc.Clone();
     _result.nunlc = (double[])nunlc.Clone();
     _result.repinneriterationscount = repinneriterationscount;
     _result.repouteriterationscount = repouteriterationscount;
     _result.repnfev = repnfev;
     _result.repvaridx = repvaridx;
     _result.repfuncidx = repfuncidx;
     _result.repterminationtype = repterminationtype;
     _result.repdbgphase0its = repdbgphase0its;
     return _result;
 }