[3839] | 1 | /*************************************************************************
|
---|
| 2 | Copyright (c) 2010, Sergey Bochkanov (ALGLIB project).
|
---|
| 3 |
|
---|
| 4 | >>> SOURCE LICENSE >>>
|
---|
| 5 | This program is free software; you can redistribute it and/or modify
|
---|
| 6 | it under the terms of the GNU General Public License as published by
|
---|
| 7 | the Free Software Foundation (www.fsf.org); either version 2 of the
|
---|
| 8 | License, or (at your option) any later version.
|
---|
| 9 |
|
---|
| 10 | This program is distributed in the hope that it will be useful,
|
---|
| 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
| 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
| 13 | GNU General Public License for more details.
|
---|
| 14 |
|
---|
| 15 | A copy of the GNU General Public License is available at
|
---|
| 16 | http://www.fsf.org/licensing/licenses
|
---|
| 17 |
|
---|
| 18 | >>> END OF LICENSE >>>
|
---|
| 19 | *************************************************************************/
|
---|
| 20 |
|
---|
| 21 | using System;
|
---|
| 22 |
|
---|
| 23 | namespace 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 | }
|
---|