Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.ALGLIB-2.5.0/ALGLIB-2.5.0/mincg.cs @ 5229

Last change on this file since 5229 was 3839, checked in by mkommend, 14 years ago

implemented first version of LR (ticket #1012)

File size: 25.0 KB
Line 
1/*************************************************************************
2Copyright (c) 2010, Sergey Bochkanov (ALGLIB project).
3
4>>> SOURCE LICENSE >>>
5This program is free software; you can redistribute it and/or modify
6it under the terms of the GNU General Public License as published by
7the Free Software Foundation (www.fsf.org); either version 2 of the
8License, or (at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13GNU General Public License for more details.
14
15A copy of the GNU General Public License is available at
16http://www.fsf.org/licensing/licenses
17
18>>> END OF LICENSE >>>
19*************************************************************************/
20
21using System;
22
23namespace alglib
24{
25    public class mincg
26    {
27        public struct mincgstate
28        {
29            public int n;
30            public double epsg;
31            public double epsf;
32            public double epsx;
33            public int maxits;
34            public double stpmax;
35            public bool xrep;
36            public int cgtype;
37            public int nfev;
38            public int mcstage;
39            public int k;
40            public double[] xk;
41            public double[] dk;
42            public double[] xn;
43            public double[] dn;
44            public double[] d;
45            public double fold;
46            public double stp;
47            public double[] work;
48            public double[] yk;
49            public double[] x;
50            public double f;
51            public double[] g;
52            public bool needfg;
53            public bool xupdated;
54            public AP.rcommstate rstate;
55            public int repiterationscount;
56            public int repnfev;
57            public int repterminationtype;
58            public int debugrestartscount;
59            public linmin.linminstate lstate;
60            public double betahs;
61            public double betady;
62        };
63
64
65        public struct mincgreport
66        {
67            public int iterationscount;
68            public int nfev;
69            public int terminationtype;
70        };
71
72
73
74
75        /*************************************************************************
76                NONLINEAR CONJUGATE GRADIENT METHOD
77
78        The subroutine minimizes function F(x) of N arguments by using one of  the
79        nonlinear conjugate gradient methods.
80
81        These CG methods are globally convergent (even on non-convex functions) as
82        long as grad(f) is Lipschitz continuous in  a  some  neighborhood  of  the
83        L = { x : f(x)<=f(x0) }.
84
85        INPUT PARAMETERS:
86            N       -   problem dimension. N>0
87            X       -   initial solution approximation, array[0..N-1].
88            EpsG    -   positive number which  defines  a  precision  of  search.  The
89                        subroutine finishes its work if the condition ||G|| < EpsG  is
90                        satisfied, where ||.|| means Euclidian norm, G - gradient, X -
91                        current approximation.
92            EpsF    -   positive number which  defines  a  precision  of  search.  The
93                        subroutine finishes its work if on iteration  number  k+1  the
94                        condition |F(k+1)-F(k)| <= EpsF*max{|F(k)|, |F(k+1)|, 1}    is
95                        satisfied.
96            EpsX    -   positive number which  defines  a  precision  of  search.  The
97                        subroutine finishes its work if on iteration number k+1    the
98                        condition |X(k+1)-X(k)| <= EpsX is fulfilled.
99            MaxIts  -   maximum number of iterations. If MaxIts=0, the number of
100                        iterations is unlimited.
101
102        OUTPUT PARAMETERS:
103            State - structure used for reverse communication.
104
105        See also MinCGIteration, MinCGResults
106
107        NOTE:
108
109        Passing EpsG=0, EpsF=0, EpsX=0 and MaxIts=0 (simultaneously) will lead to
110        automatic stopping criterion selection (small EpsX).
111
112          -- ALGLIB --
113             Copyright 25.03.2010 by Bochkanov Sergey
114        *************************************************************************/
115        public static void mincgcreate(int n,
116            ref double[] x,
117            ref mincgstate state)
118        {
119            int i_ = 0;
120
121            System.Diagnostics.Debug.Assert(n>=1, "MinCGCreate: N too small!");
122           
123            //
124            // Initialize
125            //
126            state.n = n;
127            mincgsetcond(ref state, 0, 0, 0, 0);
128            mincgsetxrep(ref state, false);
129            mincgsetstpmax(ref state, 0);
130            mincgsetcgtype(ref state, -1);
131            state.xk = new double[n];
132            state.dk = new double[n];
133            state.xn = new double[n];
134            state.dn = new double[n];
135            state.x = new double[n];
136            state.d = new double[n];
137            state.g = new double[n];
138            state.work = new double[n];
139            state.yk = new double[n];
140           
141            //
142            // Prepare first run
143            //
144            for(i_=0; i_<=n-1;i_++)
145            {
146                state.x[i_] = x[i_];
147            }
148            state.rstate.ia = new int[2+1];
149            state.rstate.ra = new double[2+1];
150            state.rstate.stage = -1;
151        }
152
153
154        /*************************************************************************
155        This function sets stopping conditions for CG optimization algorithm.
156
157        INPUT PARAMETERS:
158            State   -   structure which stores algorithm state between calls and
159                        which is used for reverse communication. Must be initialized
160                        with MinCGCreate()
161            EpsG    -   >=0
162                        The  subroutine  finishes  its  work   if   the  condition
163                        ||G||<EpsG is satisfied, where ||.|| means Euclidian norm,
164                        G - gradient.
165            EpsF    -   >=0
166                        The  subroutine  finishes  its work if on k+1-th iteration
167                        the  condition  |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1}
168                        is satisfied.
169            EpsX    -   >=0
170                        The subroutine finishes its work if  on  k+1-th  iteration
171                        the condition |X(k+1)-X(k)| <= EpsX is fulfilled.
172            MaxIts  -   maximum number of iterations. If MaxIts=0, the  number  of
173                        iterations is unlimited.
174
175        Passing EpsG=0, EpsF=0, EpsX=0 and MaxIts=0 (simultaneously) will lead to
176        automatic stopping criterion selection (small EpsX).
177
178          -- ALGLIB --
179             Copyright 02.04.2010 by Bochkanov Sergey
180        *************************************************************************/
181        public static void mincgsetcond(ref mincgstate state,
182            double epsg,
183            double epsf,
184            double epsx,
185            int maxits)
186        {
187            System.Diagnostics.Debug.Assert((double)(epsg)>=(double)(0), "MinCGSetCond: negative EpsG!");
188            System.Diagnostics.Debug.Assert((double)(epsf)>=(double)(0), "MinCGSetCond: negative EpsF!");
189            System.Diagnostics.Debug.Assert((double)(epsx)>=(double)(0), "MinCGSetCond: negative EpsX!");
190            System.Diagnostics.Debug.Assert(maxits>=0, "MinCGSetCond: negative MaxIts!");
191            if( (double)(epsg)==(double)(0) & (double)(epsf)==(double)(0) & (double)(epsx)==(double)(0) & maxits==0 )
192            {
193                epsx = 1.0E-6;
194            }
195            state.epsg = epsg;
196            state.epsf = epsf;
197            state.epsx = epsx;
198            state.maxits = maxits;
199        }
200
201
202        /*************************************************************************
203        This function turns on/off reporting.
204
205        INPUT PARAMETERS:
206            State   -   structure which stores algorithm state between calls and
207                        which is used for reverse communication. Must be
208                        initialized with MinCGCreate()
209            NeedXRep-   whether iteration reports are needed or not
210
211        Usually  algorithm  returns  from  MinCGIteration()  only  when  it  needs
212        function/gradient. However, with this function we can let  it  stop  after
213        each  iteration  (one  iteration  may  include   more  than  one  function
214        evaluation), which is indicated by XUpdated field.
215
216          -- ALGLIB --
217             Copyright 02.04.2010 by Bochkanov Sergey
218        *************************************************************************/
219        public static void mincgsetxrep(ref mincgstate state,
220            bool needxrep)
221        {
222            state.xrep = needxrep;
223        }
224
225
226        /*************************************************************************
227        This function sets CG algorithm.
228
229        INPUT PARAMETERS:
230            State   -   structure which stores algorithm state between calls and
231                        which is used for reverse communication. Must be
232                        initialized with MinCGCreate()
233            CGType  -   algorithm type:
234                        * -1    automatic selection of the best algorithm
235                        * 0     DY (Dai and Yuan) algorithm
236                        * 1     Hybrid DY-HS algorithm
237
238          -- ALGLIB --
239             Copyright 02.04.2010 by Bochkanov Sergey
240        *************************************************************************/
241        public static void mincgsetcgtype(ref mincgstate state,
242            int cgtype)
243        {
244            System.Diagnostics.Debug.Assert(cgtype>=-1 & cgtype<=1, "MinCGSetCGType: incorrect CGType!");
245            if( cgtype==-1 )
246            {
247                cgtype = 1;
248            }
249            state.cgtype = cgtype;
250        }
251
252
253        /*************************************************************************
254        This function sets maximum step length
255
256        INPUT PARAMETERS:
257            State   -   structure which stores algorithm state between calls and
258                        which is used for reverse communication. Must be
259                        initialized with MinCGCreate()
260            StpMax  -   maximum step length, >=0. Set StpMax to 0.0,  if you don't
261                        want to limit step length.
262
263        Use this subroutine when you optimize target function which contains exp()
264        or  other  fast  growing  functions,  and optimization algorithm makes too
265        large  steps  which  leads  to overflow. This function allows us to reject
266        steps  that  are  too  large  (and  therefore  expose  us  to the possible
267        overflow) without actually calculating function value at the x+stp*d.
268
269          -- ALGLIB --
270             Copyright 02.04.2010 by Bochkanov Sergey
271        *************************************************************************/
272        public static void mincgsetstpmax(ref mincgstate state,
273            double stpmax)
274        {
275            System.Diagnostics.Debug.Assert((double)(stpmax)>=(double)(0), "MinCGSetStpMax: StpMax<0!");
276            state.stpmax = stpmax;
277        }
278
279
280        /*************************************************************************
281        One conjugate gradient iteration
282
283        Called after initialization with MinCG.
284        See HTML documentation for examples.
285
286        INPUT PARAMETERS:
287            State   -   structure which stores algorithm state between calls and
288                        which is used for reverse communication. Must be initialized
289                        with MinCG.
290
291        RESULT:
292        * if function returned False, iterative proces has converged.
293          Use MinLBFGSResults() to obtain optimization results.
294        * if subroutine returned True, then, depending on structure fields, we
295          have one of the following situations
296
297
298        === FUNC/GRAD REQUEST ===
299        State.NeedFG is True => function value/gradient are needed.
300        Caller should calculate function value State.F and gradient
301        State.G[0..N-1] at State.X[0..N-1] and call MinLBFGSIteration() again.
302
303        === NEW INTERATION IS REPORTED ===
304        State.XUpdated is True => one more iteration was made.
305        State.X contains current position, State.F contains function value at X.
306        You can read info from these fields, but never modify  them  because  they
307        contain the only copy of optimization algorithm state.
308
309        One and only one of these fields (NeedFG, XUpdated) is true on return. New
310        iterations are reported only when reports  are  explicitly  turned  on  by
311        MinLBFGSSetXRep() function, so if you never called it, you can expect that
312        NeedFG is always True.
313
314
315          -- ALGLIB --
316             Copyright 20.04.2009 by Bochkanov Sergey
317        *************************************************************************/
318        public static bool mincgiteration(ref mincgstate state)
319        {
320            bool result = new bool();
321            int n = 0;
322            int i = 0;
323            double betak = 0;
324            double v = 0;
325            double vv = 0;
326            int mcinfo = 0;
327            int i_ = 0;
328
329           
330            //
331            // Reverse communication preparations
332            // I know it looks ugly, but it works the same way
333            // anywhere from C++ to Python.
334            //
335            // This code initializes locals by:
336            // * random values determined during code
337            //   generation - on first subroutine call
338            // * values from previous call - on subsequent calls
339            //
340            if( state.rstate.stage>=0 )
341            {
342                n = state.rstate.ia[0];
343                i = state.rstate.ia[1];
344                mcinfo = state.rstate.ia[2];
345                betak = state.rstate.ra[0];
346                v = state.rstate.ra[1];
347                vv = state.rstate.ra[2];
348            }
349            else
350            {
351                n = -983;
352                i = -989;
353                mcinfo = -834;
354                betak = 900;
355                v = -287;
356                vv = 364;
357            }
358            if( state.rstate.stage==0 )
359            {
360                goto lbl_0;
361            }
362            if( state.rstate.stage==1 )
363            {
364                goto lbl_1;
365            }
366            if( state.rstate.stage==2 )
367            {
368                goto lbl_2;
369            }
370            if( state.rstate.stage==3 )
371            {
372                goto lbl_3;
373            }
374           
375            //
376            // Routine body
377            //
378           
379            //
380            // Prepare
381            //
382            n = state.n;
383            state.repterminationtype = 0;
384            state.repiterationscount = 0;
385            state.repnfev = 0;
386            state.debugrestartscount = 0;
387           
388            //
389            // Calculate F/G, initialize algorithm
390            //
391            clearrequestfields(ref state);
392            state.needfg = true;
393            state.rstate.stage = 0;
394            goto lbl_rcomm;
395        lbl_0:
396            if( ! state.xrep )
397            {
398                goto lbl_4;
399            }
400            clearrequestfields(ref state);
401            state.xupdated = true;
402            state.rstate.stage = 1;
403            goto lbl_rcomm;
404        lbl_1:
405        lbl_4:
406            v = 0.0;
407            for(i_=0; i_<=n-1;i_++)
408            {
409                v += state.g[i_]*state.g[i_];
410            }
411            v = Math.Sqrt(v);
412            if( (double)(v)==(double)(0) )
413            {
414                state.repterminationtype = 4;
415                result = false;
416                return result;
417            }
418            state.repnfev = 1;
419            state.k = 0;
420            state.fold = state.f;
421            for(i_=0; i_<=n-1;i_++)
422            {
423                state.xk[i_] = state.x[i_];
424            }
425            for(i_=0; i_<=n-1;i_++)
426            {
427                state.dk[i_] = -state.g[i_];
428            }
429           
430            //
431            // Main cycle
432            //
433        lbl_6:
434            if( false )
435            {
436                goto lbl_7;
437            }
438           
439            //
440            // Store G[k] for later calculation of Y[k]
441            //
442            for(i_=0; i_<=n-1;i_++)
443            {
444                state.yk[i_] = -state.g[i_];
445            }
446           
447            //
448            // Calculate X(k+1): minimize F(x+alpha*d)
449            //
450            for(i_=0; i_<=n-1;i_++)
451            {
452                state.d[i_] = state.dk[i_];
453            }
454            for(i_=0; i_<=n-1;i_++)
455            {
456                state.x[i_] = state.xk[i_];
457            }
458            state.mcstage = 0;
459            state.stp = 1.0;
460            linmin.linminnormalized(ref state.d, ref state.stp, n);
461            linmin.mcsrch(n, ref state.x, ref state.f, ref state.g, ref state.d, ref state.stp, state.stpmax, ref mcinfo, ref state.nfev, ref state.work, ref state.lstate, ref state.mcstage);
462        lbl_8:
463            if( state.mcstage==0 )
464            {
465                goto lbl_9;
466            }
467            clearrequestfields(ref state);
468            state.needfg = true;
469            state.rstate.stage = 2;
470            goto lbl_rcomm;
471        lbl_2:
472            linmin.mcsrch(n, ref state.x, ref state.f, ref state.g, ref state.d, ref state.stp, state.stpmax, ref mcinfo, ref state.nfev, ref state.work, ref state.lstate, ref state.mcstage);
473            goto lbl_8;
474        lbl_9:
475            if( ! state.xrep )
476            {
477                goto lbl_10;
478            }
479            clearrequestfields(ref state);
480            state.xupdated = true;
481            state.rstate.stage = 3;
482            goto lbl_rcomm;
483        lbl_3:
484        lbl_10:
485            for(i_=0; i_<=n-1;i_++)
486            {
487                state.xn[i_] = state.x[i_];
488            }
489            if( mcinfo==1 )
490            {
491               
492                //
493                // Standard Wolfe conditions hold
494                // Calculate Y[K] and BetaK
495                //
496                for(i_=0; i_<=n-1;i_++)
497                {
498                    state.yk[i_] = state.yk[i_] + state.g[i_];
499                }
500                vv = 0.0;
501                for(i_=0; i_<=n-1;i_++)
502                {
503                    vv += state.yk[i_]*state.dk[i_];
504                }
505                v = 0.0;
506                for(i_=0; i_<=n-1;i_++)
507                {
508                    v += state.g[i_]*state.g[i_];
509                }
510                state.betady = v/vv;
511                v = 0.0;
512                for(i_=0; i_<=n-1;i_++)
513                {
514                    v += state.g[i_]*state.yk[i_];
515                }
516                state.betahs = v/vv;
517                if( state.cgtype==0 )
518                {
519                    betak = state.betady;
520                }
521                if( state.cgtype==1 )
522                {
523                    betak = Math.Max(0, Math.Min(state.betady, state.betahs));
524                }
525            }
526            else
527            {
528               
529                //
530                // Something is wrong (may be function is too wild or too flat).
531                //
532                // We'll set BetaK=0, which will restart CG algorithm.
533                // We can stop later (during normal checks) if stopping conditions are met.
534                //
535                betak = 0;
536                state.debugrestartscount = state.debugrestartscount+1;
537            }
538           
539            //
540            // Calculate D(k+1)
541            //
542            for(i_=0; i_<=n-1;i_++)
543            {
544                state.dn[i_] = -state.g[i_];
545            }
546            for(i_=0; i_<=n-1;i_++)
547            {
548                state.dn[i_] = state.dn[i_] + betak*state.dk[i_];
549            }
550           
551            //
552            // Update information and Hessian.
553            // Check stopping conditions.
554            //
555            state.repnfev = state.repnfev+state.nfev;
556            state.repiterationscount = state.repiterationscount+1;
557            if( state.repiterationscount>=state.maxits & state.maxits>0 )
558            {
559               
560                //
561                // Too many iterations
562                //
563                state.repterminationtype = 5;
564                result = false;
565                return result;
566            }
567            v = 0.0;
568            for(i_=0; i_<=n-1;i_++)
569            {
570                v += state.g[i_]*state.g[i_];
571            }
572            if( (double)(Math.Sqrt(v))<=(double)(state.epsg) )
573            {
574               
575                //
576                // Gradient is small enough
577                //
578                state.repterminationtype = 4;
579                result = false;
580                return result;
581            }
582            if( (double)(state.fold-state.f)<=(double)(state.epsf*Math.Max(Math.Abs(state.fold), Math.Max(Math.Abs(state.f), 1.0))) )
583            {
584               
585                //
586                // F(k+1)-F(k) is small enough
587                //
588                state.repterminationtype = 1;
589                result = false;
590                return result;
591            }
592            v = 0.0;
593            for(i_=0; i_<=n-1;i_++)
594            {
595                v += state.d[i_]*state.d[i_];
596            }
597            if( (double)(Math.Sqrt(v)*state.stp)<=(double)(state.epsx) )
598            {
599               
600                //
601                // X(k+1)-X(k) is small enough
602                //
603                state.repterminationtype = 2;
604                result = false;
605                return result;
606            }
607           
608            //
609            // Shift Xk/Dk, update other information
610            //
611            for(i_=0; i_<=n-1;i_++)
612            {
613                state.xk[i_] = state.xn[i_];
614            }
615            for(i_=0; i_<=n-1;i_++)
616            {
617                state.dk[i_] = state.dn[i_];
618            }
619            state.fold = state.f;
620            state.k = state.k+1;
621            goto lbl_6;
622        lbl_7:
623            result = false;
624            return result;
625           
626            //
627            // Saving state
628            //
629        lbl_rcomm:
630            result = true;
631            state.rstate.ia[0] = n;
632            state.rstate.ia[1] = i;
633            state.rstate.ia[2] = mcinfo;
634            state.rstate.ra[0] = betak;
635            state.rstate.ra[1] = v;
636            state.rstate.ra[2] = vv;
637            return result;
638        }
639
640
641        /*************************************************************************
642        Conjugate gradient results
643
644        Called after MinCG returned False.
645
646        INPUT PARAMETERS:
647            State   -   algorithm state (used by MinCGIteration).
648
649        OUTPUT PARAMETERS:
650            X       -   array[0..N-1], solution
651            Rep     -   optimization report:
652                        * Rep.TerminationType completetion code:
653                            * -2    rounding errors prevent further improvement.
654                                    X contains best point found.
655                            * -1    incorrect parameters were specified
656                            *  1    relative function improvement is no more than
657                                    EpsF.
658                            *  2    relative step is no more than EpsX.
659                            *  4    gradient norm is no more than EpsG
660                            *  5    MaxIts steps was taken
661                            *  7    stopping conditions are too stringent,
662                                    further improvement is impossible
663                        * Rep.IterationsCount contains iterations count
664                        * NFEV countains number of function calculations
665
666          -- ALGLIB --
667             Copyright 20.04.2009 by Bochkanov Sergey
668        *************************************************************************/
669        public static void mincgresults(ref mincgstate state,
670            ref double[] x,
671            ref mincgreport rep)
672        {
673            int i_ = 0;
674
675            x = new double[state.n-1+1];
676            for(i_=0; i_<=state.n-1;i_++)
677            {
678                x[i_] = state.xn[i_];
679            }
680            rep.iterationscount = state.repiterationscount;
681            rep.nfev = state.repnfev;
682            rep.terminationtype = state.repterminationtype;
683        }
684
685
686        /*************************************************************************
687        Clears request fileds (to be sure that we don't forgot to clear something)
688        *************************************************************************/
689        private static void clearrequestfields(ref mincgstate state)
690        {
691            state.needfg = false;
692            state.xupdated = false;
693        }
694    }
695}
Note: See TracBrowser for help on using the repository browser.