Xmipp  v3.23.11-Nereus
optimization.cpp
Go to the documentation of this file.
1 /*************************************************************************
2 Copyright (c) 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 >>> END OF LICENSE >>>
18 *************************************************************************/
19 #include "stdafx.h"
20 #include "optimization.h"
21 
22 // disable some irrelevant warnings
23 #if (AE_COMPILER==AE_MSVC)
24 #pragma warning(disable:4100)
25 #pragma warning(disable:4127)
26 #pragma warning(disable:4702)
27 #pragma warning(disable:4996)
28 #endif
29 using namespace std;
30 
32 //
33 // THIS SECTION CONTAINS IMPLEMENTATION OF C++ INTERFACE
34 //
36 namespace alglib
37 {
38 
39 
40 
41 
42 
43 
44 
45 
46 
47 
48 /*************************************************************************
49 This object stores state of the nonlinear CG optimizer.
50 
51 You should use ALGLIB functions to work with this object.
52 *************************************************************************/
53 _mincgstate_owner::_mincgstate_owner()
54 {
56  if( p_struct==NULL )
57  throw ap_error("ALGLIB: malloc error");
58  if( !alglib_impl::_mincgstate_init(p_struct, NULL, ae_false) )
59  throw ap_error("ALGLIB: malloc error");
60 }
61 
62 _mincgstate_owner::_mincgstate_owner(const _mincgstate_owner &rhs)
63 {
65  if( p_struct==NULL )
66  throw ap_error("ALGLIB: malloc error");
67  if( !alglib_impl::_mincgstate_init_copy(p_struct, const_cast<alglib_impl::mincgstate*>(rhs.p_struct), NULL, ae_false) )
68  throw ap_error("ALGLIB: malloc error");
69 }
70 
71 _mincgstate_owner& _mincgstate_owner::operator=(const _mincgstate_owner &rhs)
72 {
73  if( this==&rhs )
74  return *this;
76  if( !alglib_impl::_mincgstate_init_copy(p_struct, const_cast<alglib_impl::mincgstate*>(rhs.p_struct), NULL, ae_false) )
77  throw ap_error("ALGLIB: malloc error");
78  return *this;
79 }
80 
81 _mincgstate_owner::~_mincgstate_owner()
82 {
84  ae_free(p_struct);
85 }
86 
87 alglib_impl::mincgstate* _mincgstate_owner::c_ptr()
88 {
89  return p_struct;
90 }
91 
92 alglib_impl::mincgstate* _mincgstate_owner::c_ptr() const
93 {
94  return const_cast<alglib_impl::mincgstate*>(p_struct);
95 }
96 mincgstate::mincgstate() : _mincgstate_owner() ,needf(p_struct->needf),needfg(p_struct->needfg),xupdated(p_struct->xupdated),f(p_struct->f),g(&p_struct->g),x(&p_struct->x)
97 {
98 }
99 
101 {
102 }
103 
105 {
106  if( this==&rhs )
107  return *this;
109  return *this;
110 }
111 
113 {
114 }
115 
116 
117 /*************************************************************************
118 
119 *************************************************************************/
121 {
123  if( p_struct==NULL )
124  throw ap_error("ALGLIB: malloc error");
126  throw ap_error("ALGLIB: malloc error");
127 }
128 
130 {
132  if( p_struct==NULL )
133  throw ap_error("ALGLIB: malloc error");
134  if( !alglib_impl::_mincgreport_init_copy(p_struct, const_cast<alglib_impl::mincgreport*>(rhs.p_struct), NULL, ae_false) )
135  throw ap_error("ALGLIB: malloc error");
136 }
137 
139 {
140  if( this==&rhs )
141  return *this;
143  if( !alglib_impl::_mincgreport_init_copy(p_struct, const_cast<alglib_impl::mincgreport*>(rhs.p_struct), NULL, ae_false) )
144  throw ap_error("ALGLIB: malloc error");
145  return *this;
146 }
147 
149 {
151  ae_free(p_struct);
152 }
153 
155 {
156  return p_struct;
157 }
158 
160 {
161  return const_cast<alglib_impl::mincgreport*>(p_struct);
162 }
163 mincgreport::mincgreport() : _mincgreport_owner() ,iterationscount(p_struct->iterationscount),nfev(p_struct->nfev),varidx(p_struct->varidx),terminationtype(p_struct->terminationtype)
164 {
165 }
166 
168 {
169 }
170 
172 {
173  if( this==&rhs )
174  return *this;
176  return *this;
177 }
178 
180 {
181 }
182 
183 /*************************************************************************
184  NONLINEAR CONJUGATE GRADIENT METHOD
185 
186 DESCRIPTION:
187 The subroutine minimizes function F(x) of N arguments by using one of the
188 nonlinear conjugate gradient methods.
189 
190 These CG methods are globally convergent (even on non-convex functions) as
191 long as grad(f) is Lipschitz continuous in a some neighborhood of the
192 L = { x : f(x)<=f(x0) }.
193 
194 
195 REQUIREMENTS:
196 Algorithm will request following information during its operation:
197 * function value F and its gradient G (simultaneously) at given point X
198 
199 
200 USAGE:
201 1. User initializes algorithm state with MinCGCreate() call
202 2. User tunes solver parameters with MinCGSetCond(), MinCGSetStpMax() and
203  other functions
204 3. User calls MinCGOptimize() function which takes algorithm state and
205  pointer (delegate, etc.) to callback function which calculates F/G.
206 4. User calls MinCGResults() to get solution
207 5. Optionally, user may call MinCGRestartFrom() to solve another problem
208  with same N but another starting point and/or another function.
209  MinCGRestartFrom() allows to reuse already initialized structure.
210 
211 
212 INPUT PARAMETERS:
213  N - problem dimension, N>0:
214  * if given, only leading N elements of X are used
215  * if not given, automatically determined from size of X
216  X - starting point, array[0..N-1].
217 
218 OUTPUT PARAMETERS:
219  State - structure which stores algorithm state
220 
221  -- ALGLIB --
222  Copyright 25.03.2010 by Bochkanov Sergey
223 *************************************************************************/
224 void mincgcreate(const ae_int_t n, const real_1d_array &x, mincgstate &state)
225 {
226  alglib_impl::ae_state _alglib_env_state;
227  alglib_impl::ae_state_init(&_alglib_env_state);
228  try
229  {
230  alglib_impl::mincgcreate(n, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::mincgstate*>(state.c_ptr()), &_alglib_env_state);
231  alglib_impl::ae_state_clear(&_alglib_env_state);
232  return;
233  }
235  {
236  throw ap_error(_alglib_env_state.error_msg);
237  }
238 }
239 
240 /*************************************************************************
241  NONLINEAR CONJUGATE GRADIENT METHOD
242 
243 DESCRIPTION:
244 The subroutine minimizes function F(x) of N arguments by using one of the
245 nonlinear conjugate gradient methods.
246 
247 These CG methods are globally convergent (even on non-convex functions) as
248 long as grad(f) is Lipschitz continuous in a some neighborhood of the
249 L = { x : f(x)<=f(x0) }.
250 
251 
252 REQUIREMENTS:
253 Algorithm will request following information during its operation:
254 * function value F and its gradient G (simultaneously) at given point X
255 
256 
257 USAGE:
258 1. User initializes algorithm state with MinCGCreate() call
259 2. User tunes solver parameters with MinCGSetCond(), MinCGSetStpMax() and
260  other functions
261 3. User calls MinCGOptimize() function which takes algorithm state and
262  pointer (delegate, etc.) to callback function which calculates F/G.
263 4. User calls MinCGResults() to get solution
264 5. Optionally, user may call MinCGRestartFrom() to solve another problem
265  with same N but another starting point and/or another function.
266  MinCGRestartFrom() allows to reuse already initialized structure.
267 
268 
269 INPUT PARAMETERS:
270  N - problem dimension, N>0:
271  * if given, only leading N elements of X are used
272  * if not given, automatically determined from size of X
273  X - starting point, array[0..N-1].
274 
275 OUTPUT PARAMETERS:
276  State - structure which stores algorithm state
277 
278  -- ALGLIB --
279  Copyright 25.03.2010 by Bochkanov Sergey
280 *************************************************************************/
281 void mincgcreate(const real_1d_array &x, mincgstate &state)
282 {
283  alglib_impl::ae_state _alglib_env_state;
284  ae_int_t n;
285 
286  n = x.length();
287  alglib_impl::ae_state_init(&_alglib_env_state);
288  try
289  {
290  alglib_impl::mincgcreate(n, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::mincgstate*>(state.c_ptr()), &_alglib_env_state);
291 
292  alglib_impl::ae_state_clear(&_alglib_env_state);
293  return;
294  }
296  {
297  throw ap_error(_alglib_env_state.error_msg);
298  }
299 }
300 
301 /*************************************************************************
302 The subroutine is finite difference variant of MinCGCreate(). It uses
303 finite differences in order to differentiate target function.
304 
305 Description below contains information which is specific to this function
306 only. We recommend to read comments on MinCGCreate() in order to get more
307 information about creation of CG optimizer.
308 
309 INPUT PARAMETERS:
310  N - problem dimension, N>0:
311  * if given, only leading N elements of X are used
312  * if not given, automatically determined from size of X
313  X - starting point, array[0..N-1].
314  DiffStep- differentiation step, >0
315 
316 OUTPUT PARAMETERS:
317  State - structure which stores algorithm state
318 
319 NOTES:
320 1. algorithm uses 4-point central formula for differentiation.
321 2. differentiation step along I-th axis is equal to DiffStep*S[I] where
322  S[] is scaling vector which can be set by MinCGSetScale() call.
323 3. we recommend you to use moderate values of differentiation step. Too
324  large step will result in too large truncation errors, while too small
325  step will result in too large numerical errors. 1.0E-6 can be good
326  value to start with.
327 4. Numerical differentiation is very inefficient - one gradient
328  calculation needs 4*N function evaluations. This function will work for
329  any N - either small (1...10), moderate (10...100) or large (100...).
330  However, performance penalty will be too severe for any N's except for
331  small ones.
332  We should also say that code which relies on numerical differentiation
333  is less robust and precise. L-BFGS needs exact gradient values.
334  Imprecise gradient may slow down convergence, especially on highly
335  nonlinear problems.
336  Thus we recommend to use this function for fast prototyping on small-
337  dimensional problems only, and to implement analytical gradient as soon
338  as possible.
339 
340  -- ALGLIB --
341  Copyright 16.05.2011 by Bochkanov Sergey
342 *************************************************************************/
343 void mincgcreatef(const ae_int_t n, const real_1d_array &x, const double diffstep, mincgstate &state)
344 {
345  alglib_impl::ae_state _alglib_env_state;
346  alglib_impl::ae_state_init(&_alglib_env_state);
347  try
348  {
349  alglib_impl::mincgcreatef(n, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), diffstep, const_cast<alglib_impl::mincgstate*>(state.c_ptr()), &_alglib_env_state);
350  alglib_impl::ae_state_clear(&_alglib_env_state);
351  return;
352  }
354  {
355  throw ap_error(_alglib_env_state.error_msg);
356  }
357 }
358 
359 /*************************************************************************
360 The subroutine is finite difference variant of MinCGCreate(). It uses
361 finite differences in order to differentiate target function.
362 
363 Description below contains information which is specific to this function
364 only. We recommend to read comments on MinCGCreate() in order to get more
365 information about creation of CG optimizer.
366 
367 INPUT PARAMETERS:
368  N - problem dimension, N>0:
369  * if given, only leading N elements of X are used
370  * if not given, automatically determined from size of X
371  X - starting point, array[0..N-1].
372  DiffStep- differentiation step, >0
373 
374 OUTPUT PARAMETERS:
375  State - structure which stores algorithm state
376 
377 NOTES:
378 1. algorithm uses 4-point central formula for differentiation.
379 2. differentiation step along I-th axis is equal to DiffStep*S[I] where
380  S[] is scaling vector which can be set by MinCGSetScale() call.
381 3. we recommend you to use moderate values of differentiation step. Too
382  large step will result in too large truncation errors, while too small
383  step will result in too large numerical errors. 1.0E-6 can be good
384  value to start with.
385 4. Numerical differentiation is very inefficient - one gradient
386  calculation needs 4*N function evaluations. This function will work for
387  any N - either small (1...10), moderate (10...100) or large (100...).
388  However, performance penalty will be too severe for any N's except for
389  small ones.
390  We should also say that code which relies on numerical differentiation
391  is less robust and precise. L-BFGS needs exact gradient values.
392  Imprecise gradient may slow down convergence, especially on highly
393  nonlinear problems.
394  Thus we recommend to use this function for fast prototyping on small-
395  dimensional problems only, and to implement analytical gradient as soon
396  as possible.
397 
398  -- ALGLIB --
399  Copyright 16.05.2011 by Bochkanov Sergey
400 *************************************************************************/
401 void mincgcreatef(const real_1d_array &x, const double diffstep, mincgstate &state)
402 {
403  alglib_impl::ae_state _alglib_env_state;
404  ae_int_t n;
405 
406  n = x.length();
407  alglib_impl::ae_state_init(&_alglib_env_state);
408  try
409  {
410  alglib_impl::mincgcreatef(n, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), diffstep, const_cast<alglib_impl::mincgstate*>(state.c_ptr()), &_alglib_env_state);
411 
412  alglib_impl::ae_state_clear(&_alglib_env_state);
413  return;
414  }
416  {
417  throw ap_error(_alglib_env_state.error_msg);
418  }
419 }
420 
421 /*************************************************************************
422 This function sets stopping conditions for CG optimization algorithm.
423 
424 INPUT PARAMETERS:
425  State - structure which stores algorithm state
426  EpsG - >=0
427  The subroutine finishes its work if the condition
428  |v|<EpsG is satisfied, where:
429  * |.| means Euclidian norm
430  * v - scaled gradient vector, v[i]=g[i]*s[i]
431  * g - gradient
432  * s - scaling coefficients set by MinCGSetScale()
433  EpsF - >=0
434  The subroutine finishes its work if on k+1-th iteration
435  the condition |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1}
436  is satisfied.
437  EpsX - >=0
438  The subroutine finishes its work if on k+1-th iteration
439  the condition |v|<=EpsX is fulfilled, where:
440  * |.| means Euclidian norm
441  * v - scaled step vector, v[i]=dx[i]/s[i]
442  * dx - ste pvector, dx=X(k+1)-X(k)
443  * s - scaling coefficients set by MinCGSetScale()
444  MaxIts - maximum number of iterations. If MaxIts=0, the number of
445  iterations is unlimited.
446 
447 Passing EpsG=0, EpsF=0, EpsX=0 and MaxIts=0 (simultaneously) will lead to
448 automatic stopping criterion selection (small EpsX).
449 
450  -- ALGLIB --
451  Copyright 02.04.2010 by Bochkanov Sergey
452 *************************************************************************/
453 void mincgsetcond(const mincgstate &state, const double epsg, const double epsf, const double epsx, const ae_int_t maxits)
454 {
455  alglib_impl::ae_state _alglib_env_state;
456  alglib_impl::ae_state_init(&_alglib_env_state);
457  try
458  {
459  alglib_impl::mincgsetcond(const_cast<alglib_impl::mincgstate*>(state.c_ptr()), epsg, epsf, epsx, maxits, &_alglib_env_state);
460  alglib_impl::ae_state_clear(&_alglib_env_state);
461  return;
462  }
464  {
465  throw ap_error(_alglib_env_state.error_msg);
466  }
467 }
468 
469 /*************************************************************************
470 This function sets scaling coefficients for CG optimizer.
471 
472 ALGLIB optimizers use scaling matrices to test stopping conditions (step
473 size and gradient are scaled before comparison with tolerances). Scale of
474 the I-th variable is a translation invariant measure of:
475 a) "how large" the variable is
476 b) how large the step should be to make significant changes in the function
477 
478 Scaling is also used by finite difference variant of CG optimizer - step
479 along I-th axis is equal to DiffStep*S[I].
480 
481 In most optimizers (and in the CG too) scaling is NOT a form of
482 preconditioning. It just affects stopping conditions. You should set
483 preconditioner by separate call to one of the MinCGSetPrec...() functions.
484 
485 There is special preconditioning mode, however, which uses scaling
486 coefficients to form diagonal preconditioning matrix. You can turn this
487 mode on, if you want. But you should understand that scaling is not the
488 same thing as preconditioning - these are two different, although related
489 forms of tuning solver.
490 
491 INPUT PARAMETERS:
492  State - structure stores algorithm state
493  S - array[N], non-zero scaling coefficients
494  S[i] may be negative, sign doesn't matter.
495 
496  -- ALGLIB --
497  Copyright 14.01.2011 by Bochkanov Sergey
498 *************************************************************************/
499 void mincgsetscale(const mincgstate &state, const real_1d_array &s)
500 {
501  alglib_impl::ae_state _alglib_env_state;
502  alglib_impl::ae_state_init(&_alglib_env_state);
503  try
504  {
505  alglib_impl::mincgsetscale(const_cast<alglib_impl::mincgstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(s.c_ptr()), &_alglib_env_state);
506  alglib_impl::ae_state_clear(&_alglib_env_state);
507  return;
508  }
510  {
511  throw ap_error(_alglib_env_state.error_msg);
512  }
513 }
514 
515 /*************************************************************************
516 This function turns on/off reporting.
517 
518 INPUT PARAMETERS:
519  State - structure which stores algorithm state
520  NeedXRep- whether iteration reports are needed or not
521 
522 If NeedXRep is True, algorithm will call rep() callback function if it is
523 provided to MinCGOptimize().
524 
525  -- ALGLIB --
526  Copyright 02.04.2010 by Bochkanov Sergey
527 *************************************************************************/
528 void mincgsetxrep(const mincgstate &state, const bool needxrep)
529 {
530  alglib_impl::ae_state _alglib_env_state;
531  alglib_impl::ae_state_init(&_alglib_env_state);
532  try
533  {
534  alglib_impl::mincgsetxrep(const_cast<alglib_impl::mincgstate*>(state.c_ptr()), needxrep, &_alglib_env_state);
535  alglib_impl::ae_state_clear(&_alglib_env_state);
536  return;
537  }
539  {
540  throw ap_error(_alglib_env_state.error_msg);
541  }
542 }
543 
544 /*************************************************************************
545 This function sets CG algorithm.
546 
547 INPUT PARAMETERS:
548  State - structure which stores algorithm state
549  CGType - algorithm type:
550  * -1 automatic selection of the best algorithm
551  * 0 DY (Dai and Yuan) algorithm
552  * 1 Hybrid DY-HS algorithm
553 
554  -- ALGLIB --
555  Copyright 02.04.2010 by Bochkanov Sergey
556 *************************************************************************/
557 void mincgsetcgtype(const mincgstate &state, const ae_int_t cgtype)
558 {
559  alglib_impl::ae_state _alglib_env_state;
560  alglib_impl::ae_state_init(&_alglib_env_state);
561  try
562  {
563  alglib_impl::mincgsetcgtype(const_cast<alglib_impl::mincgstate*>(state.c_ptr()), cgtype, &_alglib_env_state);
564  alglib_impl::ae_state_clear(&_alglib_env_state);
565  return;
566  }
568  {
569  throw ap_error(_alglib_env_state.error_msg);
570  }
571 }
572 
573 /*************************************************************************
574 This function sets maximum step length
575 
576 INPUT PARAMETERS:
577  State - structure which stores algorithm state
578  StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't
579  want to limit step length.
580 
581 Use this subroutine when you optimize target function which contains exp()
582 or other fast growing functions, and optimization algorithm makes too
583 large steps which leads to overflow. This function allows us to reject
584 steps that are too large (and therefore expose us to the possible
585 overflow) without actually calculating function value at the x+stp*d.
586 
587  -- ALGLIB --
588  Copyright 02.04.2010 by Bochkanov Sergey
589 *************************************************************************/
590 void mincgsetstpmax(const mincgstate &state, const double stpmax)
591 {
592  alglib_impl::ae_state _alglib_env_state;
593  alglib_impl::ae_state_init(&_alglib_env_state);
594  try
595  {
596  alglib_impl::mincgsetstpmax(const_cast<alglib_impl::mincgstate*>(state.c_ptr()), stpmax, &_alglib_env_state);
597  alglib_impl::ae_state_clear(&_alglib_env_state);
598  return;
599  }
601  {
602  throw ap_error(_alglib_env_state.error_msg);
603  }
604 }
605 
606 /*************************************************************************
607 This function allows to suggest initial step length to the CG algorithm.
608 
609 Suggested step length is used as starting point for the line search. It
610 can be useful when you have badly scaled problem, i.e. when ||grad||
611 (which is used as initial estimate for the first step) is many orders of
612 magnitude different from the desired step.
613 
614 Line search may fail on such problems without good estimate of initial
615 step length. Imagine, for example, problem with ||grad||=10^50 and desired
616 step equal to 0.1 Line search function will use 10^50 as initial step,
617 then it will decrease step length by 2 (up to 20 attempts) and will get
618 10^44, which is still too large.
619 
620 This function allows us to tell than line search should be started from
621 some moderate step length, like 1.0, so algorithm will be able to detect
622 desired step length in a several searches.
623 
624 Default behavior (when no step is suggested) is to use preconditioner, if
625 it is available, to generate initial estimate of step length.
626 
627 This function influences only first iteration of algorithm. It should be
628 called between MinCGCreate/MinCGRestartFrom() call and MinCGOptimize call.
629 Suggested step is ignored if you have preconditioner.
630 
631 INPUT PARAMETERS:
632  State - structure used to store algorithm state.
633  Stp - initial estimate of the step length.
634  Can be zero (no estimate).
635 
636  -- ALGLIB --
637  Copyright 30.07.2010 by Bochkanov Sergey
638 *************************************************************************/
639 void mincgsuggeststep(const mincgstate &state, const double stp)
640 {
641  alglib_impl::ae_state _alglib_env_state;
642  alglib_impl::ae_state_init(&_alglib_env_state);
643  try
644  {
645  alglib_impl::mincgsuggeststep(const_cast<alglib_impl::mincgstate*>(state.c_ptr()), stp, &_alglib_env_state);
646  alglib_impl::ae_state_clear(&_alglib_env_state);
647  return;
648  }
650  {
651  throw ap_error(_alglib_env_state.error_msg);
652  }
653 }
654 
655 /*************************************************************************
656 Modification of the preconditioner: preconditioning is turned off.
657 
658 INPUT PARAMETERS:
659  State - structure which stores algorithm state
660 
661 NOTE: you can change preconditioner "on the fly", during algorithm
662 iterations.
663 
664  -- ALGLIB --
665  Copyright 13.10.2010 by Bochkanov Sergey
666 *************************************************************************/
667 void mincgsetprecdefault(const mincgstate &state)
668 {
669  alglib_impl::ae_state _alglib_env_state;
670  alglib_impl::ae_state_init(&_alglib_env_state);
671  try
672  {
673  alglib_impl::mincgsetprecdefault(const_cast<alglib_impl::mincgstate*>(state.c_ptr()), &_alglib_env_state);
674  alglib_impl::ae_state_clear(&_alglib_env_state);
675  return;
676  }
678  {
679  throw ap_error(_alglib_env_state.error_msg);
680  }
681 }
682 
683 /*************************************************************************
684 Modification of the preconditioner: diagonal of approximate Hessian is
685 used.
686 
687 INPUT PARAMETERS:
688  State - structure which stores algorithm state
689  D - diagonal of the approximate Hessian, array[0..N-1],
690  (if larger, only leading N elements are used).
691 
692 NOTE: you can change preconditioner "on the fly", during algorithm
693 iterations.
694 
695 NOTE 2: D[i] should be positive. Exception will be thrown otherwise.
696 
697 NOTE 3: you should pass diagonal of approximate Hessian - NOT ITS INVERSE.
698 
699  -- ALGLIB --
700  Copyright 13.10.2010 by Bochkanov Sergey
701 *************************************************************************/
702 void mincgsetprecdiag(const mincgstate &state, const real_1d_array &d)
703 {
704  alglib_impl::ae_state _alglib_env_state;
705  alglib_impl::ae_state_init(&_alglib_env_state);
706  try
707  {
708  alglib_impl::mincgsetprecdiag(const_cast<alglib_impl::mincgstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(d.c_ptr()), &_alglib_env_state);
709  alglib_impl::ae_state_clear(&_alglib_env_state);
710  return;
711  }
713  {
714  throw ap_error(_alglib_env_state.error_msg);
715  }
716 }
717 
718 /*************************************************************************
719 Modification of the preconditioner: scale-based diagonal preconditioning.
720 
721 This preconditioning mode can be useful when you don't have approximate
722 diagonal of Hessian, but you know that your variables are badly scaled
723 (for example, one variable is in [1,10], and another in [1000,100000]),
724 and most part of the ill-conditioning comes from different scales of vars.
725 
726 In this case simple scale-based preconditioner, with H[i] = 1/(s[i]^2),
727 can greatly improve convergence.
728 
729 IMPRTANT: you should set scale of your variables with MinCGSetScale() call
730 (before or after MinCGSetPrecScale() call). Without knowledge of the scale
731 of your variables scale-based preconditioner will be just unit matrix.
732 
733 INPUT PARAMETERS:
734  State - structure which stores algorithm state
735 
736 NOTE: you can change preconditioner "on the fly", during algorithm
737 iterations.
738 
739  -- ALGLIB --
740  Copyright 13.10.2010 by Bochkanov Sergey
741 *************************************************************************/
742 void mincgsetprecscale(const mincgstate &state)
743 {
744  alglib_impl::ae_state _alglib_env_state;
745  alglib_impl::ae_state_init(&_alglib_env_state);
746  try
747  {
748  alglib_impl::mincgsetprecscale(const_cast<alglib_impl::mincgstate*>(state.c_ptr()), &_alglib_env_state);
749  alglib_impl::ae_state_clear(&_alglib_env_state);
750  return;
751  }
753  {
754  throw ap_error(_alglib_env_state.error_msg);
755  }
756 }
757 
758 /*************************************************************************
759 This function provides reverse communication interface
760 Reverse communication interface is not documented or recommended to use.
761 See below for functions which provide better documented API
762 *************************************************************************/
763 bool mincgiteration(const mincgstate &state)
764 {
765  alglib_impl::ae_state _alglib_env_state;
766  alglib_impl::ae_state_init(&_alglib_env_state);
767  try
768  {
769  ae_bool result = alglib_impl::mincgiteration(const_cast<alglib_impl::mincgstate*>(state.c_ptr()), &_alglib_env_state);
770  alglib_impl::ae_state_clear(&_alglib_env_state);
771  return *(reinterpret_cast<bool*>(&result));
772  }
774  {
775  throw ap_error(_alglib_env_state.error_msg);
776  }
777 }
778 
779 
781  void (*func)(const real_1d_array &x, double &func, void *ptr),
782  void (*rep)(const real_1d_array &x, double func, void *ptr),
783  void *ptr)
784 {
785  alglib_impl::ae_state _alglib_env_state;
786  if( func==NULL )
787  throw ap_error("ALGLIB: error in 'mincgoptimize()' (func is NULL)");
788  alglib_impl::ae_state_init(&_alglib_env_state);
789  try
790  {
791  while( alglib_impl::mincgiteration(state.c_ptr(), &_alglib_env_state) )
792  {
793  if( state.needf )
794  {
795  func(state.x, state.f, ptr);
796  continue;
797  }
798  if( state.xupdated )
799  {
800  if( rep!=NULL )
801  rep(state.x, state.f, ptr);
802  continue;
803  }
804  throw ap_error("ALGLIB: error in 'mincgoptimize' (some derivatives were not provided?)");
805  }
806  alglib_impl::ae_state_clear(&_alglib_env_state);
807  }
809  {
810  throw ap_error(_alglib_env_state.error_msg);
811  }
812 }
813 
814 
816  void (*grad)(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr),
817  void (*rep)(const real_1d_array &x, double func, void *ptr),
818  void *ptr)
819 {
820  alglib_impl::ae_state _alglib_env_state;
821  if( grad==NULL )
822  throw ap_error("ALGLIB: error in 'mincgoptimize()' (grad is NULL)");
823  alglib_impl::ae_state_init(&_alglib_env_state);
824  try
825  {
826  while( alglib_impl::mincgiteration(state.c_ptr(), &_alglib_env_state) )
827  {
828  if( state.needfg )
829  {
830  grad(state.x, state.f, state.g, ptr);
831  continue;
832  }
833  if( state.xupdated )
834  {
835  if( rep!=NULL )
836  rep(state.x, state.f, ptr);
837  continue;
838  }
839  throw ap_error("ALGLIB: error in 'mincgoptimize' (some derivatives were not provided?)");
840  }
841  alglib_impl::ae_state_clear(&_alglib_env_state);
842  }
844  {
845  throw ap_error(_alglib_env_state.error_msg);
846  }
847 }
848 
849 
850 
851 /*************************************************************************
852 Conjugate gradient results
853 
854 INPUT PARAMETERS:
855  State - algorithm state
856 
857 OUTPUT PARAMETERS:
858  X - array[0..N-1], solution
859  Rep - optimization report:
860  * Rep.TerminationType completion code:
861  * -7 gradient verification failed.
862  See MinCGSetGradientCheck() for more information.
863  * 1 relative function improvement is no more than
864  EpsF.
865  * 2 relative step is no more than EpsX.
866  * 4 gradient norm is no more than EpsG
867  * 5 MaxIts steps was taken
868  * 7 stopping conditions are too stringent,
869  further improvement is impossible,
870  we return best X found so far
871  * 8 terminated by user
872  * Rep.IterationsCount contains iterations count
873  * NFEV contains number of function calculations
874 
875  -- ALGLIB --
876  Copyright 20.04.2009 by Bochkanov Sergey
877 *************************************************************************/
878 void mincgresults(const mincgstate &state, real_1d_array &x, mincgreport &rep)
879 {
880  alglib_impl::ae_state _alglib_env_state;
881  alglib_impl::ae_state_init(&_alglib_env_state);
882  try
883  {
884  alglib_impl::mincgresults(const_cast<alglib_impl::mincgstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::mincgreport*>(rep.c_ptr()), &_alglib_env_state);
885  alglib_impl::ae_state_clear(&_alglib_env_state);
886  return;
887  }
889  {
890  throw ap_error(_alglib_env_state.error_msg);
891  }
892 }
893 
894 /*************************************************************************
895 Conjugate gradient results
896 
897 Buffered implementation of MinCGResults(), which uses pre-allocated buffer
898 to store X[]. If buffer size is too small, it resizes buffer. It is
899 intended to be used in the inner cycles of performance critical algorithms
900 where array reallocation penalty is too large to be ignored.
901 
902  -- ALGLIB --
903  Copyright 20.04.2009 by Bochkanov Sergey
904 *************************************************************************/
906 {
907  alglib_impl::ae_state _alglib_env_state;
908  alglib_impl::ae_state_init(&_alglib_env_state);
909  try
910  {
911  alglib_impl::mincgresultsbuf(const_cast<alglib_impl::mincgstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::mincgreport*>(rep.c_ptr()), &_alglib_env_state);
912  alglib_impl::ae_state_clear(&_alglib_env_state);
913  return;
914  }
916  {
917  throw ap_error(_alglib_env_state.error_msg);
918  }
919 }
920 
921 /*************************************************************************
922 This subroutine restarts CG algorithm from new point. All optimization
923 parameters are left unchanged.
924 
925 This function allows to solve multiple optimization problems (which
926 must have same number of dimensions) without object reallocation penalty.
927 
928 INPUT PARAMETERS:
929  State - structure used to store algorithm state.
930  X - new starting point.
931 
932  -- ALGLIB --
933  Copyright 30.07.2010 by Bochkanov Sergey
934 *************************************************************************/
935 void mincgrestartfrom(const mincgstate &state, const real_1d_array &x)
936 {
937  alglib_impl::ae_state _alglib_env_state;
938  alglib_impl::ae_state_init(&_alglib_env_state);
939  try
940  {
941  alglib_impl::mincgrestartfrom(const_cast<alglib_impl::mincgstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), &_alglib_env_state);
942  alglib_impl::ae_state_clear(&_alglib_env_state);
943  return;
944  }
946  {
947  throw ap_error(_alglib_env_state.error_msg);
948  }
949 }
950 
951 /*************************************************************************
952 
953 This subroutine turns on verification of the user-supplied analytic
954 gradient:
955 * user calls this subroutine before optimization begins
956 * MinCGOptimize() is called
957 * prior to actual optimization, for each component of parameters being
958  optimized X[i] algorithm performs following steps:
959  * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i],
960  where X[i] is i-th component of the initial point and S[i] is a scale
961  of i-th parameter
962  * F(X) is evaluated at these trial points
963  * we perform one more evaluation in the middle point of the interval
964  * we build cubic model using function values and derivatives at trial
965  points and we compare its prediction with actual value in the middle
966  point
967  * in case difference between prediction and actual value is higher than
968  some predetermined threshold, algorithm stops with completion code -7;
969  Rep.VarIdx is set to index of the parameter with incorrect derivative.
970 * after verification is over, algorithm proceeds to the actual optimization.
971 
972 NOTE 1: verification needs N (parameters count) gradient evaluations. It
973  is very costly and you should use it only for low dimensional
974  problems, when you want to be sure that you've correctly
975  calculated analytic derivatives. You should not use it in the
976  production code (unless you want to check derivatives provided by
977  some third party).
978 
979 NOTE 2: you should carefully choose TestStep. Value which is too large
980  (so large that function behaviour is significantly non-cubic) will
981  lead to false alarms. You may use different step for different
982  parameters by means of setting scale with MinCGSetScale().
983 
984 NOTE 3: this function may lead to false positives. In case it reports that
985  I-th derivative was calculated incorrectly, you may decrease test
986  step and try one more time - maybe your function changes too
987  sharply and your step is too large for such rapidly chanding
988  function.
989 
990 INPUT PARAMETERS:
991  State - structure used to store algorithm state
992  TestStep - verification step:
993  * TestStep=0 turns verification off
994  * TestStep>0 activates verification
995 
996  -- ALGLIB --
997  Copyright 31.05.2012 by Bochkanov Sergey
998 *************************************************************************/
999 void mincgsetgradientcheck(const mincgstate &state, const double teststep)
1000 {
1001  alglib_impl::ae_state _alglib_env_state;
1002  alglib_impl::ae_state_init(&_alglib_env_state);
1003  try
1004  {
1005  alglib_impl::mincgsetgradientcheck(const_cast<alglib_impl::mincgstate*>(state.c_ptr()), teststep, &_alglib_env_state);
1006  alglib_impl::ae_state_clear(&_alglib_env_state);
1007  return;
1008  }
1010  {
1011  throw ap_error(_alglib_env_state.error_msg);
1012  }
1013 }
1014 
1015 /*************************************************************************
1016 This object stores nonlinear optimizer state.
1017 You should use functions provided by MinBLEIC subpackage to work with this
1018 object
1019 *************************************************************************/
1021 {
1023  if( p_struct==NULL )
1024  throw ap_error("ALGLIB: malloc error");
1026  throw ap_error("ALGLIB: malloc error");
1027 }
1028 
1030 {
1032  if( p_struct==NULL )
1033  throw ap_error("ALGLIB: malloc error");
1034  if( !alglib_impl::_minbleicstate_init_copy(p_struct, const_cast<alglib_impl::minbleicstate*>(rhs.p_struct), NULL, ae_false) )
1035  throw ap_error("ALGLIB: malloc error");
1036 }
1037 
1039 {
1040  if( this==&rhs )
1041  return *this;
1043  if( !alglib_impl::_minbleicstate_init_copy(p_struct, const_cast<alglib_impl::minbleicstate*>(rhs.p_struct), NULL, ae_false) )
1044  throw ap_error("ALGLIB: malloc error");
1045  return *this;
1046 }
1047 
1049 {
1051  ae_free(p_struct);
1052 }
1053 
1055 {
1056  return p_struct;
1057 }
1058 
1060 {
1061  return const_cast<alglib_impl::minbleicstate*>(p_struct);
1062 }
1063 minbleicstate::minbleicstate() : _minbleicstate_owner() ,needf(p_struct->needf),needfg(p_struct->needfg),xupdated(p_struct->xupdated),f(p_struct->f),g(&p_struct->g),x(&p_struct->x)
1064 {
1065 }
1066 
1068 {
1069 }
1070 
1072 {
1073  if( this==&rhs )
1074  return *this;
1076  return *this;
1077 }
1078 
1080 {
1081 }
1082 
1083 
1084 /*************************************************************************
1085 This structure stores optimization report:
1086 * IterationsCount number of iterations
1087 * NFEV number of gradient evaluations
1088 * TerminationType termination type (see below)
1089 
1090 TERMINATION CODES
1091 
1092 TerminationType field contains completion code, which can be:
1093  -7 gradient verification failed.
1094  See MinBLEICSetGradientCheck() for more information.
1095  -3 inconsistent constraints. Feasible point is
1096  either nonexistent or too hard to find. Try to
1097  restart optimizer with better initial approximation
1098  1 relative function improvement is no more than EpsF.
1099  2 relative step is no more than EpsX.
1100  4 gradient norm is no more than EpsG
1101  5 MaxIts steps was taken
1102  7 stopping conditions are too stringent,
1103  further improvement is impossible,
1104  X contains best point found so far.
1105 
1106 ADDITIONAL FIELDS
1107 
1108 There are additional fields which can be used for debugging:
1109 * DebugEqErr error in the equality constraints (2-norm)
1110 * DebugFS f, calculated at projection of initial point
1111  to the feasible set
1112 * DebugFF f, calculated at the final point
1113 * DebugDX |X_start-X_final|
1114 *************************************************************************/
1116 {
1118  if( p_struct==NULL )
1119  throw ap_error("ALGLIB: malloc error");
1121  throw ap_error("ALGLIB: malloc error");
1122 }
1123 
1125 {
1127  if( p_struct==NULL )
1128  throw ap_error("ALGLIB: malloc error");
1129  if( !alglib_impl::_minbleicreport_init_copy(p_struct, const_cast<alglib_impl::minbleicreport*>(rhs.p_struct), NULL, ae_false) )
1130  throw ap_error("ALGLIB: malloc error");
1131 }
1132 
1134 {
1135  if( this==&rhs )
1136  return *this;
1138  if( !alglib_impl::_minbleicreport_init_copy(p_struct, const_cast<alglib_impl::minbleicreport*>(rhs.p_struct), NULL, ae_false) )
1139  throw ap_error("ALGLIB: malloc error");
1140  return *this;
1141 }
1142 
1144 {
1146  ae_free(p_struct);
1147 }
1148 
1150 {
1151  return p_struct;
1152 }
1153 
1155 {
1156  return const_cast<alglib_impl::minbleicreport*>(p_struct);
1157 }
1158 minbleicreport::minbleicreport() : _minbleicreport_owner() ,iterationscount(p_struct->iterationscount),nfev(p_struct->nfev),varidx(p_struct->varidx),terminationtype(p_struct->terminationtype),debugeqerr(p_struct->debugeqerr),debugfs(p_struct->debugfs),debugff(p_struct->debugff),debugdx(p_struct->debugdx),debugfeasqpits(p_struct->debugfeasqpits),debugfeasgpaits(p_struct->debugfeasgpaits),inneriterationscount(p_struct->inneriterationscount),outeriterationscount(p_struct->outeriterationscount)
1159 {
1160 }
1161 
1163 {
1164 }
1165 
1167 {
1168  if( this==&rhs )
1169  return *this;
1171  return *this;
1172 }
1173 
1175 {
1176 }
1177 
1178 /*************************************************************************
1179  BOUND CONSTRAINED OPTIMIZATION
1180  WITH ADDITIONAL LINEAR EQUALITY AND INEQUALITY CONSTRAINTS
1181 
1182 DESCRIPTION:
1183 The subroutine minimizes function F(x) of N arguments subject to any
1184 combination of:
1185 * bound constraints
1186 * linear inequality constraints
1187 * linear equality constraints
1188 
1189 REQUIREMENTS:
1190 * user must provide function value and gradient
1191 * starting point X0 must be feasible or
1192  not too far away from the feasible set
1193 * grad(f) must be Lipschitz continuous on a level set:
1194  L = { x : f(x)<=f(x0) }
1195 * function must be defined everywhere on the feasible set F
1196 
1197 USAGE:
1198 
1199 Constrained optimization if far more complex than the unconstrained one.
1200 Here we give very brief outline of the BLEIC optimizer. We strongly recommend
1201 you to read examples in the ALGLIB Reference Manual and to read ALGLIB User Guide
1202 on optimization, which is available at http://www.alglib.net/optimization/
1203 
1204 1. User initializes algorithm state with MinBLEICCreate() call
1205 
1206 2. USer adds boundary and/or linear constraints by calling
1207  MinBLEICSetBC() and MinBLEICSetLC() functions.
1208 
1209 3. User sets stopping conditions with MinBLEICSetCond().
1210 
1211 4. User calls MinBLEICOptimize() function which takes algorithm state and
1212  pointer (delegate, etc.) to callback function which calculates F/G.
1213 
1214 5. User calls MinBLEICResults() to get solution
1215 
1216 6. Optionally user may call MinBLEICRestartFrom() to solve another problem
1217  with same N but another starting point.
1218  MinBLEICRestartFrom() allows to reuse already initialized structure.
1219 
1220 
1221 INPUT PARAMETERS:
1222  N - problem dimension, N>0:
1223  * if given, only leading N elements of X are used
1224  * if not given, automatically determined from size ofX
1225  X - starting point, array[N]:
1226  * it is better to set X to a feasible point
1227  * but X can be infeasible, in which case algorithm will try
1228  to find feasible point first, using X as initial
1229  approximation.
1230 
1231 OUTPUT PARAMETERS:
1232  State - structure stores algorithm state
1233 
1234  -- ALGLIB --
1235  Copyright 28.11.2010 by Bochkanov Sergey
1236 *************************************************************************/
1237 void minbleiccreate(const ae_int_t n, const real_1d_array &x, minbleicstate &state)
1238 {
1239  alglib_impl::ae_state _alglib_env_state;
1240  alglib_impl::ae_state_init(&_alglib_env_state);
1241  try
1242  {
1243  alglib_impl::minbleiccreate(n, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minbleicstate*>(state.c_ptr()), &_alglib_env_state);
1244  alglib_impl::ae_state_clear(&_alglib_env_state);
1245  return;
1246  }
1248  {
1249  throw ap_error(_alglib_env_state.error_msg);
1250  }
1251 }
1252 
1253 /*************************************************************************
1254  BOUND CONSTRAINED OPTIMIZATION
1255  WITH ADDITIONAL LINEAR EQUALITY AND INEQUALITY CONSTRAINTS
1256 
1257 DESCRIPTION:
1258 The subroutine minimizes function F(x) of N arguments subject to any
1259 combination of:
1260 * bound constraints
1261 * linear inequality constraints
1262 * linear equality constraints
1263 
1264 REQUIREMENTS:
1265 * user must provide function value and gradient
1266 * starting point X0 must be feasible or
1267  not too far away from the feasible set
1268 * grad(f) must be Lipschitz continuous on a level set:
1269  L = { x : f(x)<=f(x0) }
1270 * function must be defined everywhere on the feasible set F
1271 
1272 USAGE:
1273 
1274 Constrained optimization if far more complex than the unconstrained one.
1275 Here we give very brief outline of the BLEIC optimizer. We strongly recommend
1276 you to read examples in the ALGLIB Reference Manual and to read ALGLIB User Guide
1277 on optimization, which is available at http://www.alglib.net/optimization/
1278 
1279 1. User initializes algorithm state with MinBLEICCreate() call
1280 
1281 2. USer adds boundary and/or linear constraints by calling
1282  MinBLEICSetBC() and MinBLEICSetLC() functions.
1283 
1284 3. User sets stopping conditions with MinBLEICSetCond().
1285 
1286 4. User calls MinBLEICOptimize() function which takes algorithm state and
1287  pointer (delegate, etc.) to callback function which calculates F/G.
1288 
1289 5. User calls MinBLEICResults() to get solution
1290 
1291 6. Optionally user may call MinBLEICRestartFrom() to solve another problem
1292  with same N but another starting point.
1293  MinBLEICRestartFrom() allows to reuse already initialized structure.
1294 
1295 
1296 INPUT PARAMETERS:
1297  N - problem dimension, N>0:
1298  * if given, only leading N elements of X are used
1299  * if not given, automatically determined from size ofX
1300  X - starting point, array[N]:
1301  * it is better to set X to a feasible point
1302  * but X can be infeasible, in which case algorithm will try
1303  to find feasible point first, using X as initial
1304  approximation.
1305 
1306 OUTPUT PARAMETERS:
1307  State - structure stores algorithm state
1308 
1309  -- ALGLIB --
1310  Copyright 28.11.2010 by Bochkanov Sergey
1311 *************************************************************************/
1313 {
1314  alglib_impl::ae_state _alglib_env_state;
1315  ae_int_t n;
1316 
1317  n = x.length();
1318  alglib_impl::ae_state_init(&_alglib_env_state);
1319  try
1320  {
1321  alglib_impl::minbleiccreate(n, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minbleicstate*>(state.c_ptr()), &_alglib_env_state);
1322 
1323  alglib_impl::ae_state_clear(&_alglib_env_state);
1324  return;
1325  }
1327  {
1328  throw ap_error(_alglib_env_state.error_msg);
1329  }
1330 }
1331 
1332 /*************************************************************************
1333 The subroutine is finite difference variant of MinBLEICCreate(). It uses
1334 finite differences in order to differentiate target function.
1335 
1336 Description below contains information which is specific to this function
1337 only. We recommend to read comments on MinBLEICCreate() in order to get
1338 more information about creation of BLEIC optimizer.
1339 
1340 INPUT PARAMETERS:
1341  N - problem dimension, N>0:
1342  * if given, only leading N elements of X are used
1343  * if not given, automatically determined from size of X
1344  X - starting point, array[0..N-1].
1345  DiffStep- differentiation step, >0
1346 
1347 OUTPUT PARAMETERS:
1348  State - structure which stores algorithm state
1349 
1350 NOTES:
1351 1. algorithm uses 4-point central formula for differentiation.
1352 2. differentiation step along I-th axis is equal to DiffStep*S[I] where
1353  S[] is scaling vector which can be set by MinBLEICSetScale() call.
1354 3. we recommend you to use moderate values of differentiation step. Too
1355  large step will result in too large truncation errors, while too small
1356  step will result in too large numerical errors. 1.0E-6 can be good
1357  value to start with.
1358 4. Numerical differentiation is very inefficient - one gradient
1359  calculation needs 4*N function evaluations. This function will work for
1360  any N - either small (1...10), moderate (10...100) or large (100...).
1361  However, performance penalty will be too severe for any N's except for
1362  small ones.
1363  We should also say that code which relies on numerical differentiation
1364  is less robust and precise. CG needs exact gradient values. Imprecise
1365  gradient may slow down convergence, especially on highly nonlinear
1366  problems.
1367  Thus we recommend to use this function for fast prototyping on small-
1368  dimensional problems only, and to implement analytical gradient as soon
1369  as possible.
1370 
1371  -- ALGLIB --
1372  Copyright 16.05.2011 by Bochkanov Sergey
1373 *************************************************************************/
1374 void minbleiccreatef(const ae_int_t n, const real_1d_array &x, const double diffstep, minbleicstate &state)
1375 {
1376  alglib_impl::ae_state _alglib_env_state;
1377  alglib_impl::ae_state_init(&_alglib_env_state);
1378  try
1379  {
1380  alglib_impl::minbleiccreatef(n, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), diffstep, const_cast<alglib_impl::minbleicstate*>(state.c_ptr()), &_alglib_env_state);
1381  alglib_impl::ae_state_clear(&_alglib_env_state);
1382  return;
1383  }
1385  {
1386  throw ap_error(_alglib_env_state.error_msg);
1387  }
1388 }
1389 
1390 /*************************************************************************
1391 The subroutine is finite difference variant of MinBLEICCreate(). It uses
1392 finite differences in order to differentiate target function.
1393 
1394 Description below contains information which is specific to this function
1395 only. We recommend to read comments on MinBLEICCreate() in order to get
1396 more information about creation of BLEIC optimizer.
1397 
1398 INPUT PARAMETERS:
1399  N - problem dimension, N>0:
1400  * if given, only leading N elements of X are used
1401  * if not given, automatically determined from size of X
1402  X - starting point, array[0..N-1].
1403  DiffStep- differentiation step, >0
1404 
1405 OUTPUT PARAMETERS:
1406  State - structure which stores algorithm state
1407 
1408 NOTES:
1409 1. algorithm uses 4-point central formula for differentiation.
1410 2. differentiation step along I-th axis is equal to DiffStep*S[I] where
1411  S[] is scaling vector which can be set by MinBLEICSetScale() call.
1412 3. we recommend you to use moderate values of differentiation step. Too
1413  large step will result in too large truncation errors, while too small
1414  step will result in too large numerical errors. 1.0E-6 can be good
1415  value to start with.
1416 4. Numerical differentiation is very inefficient - one gradient
1417  calculation needs 4*N function evaluations. This function will work for
1418  any N - either small (1...10), moderate (10...100) or large (100...).
1419  However, performance penalty will be too severe for any N's except for
1420  small ones.
1421  We should also say that code which relies on numerical differentiation
1422  is less robust and precise. CG needs exact gradient values. Imprecise
1423  gradient may slow down convergence, especially on highly nonlinear
1424  problems.
1425  Thus we recommend to use this function for fast prototyping on small-
1426  dimensional problems only, and to implement analytical gradient as soon
1427  as possible.
1428 
1429  -- ALGLIB --
1430  Copyright 16.05.2011 by Bochkanov Sergey
1431 *************************************************************************/
1432 void minbleiccreatef(const real_1d_array &x, const double diffstep, minbleicstate &state)
1433 {
1434  alglib_impl::ae_state _alglib_env_state;
1435  ae_int_t n;
1436 
1437  n = x.length();
1438  alglib_impl::ae_state_init(&_alglib_env_state);
1439  try
1440  {
1441  alglib_impl::minbleiccreatef(n, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), diffstep, const_cast<alglib_impl::minbleicstate*>(state.c_ptr()), &_alglib_env_state);
1442 
1443  alglib_impl::ae_state_clear(&_alglib_env_state);
1444  return;
1445  }
1447  {
1448  throw ap_error(_alglib_env_state.error_msg);
1449  }
1450 }
1451 
1452 /*************************************************************************
1453 This function sets boundary constraints for BLEIC optimizer.
1454 
1455 Boundary constraints are inactive by default (after initial creation).
1456 They are preserved after algorithm restart with MinBLEICRestartFrom().
1457 
1458 INPUT PARAMETERS:
1459  State - structure stores algorithm state
1460  BndL - lower bounds, array[N].
1461  If some (all) variables are unbounded, you may specify
1462  very small number or -INF.
1463  BndU - upper bounds, array[N].
1464  If some (all) variables are unbounded, you may specify
1465  very large number or +INF.
1466 
1467 NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case I-th
1468 variable will be "frozen" at X[i]=BndL[i]=BndU[i].
1469 
1470 NOTE 2: this solver has following useful properties:
1471 * bound constraints are always satisfied exactly
1472 * function is evaluated only INSIDE area specified by bound constraints,
1473  even when numerical differentiation is used (algorithm adjusts nodes
1474  according to boundary constraints)
1475 
1476  -- ALGLIB --
1477  Copyright 28.11.2010 by Bochkanov Sergey
1478 *************************************************************************/
1479 void minbleicsetbc(const minbleicstate &state, const real_1d_array &bndl, const real_1d_array &bndu)
1480 {
1481  alglib_impl::ae_state _alglib_env_state;
1482  alglib_impl::ae_state_init(&_alglib_env_state);
1483  try
1484  {
1485  alglib_impl::minbleicsetbc(const_cast<alglib_impl::minbleicstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(bndl.c_ptr()), const_cast<alglib_impl::ae_vector*>(bndu.c_ptr()), &_alglib_env_state);
1486  alglib_impl::ae_state_clear(&_alglib_env_state);
1487  return;
1488  }
1490  {
1491  throw ap_error(_alglib_env_state.error_msg);
1492  }
1493 }
1494 
1495 /*************************************************************************
1496 This function sets linear constraints for BLEIC optimizer.
1497 
1498 Linear constraints are inactive by default (after initial creation).
1499 They are preserved after algorithm restart with MinBLEICRestartFrom().
1500 
1501 INPUT PARAMETERS:
1502  State - structure previously allocated with MinBLEICCreate call.
1503  C - linear constraints, array[K,N+1].
1504  Each row of C represents one constraint, either equality
1505  or inequality (see below):
1506  * first N elements correspond to coefficients,
1507  * last element corresponds to the right part.
1508  All elements of C (including right part) must be finite.
1509  CT - type of constraints, array[K]:
1510  * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1]
1511  * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1]
1512  * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1]
1513  K - number of equality/inequality constraints, K>=0:
1514  * if given, only leading K elements of C/CT are used
1515  * if not given, automatically determined from sizes of C/CT
1516 
1517 NOTE 1: linear (non-bound) constraints are satisfied only approximately:
1518 * there always exists some minor violation (about Epsilon in magnitude)
1519  due to rounding errors
1520 * numerical differentiation, if used, may lead to function evaluations
1521  outside of the feasible area, because algorithm does NOT change
1522  numerical differentiation formula according to linear constraints.
1523 If you want constraints to be satisfied exactly, try to reformulate your
1524 problem in such manner that all constraints will become boundary ones
1525 (this kind of constraints is always satisfied exactly, both in the final
1526 solution and in all intermediate points).
1527 
1528  -- ALGLIB --
1529  Copyright 28.11.2010 by Bochkanov Sergey
1530 *************************************************************************/
1531 void minbleicsetlc(const minbleicstate &state, const real_2d_array &c, const integer_1d_array &ct, const ae_int_t k)
1532 {
1533  alglib_impl::ae_state _alglib_env_state;
1534  alglib_impl::ae_state_init(&_alglib_env_state);
1535  try
1536  {
1537  alglib_impl::minbleicsetlc(const_cast<alglib_impl::minbleicstate*>(state.c_ptr()), const_cast<alglib_impl::ae_matrix*>(c.c_ptr()), const_cast<alglib_impl::ae_vector*>(ct.c_ptr()), k, &_alglib_env_state);
1538  alglib_impl::ae_state_clear(&_alglib_env_state);
1539  return;
1540  }
1542  {
1543  throw ap_error(_alglib_env_state.error_msg);
1544  }
1545 }
1546 
1547 /*************************************************************************
1548 This function sets linear constraints for BLEIC optimizer.
1549 
1550 Linear constraints are inactive by default (after initial creation).
1551 They are preserved after algorithm restart with MinBLEICRestartFrom().
1552 
1553 INPUT PARAMETERS:
1554  State - structure previously allocated with MinBLEICCreate call.
1555  C - linear constraints, array[K,N+1].
1556  Each row of C represents one constraint, either equality
1557  or inequality (see below):
1558  * first N elements correspond to coefficients,
1559  * last element corresponds to the right part.
1560  All elements of C (including right part) must be finite.
1561  CT - type of constraints, array[K]:
1562  * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1]
1563  * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1]
1564  * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1]
1565  K - number of equality/inequality constraints, K>=0:
1566  * if given, only leading K elements of C/CT are used
1567  * if not given, automatically determined from sizes of C/CT
1568 
1569 NOTE 1: linear (non-bound) constraints are satisfied only approximately:
1570 * there always exists some minor violation (about Epsilon in magnitude)
1571  due to rounding errors
1572 * numerical differentiation, if used, may lead to function evaluations
1573  outside of the feasible area, because algorithm does NOT change
1574  numerical differentiation formula according to linear constraints.
1575 If you want constraints to be satisfied exactly, try to reformulate your
1576 problem in such manner that all constraints will become boundary ones
1577 (this kind of constraints is always satisfied exactly, both in the final
1578 solution and in all intermediate points).
1579 
1580  -- ALGLIB --
1581  Copyright 28.11.2010 by Bochkanov Sergey
1582 *************************************************************************/
1583 void minbleicsetlc(const minbleicstate &state, const real_2d_array &c, const integer_1d_array &ct)
1584 {
1585  alglib_impl::ae_state _alglib_env_state;
1586  ae_int_t k;
1587  if( (c.rows()!=ct.length()))
1588  throw ap_error("Error while calling 'minbleicsetlc': looks like one of arguments has wrong size");
1589  k = c.rows();
1590  alglib_impl::ae_state_init(&_alglib_env_state);
1591  try
1592  {
1593  alglib_impl::minbleicsetlc(const_cast<alglib_impl::minbleicstate*>(state.c_ptr()), const_cast<alglib_impl::ae_matrix*>(c.c_ptr()), const_cast<alglib_impl::ae_vector*>(ct.c_ptr()), k, &_alglib_env_state);
1594 
1595  alglib_impl::ae_state_clear(&_alglib_env_state);
1596  return;
1597  }
1599  {
1600  throw ap_error(_alglib_env_state.error_msg);
1601  }
1602 }
1603 
1604 /*************************************************************************
1605 This function sets stopping conditions for the optimizer.
1606 
1607 INPUT PARAMETERS:
1608  State - structure which stores algorithm state
1609  EpsG - >=0
1610  The subroutine finishes its work if the condition
1611  |v|<EpsG is satisfied, where:
1612  * |.| means Euclidian norm
1613  * v - scaled gradient vector, v[i]=g[i]*s[i]
1614  * g - gradient
1615  * s - scaling coefficients set by MinBLEICSetScale()
1616  EpsF - >=0
1617  The subroutine finishes its work if on k+1-th iteration
1618  the condition |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1}
1619  is satisfied.
1620  EpsX - >=0
1621  The subroutine finishes its work if on k+1-th iteration
1622  the condition |v|<=EpsX is fulfilled, where:
1623  * |.| means Euclidian norm
1624  * v - scaled step vector, v[i]=dx[i]/s[i]
1625  * dx - step vector, dx=X(k+1)-X(k)
1626  * s - scaling coefficients set by MinBLEICSetScale()
1627  MaxIts - maximum number of iterations. If MaxIts=0, the number of
1628  iterations is unlimited.
1629 
1630 Passing EpsG=0, EpsF=0 and EpsX=0 and MaxIts=0 (simultaneously) will lead
1631 to automatic stopping criterion selection.
1632 
1633 NOTE: when SetCond() called with non-zero MaxIts, BLEIC solver may perform
1634  slightly more than MaxIts iterations. I.e., MaxIts sets non-strict
1635  limit on iterations count.
1636 
1637  -- ALGLIB --
1638  Copyright 28.11.2010 by Bochkanov Sergey
1639 *************************************************************************/
1640 void minbleicsetcond(const minbleicstate &state, const double epsg, const double epsf, const double epsx, const ae_int_t maxits)
1641 {
1642  alglib_impl::ae_state _alglib_env_state;
1643  alglib_impl::ae_state_init(&_alglib_env_state);
1644  try
1645  {
1646  alglib_impl::minbleicsetcond(const_cast<alglib_impl::minbleicstate*>(state.c_ptr()), epsg, epsf, epsx, maxits, &_alglib_env_state);
1647  alglib_impl::ae_state_clear(&_alglib_env_state);
1648  return;
1649  }
1651  {
1652  throw ap_error(_alglib_env_state.error_msg);
1653  }
1654 }
1655 
1656 /*************************************************************************
1657 This function sets scaling coefficients for BLEIC optimizer.
1658 
1659 ALGLIB optimizers use scaling matrices to test stopping conditions (step
1660 size and gradient are scaled before comparison with tolerances). Scale of
1661 the I-th variable is a translation invariant measure of:
1662 a) "how large" the variable is
1663 b) how large the step should be to make significant changes in the function
1664 
1665 Scaling is also used by finite difference variant of the optimizer - step
1666 along I-th axis is equal to DiffStep*S[I].
1667 
1668 In most optimizers (and in the BLEIC too) scaling is NOT a form of
1669 preconditioning. It just affects stopping conditions. You should set
1670 preconditioner by separate call to one of the MinBLEICSetPrec...()
1671 functions.
1672 
1673 There is a special preconditioning mode, however, which uses scaling
1674 coefficients to form diagonal preconditioning matrix. You can turn this
1675 mode on, if you want. But you should understand that scaling is not the
1676 same thing as preconditioning - these are two different, although related
1677 forms of tuning solver.
1678 
1679 INPUT PARAMETERS:
1680  State - structure stores algorithm state
1681  S - array[N], non-zero scaling coefficients
1682  S[i] may be negative, sign doesn't matter.
1683 
1684  -- ALGLIB --
1685  Copyright 14.01.2011 by Bochkanov Sergey
1686 *************************************************************************/
1687 void minbleicsetscale(const minbleicstate &state, const real_1d_array &s)
1688 {
1689  alglib_impl::ae_state _alglib_env_state;
1690  alglib_impl::ae_state_init(&_alglib_env_state);
1691  try
1692  {
1693  alglib_impl::minbleicsetscale(const_cast<alglib_impl::minbleicstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(s.c_ptr()), &_alglib_env_state);
1694  alglib_impl::ae_state_clear(&_alglib_env_state);
1695  return;
1696  }
1698  {
1699  throw ap_error(_alglib_env_state.error_msg);
1700  }
1701 }
1702 
1703 /*************************************************************************
1704 Modification of the preconditioner: preconditioning is turned off.
1705 
1706 INPUT PARAMETERS:
1707  State - structure which stores algorithm state
1708 
1709  -- ALGLIB --
1710  Copyright 13.10.2010 by Bochkanov Sergey
1711 *************************************************************************/
1713 {
1714  alglib_impl::ae_state _alglib_env_state;
1715  alglib_impl::ae_state_init(&_alglib_env_state);
1716  try
1717  {
1718  alglib_impl::minbleicsetprecdefault(const_cast<alglib_impl::minbleicstate*>(state.c_ptr()), &_alglib_env_state);
1719  alglib_impl::ae_state_clear(&_alglib_env_state);
1720  return;
1721  }
1723  {
1724  throw ap_error(_alglib_env_state.error_msg);
1725  }
1726 }
1727 
1728 /*************************************************************************
1729 Modification of the preconditioner: diagonal of approximate Hessian is
1730 used.
1731 
1732 INPUT PARAMETERS:
1733  State - structure which stores algorithm state
1734  D - diagonal of the approximate Hessian, array[0..N-1],
1735  (if larger, only leading N elements are used).
1736 
1737 NOTE 1: D[i] should be positive. Exception will be thrown otherwise.
1738 
1739 NOTE 2: you should pass diagonal of approximate Hessian - NOT ITS INVERSE.
1740 
1741  -- ALGLIB --
1742  Copyright 13.10.2010 by Bochkanov Sergey
1743 *************************************************************************/
1745 {
1746  alglib_impl::ae_state _alglib_env_state;
1747  alglib_impl::ae_state_init(&_alglib_env_state);
1748  try
1749  {
1750  alglib_impl::minbleicsetprecdiag(const_cast<alglib_impl::minbleicstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(d.c_ptr()), &_alglib_env_state);
1751  alglib_impl::ae_state_clear(&_alglib_env_state);
1752  return;
1753  }
1755  {
1756  throw ap_error(_alglib_env_state.error_msg);
1757  }
1758 }
1759 
1760 /*************************************************************************
1761 Modification of the preconditioner: scale-based diagonal preconditioning.
1762 
1763 This preconditioning mode can be useful when you don't have approximate
1764 diagonal of Hessian, but you know that your variables are badly scaled
1765 (for example, one variable is in [1,10], and another in [1000,100000]),
1766 and most part of the ill-conditioning comes from different scales of vars.
1767 
1768 In this case simple scale-based preconditioner, with H[i] = 1/(s[i]^2),
1769 can greatly improve convergence.
1770 
1771 IMPRTANT: you should set scale of your variables with MinBLEICSetScale()
1772 call (before or after MinBLEICSetPrecScale() call). Without knowledge of
1773 the scale of your variables scale-based preconditioner will be just unit
1774 matrix.
1775 
1776 INPUT PARAMETERS:
1777  State - structure which stores algorithm state
1778 
1779  -- ALGLIB --
1780  Copyright 13.10.2010 by Bochkanov Sergey
1781 *************************************************************************/
1783 {
1784  alglib_impl::ae_state _alglib_env_state;
1785  alglib_impl::ae_state_init(&_alglib_env_state);
1786  try
1787  {
1788  alglib_impl::minbleicsetprecscale(const_cast<alglib_impl::minbleicstate*>(state.c_ptr()), &_alglib_env_state);
1789  alglib_impl::ae_state_clear(&_alglib_env_state);
1790  return;
1791  }
1793  {
1794  throw ap_error(_alglib_env_state.error_msg);
1795  }
1796 }
1797 
1798 /*************************************************************************
1799 This function turns on/off reporting.
1800 
1801 INPUT PARAMETERS:
1802  State - structure which stores algorithm state
1803  NeedXRep- whether iteration reports are needed or not
1804 
1805 If NeedXRep is True, algorithm will call rep() callback function if it is
1806 provided to MinBLEICOptimize().
1807 
1808  -- ALGLIB --
1809  Copyright 28.11.2010 by Bochkanov Sergey
1810 *************************************************************************/
1811 void minbleicsetxrep(const minbleicstate &state, const bool needxrep)
1812 {
1813  alglib_impl::ae_state _alglib_env_state;
1814  alglib_impl::ae_state_init(&_alglib_env_state);
1815  try
1816  {
1817  alglib_impl::minbleicsetxrep(const_cast<alglib_impl::minbleicstate*>(state.c_ptr()), needxrep, &_alglib_env_state);
1818  alglib_impl::ae_state_clear(&_alglib_env_state);
1819  return;
1820  }
1822  {
1823  throw ap_error(_alglib_env_state.error_msg);
1824  }
1825 }
1826 
1827 /*************************************************************************
1828 This function sets maximum step length
1829 
1830 IMPORTANT: this feature is hard to combine with preconditioning. You can't
1831 set upper limit on step length, when you solve optimization problem with
1832 linear (non-boundary) constraints AND preconditioner turned on.
1833 
1834 When non-boundary constraints are present, you have to either a) use
1835 preconditioner, or b) use upper limit on step length. YOU CAN'T USE BOTH!
1836 In this case algorithm will terminate with appropriate error code.
1837 
1838 INPUT PARAMETERS:
1839  State - structure which stores algorithm state
1840  StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't
1841  want to limit step length.
1842 
1843 Use this subroutine when you optimize target function which contains exp()
1844 or other fast growing functions, and optimization algorithm makes too
1845 large steps which lead to overflow. This function allows us to reject
1846 steps that are too large (and therefore expose us to the possible
1847 overflow) without actually calculating function value at the x+stp*d.
1848 
1849  -- ALGLIB --
1850  Copyright 02.04.2010 by Bochkanov Sergey
1851 *************************************************************************/
1852 void minbleicsetstpmax(const minbleicstate &state, const double stpmax)
1853 {
1854  alglib_impl::ae_state _alglib_env_state;
1855  alglib_impl::ae_state_init(&_alglib_env_state);
1856  try
1857  {
1858  alglib_impl::minbleicsetstpmax(const_cast<alglib_impl::minbleicstate*>(state.c_ptr()), stpmax, &_alglib_env_state);
1859  alglib_impl::ae_state_clear(&_alglib_env_state);
1860  return;
1861  }
1863  {
1864  throw ap_error(_alglib_env_state.error_msg);
1865  }
1866 }
1867 
1868 /*************************************************************************
1869 This function provides reverse communication interface
1870 Reverse communication interface is not documented or recommended to use.
1871 See below for functions which provide better documented API
1872 *************************************************************************/
1874 {
1875  alglib_impl::ae_state _alglib_env_state;
1876  alglib_impl::ae_state_init(&_alglib_env_state);
1877  try
1878  {
1879  ae_bool result = alglib_impl::minbleiciteration(const_cast<alglib_impl::minbleicstate*>(state.c_ptr()), &_alglib_env_state);
1880  alglib_impl::ae_state_clear(&_alglib_env_state);
1881  return *(reinterpret_cast<bool*>(&result));
1882  }
1884  {
1885  throw ap_error(_alglib_env_state.error_msg);
1886  }
1887 }
1888 
1889 
1891  void (*func)(const real_1d_array &x, double &func, void *ptr),
1892  void (*rep)(const real_1d_array &x, double func, void *ptr),
1893  void *ptr)
1894 {
1895  alglib_impl::ae_state _alglib_env_state;
1896  if( func==NULL )
1897  throw ap_error("ALGLIB: error in 'minbleicoptimize()' (func is NULL)");
1898  alglib_impl::ae_state_init(&_alglib_env_state);
1899  try
1900  {
1901  while( alglib_impl::minbleiciteration(state.c_ptr(), &_alglib_env_state) )
1902  {
1903  if( state.needf )
1904  {
1905  func(state.x, state.f, ptr);
1906  continue;
1907  }
1908  if( state.xupdated )
1909  {
1910  if( rep!=NULL )
1911  rep(state.x, state.f, ptr);
1912  continue;
1913  }
1914  throw ap_error("ALGLIB: error in 'minbleicoptimize' (some derivatives were not provided?)");
1915  }
1916  alglib_impl::ae_state_clear(&_alglib_env_state);
1917  }
1919  {
1920  throw ap_error(_alglib_env_state.error_msg);
1921  }
1922 }
1923 
1924 
1926  void (*grad)(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr),
1927  void (*rep)(const real_1d_array &x, double func, void *ptr),
1928  void *ptr)
1929 {
1930  alglib_impl::ae_state _alglib_env_state;
1931  if( grad==NULL )
1932  throw ap_error("ALGLIB: error in 'minbleicoptimize()' (grad is NULL)");
1933  alglib_impl::ae_state_init(&_alglib_env_state);
1934  try
1935  {
1936  while( alglib_impl::minbleiciteration(state.c_ptr(), &_alglib_env_state) )
1937  {
1938  if( state.needfg )
1939  {
1940  grad(state.x, state.f, state.g, ptr);
1941  continue;
1942  }
1943  if( state.xupdated )
1944  {
1945  if( rep!=NULL )
1946  rep(state.x, state.f, ptr);
1947  continue;
1948  }
1949  throw ap_error("ALGLIB: error in 'minbleicoptimize' (some derivatives were not provided?)");
1950  }
1951  alglib_impl::ae_state_clear(&_alglib_env_state);
1952  }
1954  {
1955  throw ap_error(_alglib_env_state.error_msg);
1956  }
1957 }
1958 
1959 
1960 
1961 /*************************************************************************
1962 BLEIC results
1963 
1964 INPUT PARAMETERS:
1965  State - algorithm state
1966 
1967 OUTPUT PARAMETERS:
1968  X - array[0..N-1], solution
1969  Rep - optimization report. You should check Rep.TerminationType
1970  in order to distinguish successful termination from
1971  unsuccessful one:
1972  * -7 gradient verification failed.
1973  See MinBLEICSetGradientCheck() for more information.
1974  * -3 inconsistent constraints. Feasible point is
1975  either nonexistent or too hard to find. Try to
1976  restart optimizer with better initial approximation
1977  * 1 relative function improvement is no more than EpsF.
1978  * 2 scaled step is no more than EpsX.
1979  * 4 scaled gradient norm is no more than EpsG.
1980  * 5 MaxIts steps was taken
1981  More information about fields of this structure can be
1982  found in the comments on MinBLEICReport datatype.
1983 
1984  -- ALGLIB --
1985  Copyright 28.11.2010 by Bochkanov Sergey
1986 *************************************************************************/
1988 {
1989  alglib_impl::ae_state _alglib_env_state;
1990  alglib_impl::ae_state_init(&_alglib_env_state);
1991  try
1992  {
1993  alglib_impl::minbleicresults(const_cast<alglib_impl::minbleicstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minbleicreport*>(rep.c_ptr()), &_alglib_env_state);
1994  alglib_impl::ae_state_clear(&_alglib_env_state);
1995  return;
1996  }
1998  {
1999  throw ap_error(_alglib_env_state.error_msg);
2000  }
2001 }
2002 
2003 /*************************************************************************
2004 BLEIC results
2005 
2006 Buffered implementation of MinBLEICResults() which uses pre-allocated buffer
2007 to store X[]. If buffer size is too small, it resizes buffer. It is
2008 intended to be used in the inner cycles of performance critical algorithms
2009 where array reallocation penalty is too large to be ignored.
2010 
2011  -- ALGLIB --
2012  Copyright 28.11.2010 by Bochkanov Sergey
2013 *************************************************************************/
2015 {
2016  alglib_impl::ae_state _alglib_env_state;
2017  alglib_impl::ae_state_init(&_alglib_env_state);
2018  try
2019  {
2020  alglib_impl::minbleicresultsbuf(const_cast<alglib_impl::minbleicstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minbleicreport*>(rep.c_ptr()), &_alglib_env_state);
2021  alglib_impl::ae_state_clear(&_alglib_env_state);
2022  return;
2023  }
2025  {
2026  throw ap_error(_alglib_env_state.error_msg);
2027  }
2028 }
2029 
2030 /*************************************************************************
2031 This subroutine restarts algorithm from new point.
2032 All optimization parameters (including constraints) are left unchanged.
2033 
2034 This function allows to solve multiple optimization problems (which
2035 must have same number of dimensions) without object reallocation penalty.
2036 
2037 INPUT PARAMETERS:
2038  State - structure previously allocated with MinBLEICCreate call.
2039  X - new starting point.
2040 
2041  -- ALGLIB --
2042  Copyright 28.11.2010 by Bochkanov Sergey
2043 *************************************************************************/
2045 {
2046  alglib_impl::ae_state _alglib_env_state;
2047  alglib_impl::ae_state_init(&_alglib_env_state);
2048  try
2049  {
2050  alglib_impl::minbleicrestartfrom(const_cast<alglib_impl::minbleicstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), &_alglib_env_state);
2051  alglib_impl::ae_state_clear(&_alglib_env_state);
2052  return;
2053  }
2055  {
2056  throw ap_error(_alglib_env_state.error_msg);
2057  }
2058 }
2059 
2060 /*************************************************************************
2061 This subroutine turns on verification of the user-supplied analytic
2062 gradient:
2063 * user calls this subroutine before optimization begins
2064 * MinBLEICOptimize() is called
2065 * prior to actual optimization, for each component of parameters being
2066  optimized X[i] algorithm performs following steps:
2067  * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i],
2068  where X[i] is i-th component of the initial point and S[i] is a scale
2069  of i-th parameter
2070  * if needed, steps are bounded with respect to constraints on X[]
2071  * F(X) is evaluated at these trial points
2072  * we perform one more evaluation in the middle point of the interval
2073  * we build cubic model using function values and derivatives at trial
2074  points and we compare its prediction with actual value in the middle
2075  point
2076  * in case difference between prediction and actual value is higher than
2077  some predetermined threshold, algorithm stops with completion code -7;
2078  Rep.VarIdx is set to index of the parameter with incorrect derivative.
2079 * after verification is over, algorithm proceeds to the actual optimization.
2080 
2081 NOTE 1: verification needs N (parameters count) gradient evaluations. It
2082  is very costly and you should use it only for low dimensional
2083  problems, when you want to be sure that you've correctly
2084  calculated analytic derivatives. You should not use it in the
2085  production code (unless you want to check derivatives provided by
2086  some third party).
2087 
2088 NOTE 2: you should carefully choose TestStep. Value which is too large
2089  (so large that function behaviour is significantly non-cubic) will
2090  lead to false alarms. You may use different step for different
2091  parameters by means of setting scale with MinBLEICSetScale().
2092 
2093 NOTE 3: this function may lead to false positives. In case it reports that
2094  I-th derivative was calculated incorrectly, you may decrease test
2095  step and try one more time - maybe your function changes too
2096  sharply and your step is too large for such rapidly chanding
2097  function.
2098 
2099 INPUT PARAMETERS:
2100  State - structure used to store algorithm state
2101  TestStep - verification step:
2102  * TestStep=0 turns verification off
2103  * TestStep>0 activates verification
2104 
2105  -- ALGLIB --
2106  Copyright 15.06.2012 by Bochkanov Sergey
2107 *************************************************************************/
2108 void minbleicsetgradientcheck(const minbleicstate &state, const double teststep)
2109 {
2110  alglib_impl::ae_state _alglib_env_state;
2111  alglib_impl::ae_state_init(&_alglib_env_state);
2112  try
2113  {
2114  alglib_impl::minbleicsetgradientcheck(const_cast<alglib_impl::minbleicstate*>(state.c_ptr()), teststep, &_alglib_env_state);
2115  alglib_impl::ae_state_clear(&_alglib_env_state);
2116  return;
2117  }
2119  {
2120  throw ap_error(_alglib_env_state.error_msg);
2121  }
2122 }
2123 
2124 /*************************************************************************
2125 
2126 *************************************************************************/
2128 {
2130  if( p_struct==NULL )
2131  throw ap_error("ALGLIB: malloc error");
2133  throw ap_error("ALGLIB: malloc error");
2134 }
2135 
2137 {
2139  if( p_struct==NULL )
2140  throw ap_error("ALGLIB: malloc error");
2141  if( !alglib_impl::_minlbfgsstate_init_copy(p_struct, const_cast<alglib_impl::minlbfgsstate*>(rhs.p_struct), NULL, ae_false) )
2142  throw ap_error("ALGLIB: malloc error");
2143 }
2144 
2146 {
2147  if( this==&rhs )
2148  return *this;
2150  if( !alglib_impl::_minlbfgsstate_init_copy(p_struct, const_cast<alglib_impl::minlbfgsstate*>(rhs.p_struct), NULL, ae_false) )
2151  throw ap_error("ALGLIB: malloc error");
2152  return *this;
2153 }
2154 
2156 {
2158  ae_free(p_struct);
2159 }
2160 
2162 {
2163  return p_struct;
2164 }
2165 
2167 {
2168  return const_cast<alglib_impl::minlbfgsstate*>(p_struct);
2169 }
2170 minlbfgsstate::minlbfgsstate() : _minlbfgsstate_owner() ,needf(p_struct->needf),needfg(p_struct->needfg),xupdated(p_struct->xupdated),f(p_struct->f),g(&p_struct->g),x(&p_struct->x)
2171 {
2172 }
2173 
2175 {
2176 }
2177 
2179 {
2180  if( this==&rhs )
2181  return *this;
2183  return *this;
2184 }
2185 
2187 {
2188 }
2189 
2190 
2191 /*************************************************************************
2192 
2193 *************************************************************************/
2195 {
2197  if( p_struct==NULL )
2198  throw ap_error("ALGLIB: malloc error");
2200  throw ap_error("ALGLIB: malloc error");
2201 }
2202 
2204 {
2206  if( p_struct==NULL )
2207  throw ap_error("ALGLIB: malloc error");
2208  if( !alglib_impl::_minlbfgsreport_init_copy(p_struct, const_cast<alglib_impl::minlbfgsreport*>(rhs.p_struct), NULL, ae_false) )
2209  throw ap_error("ALGLIB: malloc error");
2210 }
2211 
2213 {
2214  if( this==&rhs )
2215  return *this;
2217  if( !alglib_impl::_minlbfgsreport_init_copy(p_struct, const_cast<alglib_impl::minlbfgsreport*>(rhs.p_struct), NULL, ae_false) )
2218  throw ap_error("ALGLIB: malloc error");
2219  return *this;
2220 }
2221 
2223 {
2225  ae_free(p_struct);
2226 }
2227 
2229 {
2230  return p_struct;
2231 }
2232 
2234 {
2235  return const_cast<alglib_impl::minlbfgsreport*>(p_struct);
2236 }
2237 minlbfgsreport::minlbfgsreport() : _minlbfgsreport_owner() ,iterationscount(p_struct->iterationscount),nfev(p_struct->nfev),varidx(p_struct->varidx),terminationtype(p_struct->terminationtype)
2238 {
2239 }
2240 
2242 {
2243 }
2244 
2246 {
2247  if( this==&rhs )
2248  return *this;
2250  return *this;
2251 }
2252 
2254 {
2255 }
2256 
2257 /*************************************************************************
2258  LIMITED MEMORY BFGS METHOD FOR LARGE SCALE OPTIMIZATION
2259 
2260 DESCRIPTION:
2261 The subroutine minimizes function F(x) of N arguments by using a quasi-
2262 Newton method (LBFGS scheme) which is optimized to use a minimum amount
2263 of memory.
2264 The subroutine generates the approximation of an inverse Hessian matrix by
2265 using information about the last M steps of the algorithm (instead of N).
2266 It lessens a required amount of memory from a value of order N^2 to a
2267 value of order 2*N*M.
2268 
2269 
2270 REQUIREMENTS:
2271 Algorithm will request following information during its operation:
2272 * function value F and its gradient G (simultaneously) at given point X
2273 
2274 
2275 USAGE:
2276 1. User initializes algorithm state with MinLBFGSCreate() call
2277 2. User tunes solver parameters with MinLBFGSSetCond() MinLBFGSSetStpMax()
2278  and other functions
2279 3. User calls MinLBFGSOptimize() function which takes algorithm state and
2280  pointer (delegate, etc.) to callback function which calculates F/G.
2281 4. User calls MinLBFGSResults() to get solution
2282 5. Optionally user may call MinLBFGSRestartFrom() to solve another problem
2283  with same N/M but another starting point and/or another function.
2284  MinLBFGSRestartFrom() allows to reuse already initialized structure.
2285 
2286 
2287 INPUT PARAMETERS:
2288  N - problem dimension. N>0
2289  M - number of corrections in the BFGS scheme of Hessian
2290  approximation update. Recommended value: 3<=M<=7. The smaller
2291  value causes worse convergence, the bigger will not cause a
2292  considerably better convergence, but will cause a fall in the
2293  performance. M<=N.
2294  X - initial solution approximation, array[0..N-1].
2295 
2296 
2297 OUTPUT PARAMETERS:
2298  State - structure which stores algorithm state
2299 
2300 
2301 NOTES:
2302 1. you may tune stopping conditions with MinLBFGSSetCond() function
2303 2. if target function contains exp() or other fast growing functions, and
2304  optimization algorithm makes too large steps which leads to overflow,
2305  use MinLBFGSSetStpMax() function to bound algorithm's steps. However,
2306  L-BFGS rarely needs such a tuning.
2307 
2308 
2309  -- ALGLIB --
2310  Copyright 02.04.2010 by Bochkanov Sergey
2311 *************************************************************************/
2312 void minlbfgscreate(const ae_int_t n, const ae_int_t m, const real_1d_array &x, minlbfgsstate &state)
2313 {
2314  alglib_impl::ae_state _alglib_env_state;
2315  alglib_impl::ae_state_init(&_alglib_env_state);
2316  try
2317  {
2318  alglib_impl::minlbfgscreate(n, m, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minlbfgsstate*>(state.c_ptr()), &_alglib_env_state);
2319  alglib_impl::ae_state_clear(&_alglib_env_state);
2320  return;
2321  }
2323  {
2324  throw ap_error(_alglib_env_state.error_msg);
2325  }
2326 }
2327 
2328 /*************************************************************************
2329  LIMITED MEMORY BFGS METHOD FOR LARGE SCALE OPTIMIZATION
2330 
2331 DESCRIPTION:
2332 The subroutine minimizes function F(x) of N arguments by using a quasi-
2333 Newton method (LBFGS scheme) which is optimized to use a minimum amount
2334 of memory.
2335 The subroutine generates the approximation of an inverse Hessian matrix by
2336 using information about the last M steps of the algorithm (instead of N).
2337 It lessens a required amount of memory from a value of order N^2 to a
2338 value of order 2*N*M.
2339 
2340 
2341 REQUIREMENTS:
2342 Algorithm will request following information during its operation:
2343 * function value F and its gradient G (simultaneously) at given point X
2344 
2345 
2346 USAGE:
2347 1. User initializes algorithm state with MinLBFGSCreate() call
2348 2. User tunes solver parameters with MinLBFGSSetCond() MinLBFGSSetStpMax()
2349  and other functions
2350 3. User calls MinLBFGSOptimize() function which takes algorithm state and
2351  pointer (delegate, etc.) to callback function which calculates F/G.
2352 4. User calls MinLBFGSResults() to get solution
2353 5. Optionally user may call MinLBFGSRestartFrom() to solve another problem
2354  with same N/M but another starting point and/or another function.
2355  MinLBFGSRestartFrom() allows to reuse already initialized structure.
2356 
2357 
2358 INPUT PARAMETERS:
2359  N - problem dimension. N>0
2360  M - number of corrections in the BFGS scheme of Hessian
2361  approximation update. Recommended value: 3<=M<=7. The smaller
2362  value causes worse convergence, the bigger will not cause a
2363  considerably better convergence, but will cause a fall in the
2364  performance. M<=N.
2365  X - initial solution approximation, array[0..N-1].
2366 
2367 
2368 OUTPUT PARAMETERS:
2369  State - structure which stores algorithm state
2370 
2371 
2372 NOTES:
2373 1. you may tune stopping conditions with MinLBFGSSetCond() function
2374 2. if target function contains exp() or other fast growing functions, and
2375  optimization algorithm makes too large steps which leads to overflow,
2376  use MinLBFGSSetStpMax() function to bound algorithm's steps. However,
2377  L-BFGS rarely needs such a tuning.
2378 
2379 
2380  -- ALGLIB --
2381  Copyright 02.04.2010 by Bochkanov Sergey
2382 *************************************************************************/
2383 void minlbfgscreate(const ae_int_t m, const real_1d_array &x, minlbfgsstate &state)
2384 {
2385  alglib_impl::ae_state _alglib_env_state;
2386  ae_int_t n;
2387 
2388  n = x.length();
2389  alglib_impl::ae_state_init(&_alglib_env_state);
2390  try
2391  {
2392  alglib_impl::minlbfgscreate(n, m, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minlbfgsstate*>(state.c_ptr()), &_alglib_env_state);
2393 
2394  alglib_impl::ae_state_clear(&_alglib_env_state);
2395  return;
2396  }
2398  {
2399  throw ap_error(_alglib_env_state.error_msg);
2400  }
2401 }
2402 
2403 /*************************************************************************
2404 The subroutine is finite difference variant of MinLBFGSCreate(). It uses
2405 finite differences in order to differentiate target function.
2406 
2407 Description below contains information which is specific to this function
2408 only. We recommend to read comments on MinLBFGSCreate() in order to get
2409 more information about creation of LBFGS optimizer.
2410 
2411 INPUT PARAMETERS:
2412  N - problem dimension, N>0:
2413  * if given, only leading N elements of X are used
2414  * if not given, automatically determined from size of X
2415  M - number of corrections in the BFGS scheme of Hessian
2416  approximation update. Recommended value: 3<=M<=7. The smaller
2417  value causes worse convergence, the bigger will not cause a
2418  considerably better convergence, but will cause a fall in the
2419  performance. M<=N.
2420  X - starting point, array[0..N-1].
2421  DiffStep- differentiation step, >0
2422 
2423 OUTPUT PARAMETERS:
2424  State - structure which stores algorithm state
2425 
2426 NOTES:
2427 1. algorithm uses 4-point central formula for differentiation.
2428 2. differentiation step along I-th axis is equal to DiffStep*S[I] where
2429  S[] is scaling vector which can be set by MinLBFGSSetScale() call.
2430 3. we recommend you to use moderate values of differentiation step. Too
2431  large step will result in too large truncation errors, while too small
2432  step will result in too large numerical errors. 1.0E-6 can be good
2433  value to start with.
2434 4. Numerical differentiation is very inefficient - one gradient
2435  calculation needs 4*N function evaluations. This function will work for
2436  any N - either small (1...10), moderate (10...100) or large (100...).
2437  However, performance penalty will be too severe for any N's except for
2438  small ones.
2439  We should also say that code which relies on numerical differentiation
2440  is less robust and precise. LBFGS needs exact gradient values.
2441  Imprecise gradient may slow down convergence, especially on highly
2442  nonlinear problems.
2443  Thus we recommend to use this function for fast prototyping on small-
2444  dimensional problems only, and to implement analytical gradient as soon
2445  as possible.
2446 
2447  -- ALGLIB --
2448  Copyright 16.05.2011 by Bochkanov Sergey
2449 *************************************************************************/
2450 void minlbfgscreatef(const ae_int_t n, const ae_int_t m, const real_1d_array &x, const double diffstep, minlbfgsstate &state)
2451 {
2452  alglib_impl::ae_state _alglib_env_state;
2453  alglib_impl::ae_state_init(&_alglib_env_state);
2454  try
2455  {
2456  alglib_impl::minlbfgscreatef(n, m, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), diffstep, const_cast<alglib_impl::minlbfgsstate*>(state.c_ptr()), &_alglib_env_state);
2457  alglib_impl::ae_state_clear(&_alglib_env_state);
2458  return;
2459  }
2461  {
2462  throw ap_error(_alglib_env_state.error_msg);
2463  }
2464 }
2465 
2466 /*************************************************************************
2467 The subroutine is finite difference variant of MinLBFGSCreate(). It uses
2468 finite differences in order to differentiate target function.
2469 
2470 Description below contains information which is specific to this function
2471 only. We recommend to read comments on MinLBFGSCreate() in order to get
2472 more information about creation of LBFGS optimizer.
2473 
2474 INPUT PARAMETERS:
2475  N - problem dimension, N>0:
2476  * if given, only leading N elements of X are used
2477  * if not given, automatically determined from size of X
2478  M - number of corrections in the BFGS scheme of Hessian
2479  approximation update. Recommended value: 3<=M<=7. The smaller
2480  value causes worse convergence, the bigger will not cause a
2481  considerably better convergence, but will cause a fall in the
2482  performance. M<=N.
2483  X - starting point, array[0..N-1].
2484  DiffStep- differentiation step, >0
2485 
2486 OUTPUT PARAMETERS:
2487  State - structure which stores algorithm state
2488 
2489 NOTES:
2490 1. algorithm uses 4-point central formula for differentiation.
2491 2. differentiation step along I-th axis is equal to DiffStep*S[I] where
2492  S[] is scaling vector which can be set by MinLBFGSSetScale() call.
2493 3. we recommend you to use moderate values of differentiation step. Too
2494  large step will result in too large truncation errors, while too small
2495  step will result in too large numerical errors. 1.0E-6 can be good
2496  value to start with.
2497 4. Numerical differentiation is very inefficient - one gradient
2498  calculation needs 4*N function evaluations. This function will work for
2499  any N - either small (1...10), moderate (10...100) or large (100...).
2500  However, performance penalty will be too severe for any N's except for
2501  small ones.
2502  We should also say that code which relies on numerical differentiation
2503  is less robust and precise. LBFGS needs exact gradient values.
2504  Imprecise gradient may slow down convergence, especially on highly
2505  nonlinear problems.
2506  Thus we recommend to use this function for fast prototyping on small-
2507  dimensional problems only, and to implement analytical gradient as soon
2508  as possible.
2509 
2510  -- ALGLIB --
2511  Copyright 16.05.2011 by Bochkanov Sergey
2512 *************************************************************************/
2513 void minlbfgscreatef(const ae_int_t m, const real_1d_array &x, const double diffstep, minlbfgsstate &state)
2514 {
2515  alglib_impl::ae_state _alglib_env_state;
2516  ae_int_t n;
2517 
2518  n = x.length();
2519  alglib_impl::ae_state_init(&_alglib_env_state);
2520  try
2521  {
2522  alglib_impl::minlbfgscreatef(n, m, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), diffstep, const_cast<alglib_impl::minlbfgsstate*>(state.c_ptr()), &_alglib_env_state);
2523 
2524  alglib_impl::ae_state_clear(&_alglib_env_state);
2525  return;
2526  }
2528  {
2529  throw ap_error(_alglib_env_state.error_msg);
2530  }
2531 }
2532 
2533 /*************************************************************************
2534 This function sets stopping conditions for L-BFGS optimization algorithm.
2535 
2536 INPUT PARAMETERS:
2537  State - structure which stores algorithm state
2538  EpsG - >=0
2539  The subroutine finishes its work if the condition
2540  |v|<EpsG is satisfied, where:
2541  * |.| means Euclidian norm
2542  * v - scaled gradient vector, v[i]=g[i]*s[i]
2543  * g - gradient
2544  * s - scaling coefficients set by MinLBFGSSetScale()
2545  EpsF - >=0
2546  The subroutine finishes its work if on k+1-th iteration
2547  the condition |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1}
2548  is satisfied.
2549  EpsX - >=0
2550  The subroutine finishes its work if on k+1-th iteration
2551  the condition |v|<=EpsX is fulfilled, where:
2552  * |.| means Euclidian norm
2553  * v - scaled step vector, v[i]=dx[i]/s[i]
2554  * dx - ste pvector, dx=X(k+1)-X(k)
2555  * s - scaling coefficients set by MinLBFGSSetScale()
2556  MaxIts - maximum number of iterations. If MaxIts=0, the number of
2557  iterations is unlimited.
2558 
2559 Passing EpsG=0, EpsF=0, EpsX=0 and MaxIts=0 (simultaneously) will lead to
2560 automatic stopping criterion selection (small EpsX).
2561 
2562  -- ALGLIB --
2563  Copyright 02.04.2010 by Bochkanov Sergey
2564 *************************************************************************/
2565 void minlbfgssetcond(const minlbfgsstate &state, const double epsg, const double epsf, const double epsx, const ae_int_t maxits)
2566 {
2567  alglib_impl::ae_state _alglib_env_state;
2568  alglib_impl::ae_state_init(&_alglib_env_state);
2569  try
2570  {
2571  alglib_impl::minlbfgssetcond(const_cast<alglib_impl::minlbfgsstate*>(state.c_ptr()), epsg, epsf, epsx, maxits, &_alglib_env_state);
2572  alglib_impl::ae_state_clear(&_alglib_env_state);
2573  return;
2574  }
2576  {
2577  throw ap_error(_alglib_env_state.error_msg);
2578  }
2579 }
2580 
2581 /*************************************************************************
2582 This function turns on/off reporting.
2583 
2584 INPUT PARAMETERS:
2585  State - structure which stores algorithm state
2586  NeedXRep- whether iteration reports are needed or not
2587 
2588 If NeedXRep is True, algorithm will call rep() callback function if it is
2589 provided to MinLBFGSOptimize().
2590 
2591 
2592  -- ALGLIB --
2593  Copyright 02.04.2010 by Bochkanov Sergey
2594 *************************************************************************/
2595 void minlbfgssetxrep(const minlbfgsstate &state, const bool needxrep)
2596 {
2597  alglib_impl::ae_state _alglib_env_state;
2598  alglib_impl::ae_state_init(&_alglib_env_state);
2599  try
2600  {
2601  alglib_impl::minlbfgssetxrep(const_cast<alglib_impl::minlbfgsstate*>(state.c_ptr()), needxrep, &_alglib_env_state);
2602  alglib_impl::ae_state_clear(&_alglib_env_state);
2603  return;
2604  }
2606  {
2607  throw ap_error(_alglib_env_state.error_msg);
2608  }
2609 }
2610 
2611 /*************************************************************************
2612 This function sets maximum step length
2613 
2614 INPUT PARAMETERS:
2615  State - structure which stores algorithm state
2616  StpMax - maximum step length, >=0. Set StpMax to 0.0 (default), if
2617  you don't want to limit step length.
2618 
2619 Use this subroutine when you optimize target function which contains exp()
2620 or other fast growing functions, and optimization algorithm makes too
2621 large steps which leads to overflow. This function allows us to reject
2622 steps that are too large (and therefore expose us to the possible
2623 overflow) without actually calculating function value at the x+stp*d.
2624 
2625  -- ALGLIB --
2626  Copyright 02.04.2010 by Bochkanov Sergey
2627 *************************************************************************/
2628 void minlbfgssetstpmax(const minlbfgsstate &state, const double stpmax)
2629 {
2630  alglib_impl::ae_state _alglib_env_state;
2631  alglib_impl::ae_state_init(&_alglib_env_state);
2632  try
2633  {
2634  alglib_impl::minlbfgssetstpmax(const_cast<alglib_impl::minlbfgsstate*>(state.c_ptr()), stpmax, &_alglib_env_state);
2635  alglib_impl::ae_state_clear(&_alglib_env_state);
2636  return;
2637  }
2639  {
2640  throw ap_error(_alglib_env_state.error_msg);
2641  }
2642 }
2643 
2644 /*************************************************************************
2645 This function sets scaling coefficients for LBFGS optimizer.
2646 
2647 ALGLIB optimizers use scaling matrices to test stopping conditions (step
2648 size and gradient are scaled before comparison with tolerances). Scale of
2649 the I-th variable is a translation invariant measure of:
2650 a) "how large" the variable is
2651 b) how large the step should be to make significant changes in the function
2652 
2653 Scaling is also used by finite difference variant of the optimizer - step
2654 along I-th axis is equal to DiffStep*S[I].
2655 
2656 In most optimizers (and in the LBFGS too) scaling is NOT a form of
2657 preconditioning. It just affects stopping conditions. You should set
2658 preconditioner by separate call to one of the MinLBFGSSetPrec...()
2659 functions.
2660 
2661 There is special preconditioning mode, however, which uses scaling
2662 coefficients to form diagonal preconditioning matrix. You can turn this
2663 mode on, if you want. But you should understand that scaling is not the
2664 same thing as preconditioning - these are two different, although related
2665 forms of tuning solver.
2666 
2667 INPUT PARAMETERS:
2668  State - structure stores algorithm state
2669  S - array[N], non-zero scaling coefficients
2670  S[i] may be negative, sign doesn't matter.
2671 
2672  -- ALGLIB --
2673  Copyright 14.01.2011 by Bochkanov Sergey
2674 *************************************************************************/
2675 void minlbfgssetscale(const minlbfgsstate &state, const real_1d_array &s)
2676 {
2677  alglib_impl::ae_state _alglib_env_state;
2678  alglib_impl::ae_state_init(&_alglib_env_state);
2679  try
2680  {
2681  alglib_impl::minlbfgssetscale(const_cast<alglib_impl::minlbfgsstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(s.c_ptr()), &_alglib_env_state);
2682  alglib_impl::ae_state_clear(&_alglib_env_state);
2683  return;
2684  }
2686  {
2687  throw ap_error(_alglib_env_state.error_msg);
2688  }
2689 }
2690 
2691 /*************************************************************************
2692 Modification of the preconditioner: default preconditioner (simple
2693 scaling, same for all elements of X) is used.
2694 
2695 INPUT PARAMETERS:
2696  State - structure which stores algorithm state
2697 
2698 NOTE: you can change preconditioner "on the fly", during algorithm
2699 iterations.
2700 
2701  -- ALGLIB --
2702  Copyright 13.10.2010 by Bochkanov Sergey
2703 *************************************************************************/
2705 {
2706  alglib_impl::ae_state _alglib_env_state;
2707  alglib_impl::ae_state_init(&_alglib_env_state);
2708  try
2709  {
2710  alglib_impl::minlbfgssetprecdefault(const_cast<alglib_impl::minlbfgsstate*>(state.c_ptr()), &_alglib_env_state);
2711  alglib_impl::ae_state_clear(&_alglib_env_state);
2712  return;
2713  }
2715  {
2716  throw ap_error(_alglib_env_state.error_msg);
2717  }
2718 }
2719 
2720 /*************************************************************************
2721 Modification of the preconditioner: Cholesky factorization of approximate
2722 Hessian is used.
2723 
2724 INPUT PARAMETERS:
2725  State - structure which stores algorithm state
2726  P - triangular preconditioner, Cholesky factorization of
2727  the approximate Hessian. array[0..N-1,0..N-1],
2728  (if larger, only leading N elements are used).
2729  IsUpper - whether upper or lower triangle of P is given
2730  (other triangle is not referenced)
2731 
2732 After call to this function preconditioner is changed to P (P is copied
2733 into the internal buffer).
2734 
2735 NOTE: you can change preconditioner "on the fly", during algorithm
2736 iterations.
2737 
2738 NOTE 2: P should be nonsingular. Exception will be thrown otherwise.
2739 
2740  -- ALGLIB --
2741  Copyright 13.10.2010 by Bochkanov Sergey
2742 *************************************************************************/
2743 void minlbfgssetpreccholesky(const minlbfgsstate &state, const real_2d_array &p, const bool isupper)
2744 {
2745  alglib_impl::ae_state _alglib_env_state;
2746  alglib_impl::ae_state_init(&_alglib_env_state);
2747  try
2748  {
2749  alglib_impl::minlbfgssetpreccholesky(const_cast<alglib_impl::minlbfgsstate*>(state.c_ptr()), const_cast<alglib_impl::ae_matrix*>(p.c_ptr()), isupper, &_alglib_env_state);
2750  alglib_impl::ae_state_clear(&_alglib_env_state);
2751  return;
2752  }
2754  {
2755  throw ap_error(_alglib_env_state.error_msg);
2756  }
2757 }
2758 
2759 /*************************************************************************
2760 Modification of the preconditioner: diagonal of approximate Hessian is
2761 used.
2762 
2763 INPUT PARAMETERS:
2764  State - structure which stores algorithm state
2765  D - diagonal of the approximate Hessian, array[0..N-1],
2766  (if larger, only leading N elements are used).
2767 
2768 NOTE: you can change preconditioner "on the fly", during algorithm
2769 iterations.
2770 
2771 NOTE 2: D[i] should be positive. Exception will be thrown otherwise.
2772 
2773 NOTE 3: you should pass diagonal of approximate Hessian - NOT ITS INVERSE.
2774 
2775  -- ALGLIB --
2776  Copyright 13.10.2010 by Bochkanov Sergey
2777 *************************************************************************/
2779 {
2780  alglib_impl::ae_state _alglib_env_state;
2781  alglib_impl::ae_state_init(&_alglib_env_state);
2782  try
2783  {
2784  alglib_impl::minlbfgssetprecdiag(const_cast<alglib_impl::minlbfgsstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(d.c_ptr()), &_alglib_env_state);
2785  alglib_impl::ae_state_clear(&_alglib_env_state);
2786  return;
2787  }
2789  {
2790  throw ap_error(_alglib_env_state.error_msg);
2791  }
2792 }
2793 
2794 /*************************************************************************
2795 Modification of the preconditioner: scale-based diagonal preconditioning.
2796 
2797 This preconditioning mode can be useful when you don't have approximate
2798 diagonal of Hessian, but you know that your variables are badly scaled
2799 (for example, one variable is in [1,10], and another in [1000,100000]),
2800 and most part of the ill-conditioning comes from different scales of vars.
2801 
2802 In this case simple scale-based preconditioner, with H[i] = 1/(s[i]^2),
2803 can greatly improve convergence.
2804 
2805 IMPRTANT: you should set scale of your variables with MinLBFGSSetScale()
2806 call (before or after MinLBFGSSetPrecScale() call). Without knowledge of
2807 the scale of your variables scale-based preconditioner will be just unit
2808 matrix.
2809 
2810 INPUT PARAMETERS:
2811  State - structure which stores algorithm state
2812 
2813  -- ALGLIB --
2814  Copyright 13.10.2010 by Bochkanov Sergey
2815 *************************************************************************/
2817 {
2818  alglib_impl::ae_state _alglib_env_state;
2819  alglib_impl::ae_state_init(&_alglib_env_state);
2820  try
2821  {
2822  alglib_impl::minlbfgssetprecscale(const_cast<alglib_impl::minlbfgsstate*>(state.c_ptr()), &_alglib_env_state);
2823  alglib_impl::ae_state_clear(&_alglib_env_state);
2824  return;
2825  }
2827  {
2828  throw ap_error(_alglib_env_state.error_msg);
2829  }
2830 }
2831 
2832 /*************************************************************************
2833 This function provides reverse communication interface
2834 Reverse communication interface is not documented or recommended to use.
2835 See below for functions which provide better documented API
2836 *************************************************************************/
2838 {
2839  alglib_impl::ae_state _alglib_env_state;
2840  alglib_impl::ae_state_init(&_alglib_env_state);
2841  try
2842  {
2843  ae_bool result = alglib_impl::minlbfgsiteration(const_cast<alglib_impl::minlbfgsstate*>(state.c_ptr()), &_alglib_env_state);
2844  alglib_impl::ae_state_clear(&_alglib_env_state);
2845  return *(reinterpret_cast<bool*>(&result));
2846  }
2848  {
2849  throw ap_error(_alglib_env_state.error_msg);
2850  }
2851 }
2852 
2853 
2855  void (*func)(const real_1d_array &x, double &func, void *ptr),
2856  void (*rep)(const real_1d_array &x, double func, void *ptr),
2857  void *ptr)
2858 {
2859  alglib_impl::ae_state _alglib_env_state;
2860  if( func==NULL )
2861  throw ap_error("ALGLIB: error in 'minlbfgsoptimize()' (func is NULL)");
2862  alglib_impl::ae_state_init(&_alglib_env_state);
2863  try
2864  {
2865  while( alglib_impl::minlbfgsiteration(state.c_ptr(), &_alglib_env_state) )
2866  {
2867  if( state.needf )
2868  {
2869  func(state.x, state.f, ptr);
2870  continue;
2871  }
2872  if( state.xupdated )
2873  {
2874  if( rep!=NULL )
2875  rep(state.x, state.f, ptr);
2876  continue;
2877  }
2878  throw ap_error("ALGLIB: error in 'minlbfgsoptimize' (some derivatives were not provided?)");
2879  }
2880  alglib_impl::ae_state_clear(&_alglib_env_state);
2881  }
2883  {
2884  throw ap_error(_alglib_env_state.error_msg);
2885  }
2886 }
2887 
2888 
2890  void (*grad)(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr),
2891  void (*rep)(const real_1d_array &x, double func, void *ptr),
2892  void *ptr)
2893 {
2894  alglib_impl::ae_state _alglib_env_state;
2895  if( grad==NULL )
2896  throw ap_error("ALGLIB: error in 'minlbfgsoptimize()' (grad is NULL)");
2897  alglib_impl::ae_state_init(&_alglib_env_state);
2898  try
2899  {
2900  while( alglib_impl::minlbfgsiteration(state.c_ptr(), &_alglib_env_state) )
2901  {
2902  if( state.needfg )
2903  {
2904  grad(state.x, state.f, state.g, ptr);
2905  continue;
2906  }
2907  if( state.xupdated )
2908  {
2909  if( rep!=NULL )
2910  rep(state.x, state.f, ptr);
2911  continue;
2912  }
2913  throw ap_error("ALGLIB: error in 'minlbfgsoptimize' (some derivatives were not provided?)");
2914  }
2915  alglib_impl::ae_state_clear(&_alglib_env_state);
2916  }
2918  {
2919  throw ap_error(_alglib_env_state.error_msg);
2920  }
2921 }
2922 
2923 
2924 
2925 /*************************************************************************
2926 L-BFGS algorithm results
2927 
2928 INPUT PARAMETERS:
2929  State - algorithm state
2930 
2931 OUTPUT PARAMETERS:
2932  X - array[0..N-1], solution
2933  Rep - optimization report:
2934  * Rep.TerminationType completion code:
2935  * -7 gradient verification failed.
2936  See MinLBFGSSetGradientCheck() for more information.
2937  * -2 rounding errors prevent further improvement.
2938  X contains best point found.
2939  * -1 incorrect parameters were specified
2940  * 1 relative function improvement is no more than
2941  EpsF.
2942  * 2 relative step is no more than EpsX.
2943  * 4 gradient norm is no more than EpsG
2944  * 5 MaxIts steps was taken
2945  * 7 stopping conditions are too stringent,
2946  further improvement is impossible
2947  * Rep.IterationsCount contains iterations count
2948  * NFEV contains number of function calculations
2949 
2950  -- ALGLIB --
2951  Copyright 02.04.2010 by Bochkanov Sergey
2952 *************************************************************************/
2954 {
2955  alglib_impl::ae_state _alglib_env_state;
2956  alglib_impl::ae_state_init(&_alglib_env_state);
2957  try
2958  {
2959  alglib_impl::minlbfgsresults(const_cast<alglib_impl::minlbfgsstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minlbfgsreport*>(rep.c_ptr()), &_alglib_env_state);
2960  alglib_impl::ae_state_clear(&_alglib_env_state);
2961  return;
2962  }
2964  {
2965  throw ap_error(_alglib_env_state.error_msg);
2966  }
2967 }
2968 
2969 /*************************************************************************
2970 L-BFGS algorithm results
2971 
2972 Buffered implementation of MinLBFGSResults which uses pre-allocated buffer
2973 to store X[]. If buffer size is too small, it resizes buffer. It is
2974 intended to be used in the inner cycles of performance critical algorithms
2975 where array reallocation penalty is too large to be ignored.
2976 
2977  -- ALGLIB --
2978  Copyright 20.08.2010 by Bochkanov Sergey
2979 *************************************************************************/
2981 {
2982  alglib_impl::ae_state _alglib_env_state;
2983  alglib_impl::ae_state_init(&_alglib_env_state);
2984  try
2985  {
2986  alglib_impl::minlbfgsresultsbuf(const_cast<alglib_impl::minlbfgsstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minlbfgsreport*>(rep.c_ptr()), &_alglib_env_state);
2987  alglib_impl::ae_state_clear(&_alglib_env_state);
2988  return;
2989  }
2991  {
2992  throw ap_error(_alglib_env_state.error_msg);
2993  }
2994 }
2995 
2996 /*************************************************************************
2997 This subroutine restarts LBFGS algorithm from new point. All optimization
2998 parameters are left unchanged.
2999 
3000 This function allows to solve multiple optimization problems (which
3001 must have same number of dimensions) without object reallocation penalty.
3002 
3003 INPUT PARAMETERS:
3004  State - structure used to store algorithm state
3005  X - new starting point.
3006 
3007  -- ALGLIB --
3008  Copyright 30.07.2010 by Bochkanov Sergey
3009 *************************************************************************/
3011 {
3012  alglib_impl::ae_state _alglib_env_state;
3013  alglib_impl::ae_state_init(&_alglib_env_state);
3014  try
3015  {
3016  alglib_impl::minlbfgsrestartfrom(const_cast<alglib_impl::minlbfgsstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), &_alglib_env_state);
3017  alglib_impl::ae_state_clear(&_alglib_env_state);
3018  return;
3019  }
3021  {
3022  throw ap_error(_alglib_env_state.error_msg);
3023  }
3024 }
3025 
3026 /*************************************************************************
3027 This subroutine turns on verification of the user-supplied analytic
3028 gradient:
3029 * user calls this subroutine before optimization begins
3030 * MinLBFGSOptimize() is called
3031 * prior to actual optimization, for each component of parameters being
3032  optimized X[i] algorithm performs following steps:
3033  * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i],
3034  where X[i] is i-th component of the initial point and S[i] is a scale
3035  of i-th parameter
3036  * if needed, steps are bounded with respect to constraints on X[]
3037  * F(X) is evaluated at these trial points
3038  * we perform one more evaluation in the middle point of the interval
3039  * we build cubic model using function values and derivatives at trial
3040  points and we compare its prediction with actual value in the middle
3041  point
3042  * in case difference between prediction and actual value is higher than
3043  some predetermined threshold, algorithm stops with completion code -7;
3044  Rep.VarIdx is set to index of the parameter with incorrect derivative.
3045 * after verification is over, algorithm proceeds to the actual optimization.
3046 
3047 NOTE 1: verification needs N (parameters count) gradient evaluations. It
3048  is very costly and you should use it only for low dimensional
3049  problems, when you want to be sure that you've correctly
3050  calculated analytic derivatives. You should not use it in the
3051  production code (unless you want to check derivatives provided by
3052  some third party).
3053 
3054 NOTE 2: you should carefully choose TestStep. Value which is too large
3055  (so large that function behaviour is significantly non-cubic) will
3056  lead to false alarms. You may use different step for different
3057  parameters by means of setting scale with MinLBFGSSetScale().
3058 
3059 NOTE 3: this function may lead to false positives. In case it reports that
3060  I-th derivative was calculated incorrectly, you may decrease test
3061  step and try one more time - maybe your function changes too
3062  sharply and your step is too large for such rapidly chanding
3063  function.
3064 
3065 INPUT PARAMETERS:
3066  State - structure used to store algorithm state
3067  TestStep - verification step:
3068  * TestStep=0 turns verification off
3069  * TestStep>0 activates verification
3070 
3071  -- ALGLIB --
3072  Copyright 24.05.2012 by Bochkanov Sergey
3073 *************************************************************************/
3074 void minlbfgssetgradientcheck(const minlbfgsstate &state, const double teststep)
3075 {
3076  alglib_impl::ae_state _alglib_env_state;
3077  alglib_impl::ae_state_init(&_alglib_env_state);
3078  try
3079  {
3080  alglib_impl::minlbfgssetgradientcheck(const_cast<alglib_impl::minlbfgsstate*>(state.c_ptr()), teststep, &_alglib_env_state);
3081  alglib_impl::ae_state_clear(&_alglib_env_state);
3082  return;
3083  }
3085  {
3086  throw ap_error(_alglib_env_state.error_msg);
3087  }
3088 }
3089 
3090 /*************************************************************************
3091 This object stores nonlinear optimizer state.
3092 You should use functions provided by MinQP subpackage to work with this
3093 object
3094 *************************************************************************/
3096 {
3098  if( p_struct==NULL )
3099  throw ap_error("ALGLIB: malloc error");
3101  throw ap_error("ALGLIB: malloc error");
3102 }
3103 
3105 {
3107  if( p_struct==NULL )
3108  throw ap_error("ALGLIB: malloc error");
3109  if( !alglib_impl::_minqpstate_init_copy(p_struct, const_cast<alglib_impl::minqpstate*>(rhs.p_struct), NULL, ae_false) )
3110  throw ap_error("ALGLIB: malloc error");
3111 }
3112 
3114 {
3115  if( this==&rhs )
3116  return *this;
3118  if( !alglib_impl::_minqpstate_init_copy(p_struct, const_cast<alglib_impl::minqpstate*>(rhs.p_struct), NULL, ae_false) )
3119  throw ap_error("ALGLIB: malloc error");
3120  return *this;
3121 }
3122 
3124 {
3126  ae_free(p_struct);
3127 }
3128 
3130 {
3131  return p_struct;
3132 }
3133 
3135 {
3136  return const_cast<alglib_impl::minqpstate*>(p_struct);
3137 }
3139 {
3140 }
3141 
3143 {
3144 }
3145 
3147 {
3148  if( this==&rhs )
3149  return *this;
3151  return *this;
3152 }
3153 
3155 {
3156 }
3157 
3158 
3159 /*************************************************************************
3160 This structure stores optimization report:
3161 * InnerIterationsCount number of inner iterations
3162 * OuterIterationsCount number of outer iterations
3163 * NCholesky number of Cholesky decomposition
3164 * NMV number of matrix-vector products
3165  (only products calculated as part of iterative
3166  process are counted)
3167 * TerminationType completion code (see below)
3168 
3169 Completion codes:
3170 * -5 inappropriate solver was used:
3171  * Cholesky solver for semidefinite or indefinite problems
3172  * Cholesky solver for problems with non-boundary constraints
3173 * -4 BLEIC-QP algorithm found unconstrained direction
3174  of negative curvature (function is unbounded from
3175  below even under constraints), no meaningful
3176  minimum can be found.
3177 * -3 inconsistent constraints (or, maybe, feasible point is
3178  too hard to find). If you are sure that constraints are feasible,
3179  try to restart optimizer with better initial approximation.
3180 * -1 solver error
3181 * 4 successful completion
3182 * 5 MaxIts steps was taken
3183 * 7 stopping conditions are too stringent,
3184  further improvement is impossible,
3185  X contains best point found so far.
3186 *************************************************************************/
3188 {
3190  if( p_struct==NULL )
3191  throw ap_error("ALGLIB: malloc error");
3193  throw ap_error("ALGLIB: malloc error");
3194 }
3195 
3197 {
3199  if( p_struct==NULL )
3200  throw ap_error("ALGLIB: malloc error");
3201  if( !alglib_impl::_minqpreport_init_copy(p_struct, const_cast<alglib_impl::minqpreport*>(rhs.p_struct), NULL, ae_false) )
3202  throw ap_error("ALGLIB: malloc error");
3203 }
3204 
3206 {
3207  if( this==&rhs )
3208  return *this;
3210  if( !alglib_impl::_minqpreport_init_copy(p_struct, const_cast<alglib_impl::minqpreport*>(rhs.p_struct), NULL, ae_false) )
3211  throw ap_error("ALGLIB: malloc error");
3212  return *this;
3213 }
3214 
3216 {
3218  ae_free(p_struct);
3219 }
3220 
3222 {
3223  return p_struct;
3224 }
3225 
3227 {
3228  return const_cast<alglib_impl::minqpreport*>(p_struct);
3229 }
3230 minqpreport::minqpreport() : _minqpreport_owner() ,inneriterationscount(p_struct->inneriterationscount),outeriterationscount(p_struct->outeriterationscount),nmv(p_struct->nmv),ncholesky(p_struct->ncholesky),terminationtype(p_struct->terminationtype)
3231 {
3232 }
3233 
3235 {
3236 }
3237 
3239 {
3240  if( this==&rhs )
3241  return *this;
3243  return *this;
3244 }
3245 
3247 {
3248 }
3249 
3250 /*************************************************************************
3251  CONSTRAINED QUADRATIC PROGRAMMING
3252 
3253 The subroutine creates QP optimizer. After initial creation, it contains
3254 default optimization problem with zero quadratic and linear terms and no
3255 constraints. You should set quadratic/linear terms with calls to functions
3256 provided by MinQP subpackage.
3257 
3258 INPUT PARAMETERS:
3259  N - problem size
3260 
3261 OUTPUT PARAMETERS:
3262  State - optimizer with zero quadratic/linear terms
3263  and no constraints
3264 
3265  -- ALGLIB --
3266  Copyright 11.01.2011 by Bochkanov Sergey
3267 *************************************************************************/
3268 void minqpcreate(const ae_int_t n, minqpstate &state)
3269 {
3270  alglib_impl::ae_state _alglib_env_state;
3271  alglib_impl::ae_state_init(&_alglib_env_state);
3272  try
3273  {
3274  alglib_impl::minqpcreate(n, const_cast<alglib_impl::minqpstate*>(state.c_ptr()), &_alglib_env_state);
3275  alglib_impl::ae_state_clear(&_alglib_env_state);
3276  return;
3277  }
3279  {
3280  throw ap_error(_alglib_env_state.error_msg);
3281  }
3282 }
3283 
3284 /*************************************************************************
3285 This function sets linear term for QP solver.
3286 
3287 By default, linear term is zero.
3288 
3289 INPUT PARAMETERS:
3290  State - structure which stores algorithm state
3291  B - linear term, array[N].
3292 
3293  -- ALGLIB --
3294  Copyright 11.01.2011 by Bochkanov Sergey
3295 *************************************************************************/
3296 void minqpsetlinearterm(const minqpstate &state, const real_1d_array &b)
3297 {
3298  alglib_impl::ae_state _alglib_env_state;
3299  alglib_impl::ae_state_init(&_alglib_env_state);
3300  try
3301  {
3302  alglib_impl::minqpsetlinearterm(const_cast<alglib_impl::minqpstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(b.c_ptr()), &_alglib_env_state);
3303  alglib_impl::ae_state_clear(&_alglib_env_state);
3304  return;
3305  }
3307  {
3308  throw ap_error(_alglib_env_state.error_msg);
3309  }
3310 }
3311 
3312 /*************************************************************************
3313 This function sets dense quadratic term for QP solver. By default,
3314 quadratic term is zero.
3315 
3316 SUPPORT BY ALGLIB QP ALGORITHMS:
3317 
3318 Dense quadratic term can be handled by any of the QP algorithms supported
3319 by ALGLIB QP Solver.
3320 
3321 IMPORTANT:
3322 
3323 This solver minimizes following function:
3324  f(x) = 0.5*x'*A*x + b'*x.
3325 Note that quadratic term has 0.5 before it. So if you want to minimize
3326  f(x) = x^2 + x
3327 you should rewrite your problem as follows:
3328  f(x) = 0.5*(2*x^2) + x
3329 and your matrix A will be equal to [[2.0]], not to [[1.0]]
3330 
3331 INPUT PARAMETERS:
3332  State - structure which stores algorithm state
3333  A - matrix, array[N,N]
3334  IsUpper - (optional) storage type:
3335  * if True, symmetric matrix A is given by its upper
3336  triangle, and the lower triangle isn’t used
3337  * if False, symmetric matrix A is given by its lower
3338  triangle, and the upper triangle isn’t used
3339  * if not given, both lower and upper triangles must be
3340  filled.
3341 
3342  -- ALGLIB --
3343  Copyright 11.01.2011 by Bochkanov Sergey
3344 *************************************************************************/
3345 void minqpsetquadraticterm(const minqpstate &state, const real_2d_array &a, const bool isupper)
3346 {
3347  alglib_impl::ae_state _alglib_env_state;
3348  alglib_impl::ae_state_init(&_alglib_env_state);
3349  try
3350  {
3351  alglib_impl::minqpsetquadraticterm(const_cast<alglib_impl::minqpstate*>(state.c_ptr()), const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), isupper, &_alglib_env_state);
3352  alglib_impl::ae_state_clear(&_alglib_env_state);
3353  return;
3354  }
3356  {
3357  throw ap_error(_alglib_env_state.error_msg);
3358  }
3359 }
3360 
3361 /*************************************************************************
3362 This function sets dense quadratic term for QP solver. By default,
3363 quadratic term is zero.
3364 
3365 SUPPORT BY ALGLIB QP ALGORITHMS:
3366 
3367 Dense quadratic term can be handled by any of the QP algorithms supported
3368 by ALGLIB QP Solver.
3369 
3370 IMPORTANT:
3371 
3372 This solver minimizes following function:
3373  f(x) = 0.5*x'*A*x + b'*x.
3374 Note that quadratic term has 0.5 before it. So if you want to minimize
3375  f(x) = x^2 + x
3376 you should rewrite your problem as follows:
3377  f(x) = 0.5*(2*x^2) + x
3378 and your matrix A will be equal to [[2.0]], not to [[1.0]]
3379 
3380 INPUT PARAMETERS:
3381  State - structure which stores algorithm state
3382  A - matrix, array[N,N]
3383  IsUpper - (optional) storage type:
3384  * if True, symmetric matrix A is given by its upper
3385  triangle, and the lower triangle isn’t used
3386  * if False, symmetric matrix A is given by its lower
3387  triangle, and the upper triangle isn’t used
3388  * if not given, both lower and upper triangles must be
3389  filled.
3390 
3391  -- ALGLIB --
3392  Copyright 11.01.2011 by Bochkanov Sergey
3393 *************************************************************************/
3395 {
3396  alglib_impl::ae_state _alglib_env_state;
3397  bool isupper;
3398  if( !alglib_impl::ae_is_symmetric(const_cast<alglib_impl::ae_matrix*>(a.c_ptr())) )
3399  throw ap_error("'a' parameter is not symmetric matrix");
3400  isupper = false;
3401  alglib_impl::ae_state_init(&_alglib_env_state);
3402  try
3403  {
3404  alglib_impl::minqpsetquadraticterm(const_cast<alglib_impl::minqpstate*>(state.c_ptr()), const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), isupper, &_alglib_env_state);
3405 
3406  alglib_impl::ae_state_clear(&_alglib_env_state);
3407  return;
3408  }
3410  {
3411  throw ap_error(_alglib_env_state.error_msg);
3412  }
3413 }
3414 
3415 /*************************************************************************
3416 This function sets sparse quadratic term for QP solver. By default,
3417 quadratic term is zero.
3418 
3419 SUPPORT BY ALGLIB QP ALGORITHMS:
3420 
3421 Sparse quadratic term is supported only by BLEIC-based QP algorithm (one
3422 which is activated by MinQPSetAlgoBLEIC function). Cholesky-based QP algo
3423 won't be able to deal with sparse quadratic term and will terminate
3424 abnormally.
3425 
3426 IF YOU CALLED THIS FUNCTION, YOU MUST SWITCH TO BLEIC-BASED QP ALGORITHM
3427 BEFORE CALLING MINQPOPTIMIZE() FUNCTION.
3428 
3429 IMPORTANT:
3430 
3431 This solver minimizes following function:
3432  f(x) = 0.5*x'*A*x + b'*x.
3433 Note that quadratic term has 0.5 before it. So if you want to minimize
3434  f(x) = x^2 + x
3435 you should rewrite your problem as follows:
3436  f(x) = 0.5*(2*x^2) + x
3437 and your matrix A will be equal to [[2.0]], not to [[1.0]]
3438 
3439 INPUT PARAMETERS:
3440  State - structure which stores algorithm state
3441  A - matrix, array[N,N]
3442  IsUpper - (optional) storage type:
3443  * if True, symmetric matrix A is given by its upper
3444  triangle, and the lower triangle isn’t used
3445  * if False, symmetric matrix A is given by its lower
3446  triangle, and the upper triangle isn’t used
3447  * if not given, both lower and upper triangles must be
3448  filled.
3449 
3450  -- ALGLIB --
3451  Copyright 11.01.2011 by Bochkanov Sergey
3452 *************************************************************************/
3453 void minqpsetquadratictermsparse(const minqpstate &state, const sparsematrix &a, const bool isupper)
3454 {
3455  alglib_impl::ae_state _alglib_env_state;
3456  alglib_impl::ae_state_init(&_alglib_env_state);
3457  try
3458  {
3459  alglib_impl::minqpsetquadratictermsparse(const_cast<alglib_impl::minqpstate*>(state.c_ptr()), const_cast<alglib_impl::sparsematrix*>(a.c_ptr()), isupper, &_alglib_env_state);
3460  alglib_impl::ae_state_clear(&_alglib_env_state);
3461  return;
3462  }
3464  {
3465  throw ap_error(_alglib_env_state.error_msg);
3466  }
3467 }
3468 
3469 /*************************************************************************
3470 This function sets starting point for QP solver. It is useful to have
3471 good initial approximation to the solution, because it will increase
3472 speed of convergence and identification of active constraints.
3473 
3474 INPUT PARAMETERS:
3475  State - structure which stores algorithm state
3476  X - starting point, array[N].
3477 
3478  -- ALGLIB --
3479  Copyright 11.01.2011 by Bochkanov Sergey
3480 *************************************************************************/
3481 void minqpsetstartingpoint(const minqpstate &state, const real_1d_array &x)
3482 {
3483  alglib_impl::ae_state _alglib_env_state;
3484  alglib_impl::ae_state_init(&_alglib_env_state);
3485  try
3486  {
3487  alglib_impl::minqpsetstartingpoint(const_cast<alglib_impl::minqpstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), &_alglib_env_state);
3488  alglib_impl::ae_state_clear(&_alglib_env_state);
3489  return;
3490  }
3492  {
3493  throw ap_error(_alglib_env_state.error_msg);
3494  }
3495 }
3496 
3497 /*************************************************************************
3498 This function sets origin for QP solver. By default, following QP program
3499 is solved:
3500 
3501  min(0.5*x'*A*x+b'*x)
3502 
3503 This function allows to solve different problem:
3504 
3505  min(0.5*(x-x_origin)'*A*(x-x_origin)+b'*(x-x_origin))
3506 
3507 INPUT PARAMETERS:
3508  State - structure which stores algorithm state
3509  XOrigin - origin, array[N].
3510 
3511  -- ALGLIB --
3512  Copyright 11.01.2011 by Bochkanov Sergey
3513 *************************************************************************/
3514 void minqpsetorigin(const minqpstate &state, const real_1d_array &xorigin)
3515 {
3516  alglib_impl::ae_state _alglib_env_state;
3517  alglib_impl::ae_state_init(&_alglib_env_state);
3518  try
3519  {
3520  alglib_impl::minqpsetorigin(const_cast<alglib_impl::minqpstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(xorigin.c_ptr()), &_alglib_env_state);
3521  alglib_impl::ae_state_clear(&_alglib_env_state);
3522  return;
3523  }
3525  {
3526  throw ap_error(_alglib_env_state.error_msg);
3527  }
3528 }
3529 
3530 /*************************************************************************
3531 This function sets scaling coefficients.
3532 
3533 ALGLIB optimizers use scaling matrices to test stopping conditions (step
3534 size and gradient are scaled before comparison with tolerances). Scale of
3535 the I-th variable is a translation invariant measure of:
3536 a) "how large" the variable is
3537 b) how large the step should be to make significant changes in the function
3538 
3539 BLEIC-based QP solver uses scale for two purposes:
3540 * to evaluate stopping conditions
3541 * for preconditioning of the underlying BLEIC solver
3542 
3543 INPUT PARAMETERS:
3544  State - structure stores algorithm state
3545  S - array[N], non-zero scaling coefficients
3546  S[i] may be negative, sign doesn't matter.
3547 
3548  -- ALGLIB --
3549  Copyright 14.01.2011 by Bochkanov Sergey
3550 *************************************************************************/
3551 void minqpsetscale(const minqpstate &state, const real_1d_array &s)
3552 {
3553  alglib_impl::ae_state _alglib_env_state;
3554  alglib_impl::ae_state_init(&_alglib_env_state);
3555  try
3556  {
3557  alglib_impl::minqpsetscale(const_cast<alglib_impl::minqpstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(s.c_ptr()), &_alglib_env_state);
3558  alglib_impl::ae_state_clear(&_alglib_env_state);
3559  return;
3560  }
3562  {
3563  throw ap_error(_alglib_env_state.error_msg);
3564  }
3565 }
3566 
3567 /*************************************************************************
3568 This function tells solver to use Cholesky-based algorithm. This algorithm
3569 is active by default.
3570 
3571 DESCRIPTION:
3572 
3573 Cholesky-based algorithm can be used only for problems which:
3574 * have dense quadratic term, set by MinQPSetQuadraticTerm(), sparse or
3575  structured problems are not supported.
3576 * are strictly convex, i.e. quadratic term is symmetric positive definite,
3577  indefinite or semidefinite problems are not supported by this algorithm.
3578 
3579 If anything of what listed above is violated, you may use BLEIC-based QP
3580 algorithm which can be activated by MinQPSetAlgoBLEIC().
3581 
3582 BENEFITS AND DRAWBACKS:
3583 
3584 This algorithm gives best precision amongst all QP solvers provided by
3585 ALGLIB (Newton iterations have much higher precision than any other
3586 optimization algorithm). This solver also gracefully handles problems with
3587 very large amount of constraints.
3588 
3589 Performance of the algorithm is good because internally it uses Level 3
3590 Dense BLAS for its performance-critical parts.
3591 
3592 
3593 From the other side, algorithm has O(N^3) complexity for unconstrained
3594 problems and up to orders of magnitude slower on constrained problems
3595 (these additional iterations are needed to identify active constraints).
3596 So, its running time depends on number of constraints active at solution.
3597 
3598 Furthermore, this algorithm can not solve problems with sparse matrices or
3599 problems with semidefinite/indefinite matrices of any kind (dense/sparse).
3600 
3601 INPUT PARAMETERS:
3602  State - structure which stores algorithm state
3603 
3604  -- ALGLIB --
3605  Copyright 11.01.2011 by Bochkanov Sergey
3606 *************************************************************************/
3608 {
3609  alglib_impl::ae_state _alglib_env_state;
3610  alglib_impl::ae_state_init(&_alglib_env_state);
3611  try
3612  {
3613  alglib_impl::minqpsetalgocholesky(const_cast<alglib_impl::minqpstate*>(state.c_ptr()), &_alglib_env_state);
3614  alglib_impl::ae_state_clear(&_alglib_env_state);
3615  return;
3616  }
3618  {
3619  throw ap_error(_alglib_env_state.error_msg);
3620  }
3621 }
3622 
3623 /*************************************************************************
3624 This function tells solver to use BLEIC-based algorithm and sets stopping
3625 criteria for the algorithm.
3626 
3627 DESCRIPTION:
3628 
3629 BLEIC-based QP algorithm can be used for any kind of QP problems:
3630 * problems with both dense and sparse quadratic terms
3631 * problems with positive definite, semidefinite, indefinite terms
3632 
3633 BLEIC-based algorithm can solve even indefinite problems - as long as they
3634 are bounded from below on the feasible set. Of course, global minimum is
3635 found only for positive definite and semidefinite problems. As for
3636 indefinite ones - only local minimum is found.
3637 
3638 BENEFITS AND DRAWBACKS:
3639 
3640 This algorithm can be used to solve both convex and indefinite QP problems
3641 and it can utilize sparsity of the quadratic term (algorithm calculates
3642 matrix-vector products, which can be performed efficiently in case of
3643 sparse matrix).
3644 
3645 Algorithm has iteration cost, which (assuming fixed amount of non-boundary
3646 linear constraints) linearly depends on problem size. Boundary constraints
3647 does not significantly change iteration cost.
3648 
3649 Thus, it outperforms Cholesky-based QP algorithm (CQP) on high-dimensional
3650 sparse problems with moderate amount of constraints.
3651 
3652 
3653 From the other side, unlike CQP solver, this algorithm does NOT make use
3654 of Level 3 Dense BLAS. Thus, its performance on dense problems is inferior
3655 to that of CQP solver.
3656 
3657 Its precision is also inferior to that of CQP. CQP performs Newton steps
3658 which are know to achieve very good precision. In many cases Newton step
3659 leads us exactly to the solution. BLEIC-QP performs LBFGS steps, which are
3660 good at detecting neighborhood of the solution, buy need many iterations
3661 to find solution with 6 digits of precision.
3662 
3663 INPUT PARAMETERS:
3664  State - structure which stores algorithm state
3665  EpsG - >=0
3666  The subroutine finishes its work if the condition
3667  |v|<EpsG is satisfied, where:
3668  * |.| means Euclidian norm
3669  * v - scaled constrained gradient vector, v[i]=g[i]*s[i]
3670  * g - gradient
3671  * s - scaling coefficients set by MinQPSetScale()
3672  EpsF - >=0
3673  The subroutine finishes its work if exploratory steepest
3674  descent step on k+1-th iteration satisfies following
3675  condition: |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1}
3676  EpsX - >=0
3677  The subroutine finishes its work if exploratory steepest
3678  descent step on k+1-th iteration satisfies following
3679  condition:
3680  * |.| means Euclidian norm
3681  * v - scaled step vector, v[i]=dx[i]/s[i]
3682  * dx - step vector, dx=X(k+1)-X(k)
3683  * s - scaling coefficients set by MinQPSetScale()
3684  MaxIts - maximum number of iterations. If MaxIts=0, the number of
3685  iterations is unlimited.
3686 
3687 Passing EpsG=0, EpsF=0 and EpsX=0 and MaxIts=0 (simultaneously) will lead
3688 to automatic stopping criterion selection (presently it is small step
3689 length, but it may change in the future versions of ALGLIB).
3690 
3691 IT IS VERY IMPORTANT THAT YOU CALL MinQPSetScale() WHEN YOU USE THIS ALGO!
3692 
3693  -- ALGLIB --
3694  Copyright 11.01.2011 by Bochkanov Sergey
3695 *************************************************************************/
3696 void minqpsetalgobleic(const minqpstate &state, const double epsg, const double epsf, const double epsx, const ae_int_t maxits)
3697 {
3698  alglib_impl::ae_state _alglib_env_state;
3699  alglib_impl::ae_state_init(&_alglib_env_state);
3700  try
3701  {
3702  alglib_impl::minqpsetalgobleic(const_cast<alglib_impl::minqpstate*>(state.c_ptr()), epsg, epsf, epsx, maxits, &_alglib_env_state);
3703  alglib_impl::ae_state_clear(&_alglib_env_state);
3704  return;
3705  }
3707  {
3708  throw ap_error(_alglib_env_state.error_msg);
3709  }
3710 }
3711 
3712 /*************************************************************************
3713 This function sets boundary constraints for QP solver
3714 
3715 Boundary constraints are inactive by default (after initial creation).
3716 After being set, they are preserved until explicitly turned off with
3717 another SetBC() call.
3718 
3719 INPUT PARAMETERS:
3720  State - structure stores algorithm state
3721  BndL - lower bounds, array[N].
3722  If some (all) variables are unbounded, you may specify
3723  very small number or -INF (latter is recommended because
3724  it will allow solver to use better algorithm).
3725  BndU - upper bounds, array[N].
3726  If some (all) variables are unbounded, you may specify
3727  very large number or +INF (latter is recommended because
3728  it will allow solver to use better algorithm).
3729 
3730 NOTE: it is possible to specify BndL[i]=BndU[i]. In this case I-th
3731 variable will be "frozen" at X[i]=BndL[i]=BndU[i].
3732 
3733  -- ALGLIB --
3734  Copyright 11.01.2011 by Bochkanov Sergey
3735 *************************************************************************/
3736 void minqpsetbc(const minqpstate &state, const real_1d_array &bndl, const real_1d_array &bndu)
3737 {
3738  alglib_impl::ae_state _alglib_env_state;
3739  alglib_impl::ae_state_init(&_alglib_env_state);
3740  try
3741  {
3742  alglib_impl::minqpsetbc(const_cast<alglib_impl::minqpstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(bndl.c_ptr()), const_cast<alglib_impl::ae_vector*>(bndu.c_ptr()), &_alglib_env_state);
3743  alglib_impl::ae_state_clear(&_alglib_env_state);
3744  return;
3745  }
3747  {
3748  throw ap_error(_alglib_env_state.error_msg);
3749  }
3750 }
3751 
3752 /*************************************************************************
3753 This function sets linear constraints for QP optimizer.
3754 
3755 Linear constraints are inactive by default (after initial creation).
3756 
3757 INPUT PARAMETERS:
3758  State - structure previously allocated with MinQPCreate call.
3759  C - linear constraints, array[K,N+1].
3760  Each row of C represents one constraint, either equality
3761  or inequality (see below):
3762  * first N elements correspond to coefficients,
3763  * last element corresponds to the right part.
3764  All elements of C (including right part) must be finite.
3765  CT - type of constraints, array[K]:
3766  * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1]
3767  * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1]
3768  * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1]
3769  K - number of equality/inequality constraints, K>=0:
3770  * if given, only leading K elements of C/CT are used
3771  * if not given, automatically determined from sizes of C/CT
3772 
3773 NOTE 1: linear (non-bound) constraints are satisfied only approximately -
3774  there always exists some minor violation (about 10^-10...10^-13)
3775  due to numerical errors.
3776 
3777  -- ALGLIB --
3778  Copyright 19.06.2012 by Bochkanov Sergey
3779 *************************************************************************/
3780 void minqpsetlc(const minqpstate &state, const real_2d_array &c, const integer_1d_array &ct, const ae_int_t k)
3781 {
3782  alglib_impl::ae_state _alglib_env_state;
3783  alglib_impl::ae_state_init(&_alglib_env_state);
3784  try
3785  {
3786  alglib_impl::minqpsetlc(const_cast<alglib_impl::minqpstate*>(state.c_ptr()), const_cast<alglib_impl::ae_matrix*>(c.c_ptr()), const_cast<alglib_impl::ae_vector*>(ct.c_ptr()), k, &_alglib_env_state);
3787  alglib_impl::ae_state_clear(&_alglib_env_state);
3788  return;
3789  }
3791  {
3792  throw ap_error(_alglib_env_state.error_msg);
3793  }
3794 }
3795 
3796 /*************************************************************************
3797 This function sets linear constraints for QP optimizer.
3798 
3799 Linear constraints are inactive by default (after initial creation).
3800 
3801 INPUT PARAMETERS:
3802  State - structure previously allocated with MinQPCreate call.
3803  C - linear constraints, array[K,N+1].
3804  Each row of C represents one constraint, either equality
3805  or inequality (see below):
3806  * first N elements correspond to coefficients,
3807  * last element corresponds to the right part.
3808  All elements of C (including right part) must be finite.
3809  CT - type of constraints, array[K]:
3810  * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1]
3811  * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1]
3812  * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1]
3813  K - number of equality/inequality constraints, K>=0:
3814  * if given, only leading K elements of C/CT are used
3815  * if not given, automatically determined from sizes of C/CT
3816 
3817 NOTE 1: linear (non-bound) constraints are satisfied only approximately -
3818  there always exists some minor violation (about 10^-10...10^-13)
3819  due to numerical errors.
3820 
3821  -- ALGLIB --
3822  Copyright 19.06.2012 by Bochkanov Sergey
3823 *************************************************************************/
3824 void minqpsetlc(const minqpstate &state, const real_2d_array &c, const integer_1d_array &ct)
3825 {
3826  alglib_impl::ae_state _alglib_env_state;
3827  ae_int_t k;
3828  if( (c.rows()!=ct.length()))
3829  throw ap_error("Error while calling 'minqpsetlc': looks like one of arguments has wrong size");
3830  k = c.rows();
3831  alglib_impl::ae_state_init(&_alglib_env_state);
3832  try
3833  {
3834  alglib_impl::minqpsetlc(const_cast<alglib_impl::minqpstate*>(state.c_ptr()), const_cast<alglib_impl::ae_matrix*>(c.c_ptr()), const_cast<alglib_impl::ae_vector*>(ct.c_ptr()), k, &_alglib_env_state);
3835 
3836  alglib_impl::ae_state_clear(&_alglib_env_state);
3837  return;
3838  }
3840  {
3841  throw ap_error(_alglib_env_state.error_msg);
3842  }
3843 }
3844 
3845 /*************************************************************************
3846 This function solves quadratic programming problem.
3847 You should call it after setting solver options with MinQPSet...() calls.
3848 
3849 INPUT PARAMETERS:
3850  State - algorithm state
3851 
3852 You should use MinQPResults() function to access results after calls
3853 to this function.
3854 
3855  -- ALGLIB --
3856  Copyright 11.01.2011 by Bochkanov Sergey.
3857  Special thanks to Elvira Illarionova for important suggestions on
3858  the linearly constrained QP algorithm.
3859 *************************************************************************/
3860 void minqpoptimize(const minqpstate &state)
3861 {
3862  alglib_impl::ae_state _alglib_env_state;
3863  alglib_impl::ae_state_init(&_alglib_env_state);
3864  try
3865  {
3866  alglib_impl::minqpoptimize(const_cast<alglib_impl::minqpstate*>(state.c_ptr()), &_alglib_env_state);
3867  alglib_impl::ae_state_clear(&_alglib_env_state);
3868  return;
3869  }
3871  {
3872  throw ap_error(_alglib_env_state.error_msg);
3873  }
3874 }
3875 
3876 /*************************************************************************
3877 QP solver results
3878 
3879 INPUT PARAMETERS:
3880  State - algorithm state
3881 
3882 OUTPUT PARAMETERS:
3883  X - array[0..N-1], solution.
3884  This array is allocated and initialized only when
3885  Rep.TerminationType parameter is positive (success).
3886  Rep - optimization report. You should check Rep.TerminationType,
3887  which contains completion code, and you may check another
3888  fields which contain another information about algorithm
3889  functioning.
3890 
3891  Failure codes returned by algorithm are:
3892  * -5 inappropriate solver was used:
3893  * Cholesky solver for (semi)indefinite problems
3894  * Cholesky solver for problems with sparse matrix
3895  * -4 BLEIC-QP algorithm found unconstrained direction
3896  of negative curvature (function is unbounded from
3897  below even under constraints), no meaningful
3898  minimum can be found.
3899  * -3 inconsistent constraints (or maybe feasible point
3900  is too hard to find). If you are sure that
3901  constraints are feasible, try to restart optimizer
3902  with better initial approximation.
3903 
3904  Completion codes specific for Cholesky algorithm:
3905  * 4 successful completion
3906 
3907  Completion codes specific for BLEIC-based algorithm:
3908  * 1 relative function improvement is no more than EpsF.
3909  * 2 scaled step is no more than EpsX.
3910  * 4 scaled gradient norm is no more than EpsG.
3911  * 5 MaxIts steps was taken
3912 
3913  -- ALGLIB --
3914  Copyright 11.01.2011 by Bochkanov Sergey
3915 *************************************************************************/
3916 void minqpresults(const minqpstate &state, real_1d_array &x, minqpreport &rep)
3917 {
3918  alglib_impl::ae_state _alglib_env_state;
3919  alglib_impl::ae_state_init(&_alglib_env_state);
3920  try
3921  {
3922  alglib_impl::minqpresults(const_cast<alglib_impl::minqpstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minqpreport*>(rep.c_ptr()), &_alglib_env_state);
3923  alglib_impl::ae_state_clear(&_alglib_env_state);
3924  return;
3925  }
3927  {
3928  throw ap_error(_alglib_env_state.error_msg);
3929  }
3930 }
3931 
3932 /*************************************************************************
3933 QP results
3934 
3935 Buffered implementation of MinQPResults() which uses pre-allocated buffer
3936 to store X[]. If buffer size is too small, it resizes buffer. It is
3937 intended to be used in the inner cycles of performance critical algorithms
3938 where array reallocation penalty is too large to be ignored.
3939 
3940  -- ALGLIB --
3941  Copyright 11.01.2011 by Bochkanov Sergey
3942 *************************************************************************/
3944 {
3945  alglib_impl::ae_state _alglib_env_state;
3946  alglib_impl::ae_state_init(&_alglib_env_state);
3947  try
3948  {
3949  alglib_impl::minqpresultsbuf(const_cast<alglib_impl::minqpstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minqpreport*>(rep.c_ptr()), &_alglib_env_state);
3950  alglib_impl::ae_state_clear(&_alglib_env_state);
3951  return;
3952  }
3954  {
3955  throw ap_error(_alglib_env_state.error_msg);
3956  }
3957 }
3958 
3959 /*************************************************************************
3960 Levenberg-Marquardt optimizer.
3961 
3962 This structure should be created using one of the MinLMCreate???()
3963 functions. You should not access its fields directly; use ALGLIB functions
3964 to work with it.
3965 *************************************************************************/
3967 {
3969  if( p_struct==NULL )
3970  throw ap_error("ALGLIB: malloc error");
3972  throw ap_error("ALGLIB: malloc error");
3973 }
3974 
3976 {
3978  if( p_struct==NULL )
3979  throw ap_error("ALGLIB: malloc error");
3980  if( !alglib_impl::_minlmstate_init_copy(p_struct, const_cast<alglib_impl::minlmstate*>(rhs.p_struct), NULL, ae_false) )
3981  throw ap_error("ALGLIB: malloc error");
3982 }
3983 
3985 {
3986  if( this==&rhs )
3987  return *this;
3989  if( !alglib_impl::_minlmstate_init_copy(p_struct, const_cast<alglib_impl::minlmstate*>(rhs.p_struct), NULL, ae_false) )
3990  throw ap_error("ALGLIB: malloc error");
3991  return *this;
3992 }
3993 
3995 {
3997  ae_free(p_struct);
3998 }
3999 
4001 {
4002  return p_struct;
4003 }
4004 
4006 {
4007  return const_cast<alglib_impl::minlmstate*>(p_struct);
4008 }
4009 minlmstate::minlmstate() : _minlmstate_owner() ,needf(p_struct->needf),needfg(p_struct->needfg),needfgh(p_struct->needfgh),needfi(p_struct->needfi),needfij(p_struct->needfij),xupdated(p_struct->xupdated),f(p_struct->f),fi(&p_struct->fi),g(&p_struct->g),h(&p_struct->h),j(&p_struct->j),x(&p_struct->x)
4010 {
4011 }
4012 
4014 {
4015 }
4016 
4018 {
4019  if( this==&rhs )
4020  return *this;
4022  return *this;
4023 }
4024 
4026 {
4027 }
4028 
4029 
4030 /*************************************************************************
4031 Optimization report, filled by MinLMResults() function
4032 
4033 FIELDS:
4034 * TerminationType, completion code:
4035  * -7 derivative correctness check failed;
4036  see Rep.WrongNum, Rep.WrongI, Rep.WrongJ for
4037  more information.
4038  * 1 relative function improvement is no more than
4039  EpsF.
4040  * 2 relative step is no more than EpsX.
4041  * 4 gradient is no more than EpsG.
4042  * 5 MaxIts steps was taken
4043  * 7 stopping conditions are too stringent,
4044  further improvement is impossible
4045 * IterationsCount, contains iterations count
4046 * NFunc, number of function calculations
4047 * NJac, number of Jacobi matrix calculations
4048 * NGrad, number of gradient calculations
4049 * NHess, number of Hessian calculations
4050 * NCholesky, number of Cholesky decomposition calculations
4051 *************************************************************************/
4053 {
4055  if( p_struct==NULL )
4056  throw ap_error("ALGLIB: malloc error");
4058  throw ap_error("ALGLIB: malloc error");
4059 }
4060 
4062 {
4064  if( p_struct==NULL )
4065  throw ap_error("ALGLIB: malloc error");
4066  if( !alglib_impl::_minlmreport_init_copy(p_struct, const_cast<alglib_impl::minlmreport*>(rhs.p_struct), NULL, ae_false) )
4067  throw ap_error("ALGLIB: malloc error");
4068 }
4069 
4071 {
4072  if( this==&rhs )
4073  return *this;
4075  if( !alglib_impl::_minlmreport_init_copy(p_struct, const_cast<alglib_impl::minlmreport*>(rhs.p_struct), NULL, ae_false) )
4076  throw ap_error("ALGLIB: malloc error");
4077  return *this;
4078 }
4079 
4081 {
4083  ae_free(p_struct);
4084 }
4085 
4087 {
4088  return p_struct;
4089 }
4090 
4092 {
4093  return const_cast<alglib_impl::minlmreport*>(p_struct);
4094 }
4095 minlmreport::minlmreport() : _minlmreport_owner() ,iterationscount(p_struct->iterationscount),terminationtype(p_struct->terminationtype),funcidx(p_struct->funcidx),varidx(p_struct->varidx),nfunc(p_struct->nfunc),njac(p_struct->njac),ngrad(p_struct->ngrad),nhess(p_struct->nhess),ncholesky(p_struct->ncholesky)
4096 {
4097 }
4098 
4100 {
4101 }
4102 
4104 {
4105  if( this==&rhs )
4106  return *this;
4108  return *this;
4109 }
4110 
4112 {
4113 }
4114 
4115 /*************************************************************************
4116  IMPROVED LEVENBERG-MARQUARDT METHOD FOR
4117  NON-LINEAR LEAST SQUARES OPTIMIZATION
4118 
4119 DESCRIPTION:
4120 This function is used to find minimum of function which is represented as
4121 sum of squares:
4122  F(x) = f[0]^2(x[0],...,x[n-1]) + ... + f[m-1]^2(x[0],...,x[n-1])
4123 using value of function vector f[] and Jacobian of f[].
4124 
4125 
4126 REQUIREMENTS:
4127 This algorithm will request following information during its operation:
4128 
4129 * function vector f[] at given point X
4130 * function vector f[] and Jacobian of f[] (simultaneously) at given point
4131 
4132 There are several overloaded versions of MinLMOptimize() function which
4133 correspond to different LM-like optimization algorithms provided by this
4134 unit. You should choose version which accepts fvec() and jac() callbacks.
4135 First one is used to calculate f[] at given point, second one calculates
4136 f[] and Jacobian df[i]/dx[j].
4137 
4138 You can try to initialize MinLMState structure with VJ function and then
4139 use incorrect version of MinLMOptimize() (for example, version which
4140 works with general form function and does not provide Jacobian), but it
4141 will lead to exception being thrown after first attempt to calculate
4142 Jacobian.
4143 
4144 
4145 USAGE:
4146 1. User initializes algorithm state with MinLMCreateVJ() call
4147 2. User tunes solver parameters with MinLMSetCond(), MinLMSetStpMax() and
4148  other functions
4149 3. User calls MinLMOptimize() function which takes algorithm state and
4150  callback functions.
4151 4. User calls MinLMResults() to get solution
4152 5. Optionally, user may call MinLMRestartFrom() to solve another problem
4153  with same N/M but another starting point and/or another function.
4154  MinLMRestartFrom() allows to reuse already initialized structure.
4155 
4156 
4157 INPUT PARAMETERS:
4158  N - dimension, N>1
4159  * if given, only leading N elements of X are used
4160  * if not given, automatically determined from size of X
4161  M - number of functions f[i]
4162  X - initial solution, array[0..N-1]
4163 
4164 OUTPUT PARAMETERS:
4165  State - structure which stores algorithm state
4166 
4167 NOTES:
4168 1. you may tune stopping conditions with MinLMSetCond() function
4169 2. if target function contains exp() or other fast growing functions, and
4170  optimization algorithm makes too large steps which leads to overflow,
4171  use MinLMSetStpMax() function to bound algorithm's steps.
4172 
4173  -- ALGLIB --
4174  Copyright 30.03.2009 by Bochkanov Sergey
4175 *************************************************************************/
4176 void minlmcreatevj(const ae_int_t n, const ae_int_t m, const real_1d_array &x, minlmstate &state)
4177 {
4178  alglib_impl::ae_state _alglib_env_state;
4179  alglib_impl::ae_state_init(&_alglib_env_state);
4180  try
4181  {
4182  alglib_impl::minlmcreatevj(n, m, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minlmstate*>(state.c_ptr()), &_alglib_env_state);
4183  alglib_impl::ae_state_clear(&_alglib_env_state);
4184  return;
4185  }
4187  {
4188  throw ap_error(_alglib_env_state.error_msg);
4189  }
4190 }
4191 
4192 /*************************************************************************
4193  IMPROVED LEVENBERG-MARQUARDT METHOD FOR
4194  NON-LINEAR LEAST SQUARES OPTIMIZATION
4195 
4196 DESCRIPTION:
4197 This function is used to find minimum of function which is represented as
4198 sum of squares:
4199  F(x) = f[0]^2(x[0],...,x[n-1]) + ... + f[m-1]^2(x[0],...,x[n-1])
4200 using value of function vector f[] and Jacobian of f[].
4201 
4202 
4203 REQUIREMENTS:
4204 This algorithm will request following information during its operation:
4205 
4206 * function vector f[] at given point X
4207 * function vector f[] and Jacobian of f[] (simultaneously) at given point
4208 
4209 There are several overloaded versions of MinLMOptimize() function which
4210 correspond to different LM-like optimization algorithms provided by this
4211 unit. You should choose version which accepts fvec() and jac() callbacks.
4212 First one is used to calculate f[] at given point, second one calculates
4213 f[] and Jacobian df[i]/dx[j].
4214 
4215 You can try to initialize MinLMState structure with VJ function and then
4216 use incorrect version of MinLMOptimize() (for example, version which
4217 works with general form function and does not provide Jacobian), but it
4218 will lead to exception being thrown after first attempt to calculate
4219 Jacobian.
4220 
4221 
4222 USAGE:
4223 1. User initializes algorithm state with MinLMCreateVJ() call
4224 2. User tunes solver parameters with MinLMSetCond(), MinLMSetStpMax() and
4225  other functions
4226 3. User calls MinLMOptimize() function which takes algorithm state and
4227  callback functions.
4228 4. User calls MinLMResults() to get solution
4229 5. Optionally, user may call MinLMRestartFrom() to solve another problem
4230  with same N/M but another starting point and/or another function.
4231  MinLMRestartFrom() allows to reuse already initialized structure.
4232 
4233 
4234 INPUT PARAMETERS:
4235  N - dimension, N>1
4236  * if given, only leading N elements of X are used
4237  * if not given, automatically determined from size of X
4238  M - number of functions f[i]
4239  X - initial solution, array[0..N-1]
4240 
4241 OUTPUT PARAMETERS:
4242  State - structure which stores algorithm state
4243 
4244 NOTES:
4245 1. you may tune stopping conditions with MinLMSetCond() function
4246 2. if target function contains exp() or other fast growing functions, and
4247  optimization algorithm makes too large steps which leads to overflow,
4248  use MinLMSetStpMax() function to bound algorithm's steps.
4249 
4250  -- ALGLIB --
4251  Copyright 30.03.2009 by Bochkanov Sergey
4252 *************************************************************************/
4253 void minlmcreatevj(const ae_int_t m, const real_1d_array &x, minlmstate &state)
4254 {
4255  alglib_impl::ae_state _alglib_env_state;
4256  ae_int_t n;
4257 
4258  n = x.length();
4259  alglib_impl::ae_state_init(&_alglib_env_state);
4260  try
4261  {
4262  alglib_impl::minlmcreatevj(n, m, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minlmstate*>(state.c_ptr()), &_alglib_env_state);
4263 
4264  alglib_impl::ae_state_clear(&_alglib_env_state);
4265  return;
4266  }
4268  {
4269  throw ap_error(_alglib_env_state.error_msg);
4270  }
4271 }
4272 
4273 /*************************************************************************
4274  IMPROVED LEVENBERG-MARQUARDT METHOD FOR
4275  NON-LINEAR LEAST SQUARES OPTIMIZATION
4276 
4277 DESCRIPTION:
4278 This function is used to find minimum of function which is represented as
4279 sum of squares:
4280  F(x) = f[0]^2(x[0],...,x[n-1]) + ... + f[m-1]^2(x[0],...,x[n-1])
4281 using value of function vector f[] only. Finite differences are used to
4282 calculate Jacobian.
4283 
4284 
4285 REQUIREMENTS:
4286 This algorithm will request following information during its operation:
4287 * function vector f[] at given point X
4288 
4289 There are several overloaded versions of MinLMOptimize() function which
4290 correspond to different LM-like optimization algorithms provided by this
4291 unit. You should choose version which accepts fvec() callback.
4292 
4293 You can try to initialize MinLMState structure with VJ function and then
4294 use incorrect version of MinLMOptimize() (for example, version which
4295 works with general form function and does not accept function vector), but
4296 it will lead to exception being thrown after first attempt to calculate
4297 Jacobian.
4298 
4299 
4300 USAGE:
4301 1. User initializes algorithm state with MinLMCreateV() call
4302 2. User tunes solver parameters with MinLMSetCond(), MinLMSetStpMax() and
4303  other functions
4304 3. User calls MinLMOptimize() function which takes algorithm state and
4305  callback functions.
4306 4. User calls MinLMResults() to get solution
4307 5. Optionally, user may call MinLMRestartFrom() to solve another problem
4308  with same N/M but another starting point and/or another function.
4309  MinLMRestartFrom() allows to reuse already initialized structure.
4310 
4311 
4312 INPUT PARAMETERS:
4313  N - dimension, N>1
4314  * if given, only leading N elements of X are used
4315  * if not given, automatically determined from size of X
4316  M - number of functions f[i]
4317  X - initial solution, array[0..N-1]
4318  DiffStep- differentiation step, >0
4319 
4320 OUTPUT PARAMETERS:
4321  State - structure which stores algorithm state
4322 
4323 See also MinLMIteration, MinLMResults.
4324 
4325 NOTES:
4326 1. you may tune stopping conditions with MinLMSetCond() function
4327 2. if target function contains exp() or other fast growing functions, and
4328  optimization algorithm makes too large steps which leads to overflow,
4329  use MinLMSetStpMax() function to bound algorithm's steps.
4330 
4331  -- ALGLIB --
4332  Copyright 30.03.2009 by Bochkanov Sergey
4333 *************************************************************************/
4334 void minlmcreatev(const ae_int_t n, const ae_int_t m, const real_1d_array &x, const double diffstep, minlmstate &state)
4335 {
4336  alglib_impl::ae_state _alglib_env_state;
4337  alglib_impl::ae_state_init(&_alglib_env_state);
4338  try
4339  {
4340  alglib_impl::minlmcreatev(n, m, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), diffstep, const_cast<alglib_impl::minlmstate*>(state.c_ptr()), &_alglib_env_state);
4341  alglib_impl::ae_state_clear(&_alglib_env_state);
4342  return;
4343  }
4345  {
4346  throw ap_error(_alglib_env_state.error_msg);
4347  }
4348 }
4349 
4350 /*************************************************************************
4351  IMPROVED LEVENBERG-MARQUARDT METHOD FOR
4352  NON-LINEAR LEAST SQUARES OPTIMIZATION
4353 
4354 DESCRIPTION:
4355 This function is used to find minimum of function which is represented as
4356 sum of squares:
4357  F(x) = f[0]^2(x[0],...,x[n-1]) + ... + f[m-1]^2(x[0],...,x[n-1])
4358 using value of function vector f[] only. Finite differences are used to
4359 calculate Jacobian.
4360 
4361 
4362 REQUIREMENTS:
4363 This algorithm will request following information during its operation:
4364 * function vector f[] at given point X
4365 
4366 There are several overloaded versions of MinLMOptimize() function which
4367 correspond to different LM-like optimization algorithms provided by this
4368 unit. You should choose version which accepts fvec() callback.
4369 
4370 You can try to initialize MinLMState structure with VJ function and then
4371 use incorrect version of MinLMOptimize() (for example, version which
4372 works with general form function and does not accept function vector), but
4373 it will lead to exception being thrown after first attempt to calculate
4374 Jacobian.
4375 
4376 
4377 USAGE:
4378 1. User initializes algorithm state with MinLMCreateV() call
4379 2. User tunes solver parameters with MinLMSetCond(), MinLMSetStpMax() and
4380  other functions
4381 3. User calls MinLMOptimize() function which takes algorithm state and
4382  callback functions.
4383 4. User calls MinLMResults() to get solution
4384 5. Optionally, user may call MinLMRestartFrom() to solve another problem
4385  with same N/M but another starting point and/or another function.
4386  MinLMRestartFrom() allows to reuse already initialized structure.
4387 
4388 
4389 INPUT PARAMETERS:
4390  N - dimension, N>1
4391  * if given, only leading N elements of X are used
4392  * if not given, automatically determined from size of X
4393  M - number of functions f[i]
4394  X - initial solution, array[0..N-1]
4395  DiffStep- differentiation step, >0
4396 
4397 OUTPUT PARAMETERS:
4398  State - structure which stores algorithm state
4399 
4400 See also MinLMIteration, MinLMResults.
4401 
4402 NOTES:
4403 1. you may tune stopping conditions with MinLMSetCond() function
4404 2. if target function contains exp() or other fast growing functions, and
4405  optimization algorithm makes too large steps which leads to overflow,
4406  use MinLMSetStpMax() function to bound algorithm's steps.
4407 
4408  -- ALGLIB --
4409  Copyright 30.03.2009 by Bochkanov Sergey
4410 *************************************************************************/
4411 void minlmcreatev(const ae_int_t m, const real_1d_array &x, const double diffstep, minlmstate &state)
4412 {
4413  alglib_impl::ae_state _alglib_env_state;
4414  ae_int_t n;
4415 
4416  n = x.length();
4417  alglib_impl::ae_state_init(&_alglib_env_state);
4418  try
4419  {
4420  alglib_impl::minlmcreatev(n, m, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), diffstep, const_cast<alglib_impl::minlmstate*>(state.c_ptr()), &_alglib_env_state);
4421 
4422  alglib_impl::ae_state_clear(&_alglib_env_state);
4423  return;
4424  }
4426  {
4427  throw ap_error(_alglib_env_state.error_msg);
4428  }
4429 }
4430 
4431 /*************************************************************************
4432  LEVENBERG-MARQUARDT-LIKE METHOD FOR NON-LINEAR OPTIMIZATION
4433 
4434 DESCRIPTION:
4435 This function is used to find minimum of general form (not "sum-of-
4436 -squares") function
4437  F = F(x[0], ..., x[n-1])
4438 using its gradient and Hessian. Levenberg-Marquardt modification with
4439 L-BFGS pre-optimization and internal pre-conditioned L-BFGS optimization
4440 after each Levenberg-Marquardt step is used.
4441 
4442 
4443 REQUIREMENTS:
4444 This algorithm will request following information during its operation:
4445 
4446 * function value F at given point X
4447 * F and gradient G (simultaneously) at given point X
4448 * F, G and Hessian H (simultaneously) at given point X
4449 
4450 There are several overloaded versions of MinLMOptimize() function which
4451 correspond to different LM-like optimization algorithms provided by this
4452 unit. You should choose version which accepts func(), grad() and hess()
4453 function pointers. First pointer is used to calculate F at given point,
4454 second one calculates F(x) and grad F(x), third one calculates F(x),
4455 grad F(x), hess F(x).
4456 
4457 You can try to initialize MinLMState structure with FGH-function and then
4458 use incorrect version of MinLMOptimize() (for example, version which does
4459 not provide Hessian matrix), but it will lead to exception being thrown
4460 after first attempt to calculate Hessian.
4461 
4462 
4463 USAGE:
4464 1. User initializes algorithm state with MinLMCreateFGH() call
4465 2. User tunes solver parameters with MinLMSetCond(), MinLMSetStpMax() and
4466  other functions
4467 3. User calls MinLMOptimize() function which takes algorithm state and
4468  pointers (delegates, etc.) to callback functions.
4469 4. User calls MinLMResults() to get solution
4470 5. Optionally, user may call MinLMRestartFrom() to solve another problem
4471  with same N but another starting point and/or another function.
4472  MinLMRestartFrom() allows to reuse already initialized structure.
4473 
4474 
4475 INPUT PARAMETERS:
4476  N - dimension, N>1
4477  * if given, only leading N elements of X are used
4478  * if not given, automatically determined from size of X
4479  X - initial solution, array[0..N-1]
4480 
4481 OUTPUT PARAMETERS:
4482  State - structure which stores algorithm state
4483 
4484 NOTES:
4485 1. you may tune stopping conditions with MinLMSetCond() function
4486 2. if target function contains exp() or other fast growing functions, and
4487  optimization algorithm makes too large steps which leads to overflow,
4488  use MinLMSetStpMax() function to bound algorithm's steps.
4489 
4490  -- ALGLIB --
4491  Copyright 30.03.2009 by Bochkanov Sergey
4492 *************************************************************************/
4493 void minlmcreatefgh(const ae_int_t n, const real_1d_array &x, minlmstate &state)
4494 {
4495  alglib_impl::ae_state _alglib_env_state;
4496  alglib_impl::ae_state_init(&_alglib_env_state);
4497  try
4498  {
4499  alglib_impl::minlmcreatefgh(n, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minlmstate*>(state.c_ptr()), &_alglib_env_state);
4500  alglib_impl::ae_state_clear(&_alglib_env_state);
4501  return;
4502  }
4504  {
4505  throw ap_error(_alglib_env_state.error_msg);
4506  }
4507 }
4508 
4509 /*************************************************************************
4510  LEVENBERG-MARQUARDT-LIKE METHOD FOR NON-LINEAR OPTIMIZATION
4511 
4512 DESCRIPTION:
4513 This function is used to find minimum of general form (not "sum-of-
4514 -squares") function
4515  F = F(x[0], ..., x[n-1])
4516 using its gradient and Hessian. Levenberg-Marquardt modification with
4517 L-BFGS pre-optimization and internal pre-conditioned L-BFGS optimization
4518 after each Levenberg-Marquardt step is used.
4519 
4520 
4521 REQUIREMENTS:
4522 This algorithm will request following information during its operation:
4523 
4524 * function value F at given point X
4525 * F and gradient G (simultaneously) at given point X
4526 * F, G and Hessian H (simultaneously) at given point X
4527 
4528 There are several overloaded versions of MinLMOptimize() function which
4529 correspond to different LM-like optimization algorithms provided by this
4530 unit. You should choose version which accepts func(), grad() and hess()
4531 function pointers. First pointer is used to calculate F at given point,
4532 second one calculates F(x) and grad F(x), third one calculates F(x),
4533 grad F(x), hess F(x).
4534 
4535 You can try to initialize MinLMState structure with FGH-function and then
4536 use incorrect version of MinLMOptimize() (for example, version which does
4537 not provide Hessian matrix), but it will lead to exception being thrown
4538 after first attempt to calculate Hessian.
4539 
4540 
4541 USAGE:
4542 1. User initializes algorithm state with MinLMCreateFGH() call
4543 2. User tunes solver parameters with MinLMSetCond(), MinLMSetStpMax() and
4544  other functions
4545 3. User calls MinLMOptimize() function which takes algorithm state and
4546  pointers (delegates, etc.) to callback functions.
4547 4. User calls MinLMResults() to get solution
4548 5. Optionally, user may call MinLMRestartFrom() to solve another problem
4549  with same N but another starting point and/or another function.
4550  MinLMRestartFrom() allows to reuse already initialized structure.
4551 
4552 
4553 INPUT PARAMETERS:
4554  N - dimension, N>1
4555  * if given, only leading N elements of X are used
4556  * if not given, automatically determined from size of X
4557  X - initial solution, array[0..N-1]
4558 
4559 OUTPUT PARAMETERS:
4560  State - structure which stores algorithm state
4561 
4562 NOTES:
4563 1. you may tune stopping conditions with MinLMSetCond() function
4564 2. if target function contains exp() or other fast growing functions, and
4565  optimization algorithm makes too large steps which leads to overflow,
4566  use MinLMSetStpMax() function to bound algorithm's steps.
4567 
4568  -- ALGLIB --
4569  Copyright 30.03.2009 by Bochkanov Sergey
4570 *************************************************************************/
4572 {
4573  alglib_impl::ae_state _alglib_env_state;
4574  ae_int_t n;
4575 
4576  n = x.length();
4577  alglib_impl::ae_state_init(&_alglib_env_state);
4578  try
4579  {
4580  alglib_impl::minlmcreatefgh(n, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minlmstate*>(state.c_ptr()), &_alglib_env_state);
4581 
4582  alglib_impl::ae_state_clear(&_alglib_env_state);
4583  return;
4584  }
4586  {
4587  throw ap_error(_alglib_env_state.error_msg);
4588  }
4589 }
4590 
4591 /*************************************************************************
4592 This function sets stopping conditions for Levenberg-Marquardt optimization
4593 algorithm.
4594 
4595 INPUT PARAMETERS:
4596  State - structure which stores algorithm state
4597  EpsG - >=0
4598  The subroutine finishes its work if the condition
4599  |v|<EpsG is satisfied, where:
4600  * |.| means Euclidian norm
4601  * v - scaled gradient vector, v[i]=g[i]*s[i]
4602  * g - gradient
4603  * s - scaling coefficients set by MinLMSetScale()
4604  EpsF - >=0
4605  The subroutine finishes its work if on k+1-th iteration
4606  the condition |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1}
4607  is satisfied.
4608  EpsX - >=0
4609  The subroutine finishes its work if on k+1-th iteration
4610  the condition |v|<=EpsX is fulfilled, where:
4611  * |.| means Euclidian norm
4612  * v - scaled step vector, v[i]=dx[i]/s[i]
4613  * dx - ste pvector, dx=X(k+1)-X(k)
4614  * s - scaling coefficients set by MinLMSetScale()
4615  MaxIts - maximum number of iterations. If MaxIts=0, the number of
4616  iterations is unlimited. Only Levenberg-Marquardt
4617  iterations are counted (L-BFGS/CG iterations are NOT
4618  counted because their cost is very low compared to that of
4619  LM).
4620 
4621 Passing EpsG=0, EpsF=0, EpsX=0 and MaxIts=0 (simultaneously) will lead to
4622 automatic stopping criterion selection (small EpsX).
4623 
4624  -- ALGLIB --
4625  Copyright 02.04.2010 by Bochkanov Sergey
4626 *************************************************************************/
4627 void minlmsetcond(const minlmstate &state, const double epsg, const double epsf, const double epsx, const ae_int_t maxits)
4628 {
4629  alglib_impl::ae_state _alglib_env_state;
4630  alglib_impl::ae_state_init(&_alglib_env_state);
4631  try
4632  {
4633  alglib_impl::minlmsetcond(const_cast<alglib_impl::minlmstate*>(state.c_ptr()), epsg, epsf, epsx, maxits, &_alglib_env_state);
4634  alglib_impl::ae_state_clear(&_alglib_env_state);
4635  return;
4636  }
4638  {
4639  throw ap_error(_alglib_env_state.error_msg);
4640  }
4641 }
4642 
4643 /*************************************************************************
4644 This function turns on/off reporting.
4645 
4646 INPUT PARAMETERS:
4647  State - structure which stores algorithm state
4648  NeedXRep- whether iteration reports are needed or not
4649 
4650 If NeedXRep is True, algorithm will call rep() callback function if it is
4651 provided to MinLMOptimize(). Both Levenberg-Marquardt and internal L-BFGS
4652 iterations are reported.
4653 
4654  -- ALGLIB --
4655  Copyright 02.04.2010 by Bochkanov Sergey
4656 *************************************************************************/
4657 void minlmsetxrep(const minlmstate &state, const bool needxrep)
4658 {
4659  alglib_impl::ae_state _alglib_env_state;
4660  alglib_impl::ae_state_init(&_alglib_env_state);
4661  try
4662  {
4663  alglib_impl::minlmsetxrep(const_cast<alglib_impl::minlmstate*>(state.c_ptr()), needxrep, &_alglib_env_state);
4664  alglib_impl::ae_state_clear(&_alglib_env_state);
4665  return;
4666  }
4668  {
4669  throw ap_error(_alglib_env_state.error_msg);
4670  }
4671 }
4672 
4673 /*************************************************************************
4674 This function sets maximum step length
4675 
4676 INPUT PARAMETERS:
4677  State - structure which stores algorithm state
4678  StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't
4679  want to limit step length.
4680 
4681 Use this subroutine when you optimize target function which contains exp()
4682 or other fast growing functions, and optimization algorithm makes too
4683 large steps which leads to overflow. This function allows us to reject
4684 steps that are too large (and therefore expose us to the possible
4685 overflow) without actually calculating function value at the x+stp*d.
4686 
4687 NOTE: non-zero StpMax leads to moderate performance degradation because
4688 intermediate step of preconditioned L-BFGS optimization is incompatible
4689 with limits on step size.
4690 
4691  -- ALGLIB --
4692  Copyright 02.04.2010 by Bochkanov Sergey
4693 *************************************************************************/
4694 void minlmsetstpmax(const minlmstate &state, const double stpmax)
4695 {
4696  alglib_impl::ae_state _alglib_env_state;
4697  alglib_impl::ae_state_init(&_alglib_env_state);
4698  try
4699  {
4700  alglib_impl::minlmsetstpmax(const_cast<alglib_impl::minlmstate*>(state.c_ptr()), stpmax, &_alglib_env_state);
4701  alglib_impl::ae_state_clear(&_alglib_env_state);
4702  return;
4703  }
4705  {
4706  throw ap_error(_alglib_env_state.error_msg);
4707  }
4708 }
4709 
4710 /*************************************************************************
4711 This function sets scaling coefficients for LM optimizer.
4712 
4713 ALGLIB optimizers use scaling matrices to test stopping conditions (step
4714 size and gradient are scaled before comparison with tolerances). Scale of
4715 the I-th variable is a translation invariant measure of:
4716 a) "how large" the variable is
4717 b) how large the step should be to make significant changes in the function
4718 
4719 Generally, scale is NOT considered to be a form of preconditioner. But LM
4720 optimizer is unique in that it uses scaling matrix both in the stopping
4721 condition tests and as Marquardt damping factor.
4722 
4723 Proper scaling is very important for the algorithm performance. It is less
4724 important for the quality of results, but still has some influence (it is
4725 easier to converge when variables are properly scaled, so premature
4726 stopping is possible when very badly scalled variables are combined with
4727 relaxed stopping conditions).
4728 
4729 INPUT PARAMETERS:
4730  State - structure stores algorithm state
4731  S - array[N], non-zero scaling coefficients
4732  S[i] may be negative, sign doesn't matter.
4733 
4734  -- ALGLIB --
4735  Copyright 14.01.2011 by Bochkanov Sergey
4736 *************************************************************************/
4737 void minlmsetscale(const minlmstate &state, const real_1d_array &s)
4738 {
4739  alglib_impl::ae_state _alglib_env_state;
4740  alglib_impl::ae_state_init(&_alglib_env_state);
4741  try
4742  {
4743  alglib_impl::minlmsetscale(const_cast<alglib_impl::minlmstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(s.c_ptr()), &_alglib_env_state);
4744  alglib_impl::ae_state_clear(&_alglib_env_state);
4745  return;
4746  }
4748  {
4749  throw ap_error(_alglib_env_state.error_msg);
4750  }
4751 }
4752 
4753 /*************************************************************************
4754 This function sets boundary constraints for LM optimizer
4755 
4756 Boundary constraints are inactive by default (after initial creation).
4757 They are preserved until explicitly turned off with another SetBC() call.
4758 
4759 INPUT PARAMETERS:
4760  State - structure stores algorithm state
4761  BndL - lower bounds, array[N].
4762  If some (all) variables are unbounded, you may specify
4763  very small number or -INF (latter is recommended because
4764  it will allow solver to use better algorithm).
4765  BndU - upper bounds, array[N].
4766  If some (all) variables are unbounded, you may specify
4767  very large number or +INF (latter is recommended because
4768  it will allow solver to use better algorithm).
4769 
4770 NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case I-th
4771 variable will be "frozen" at X[i]=BndL[i]=BndU[i].
4772 
4773 NOTE 2: this solver has following useful properties:
4774 * bound constraints are always satisfied exactly
4775 * function is evaluated only INSIDE area specified by bound constraints
4776  or at its boundary
4777 
4778  -- ALGLIB --
4779  Copyright 14.01.2011 by Bochkanov Sergey
4780 *************************************************************************/
4781 void minlmsetbc(const minlmstate &state, const real_1d_array &bndl, const real_1d_array &bndu)
4782 {
4783  alglib_impl::ae_state _alglib_env_state;
4784  alglib_impl::ae_state_init(&_alglib_env_state);
4785  try
4786  {
4787  alglib_impl::minlmsetbc(const_cast<alglib_impl::minlmstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(bndl.c_ptr()), const_cast<alglib_impl::ae_vector*>(bndu.c_ptr()), &_alglib_env_state);
4788  alglib_impl::ae_state_clear(&_alglib_env_state);
4789  return;
4790  }
4792  {
4793  throw ap_error(_alglib_env_state.error_msg);
4794  }
4795 }
4796 
4797 /*************************************************************************
4798 This function is used to change acceleration settings
4799 
4800 You can choose between three acceleration strategies:
4801 * AccType=0, no acceleration.
4802 * AccType=1, secant updates are used to update quadratic model after each
4803  iteration. After fixed number of iterations (or after model breakdown)
4804  we recalculate quadratic model using analytic Jacobian or finite
4805  differences. Number of secant-based iterations depends on optimization
4806  settings: about 3 iterations - when we have analytic Jacobian, up to 2*N
4807  iterations - when we use finite differences to calculate Jacobian.
4808 
4809 AccType=1 is recommended when Jacobian calculation cost is prohibitive
4810 high (several Mx1 function vector calculations followed by several NxN
4811 Cholesky factorizations are faster than calculation of one M*N Jacobian).
4812 It should also be used when we have no Jacobian, because finite difference
4813 approximation takes too much time to compute.
4814 
4815 Table below list optimization protocols (XYZ protocol corresponds to
4816 MinLMCreateXYZ) and acceleration types they support (and use by default).
4817 
4818 ACCELERATION TYPES SUPPORTED BY OPTIMIZATION PROTOCOLS:
4819 
4820 protocol 0 1 comment
4821 V + +
4822 VJ + +
4823 FGH +
4824 
4825 DAFAULT VALUES:
4826 
4827 protocol 0 1 comment
4828 V x without acceleration it is so slooooooooow
4829 VJ x
4830 FGH x
4831 
4832 NOTE: this function should be called before optimization. Attempt to call
4833 it during algorithm iterations may result in unexpected behavior.
4834 
4835 NOTE: attempt to call this function with unsupported protocol/acceleration
4836 combination will result in exception being thrown.
4837 
4838  -- ALGLIB --
4839  Copyright 14.10.2010 by Bochkanov Sergey
4840 *************************************************************************/
4841 void minlmsetacctype(const minlmstate &state, const ae_int_t acctype)
4842 {
4843  alglib_impl::ae_state _alglib_env_state;
4844  alglib_impl::ae_state_init(&_alglib_env_state);
4845  try
4846  {
4847  alglib_impl::minlmsetacctype(const_cast<alglib_impl::minlmstate*>(state.c_ptr()), acctype, &_alglib_env_state);
4848  alglib_impl::ae_state_clear(&_alglib_env_state);
4849  return;
4850  }
4852  {
4853  throw ap_error(_alglib_env_state.error_msg);
4854  }
4855 }
4856 
4857 /*************************************************************************
4858 This function provides reverse communication interface
4859 Reverse communication interface is not documented or recommended to use.
4860 See below for functions which provide better documented API
4861 *************************************************************************/
4862 bool minlmiteration(const minlmstate &state)
4863 {
4864  alglib_impl::ae_state _alglib_env_state;
4865  alglib_impl::ae_state_init(&_alglib_env_state);
4866  try
4867  {
4868  ae_bool result = alglib_impl::minlmiteration(const_cast<alglib_impl::minlmstate*>(state.c_ptr()), &_alglib_env_state);
4869  alglib_impl::ae_state_clear(&_alglib_env_state);
4870  return *(reinterpret_cast<bool*>(&result));
4871  }
4873  {
4874  throw ap_error(_alglib_env_state.error_msg);
4875  }
4876 }
4877 
4878 
4880  void (*fvec)(const real_1d_array &x, real_1d_array &fi, void *ptr),
4881  void (*rep)(const real_1d_array &x, double func, void *ptr),
4882  void *ptr)
4883 {
4884  alglib_impl::ae_state _alglib_env_state;
4885  if( fvec==NULL )
4886  throw ap_error("ALGLIB: error in 'minlmoptimize()' (fvec is NULL)");
4887  alglib_impl::ae_state_init(&_alglib_env_state);
4888  try
4889  {
4890  while( alglib_impl::minlmiteration(state.c_ptr(), &_alglib_env_state) )
4891  {
4892  if( state.needfi )
4893  {
4894  fvec(state.x, state.fi, ptr);
4895  continue;
4896  }
4897  if( state.xupdated )
4898  {
4899  if( rep!=NULL )
4900  rep(state.x, state.f, ptr);
4901  continue;
4902  }
4903  throw ap_error("ALGLIB: error in 'minlmoptimize' (some derivatives were not provided?)");
4904  }
4905  alglib_impl::ae_state_clear(&_alglib_env_state);
4906  }
4908  {
4909  throw ap_error(_alglib_env_state.error_msg);
4910  }
4911 }
4912 
4913 
4915  void (*fvec)(const real_1d_array &x, real_1d_array &fi, void *ptr),
4916  void (*jac)(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr),
4917  void (*rep)(const real_1d_array &x, double func, void *ptr),
4918  void *ptr)
4919 {
4920  alglib_impl::ae_state _alglib_env_state;
4921  if( fvec==NULL )
4922  throw ap_error("ALGLIB: error in 'minlmoptimize()' (fvec is NULL)");
4923  if( jac==NULL )
4924  throw ap_error("ALGLIB: error in 'minlmoptimize()' (jac is NULL)");
4925  alglib_impl::ae_state_init(&_alglib_env_state);
4926  try
4927  {
4928  while( alglib_impl::minlmiteration(state.c_ptr(), &_alglib_env_state) )
4929  {
4930  if( state.needfi )
4931  {
4932  fvec(state.x, state.fi, ptr);
4933  continue;
4934  }
4935  if( state.needfij )
4936  {
4937  jac(state.x, state.fi, state.j, ptr);
4938  continue;
4939  }
4940  if( state.xupdated )
4941  {
4942  if( rep!=NULL )
4943  rep(state.x, state.f, ptr);
4944  continue;
4945  }
4946  throw ap_error("ALGLIB: error in 'minlmoptimize' (some derivatives were not provided?)");
4947  }
4948  alglib_impl::ae_state_clear(&_alglib_env_state);
4949  }
4951  {
4952  throw ap_error(_alglib_env_state.error_msg);
4953  }
4954 }
4955 
4956 
4958  void (*func)(const real_1d_array &x, double &func, void *ptr),
4959  void (*grad)(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr),
4960  void (*hess)(const real_1d_array &x, double &func, real_1d_array &grad, real_2d_array &hess, void *ptr),
4961  void (*rep)(const real_1d_array &x, double func, void *ptr),
4962  void *ptr)
4963 {
4964  alglib_impl::ae_state _alglib_env_state;
4965  if( func==NULL )
4966  throw ap_error("ALGLIB: error in 'minlmoptimize()' (func is NULL)");
4967  if( grad==NULL )
4968  throw ap_error("ALGLIB: error in 'minlmoptimize()' (grad is NULL)");
4969  if( hess==NULL )
4970  throw ap_error("ALGLIB: error in 'minlmoptimize()' (hess is NULL)");
4971  alglib_impl::ae_state_init(&_alglib_env_state);
4972  try
4973  {
4974  while( alglib_impl::minlmiteration(state.c_ptr(), &_alglib_env_state) )
4975  {
4976  if( state.needf )
4977  {
4978  func(state.x, state.f, ptr);
4979  continue;
4980  }
4981  if( state.needfg )
4982  {
4983  grad(state.x, state.f, state.g, ptr);
4984  continue;
4985  }
4986  if( state.needfgh )
4987  {
4988  hess(state.x, state.f, state.g, state.h, ptr);
4989  continue;
4990  }
4991  if( state.xupdated )
4992  {
4993  if( rep!=NULL )
4994  rep(state.x, state.f, ptr);
4995  continue;
4996  }
4997  throw ap_error("ALGLIB: error in 'minlmoptimize' (some derivatives were not provided?)");
4998  }
4999  alglib_impl::ae_state_clear(&_alglib_env_state);
5000  }
5002  {
5003  throw ap_error(_alglib_env_state.error_msg);
5004  }
5005 }
5006 
5007 
5009  void (*func)(const real_1d_array &x, double &func, void *ptr),
5010  void (*jac)(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr),
5011  void (*rep)(const real_1d_array &x, double func, void *ptr),
5012  void *ptr)
5013 {
5014  alglib_impl::ae_state _alglib_env_state;
5015  if( func==NULL )
5016  throw ap_error("ALGLIB: error in 'minlmoptimize()' (func is NULL)");
5017  if( jac==NULL )
5018  throw ap_error("ALGLIB: error in 'minlmoptimize()' (jac is NULL)");
5019  alglib_impl::ae_state_init(&_alglib_env_state);
5020  try
5021  {
5022  while( alglib_impl::minlmiteration(state.c_ptr(), &_alglib_env_state) )
5023  {
5024  if( state.needf )
5025  {
5026  func(state.x, state.f, ptr);
5027  continue;
5028  }
5029  if( state.needfij )
5030  {
5031  jac(state.x, state.fi, state.j, ptr);
5032  continue;
5033  }
5034  if( state.xupdated )
5035  {
5036  if( rep!=NULL )
5037  rep(state.x, state.f, ptr);
5038  continue;
5039  }
5040  throw ap_error("ALGLIB: error in 'minlmoptimize' (some derivatives were not provided?)");
5041  }
5042  alglib_impl::ae_state_clear(&_alglib_env_state);
5043  }
5045  {
5046  throw ap_error(_alglib_env_state.error_msg);
5047  }
5048 }
5049 
5050 
5052  void (*func)(const real_1d_array &x, double &func, void *ptr),
5053  void (*grad)(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr),
5054  void (*jac)(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr),
5055  void (*rep)(const real_1d_array &x, double func, void *ptr),
5056  void *ptr)
5057 {
5058  alglib_impl::ae_state _alglib_env_state;
5059  if( func==NULL )
5060  throw ap_error("ALGLIB: error in 'minlmoptimize()' (func is NULL)");
5061  if( grad==NULL )
5062  throw ap_error("ALGLIB: error in 'minlmoptimize()' (grad is NULL)");
5063  if( jac==NULL )
5064  throw ap_error("ALGLIB: error in 'minlmoptimize()' (jac is NULL)");
5065  alglib_impl::ae_state_init(&_alglib_env_state);
5066  try
5067  {
5068  while( alglib_impl::minlmiteration(state.c_ptr(), &_alglib_env_state) )
5069  {
5070  if( state.needf )
5071  {
5072  func(state.x, state.f, ptr);
5073  continue;
5074  }
5075  if( state.needfg )
5076  {
5077  grad(state.x, state.f, state.g, ptr);
5078  continue;
5079  }
5080  if( state.needfij )
5081  {
5082  jac(state.x, state.fi, state.j, ptr);
5083  continue;
5084  }
5085  if( state.xupdated )
5086  {
5087  if( rep!=NULL )
5088  rep(state.x, state.f, ptr);
5089  continue;
5090  }
5091  throw ap_error("ALGLIB: error in 'minlmoptimize' (some derivatives were not provided?)");
5092  }
5093  alglib_impl::ae_state_clear(&_alglib_env_state);
5094  }
5096  {
5097  throw ap_error(_alglib_env_state.error_msg);
5098  }
5099 }
5100 
5101 
5102 
5103 /*************************************************************************
5104 Levenberg-Marquardt algorithm results
5105 
5106 INPUT PARAMETERS:
5107  State - algorithm state
5108 
5109 OUTPUT PARAMETERS:
5110  X - array[0..N-1], solution
5111  Rep - optimization report;
5112  see comments for this structure for more info.
5113 
5114  -- ALGLIB --
5115  Copyright 10.03.2009 by Bochkanov Sergey
5116 *************************************************************************/
5117 void minlmresults(const minlmstate &state, real_1d_array &x, minlmreport &rep)
5118 {
5119  alglib_impl::ae_state _alglib_env_state;
5120  alglib_impl::ae_state_init(&_alglib_env_state);
5121  try
5122  {
5123  alglib_impl::minlmresults(const_cast<alglib_impl::minlmstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minlmreport*>(rep.c_ptr()), &_alglib_env_state);
5124  alglib_impl::ae_state_clear(&_alglib_env_state);
5125  return;
5126  }
5128  {
5129  throw ap_error(_alglib_env_state.error_msg);
5130  }
5131 }
5132 
5133 /*************************************************************************
5134 Levenberg-Marquardt algorithm results
5135 
5136 Buffered implementation of MinLMResults(), which uses pre-allocated buffer
5137 to store X[]. If buffer size is too small, it resizes buffer. It is
5138 intended to be used in the inner cycles of performance critical algorithms
5139 where array reallocation penalty is too large to be ignored.
5140 
5141  -- ALGLIB --
5142  Copyright 10.03.2009 by Bochkanov Sergey
5143 *************************************************************************/
5145 {
5146  alglib_impl::ae_state _alglib_env_state;
5147  alglib_impl::ae_state_init(&_alglib_env_state);
5148  try
5149  {
5150  alglib_impl::minlmresultsbuf(const_cast<alglib_impl::minlmstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minlmreport*>(rep.c_ptr()), &_alglib_env_state);
5151  alglib_impl::ae_state_clear(&_alglib_env_state);
5152  return;
5153  }
5155  {
5156  throw ap_error(_alglib_env_state.error_msg);
5157  }
5158 }
5159 
5160 /*************************************************************************
5161 This subroutine restarts LM algorithm from new point. All optimization
5162 parameters are left unchanged.
5163 
5164 This function allows to solve multiple optimization problems (which
5165 must have same number of dimensions) without object reallocation penalty.
5166 
5167 INPUT PARAMETERS:
5168  State - structure used for reverse communication previously
5169  allocated with MinLMCreateXXX call.
5170  X - new starting point.
5171 
5172  -- ALGLIB --
5173  Copyright 30.07.2010 by Bochkanov Sergey
5174 *************************************************************************/
5175 void minlmrestartfrom(const minlmstate &state, const real_1d_array &x)
5176 {
5177  alglib_impl::ae_state _alglib_env_state;
5178  alglib_impl::ae_state_init(&_alglib_env_state);
5179  try
5180  {
5181  alglib_impl::minlmrestartfrom(const_cast<alglib_impl::minlmstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), &_alglib_env_state);
5182  alglib_impl::ae_state_clear(&_alglib_env_state);
5183  return;
5184  }
5186  {
5187  throw ap_error(_alglib_env_state.error_msg);
5188  }
5189 }
5190 
5191 /*************************************************************************
5192 This is obsolete function.
5193 
5194 Since ALGLIB 3.3 it is equivalent to MinLMCreateVJ().
5195 
5196  -- ALGLIB --
5197  Copyright 30.03.2009 by Bochkanov Sergey
5198 *************************************************************************/
5199 void minlmcreatevgj(const ae_int_t n, const ae_int_t m, const real_1d_array &x, minlmstate &state)
5200 {
5201  alglib_impl::ae_state _alglib_env_state;
5202  alglib_impl::ae_state_init(&_alglib_env_state);
5203  try
5204  {
5205  alglib_impl::minlmcreatevgj(n, m, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minlmstate*>(state.c_ptr()), &_alglib_env_state);
5206  alglib_impl::ae_state_clear(&_alglib_env_state);
5207  return;
5208  }
5210  {
5211  throw ap_error(_alglib_env_state.error_msg);
5212  }
5213 }
5214 
5215 /*************************************************************************
5216 This is obsolete function.
5217 
5218 Since ALGLIB 3.3 it is equivalent to MinLMCreateVJ().
5219 
5220  -- ALGLIB --
5221  Copyright 30.03.2009 by Bochkanov Sergey
5222 *************************************************************************/
5223 void minlmcreatevgj(const ae_int_t m, const real_1d_array &x, minlmstate &state)
5224 {
5225  alglib_impl::ae_state _alglib_env_state;
5226  ae_int_t n;
5227 
5228  n = x.length();
5229  alglib_impl::ae_state_init(&_alglib_env_state);
5230  try
5231  {
5232  alglib_impl::minlmcreatevgj(n, m, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minlmstate*>(state.c_ptr()), &_alglib_env_state);
5233 
5234  alglib_impl::ae_state_clear(&_alglib_env_state);
5235  return;
5236  }
5238  {
5239  throw ap_error(_alglib_env_state.error_msg);
5240  }
5241 }
5242 
5243 /*************************************************************************
5244 This is obsolete function.
5245 
5246 Since ALGLIB 3.3 it is equivalent to MinLMCreateFJ().
5247 
5248  -- ALGLIB --
5249  Copyright 30.03.2009 by Bochkanov Sergey
5250 *************************************************************************/
5251 void minlmcreatefgj(const ae_int_t n, const ae_int_t m, const real_1d_array &x, minlmstate &state)
5252 {
5253  alglib_impl::ae_state _alglib_env_state;
5254  alglib_impl::ae_state_init(&_alglib_env_state);
5255  try
5256  {
5257  alglib_impl::minlmcreatefgj(n, m, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minlmstate*>(state.c_ptr()), &_alglib_env_state);
5258  alglib_impl::ae_state_clear(&_alglib_env_state);
5259  return;
5260  }
5262  {
5263  throw ap_error(_alglib_env_state.error_msg);
5264  }
5265 }
5266 
5267 /*************************************************************************
5268 This is obsolete function.
5269 
5270 Since ALGLIB 3.3 it is equivalent to MinLMCreateFJ().
5271 
5272  -- ALGLIB --
5273  Copyright 30.03.2009 by Bochkanov Sergey
5274 *************************************************************************/
5275 void minlmcreatefgj(const ae_int_t m, const real_1d_array &x, minlmstate &state)
5276 {
5277  alglib_impl::ae_state _alglib_env_state;
5278  ae_int_t n;
5279 
5280  n = x.length();
5281  alglib_impl::ae_state_init(&_alglib_env_state);
5282  try
5283  {
5284  alglib_impl::minlmcreatefgj(n, m, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minlmstate*>(state.c_ptr()), &_alglib_env_state);
5285 
5286  alglib_impl::ae_state_clear(&_alglib_env_state);
5287  return;
5288  }
5290  {
5291  throw ap_error(_alglib_env_state.error_msg);
5292  }
5293 }
5294 
5295 /*************************************************************************
5296 This function is considered obsolete since ALGLIB 3.1.0 and is present for
5297 backward compatibility only. We recommend to use MinLMCreateVJ, which
5298 provides similar, but more consistent and feature-rich interface.
5299 
5300  -- ALGLIB --
5301  Copyright 30.03.2009 by Bochkanov Sergey
5302 *************************************************************************/
5303 void minlmcreatefj(const ae_int_t n, const ae_int_t m, const real_1d_array &x, minlmstate &state)
5304 {
5305  alglib_impl::ae_state _alglib_env_state;
5306  alglib_impl::ae_state_init(&_alglib_env_state);
5307  try
5308  {
5309  alglib_impl::minlmcreatefj(n, m, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minlmstate*>(state.c_ptr()), &_alglib_env_state);
5310  alglib_impl::ae_state_clear(&_alglib_env_state);
5311  return;
5312  }
5314  {
5315  throw ap_error(_alglib_env_state.error_msg);
5316  }
5317 }
5318 
5319 /*************************************************************************
5320 This function is considered obsolete since ALGLIB 3.1.0 and is present for
5321 backward compatibility only. We recommend to use MinLMCreateVJ, which
5322 provides similar, but more consistent and feature-rich interface.
5323 
5324  -- ALGLIB --
5325  Copyright 30.03.2009 by Bochkanov Sergey
5326 *************************************************************************/
5327 void minlmcreatefj(const ae_int_t m, const real_1d_array &x, minlmstate &state)
5328 {
5329  alglib_impl::ae_state _alglib_env_state;
5330  ae_int_t n;
5331 
5332  n = x.length();
5333  alglib_impl::ae_state_init(&_alglib_env_state);
5334  try
5335  {
5336  alglib_impl::minlmcreatefj(n, m, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minlmstate*>(state.c_ptr()), &_alglib_env_state);
5337 
5338  alglib_impl::ae_state_clear(&_alglib_env_state);
5339  return;
5340  }
5342  {
5343  throw ap_error(_alglib_env_state.error_msg);
5344  }
5345 }
5346 
5347 /*************************************************************************
5348 This subroutine turns on verification of the user-supplied analytic
5349 gradient:
5350 * user calls this subroutine before optimization begins
5351 * MinLMOptimize() is called
5352 * prior to actual optimization, for each function Fi and each component
5353  of parameters being optimized X[j] algorithm performs following steps:
5354  * two trial steps are made to X[j]-TestStep*S[j] and X[j]+TestStep*S[j],
5355  where X[j] is j-th parameter and S[j] is a scale of j-th parameter
5356  * if needed, steps are bounded with respect to constraints on X[]
5357  * Fi(X) is evaluated at these trial points
5358  * we perform one more evaluation in the middle point of the interval
5359  * we build cubic model using function values and derivatives at trial
5360  points and we compare its prediction with actual value in the middle
5361  point
5362  * in case difference between prediction and actual value is higher than
5363  some predetermined threshold, algorithm stops with completion code -7;
5364  Rep.VarIdx is set to index of the parameter with incorrect derivative,
5365  Rep.FuncIdx is set to index of the function.
5366 * after verification is over, algorithm proceeds to the actual optimization.
5367 
5368 NOTE 1: verification needs N (parameters count) Jacobian evaluations. It
5369  is very costly and you should use it only for low dimensional
5370  problems, when you want to be sure that you've correctly
5371  calculated analytic derivatives. You should not use it in the
5372  production code (unless you want to check derivatives provided
5373  by some third party).
5374 
5375 NOTE 2: you should carefully choose TestStep. Value which is too large
5376  (so large that function behaviour is significantly non-cubic) will
5377  lead to false alarms. You may use different step for different
5378  parameters by means of setting scale with MinLMSetScale().
5379 
5380 NOTE 3: this function may lead to false positives. In case it reports that
5381  I-th derivative was calculated incorrectly, you may decrease test
5382  step and try one more time - maybe your function changes too
5383  sharply and your step is too large for such rapidly chanding
5384  function.
5385 
5386 INPUT PARAMETERS:
5387  State - structure used to store algorithm state
5388  TestStep - verification step:
5389  * TestStep=0 turns verification off
5390  * TestStep>0 activates verification
5391 
5392  -- ALGLIB --
5393  Copyright 15.06.2012 by Bochkanov Sergey
5394 *************************************************************************/
5395 void minlmsetgradientcheck(const minlmstate &state, const double teststep)
5396 {
5397  alglib_impl::ae_state _alglib_env_state;
5398  alglib_impl::ae_state_init(&_alglib_env_state);
5399  try
5400  {
5401  alglib_impl::minlmsetgradientcheck(const_cast<alglib_impl::minlmstate*>(state.c_ptr()), teststep, &_alglib_env_state);
5402  alglib_impl::ae_state_clear(&_alglib_env_state);
5403  return;
5404  }
5406  {
5407  throw ap_error(_alglib_env_state.error_msg);
5408  }
5409 }
5410 
5411 /*************************************************************************
5412 
5413 *************************************************************************/
5415 {
5417  if( p_struct==NULL )
5418  throw ap_error("ALGLIB: malloc error");
5420  throw ap_error("ALGLIB: malloc error");
5421 }
5422 
5424 {
5426  if( p_struct==NULL )
5427  throw ap_error("ALGLIB: malloc error");
5428  if( !alglib_impl::_minasastate_init_copy(p_struct, const_cast<alglib_impl::minasastate*>(rhs.p_struct), NULL, ae_false) )
5429  throw ap_error("ALGLIB: malloc error");
5430 }
5431 
5433 {
5434  if( this==&rhs )
5435  return *this;
5437  if( !alglib_impl::_minasastate_init_copy(p_struct, const_cast<alglib_impl::minasastate*>(rhs.p_struct), NULL, ae_false) )
5438  throw ap_error("ALGLIB: malloc error");
5439  return *this;
5440 }
5441 
5443 {
5445  ae_free(p_struct);
5446 }
5447 
5449 {
5450  return p_struct;
5451 }
5452 
5454 {
5455  return const_cast<alglib_impl::minasastate*>(p_struct);
5456 }
5457 minasastate::minasastate() : _minasastate_owner() ,needfg(p_struct->needfg),xupdated(p_struct->xupdated),f(p_struct->f),g(&p_struct->g),x(&p_struct->x)
5458 {
5459 }
5460 
5462 {
5463 }
5464 
5466 {
5467  if( this==&rhs )
5468  return *this;
5470  return *this;
5471 }
5472 
5474 {
5475 }
5476 
5477 
5478 /*************************************************************************
5479 
5480 *************************************************************************/
5482 {
5484  if( p_struct==NULL )
5485  throw ap_error("ALGLIB: malloc error");
5487  throw ap_error("ALGLIB: malloc error");
5488 }
5489 
5491 {
5493  if( p_struct==NULL )
5494  throw ap_error("ALGLIB: malloc error");
5495  if( !alglib_impl::_minasareport_init_copy(p_struct, const_cast<alglib_impl::minasareport*>(rhs.p_struct), NULL, ae_false) )
5496  throw ap_error("ALGLIB: malloc error");
5497 }
5498 
5500 {
5501  if( this==&rhs )
5502  return *this;
5504  if( !alglib_impl::_minasareport_init_copy(p_struct, const_cast<alglib_impl::minasareport*>(rhs.p_struct), NULL, ae_false) )
5505  throw ap_error("ALGLIB: malloc error");
5506  return *this;
5507 }
5508 
5510 {
5512  ae_free(p_struct);
5513 }
5514 
5516 {
5517  return p_struct;
5518 }
5519 
5521 {
5522  return const_cast<alglib_impl::minasareport*>(p_struct);
5523 }
5524 minasareport::minasareport() : _minasareport_owner() ,iterationscount(p_struct->iterationscount),nfev(p_struct->nfev),terminationtype(p_struct->terminationtype),activeconstraints(p_struct->activeconstraints)
5525 {
5526 }
5527 
5529 {
5530 }
5531 
5533 {
5534  if( this==&rhs )
5535  return *this;
5537  return *this;
5538 }
5539 
5541 {
5542 }
5543 
5544 /*************************************************************************
5545 Obsolete function, use MinLBFGSSetPrecDefault() instead.
5546 
5547  -- ALGLIB --
5548  Copyright 13.10.2010 by Bochkanov Sergey
5549 *************************************************************************/
5551 {
5552  alglib_impl::ae_state _alglib_env_state;
5553  alglib_impl::ae_state_init(&_alglib_env_state);
5554  try
5555  {
5556  alglib_impl::minlbfgssetdefaultpreconditioner(const_cast<alglib_impl::minlbfgsstate*>(state.c_ptr()), &_alglib_env_state);
5557  alglib_impl::ae_state_clear(&_alglib_env_state);
5558  return;
5559  }
5561  {
5562  throw ap_error(_alglib_env_state.error_msg);
5563  }
5564 }
5565 
5566 /*************************************************************************
5567 Obsolete function, use MinLBFGSSetCholeskyPreconditioner() instead.
5568 
5569  -- ALGLIB --
5570  Copyright 13.10.2010 by Bochkanov Sergey
5571 *************************************************************************/
5572 void minlbfgssetcholeskypreconditioner(const minlbfgsstate &state, const real_2d_array &p, const bool isupper)
5573 {
5574  alglib_impl::ae_state _alglib_env_state;
5575  alglib_impl::ae_state_init(&_alglib_env_state);
5576  try
5577  {
5578  alglib_impl::minlbfgssetcholeskypreconditioner(const_cast<alglib_impl::minlbfgsstate*>(state.c_ptr()), const_cast<alglib_impl::ae_matrix*>(p.c_ptr()), isupper, &_alglib_env_state);
5579  alglib_impl::ae_state_clear(&_alglib_env_state);
5580  return;
5581  }
5583  {
5584  throw ap_error(_alglib_env_state.error_msg);
5585  }
5586 }
5587 
5588 /*************************************************************************
5589 This is obsolete function which was used by previous version of the BLEIC
5590 optimizer. It does nothing in the current version of BLEIC.
5591 
5592  -- ALGLIB --
5593  Copyright 28.11.2010 by Bochkanov Sergey
5594 *************************************************************************/
5595 void minbleicsetbarrierwidth(const minbleicstate &state, const double mu)
5596 {
5597  alglib_impl::ae_state _alglib_env_state;
5598  alglib_impl::ae_state_init(&_alglib_env_state);
5599  try
5600  {
5601  alglib_impl::minbleicsetbarrierwidth(const_cast<alglib_impl::minbleicstate*>(state.c_ptr()), mu, &_alglib_env_state);
5602  alglib_impl::ae_state_clear(&_alglib_env_state);
5603  return;
5604  }
5606  {
5607  throw ap_error(_alglib_env_state.error_msg);
5608  }
5609 }
5610 
5611 /*************************************************************************
5612 This is obsolete function which was used by previous version of the BLEIC
5613 optimizer. It does nothing in the current version of BLEIC.
5614 
5615  -- ALGLIB --
5616  Copyright 28.11.2010 by Bochkanov Sergey
5617 *************************************************************************/
5618 void minbleicsetbarrierdecay(const minbleicstate &state, const double mudecay)
5619 {
5620  alglib_impl::ae_state _alglib_env_state;
5621  alglib_impl::ae_state_init(&_alglib_env_state);
5622  try
5623  {
5624  alglib_impl::minbleicsetbarrierdecay(const_cast<alglib_impl::minbleicstate*>(state.c_ptr()), mudecay, &_alglib_env_state);
5625  alglib_impl::ae_state_clear(&_alglib_env_state);
5626  return;
5627  }
5629  {
5630  throw ap_error(_alglib_env_state.error_msg);
5631  }
5632 }
5633 
5634 /*************************************************************************
5635 Obsolete optimization algorithm.
5636 Was replaced by MinBLEIC subpackage.
5637 
5638  -- ALGLIB --
5639  Copyright 25.03.2010 by Bochkanov Sergey
5640 *************************************************************************/
5641 void minasacreate(const ae_int_t n, const real_1d_array &x, const real_1d_array &bndl, const real_1d_array &bndu, minasastate &state)
5642 {
5643  alglib_impl::ae_state _alglib_env_state;
5644  alglib_impl::ae_state_init(&_alglib_env_state);
5645  try
5646  {
5647  alglib_impl::minasacreate(n, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(bndl.c_ptr()), const_cast<alglib_impl::ae_vector*>(bndu.c_ptr()), const_cast<alglib_impl::minasastate*>(state.c_ptr()), &_alglib_env_state);
5648  alglib_impl::ae_state_clear(&_alglib_env_state);
5649  return;
5650  }
5652  {
5653  throw ap_error(_alglib_env_state.error_msg);
5654  }
5655 }
5656 
5657 /*************************************************************************
5658 Obsolete optimization algorithm.
5659 Was replaced by MinBLEIC subpackage.
5660 
5661  -- ALGLIB --
5662  Copyright 25.03.2010 by Bochkanov Sergey
5663 *************************************************************************/
5664 void minasacreate(const real_1d_array &x, const real_1d_array &bndl, const real_1d_array &bndu, minasastate &state)
5665 {
5666  alglib_impl::ae_state _alglib_env_state;
5667  ae_int_t n;
5668  if( (x.length()!=bndl.length()) || (x.length()!=bndu.length()))
5669  throw ap_error("Error while calling 'minasacreate': looks like one of arguments has wrong size");
5670  n = x.length();
5671  alglib_impl::ae_state_init(&_alglib_env_state);
5672  try
5673  {
5674  alglib_impl::minasacreate(n, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(bndl.c_ptr()), const_cast<alglib_impl::ae_vector*>(bndu.c_ptr()), const_cast<alglib_impl::minasastate*>(state.c_ptr()), &_alglib_env_state);
5675 
5676  alglib_impl::ae_state_clear(&_alglib_env_state);
5677  return;
5678  }
5680  {
5681  throw ap_error(_alglib_env_state.error_msg);
5682  }
5683 }
5684 
5685 /*************************************************************************
5686 Obsolete optimization algorithm.
5687 Was replaced by MinBLEIC subpackage.
5688 
5689  -- ALGLIB --
5690  Copyright 02.04.2010 by Bochkanov Sergey
5691 *************************************************************************/
5692 void minasasetcond(const minasastate &state, const double epsg, const double epsf, const double epsx, const ae_int_t maxits)
5693 {
5694  alglib_impl::ae_state _alglib_env_state;
5695  alglib_impl::ae_state_init(&_alglib_env_state);
5696  try
5697  {
5698  alglib_impl::minasasetcond(const_cast<alglib_impl::minasastate*>(state.c_ptr()), epsg, epsf, epsx, maxits, &_alglib_env_state);
5699  alglib_impl::ae_state_clear(&_alglib_env_state);
5700  return;
5701  }
5703  {
5704  throw ap_error(_alglib_env_state.error_msg);
5705  }
5706 }
5707 
5708 /*************************************************************************
5709 Obsolete optimization algorithm.
5710 Was replaced by MinBLEIC subpackage.
5711 
5712  -- ALGLIB --
5713  Copyright 02.04.2010 by Bochkanov Sergey
5714 *************************************************************************/
5715 void minasasetxrep(const minasastate &state, const bool needxrep)
5716 {
5717  alglib_impl::ae_state _alglib_env_state;
5718  alglib_impl::ae_state_init(&_alglib_env_state);
5719  try
5720  {
5721  alglib_impl::minasasetxrep(const_cast<alglib_impl::minasastate*>(state.c_ptr()), needxrep, &_alglib_env_state);
5722  alglib_impl::ae_state_clear(&_alglib_env_state);
5723  return;
5724  }
5726  {
5727  throw ap_error(_alglib_env_state.error_msg);
5728  }
5729 }
5730 
5731 /*************************************************************************
5732 Obsolete optimization algorithm.
5733 Was replaced by MinBLEIC subpackage.
5734 
5735  -- ALGLIB --
5736  Copyright 02.04.2010 by Bochkanov Sergey
5737 *************************************************************************/
5738 void minasasetalgorithm(const minasastate &state, const ae_int_t algotype)
5739 {
5740  alglib_impl::ae_state _alglib_env_state;
5741  alglib_impl::ae_state_init(&_alglib_env_state);
5742  try
5743  {
5744  alglib_impl::minasasetalgorithm(const_cast<alglib_impl::minasastate*>(state.c_ptr()), algotype, &_alglib_env_state);
5745  alglib_impl::ae_state_clear(&_alglib_env_state);
5746  return;
5747  }
5749  {
5750  throw ap_error(_alglib_env_state.error_msg);
5751  }
5752 }
5753 
5754 /*************************************************************************
5755 Obsolete optimization algorithm.
5756 Was replaced by MinBLEIC subpackage.
5757 
5758  -- ALGLIB --
5759  Copyright 02.04.2010 by Bochkanov Sergey
5760 *************************************************************************/
5761 void minasasetstpmax(const minasastate &state, const double stpmax)
5762 {
5763  alglib_impl::ae_state _alglib_env_state;
5764  alglib_impl::ae_state_init(&_alglib_env_state);
5765  try
5766  {
5767  alglib_impl::minasasetstpmax(const_cast<alglib_impl::minasastate*>(state.c_ptr()), stpmax, &_alglib_env_state);
5768  alglib_impl::ae_state_clear(&_alglib_env_state);
5769  return;
5770  }
5772  {
5773  throw ap_error(_alglib_env_state.error_msg);
5774  }
5775 }
5776 
5777 /*************************************************************************
5778 This function provides reverse communication interface
5779 Reverse communication interface is not documented or recommended to use.
5780 See below for functions which provide better documented API
5781 *************************************************************************/
5782 bool minasaiteration(const minasastate &state)
5783 {
5784  alglib_impl::ae_state _alglib_env_state;
5785  alglib_impl::ae_state_init(&_alglib_env_state);
5786  try
5787  {
5788  ae_bool result = alglib_impl::minasaiteration(const_cast<alglib_impl::minasastate*>(state.c_ptr()), &_alglib_env_state);
5789  alglib_impl::ae_state_clear(&_alglib_env_state);
5790  return *(reinterpret_cast<bool*>(&result));
5791  }
5793  {
5794  throw ap_error(_alglib_env_state.error_msg);
5795  }
5796 }
5797 
5798 
5800  void (*grad)(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr),
5801  void (*rep)(const real_1d_array &x, double func, void *ptr),
5802  void *ptr)
5803 {
5804  alglib_impl::ae_state _alglib_env_state;
5805  if( grad==NULL )
5806  throw ap_error("ALGLIB: error in 'minasaoptimize()' (grad is NULL)");
5807  alglib_impl::ae_state_init(&_alglib_env_state);
5808  try
5809  {
5810  while( alglib_impl::minasaiteration(state.c_ptr(), &_alglib_env_state) )
5811  {
5812  if( state.needfg )
5813  {
5814  grad(state.x, state.f, state.g, ptr);
5815  continue;
5816  }
5817  if( state.xupdated )
5818  {
5819  if( rep!=NULL )
5820  rep(state.x, state.f, ptr);
5821  continue;
5822  }
5823  throw ap_error("ALGLIB: error in 'minasaoptimize' (some derivatives were not provided?)");
5824  }
5825  alglib_impl::ae_state_clear(&_alglib_env_state);
5826  }
5828  {
5829  throw ap_error(_alglib_env_state.error_msg);
5830  }
5831 }
5832 
5833 
5834 
5835 /*************************************************************************
5836 Obsolete optimization algorithm.
5837 Was replaced by MinBLEIC subpackage.
5838 
5839  -- ALGLIB --
5840  Copyright 20.03.2009 by Bochkanov Sergey
5841 *************************************************************************/
5843 {
5844  alglib_impl::ae_state _alglib_env_state;
5845  alglib_impl::ae_state_init(&_alglib_env_state);
5846  try
5847  {
5848  alglib_impl::minasaresults(const_cast<alglib_impl::minasastate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minasareport*>(rep.c_ptr()), &_alglib_env_state);
5849  alglib_impl::ae_state_clear(&_alglib_env_state);
5850  return;
5851  }
5853  {
5854  throw ap_error(_alglib_env_state.error_msg);
5855  }
5856 }
5857 
5858 /*************************************************************************
5859 Obsolete optimization algorithm.
5860 Was replaced by MinBLEIC subpackage.
5861 
5862  -- ALGLIB --
5863  Copyright 20.03.2009 by Bochkanov Sergey
5864 *************************************************************************/
5866 {
5867  alglib_impl::ae_state _alglib_env_state;
5868  alglib_impl::ae_state_init(&_alglib_env_state);
5869  try
5870  {
5871  alglib_impl::minasaresultsbuf(const_cast<alglib_impl::minasastate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::minasareport*>(rep.c_ptr()), &_alglib_env_state);
5872  alglib_impl::ae_state_clear(&_alglib_env_state);
5873  return;
5874  }
5876  {
5877  throw ap_error(_alglib_env_state.error_msg);
5878  }
5879 }
5880 
5881 /*************************************************************************
5882 Obsolete optimization algorithm.
5883 Was replaced by MinBLEIC subpackage.
5884 
5885  -- ALGLIB --
5886  Copyright 30.07.2010 by Bochkanov Sergey
5887 *************************************************************************/
5888 void minasarestartfrom(const minasastate &state, const real_1d_array &x, const real_1d_array &bndl, const real_1d_array &bndu)
5889 {
5890  alglib_impl::ae_state _alglib_env_state;
5891  alglib_impl::ae_state_init(&_alglib_env_state);
5892  try
5893  {
5894  alglib_impl::minasarestartfrom(const_cast<alglib_impl::minasastate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(bndl.c_ptr()), const_cast<alglib_impl::ae_vector*>(bndu.c_ptr()), &_alglib_env_state);
5895  alglib_impl::ae_state_clear(&_alglib_env_state);
5896  return;
5897  }
5899  {
5900  throw ap_error(_alglib_env_state.error_msg);
5901  }
5902 }
5903 }
5904 
5906 //
5907 // THIS SECTION CONTAINS IMPLEMENTATION OF COMPUTATIONAL CORE
5908 //
5910 namespace alglib_impl
5911 {
5912 
5913 
5914 static ae_int_t cqmodels_newtonrefinementits = 3;
5915 static ae_bool cqmodels_cqmrebuild(convexquadraticmodel* s,
5916  ae_state *_state);
5917 static void cqmodels_cqmsolveea(convexquadraticmodel* s,
5918  /* Real */ ae_vector* x,
5919  /* Real */ ae_vector* tmp,
5920  ae_state *_state);
5921 
5922 
5923 static ae_int_t snnls_iterativerefinementits = 3;
5924 static ae_bool snnls_boundedstepandactivation(/* Real */ ae_vector* xc,
5925  /* Real */ ae_vector* xn,
5926  /* Boolean */ ae_vector* nnc,
5927  ae_int_t n,
5928  ae_state *_state);
5929 
5930 
5931 static void sactivesets_constraineddescent(sactiveset* state,
5932  /* Real */ ae_vector* g,
5933  /* Real */ ae_vector* h,
5934  /* Real */ ae_matrix* ha,
5936  /* Real */ ae_vector* d,
5937  ae_state *_state);
5938 static void sactivesets_reactivateconstraints(sactiveset* state,
5939  /* Real */ ae_vector* gc,
5940  /* Real */ ae_vector* h,
5941  ae_state *_state);
5942 
5943 
5944 static ae_int_t mincg_rscountdownlen = 10;
5945 static double mincg_gtol = 0.3;
5946 static void mincg_clearrequestfields(mincgstate* state, ae_state *_state);
5947 static void mincg_preconditionedmultiply(mincgstate* state,
5948  /* Real */ ae_vector* x,
5949  /* Real */ ae_vector* work0,
5950  /* Real */ ae_vector* work1,
5951  ae_state *_state);
5952 static double mincg_preconditionedmultiply2(mincgstate* state,
5953  /* Real */ ae_vector* x,
5954  /* Real */ ae_vector* y,
5955  /* Real */ ae_vector* work0,
5956  /* Real */ ae_vector* work1,
5957  ae_state *_state);
5958 static void mincg_mincginitinternal(ae_int_t n,
5959  double diffstep,
5960  mincgstate* state,
5961  ae_state *_state);
5962 
5963 
5964 static double minbleic_gtol = 0.4;
5965 static double minbleic_maxnonmonotoniclen = 1.0E-5;
5966 static double minbleic_initialdecay = 0.5;
5967 static double minbleic_mindecay = 0.1;
5968 static double minbleic_decaycorrection = 0.8;
5969 static double minbleic_penaltyfactor = 100;
5970 static void minbleic_clearrequestfields(minbleicstate* state,
5971  ae_state *_state);
5972 static void minbleic_minbleicinitinternal(ae_int_t n,
5973  /* Real */ ae_vector* x,
5974  double diffstep,
5975  minbleicstate* state,
5976  ae_state *_state);
5977 static void minbleic_updateestimateofgoodstep(double* estimate,
5978  double newstep,
5979  ae_state *_state);
5980 
5981 
5982 static double minlbfgs_gtol = 0.4;
5983 static void minlbfgs_clearrequestfields(minlbfgsstate* state,
5984  ae_state *_state);
5985 
5986 
5987 static ae_int_t minqp_maxlagrangeits = 10;
5988 static ae_int_t minqp_maxbadnewtonits = 7;
5989 static double minqp_penaltyfactor = 100.0;
5990 static ae_int_t minqp_minqpboundedstepandactivation(minqpstate* state,
5991  /* Real */ ae_vector* xn,
5992  /* Real */ ae_vector* buf,
5993  ae_state *_state);
5994 static double minqp_minqpmodelvalue(convexquadraticmodel* a,
5995  /* Real */ ae_vector* b,
5996  /* Real */ ae_vector* xc,
5997  ae_int_t n,
5998  /* Real */ ae_vector* tmp,
5999  ae_state *_state);
6000 static ae_bool minqp_minqpconstrainedoptimum(minqpstate* state,
6001  convexquadraticmodel* a,
6002  double anorm,
6003  /* Real */ ae_vector* b,
6004  /* Real */ ae_vector* xn,
6005  /* Real */ ae_vector* tmp,
6006  /* Boolean */ ae_vector* tmpb,
6007  /* Real */ ae_vector* lagrangec,
6008  ae_state *_state);
6009 
6010 
6011 static double minlm_lambdaup = 2.0;
6012 static double minlm_lambdadown = 0.33;
6013 static double minlm_suspiciousnu = 16;
6014 static ae_int_t minlm_smallmodelage = 3;
6015 static ae_int_t minlm_additers = 5;
6016 static void minlm_lmprepare(ae_int_t n,
6017  ae_int_t m,
6018  ae_bool havegrad,
6019  minlmstate* state,
6020  ae_state *_state);
6021 static void minlm_clearrequestfields(minlmstate* state, ae_state *_state);
6022 static ae_bool minlm_increaselambda(double* lambdav,
6023  double* nu,
6024  ae_state *_state);
6025 static void minlm_decreaselambda(double* lambdav,
6026  double* nu,
6027  ae_state *_state);
6028 static double minlm_boundedscaledantigradnorm(minlmstate* state,
6029  /* Real */ ae_vector* x,
6030  /* Real */ ae_vector* g,
6031  ae_state *_state);
6032 
6033 
6034 static ae_int_t mincomp_n1 = 2;
6035 static ae_int_t mincomp_n2 = 2;
6036 static double mincomp_stpmin = 1.0E-300;
6037 static double mincomp_gtol = 0.3;
6038 static double mincomp_gpaftol = 0.0001;
6039 static double mincomp_gpadecay = 0.5;
6040 static double mincomp_asarho = 0.5;
6041 static double mincomp_asaboundedantigradnorm(minasastate* state,
6042  ae_state *_state);
6043 static double mincomp_asaginorm(minasastate* state, ae_state *_state);
6044 static double mincomp_asad1norm(minasastate* state, ae_state *_state);
6045 static ae_bool mincomp_asauisempty(minasastate* state, ae_state *_state);
6046 static void mincomp_clearrequestfields(minasastate* state,
6047  ae_state *_state);
6048 
6049 
6050 
6051 
6052 
6053 /*************************************************************************
6054 This subroutine is used to prepare threshold value which will be used for
6055 trimming of the target function (see comments on TrimFunction() for more
6056 information).
6057 
6058 This function accepts only one parameter: function value at the starting
6059 point. It returns threshold which will be used for trimming.
6060 
6061  -- ALGLIB --
6062  Copyright 10.05.2011 by Bochkanov Sergey
6063 *************************************************************************/
6064 void trimprepare(double f, double* threshold, ae_state *_state)
6065 {
6066 
6067  *threshold = 0;
6068 
6069  *threshold = 10*(ae_fabs(f, _state)+1);
6070 }
6071 
6072 
6073 /*************************************************************************
6074 This subroutine is used to "trim" target function, i.e. to do following
6075 transformation:
6076 
6077  { {F,G} if F<Threshold
6078  {F_tr, G_tr} = {
6079  { {Threshold, 0} if F>=Threshold
6080 
6081 Such transformation allows us to solve problems with singularities by
6082 redefining function in such way that it becomes bounded from above.
6083 
6084  -- ALGLIB --
6085  Copyright 10.05.2011 by Bochkanov Sergey
6086 *************************************************************************/
6087 void trimfunction(double* f,
6088  /* Real */ ae_vector* g,
6089  ae_int_t n,
6090  double threshold,
6091  ae_state *_state)
6092 {
6093  ae_int_t i;
6094 
6095 
6096  if( ae_fp_greater_eq(*f,threshold) )
6097  {
6098  *f = threshold;
6099  for(i=0; i<=n-1; i++)
6100  {
6101  g->ptr.p_double[i] = 0.0;
6102  }
6103  }
6104 }
6105 
6106 
6107 /*************************************************************************
6108 This function enforces boundary constraints in the X.
6109 
6110 This function correctly (although a bit inefficient) handles BL[i] which
6111 are -INF and BU[i] which are +INF.
6112 
6113 We have NMain+NSlack dimensional X, with first NMain components bounded
6114 by BL/BU, and next NSlack ones bounded by non-negativity constraints.
6115 
6116 INPUT PARAMETERS
6117  X - array[NMain+NSlack], point
6118  BL - array[NMain], lower bounds
6119  (may contain -INF, when bound is not present)
6120  HaveBL - array[NMain], if HaveBL[i] is False,
6121  then i-th bound is not present
6122  BU - array[NMain], upper bounds
6123  (may contain +INF, when bound is not present)
6124  HaveBU - array[NMain], if HaveBU[i] is False,
6125  then i-th bound is not present
6126 
6127 OUTPUT PARAMETERS
6128  X - X with all constraints being enforced
6129 
6130 It returns True when constraints are consistent,
6131 False - when constraints are inconsistent.
6132 
6133  -- ALGLIB --
6134  Copyright 10.01.2012 by Bochkanov Sergey
6135 *************************************************************************/
6137  /* Real */ ae_vector* bl,
6138  /* Boolean */ ae_vector* havebl,
6139  /* Real */ ae_vector* bu,
6140  /* Boolean */ ae_vector* havebu,
6141  ae_int_t nmain,
6142  ae_int_t nslack,
6143  ae_state *_state)
6144 {
6145  ae_int_t i;
6146  ae_bool result;
6147 
6148 
6149  result = ae_false;
6150  for(i=0; i<=nmain-1; i++)
6151  {
6152  if( (havebl->ptr.p_bool[i]&&havebu->ptr.p_bool[i])&&ae_fp_greater(bl->ptr.p_double[i],bu->ptr.p_double[i]) )
6153  {
6154  return result;
6155  }
6156  if( havebl->ptr.p_bool[i]&&ae_fp_less(x->ptr.p_double[i],bl->ptr.p_double[i]) )
6157  {
6158  x->ptr.p_double[i] = bl->ptr.p_double[i];
6159  }
6160  if( havebu->ptr.p_bool[i]&&ae_fp_greater(x->ptr.p_double[i],bu->ptr.p_double[i]) )
6161  {
6162  x->ptr.p_double[i] = bu->ptr.p_double[i];
6163  }
6164  }
6165  for(i=0; i<=nslack-1; i++)
6166  {
6167  if( ae_fp_less(x->ptr.p_double[nmain+i],0) )
6168  {
6169  x->ptr.p_double[nmain+i] = 0;
6170  }
6171  }
6172  result = ae_true;
6173  return result;
6174 }
6175 
6176 
6177 /*************************************************************************
6178 This function projects gradient into feasible area of boundary constrained
6179 optimization problem. X can be infeasible with respect to boundary
6180 constraints. We have NMain+NSlack dimensional X, with first NMain
6181 components bounded by BL/BU, and next NSlack ones bounded by non-negativity
6182 constraints.
6183 
6184 INPUT PARAMETERS
6185  X - array[NMain+NSlack], point
6186  G - array[NMain+NSlack], gradient
6187  BL - lower bounds (may contain -INF, when bound is not present)
6188  HaveBL - if HaveBL[i] is False, then i-th bound is not present
6189  BU - upper bounds (may contain +INF, when bound is not present)
6190  HaveBU - if HaveBU[i] is False, then i-th bound is not present
6191 
6192 OUTPUT PARAMETERS
6193  G - projection of G. Components of G which satisfy one of the
6194  following
6195  (1) (X[I]<=BndL[I]) and (G[I]>0), OR
6196  (2) (X[I]>=BndU[I]) and (G[I]<0)
6197  are replaced by zeros.
6198 
6199 NOTE 1: this function assumes that constraints are feasible. It throws
6200 exception otherwise.
6201 
6202 NOTE 2: in fact, projection of ANTI-gradient is calculated, because this
6203 function trims components of -G which points outside of the feasible area.
6204 However, working with -G is considered confusing, because all optimization
6205 source work with G.
6206 
6207  -- ALGLIB --
6208  Copyright 10.01.2012 by Bochkanov Sergey
6209 *************************************************************************/
6211  /* Real */ ae_vector* g,
6212  /* Real */ ae_vector* bl,
6213  /* Boolean */ ae_vector* havebl,
6214  /* Real */ ae_vector* bu,
6215  /* Boolean */ ae_vector* havebu,
6216  ae_int_t nmain,
6217  ae_int_t nslack,
6218  ae_state *_state)
6219 {
6220  ae_int_t i;
6221 
6222 
6223  for(i=0; i<=nmain-1; i++)
6224  {
6225  ae_assert((!havebl->ptr.p_bool[i]||!havebu->ptr.p_bool[i])||ae_fp_less_eq(bl->ptr.p_double[i],bu->ptr.p_double[i]), "ProjectGradientIntoBC: internal error (infeasible constraints)", _state);
6226  if( (havebl->ptr.p_bool[i]&&ae_fp_less_eq(x->ptr.p_double[i],bl->ptr.p_double[i]))&&ae_fp_greater(g->ptr.p_double[i],0) )
6227  {
6228  g->ptr.p_double[i] = 0;
6229  }
6230  if( (havebu->ptr.p_bool[i]&&ae_fp_greater_eq(x->ptr.p_double[i],bu->ptr.p_double[i]))&&ae_fp_less(g->ptr.p_double[i],0) )
6231  {
6232  g->ptr.p_double[i] = 0;
6233  }
6234  }
6235  for(i=0; i<=nslack-1; i++)
6236  {
6237  if( ae_fp_less_eq(x->ptr.p_double[nmain+i],0)&&ae_fp_greater(g->ptr.p_double[nmain+i],0) )
6238  {
6239  g->ptr.p_double[nmain+i] = 0;
6240  }
6241  }
6242 }
6243 
6244 
6245 /*************************************************************************
6246 Given
6247  a) initial point X0[NMain+NSlack]
6248  (feasible with respect to bound constraints)
6249  b) step vector alpha*D[NMain+NSlack]
6250  c) boundary constraints BndL[NMain], BndU[NMain]
6251  d) implicit non-negativity constraints for slack variables
6252 this function calculates bound on the step length subject to boundary
6253 constraints.
6254 
6255 It returns:
6256  * MaxStepLen - such step length that X0+MaxStepLen*alpha*D is exactly
6257  at the boundary given by constraints
6258  * VariableToFreeze - index of the constraint to be activated,
6259  0 <= VariableToFreeze < NMain+NSlack
6260  * ValueToFreeze - value of the corresponding constraint.
6261 
6262 Notes:
6263  * it is possible that several constraints can be activated by the step
6264  at once. In such cases only one constraint is returned. It is caller
6265  responsibility to check other constraints. This function makes sure
6266  that we activate at least one constraint, and everything else is the
6267  responsibility of the caller.
6268  * steps smaller than MaxStepLen still can activate constraints due to
6269  numerical errors. Thus purpose of this function is not to guard
6270  against accidental activation of the constraints - quite the reverse,
6271  its purpose is to activate at least constraint upon performing step
6272  which is too long.
6273  * in case there is no constraints to activate, we return negative
6274  VariableToFreeze and zero MaxStepLen and ValueToFreeze.
6275  * this function assumes that constraints are consistent; it throws
6276  exception otherwise.
6277 
6278 INPUT PARAMETERS
6279  X - array[NMain+NSlack], point. Must be feasible with respect
6280  to bound constraints (exception will be thrown otherwise)
6281  D - array[NMain+NSlack], step direction
6282  alpha - scalar multiplier before D, alpha<>0
6283  BndL - lower bounds, array[NMain]
6284  (may contain -INF, when bound is not present)
6285  HaveBndL - array[NMain], if HaveBndL[i] is False,
6286  then i-th bound is not present
6287  BndU - array[NMain], upper bounds
6288  (may contain +INF, when bound is not present)
6289  HaveBndU - array[NMain], if HaveBndU[i] is False,
6290  then i-th bound is not present
6291  NMain - number of main variables
6292  NSlack - number of slack variables
6293 
6294 OUTPUT PARAMETERS
6295  VariableToFreeze:
6296  * negative value = step is unbounded, ValueToFreeze=0,
6297  MaxStepLen=0.
6298  * non-negative value = at least one constraint, given by
6299  this parameter, will be activated
6300  upon performing maximum step.
6301  ValueToFreeze- value of the variable which will be constrained
6302  MaxStepLen - maximum length of the step. Can be zero when step vector
6303  looks outside of the feasible area.
6304 
6305  -- ALGLIB --
6306  Copyright 10.01.2012 by Bochkanov Sergey
6307 *************************************************************************/
6308 void calculatestepbound(/* Real */ ae_vector* x,
6309  /* Real */ ae_vector* d,
6310  double alpha,
6311  /* Real */ ae_vector* bndl,
6312  /* Boolean */ ae_vector* havebndl,
6313  /* Real */ ae_vector* bndu,
6314  /* Boolean */ ae_vector* havebndu,
6315  ae_int_t nmain,
6316  ae_int_t nslack,
6317  ae_int_t* variabletofreeze,
6318  double* valuetofreeze,
6319  double* maxsteplen,
6320  ae_state *_state)
6321 {
6322  ae_int_t i;
6323  double prevmax;
6324  double initval;
6325 
6326  *variabletofreeze = 0;
6327  *valuetofreeze = 0;
6328  *maxsteplen = 0;
6329 
6330  ae_assert(ae_fp_neq(alpha,0), "CalculateStepBound: zero alpha", _state);
6331  *variabletofreeze = -1;
6332  initval = ae_maxrealnumber;
6333  *maxsteplen = initval;
6334  for(i=0; i<=nmain-1; i++)
6335  {
6336  if( havebndl->ptr.p_bool[i]&&ae_fp_less(alpha*d->ptr.p_double[i],0) )
6337  {
6338  ae_assert(ae_fp_greater_eq(x->ptr.p_double[i],bndl->ptr.p_double[i]), "CalculateStepBound: infeasible X", _state);
6339  prevmax = *maxsteplen;
6340  *maxsteplen = safeminposrv(x->ptr.p_double[i]-bndl->ptr.p_double[i], -alpha*d->ptr.p_double[i], *maxsteplen, _state);
6341  if( ae_fp_less(*maxsteplen,prevmax) )
6342  {
6343  *variabletofreeze = i;
6344  *valuetofreeze = bndl->ptr.p_double[i];
6345  }
6346  }
6347  if( havebndu->ptr.p_bool[i]&&ae_fp_greater(alpha*d->ptr.p_double[i],0) )
6348  {
6349  ae_assert(ae_fp_less_eq(x->ptr.p_double[i],bndu->ptr.p_double[i]), "CalculateStepBound: infeasible X", _state);
6350  prevmax = *maxsteplen;
6351  *maxsteplen = safeminposrv(bndu->ptr.p_double[i]-x->ptr.p_double[i], alpha*d->ptr.p_double[i], *maxsteplen, _state);
6352  if( ae_fp_less(*maxsteplen,prevmax) )
6353  {
6354  *variabletofreeze = i;
6355  *valuetofreeze = bndu->ptr.p_double[i];
6356  }
6357  }
6358  }
6359  for(i=0; i<=nslack-1; i++)
6360  {
6361  if( ae_fp_less(alpha*d->ptr.p_double[nmain+i],0) )
6362  {
6363  ae_assert(ae_fp_greater_eq(x->ptr.p_double[nmain+i],0), "CalculateStepBound: infeasible X", _state);
6364  prevmax = *maxsteplen;
6365  *maxsteplen = safeminposrv(x->ptr.p_double[nmain+i], -alpha*d->ptr.p_double[nmain+i], *maxsteplen, _state);
6366  if( ae_fp_less(*maxsteplen,prevmax) )
6367  {
6368  *variabletofreeze = nmain+i;
6369  *valuetofreeze = 0;
6370  }
6371  }
6372  }
6373  if( ae_fp_eq(*maxsteplen,initval) )
6374  {
6375  *valuetofreeze = 0;
6376  *maxsteplen = 0;
6377  }
6378 }
6379 
6380 
6381 /*************************************************************************
6382 This function postprocesses bounded step by:
6383 * analysing step length (whether it is equal to MaxStepLen) and activating
6384  constraint given by VariableToFreeze if needed
6385 * checking for additional bound constraints to activate
6386 
6387 This function uses final point of the step, quantities calculated by the
6388 CalculateStepBound() function. As result, it returns point which is
6389 exactly feasible with respect to boundary constraints.
6390 
6391 NOTE 1: this function does NOT handle and check linear equality constraints
6392 NOTE 2: when StepTaken=MaxStepLen we always activate at least one constraint
6393 
6394 INPUT PARAMETERS
6395  X - array[NMain+NSlack], final point to postprocess
6396  XPrev - array[NMain+NSlack], initial point
6397  BndL - lower bounds, array[NMain]
6398  (may contain -INF, when bound is not present)
6399  HaveBndL - array[NMain], if HaveBndL[i] is False,
6400  then i-th bound is not present
6401  BndU - array[NMain], upper bounds
6402  (may contain +INF, when bound is not present)
6403  HaveBndU - array[NMain], if HaveBndU[i] is False,
6404  then i-th bound is not present
6405  NMain - number of main variables
6406  NSlack - number of slack variables
6407  VariableToFreeze-result of CalculateStepBound()
6408  ValueToFreeze- result of CalculateStepBound()
6409  StepTaken - actual step length (actual step is equal to the possibly
6410  non-unit step direction vector times this parameter).
6411  StepTaken<=MaxStepLen.
6412  MaxStepLen - result of CalculateStepBound()
6413 
6414 OUTPUT PARAMETERS
6415  X - point bounded with respect to constraints.
6416  components corresponding to active constraints are exactly
6417  equal to the boundary values.
6418 
6419 RESULT:
6420  number of constraints activated in addition to previously active ones.
6421  Constraints which were DEACTIVATED are ignored (do not influence
6422  function value).
6423 
6424  -- ALGLIB --
6425  Copyright 10.01.2012 by Bochkanov Sergey
6426 *************************************************************************/
6428  /* Real */ ae_vector* xprev,
6429  /* Real */ ae_vector* bndl,
6430  /* Boolean */ ae_vector* havebndl,
6431  /* Real */ ae_vector* bndu,
6432  /* Boolean */ ae_vector* havebndu,
6433  ae_int_t nmain,
6434  ae_int_t nslack,
6435  ae_int_t variabletofreeze,
6436  double valuetofreeze,
6437  double steptaken,
6438  double maxsteplen,
6439  ae_state *_state)
6440 {
6441  ae_int_t i;
6442  ae_bool wasactivated;
6443  ae_int_t result;
6444 
6445 
6446  ae_assert(variabletofreeze<0||ae_fp_less_eq(steptaken,maxsteplen), "Assertion failed", _state);
6447 
6448  /*
6449  * Activate constraints
6450  */
6451  if( variabletofreeze>=0&&ae_fp_eq(steptaken,maxsteplen) )
6452  {
6453  x->ptr.p_double[variabletofreeze] = valuetofreeze;
6454  }
6455  for(i=0; i<=nmain-1; i++)
6456  {
6457  if( havebndl->ptr.p_bool[i]&&ae_fp_less(x->ptr.p_double[i],bndl->ptr.p_double[i]) )
6458  {
6459  x->ptr.p_double[i] = bndl->ptr.p_double[i];
6460  }
6461  if( havebndu->ptr.p_bool[i]&&ae_fp_greater(x->ptr.p_double[i],bndu->ptr.p_double[i]) )
6462  {
6463  x->ptr.p_double[i] = bndu->ptr.p_double[i];
6464  }
6465  }
6466  for(i=0; i<=nslack-1; i++)
6467  {
6468  if( ae_fp_less_eq(x->ptr.p_double[nmain+i],0) )
6469  {
6470  x->ptr.p_double[nmain+i] = 0;
6471  }
6472  }
6473 
6474  /*
6475  * Calculate number of constraints being activated
6476  */
6477  result = 0;
6478  for(i=0; i<=nmain-1; i++)
6479  {
6480  wasactivated = ae_fp_neq(x->ptr.p_double[i],xprev->ptr.p_double[i])&&((havebndl->ptr.p_bool[i]&&ae_fp_eq(x->ptr.p_double[i],bndl->ptr.p_double[i]))||(havebndu->ptr.p_bool[i]&&ae_fp_eq(x->ptr.p_double[i],bndu->ptr.p_double[i])));
6481  wasactivated = wasactivated||variabletofreeze==i;
6482  if( wasactivated )
6483  {
6484  result = result+1;
6485  }
6486  }
6487  for(i=0; i<=nslack-1; i++)
6488  {
6489  wasactivated = ae_fp_neq(x->ptr.p_double[nmain+i],xprev->ptr.p_double[nmain+i])&&ae_fp_eq(x->ptr.p_double[nmain+i],0.0);
6490  wasactivated = wasactivated||variabletofreeze==nmain+i;
6491  if( wasactivated )
6492  {
6493  result = result+1;
6494  }
6495  }
6496  return result;
6497 }
6498 
6499 
6500 /*************************************************************************
6501 The purpose of this function is to prevent algorithm from "unsticking"
6502 from the active bound constraints because of numerical noise in the
6503 gradient or Hessian.
6504 
6505 It is done by zeroing some components of the search direction D. D[i] is
6506 zeroed when both (a) and (b) are true:
6507 a) corresponding X[i] is exactly at the boundary
6508 b) |D[i]*S[i]| <= DropTol*Sqrt(SUM(D[i]^2*S[I]^2))
6509 
6510 D can be step direction , antigradient, gradient, or anything similar.
6511 Sign of D does not matter, nor matters step length.
6512 
6513 NOTE 1: boundary constraints are expected to be consistent, as well as X
6514  is expected to be feasible. Exception will be thrown otherwise.
6515 
6516 INPUT PARAMETERS
6517  D - array[NMain+NSlack], direction
6518  X - array[NMain+NSlack], current point
6519  BndL - lower bounds, array[NMain]
6520  (may contain -INF, when bound is not present)
6521  HaveBndL - array[NMain], if HaveBndL[i] is False,
6522  then i-th bound is not present
6523  BndU - array[NMain], upper bounds
6524  (may contain +INF, when bound is not present)
6525  HaveBndU - array[NMain], if HaveBndU[i] is False,
6526  then i-th bound is not present
6527  S - array[NMain+NSlack], scaling of the variables
6528  NMain - number of main variables
6529  NSlack - number of slack variables
6530  DropTol - drop tolerance, >=0
6531 
6532 OUTPUT PARAMETERS
6533  X - point bounded with respect to constraints.
6534  components corresponding to active constraints are exactly
6535  equal to the boundary values.
6536 
6537  -- ALGLIB --
6538  Copyright 10.01.2012 by Bochkanov Sergey
6539 *************************************************************************/
6540 void filterdirection(/* Real */ ae_vector* d,
6541  /* Real */ ae_vector* x,
6542  /* Real */ ae_vector* bndl,
6543  /* Boolean */ ae_vector* havebndl,
6544  /* Real */ ae_vector* bndu,
6545  /* Boolean */ ae_vector* havebndu,
6546  /* Real */ ae_vector* s,
6547  ae_int_t nmain,
6548  ae_int_t nslack,
6549  double droptol,
6550  ae_state *_state)
6551 {
6552  ae_int_t i;
6553  double scalednorm;
6554  ae_bool isactive;
6555 
6556 
6557  scalednorm = 0.0;
6558  for(i=0; i<=nmain+nslack-1; i++)
6559  {
6560  scalednorm = scalednorm+ae_sqr(d->ptr.p_double[i]*s->ptr.p_double[i], _state);
6561  }
6562  scalednorm = ae_sqrt(scalednorm, _state);
6563  for(i=0; i<=nmain-1; i++)
6564  {
6565  ae_assert(!havebndl->ptr.p_bool[i]||ae_fp_greater_eq(x->ptr.p_double[i],bndl->ptr.p_double[i]), "FilterDirection: infeasible point", _state);
6566  ae_assert(!havebndu->ptr.p_bool[i]||ae_fp_less_eq(x->ptr.p_double[i],bndu->ptr.p_double[i]), "FilterDirection: infeasible point", _state);
6567  isactive = (havebndl->ptr.p_bool[i]&&ae_fp_eq(x->ptr.p_double[i],bndl->ptr.p_double[i]))||(havebndu->ptr.p_bool[i]&&ae_fp_eq(x->ptr.p_double[i],bndu->ptr.p_double[i]));
6568  if( isactive&&ae_fp_less_eq(ae_fabs(d->ptr.p_double[i]*s->ptr.p_double[i], _state),droptol*scalednorm) )
6569  {
6570  d->ptr.p_double[i] = 0.0;
6571  }
6572  }
6573  for(i=0; i<=nslack-1; i++)
6574  {
6575  ae_assert(ae_fp_greater_eq(x->ptr.p_double[nmain+i],0), "FilterDirection: infeasible point", _state);
6576  if( ae_fp_eq(x->ptr.p_double[nmain+i],0)&&ae_fp_less_eq(ae_fabs(d->ptr.p_double[nmain+i]*s->ptr.p_double[nmain+i], _state),droptol*scalednorm) )
6577  {
6578  d->ptr.p_double[nmain+i] = 0.0;
6579  }
6580  }
6581 }
6582 
6583 
6584 /*************************************************************************
6585 This function returns number of bound constraints whose state was changed
6586 (either activated or deactivated) when making step from XPrev to X.
6587 
6588 Constraints are considered:
6589 * active - when we are exactly at the boundary
6590 * inactive - when we are not at the boundary
6591 
6592 You should note that antigradient direction is NOT taken into account when
6593 we make decions on the constraint status.
6594 
6595 INPUT PARAMETERS
6596  X - array[NMain+NSlack], final point.
6597  Must be feasible with respect to bound constraints.
6598  XPrev - array[NMain+NSlack], initial point.
6599  Must be feasible with respect to bound constraints.
6600  BndL - lower bounds, array[NMain]
6601  (may contain -INF, when bound is not present)
6602  HaveBndL - array[NMain], if HaveBndL[i] is False,
6603  then i-th bound is not present
6604  BndU - array[NMain], upper bounds
6605  (may contain +INF, when bound is not present)
6606  HaveBndU - array[NMain], if HaveBndU[i] is False,
6607  then i-th bound is not present
6608  NMain - number of main variables
6609  NSlack - number of slack variables
6610 
6611 RESULT:
6612  number of constraints whose state was changed.
6613 
6614  -- ALGLIB --
6615  Copyright 10.01.2012 by Bochkanov Sergey
6616 *************************************************************************/
6618  /* Real */ ae_vector* xprev,
6619  /* Real */ ae_vector* bndl,
6620  /* Boolean */ ae_vector* havebndl,
6621  /* Real */ ae_vector* bndu,
6622  /* Boolean */ ae_vector* havebndu,
6623  ae_int_t nmain,
6624  ae_int_t nslack,
6625  ae_state *_state)
6626 {
6627  ae_int_t i;
6628  ae_bool statuschanged;
6629  ae_int_t result;
6630 
6631 
6632  result = 0;
6633  for(i=0; i<=nmain-1; i++)
6634  {
6635  if( ae_fp_neq(x->ptr.p_double[i],xprev->ptr.p_double[i]) )
6636  {
6637  statuschanged = ae_false;
6638  if( havebndl->ptr.p_bool[i]&&(ae_fp_eq(x->ptr.p_double[i],bndl->ptr.p_double[i])||ae_fp_eq(xprev->ptr.p_double[i],bndl->ptr.p_double[i])) )
6639  {
6640  statuschanged = ae_true;
6641  }
6642  if( havebndu->ptr.p_bool[i]&&(ae_fp_eq(x->ptr.p_double[i],bndu->ptr.p_double[i])||ae_fp_eq(xprev->ptr.p_double[i],bndu->ptr.p_double[i])) )
6643  {
6644  statuschanged = ae_true;
6645  }
6646  if( statuschanged )
6647  {
6648  result = result+1;
6649  }
6650  }
6651  }
6652  for(i=0; i<=nslack-1; i++)
6653  {
6654  if( ae_fp_neq(x->ptr.p_double[nmain+i],xprev->ptr.p_double[nmain+i])&&(ae_fp_eq(x->ptr.p_double[nmain+i],0)||ae_fp_eq(xprev->ptr.p_double[nmain+i],0)) )
6655  {
6656  result = result+1;
6657  }
6658  }
6659  return result;
6660 }
6661 
6662 
6663 /*************************************************************************
6664 This function finds feasible point of (NMain+NSlack)-dimensional problem
6665 subject to NMain explicit boundary constraints (some constraints can be
6666 omitted), NSlack implicit non-negativity constraints, K linear equality
6667 constraints.
6668 
6669 INPUT PARAMETERS
6670  X - array[NMain+NSlack], initial point.
6671  BndL - lower bounds, array[NMain]
6672  (may contain -INF, when bound is not present)
6673  HaveBndL - array[NMain], if HaveBndL[i] is False,
6674  then i-th bound is not present
6675  BndU - array[NMain], upper bounds
6676  (may contain +INF, when bound is not present)
6677  HaveBndU - array[NMain], if HaveBndU[i] is False,
6678  then i-th bound is not present
6679  NMain - number of main variables
6680  NSlack - number of slack variables
6681  CE - array[K,NMain+NSlack+1], equality constraints CE*x=b.
6682  Rows contain constraints, first NMain+NSlack columns
6683  contain coefficients before X[], last column contain
6684  right part.
6685  K - number of linear constraints
6686  EpsI - infeasibility (error in the right part) allowed in the
6687  solution
6688 
6689 OUTPUT PARAMETERS:
6690  X - feasible point or best infeasible point found before
6691  algorithm termination
6692  QPIts - number of QP iterations (for debug purposes)
6693  GPAIts - number of GPA iterations (for debug purposes)
6694 
6695 RESULT:
6696  True in case X is feasible, False - if it is infeasible.
6697 
6698  -- ALGLIB --
6699  Copyright 20.01.2012 by Bochkanov Sergey
6700 *************************************************************************/
6702  /* Real */ ae_vector* bndl,
6703  /* Boolean */ ae_vector* havebndl,
6704  /* Real */ ae_vector* bndu,
6705  /* Boolean */ ae_vector* havebndu,
6706  ae_int_t nmain,
6707  ae_int_t nslack,
6708  /* Real */ ae_matrix* ce,
6709  ae_int_t k,
6710  double epsi,
6711  ae_int_t* qpits,
6712  ae_int_t* gpaits,
6713  ae_state *_state)
6714 {
6715  ae_frame _frame_block;
6716  ae_matrix _ce;
6717  ae_int_t i;
6718  ae_int_t j;
6719  ae_int_t idx0;
6720  ae_int_t idx1;
6721  ae_vector permx;
6722  ae_vector xn;
6723  ae_vector xa;
6724  ae_vector newtonstep;
6725  ae_vector g;
6726  ae_vector pg;
6727  ae_matrix a;
6728  double armijostep;
6729  double armijobeststep;
6730  double armijobestfeas;
6731  double v;
6732  double mx;
6733  double feaserr;
6734  double feasold;
6735  double feasnew;
6736  double pgnorm;
6737  double vn;
6738  double vd;
6739  double stp;
6740  ae_int_t vartofreeze;
6741  double valtofreeze;
6742  double maxsteplen;
6743  ae_bool werechangesinconstraints;
6744  ae_bool stage1isover;
6745  ae_bool converged;
6747  ae_vector tmpk;
6748  ae_vector colnorms;
6749  ae_int_t nactive;
6750  ae_int_t nfree;
6751  ae_int_t nsvd;
6752  ae_vector p1;
6753  ae_vector p2;
6754  apbuffers buf;
6755  ae_vector w;
6756  ae_vector s;
6757  ae_matrix u;
6758  ae_matrix vt;
6759  ae_int_t itscount;
6760  ae_int_t itswithintolerance;
6761  ae_int_t maxitswithintolerance;
6762  ae_int_t gparuns;
6763  ae_int_t maxarmijoruns;
6764  ae_bool result;
6765 
6766  ae_frame_make(_state, &_frame_block);
6767  ae_matrix_init_copy(&_ce, ce, _state, ae_true);
6768  ce = &_ce;
6769  *qpits = 0;
6770  *gpaits = 0;
6771  ae_vector_init(&permx, 0, DT_REAL, _state, ae_true);
6772  ae_vector_init(&xn, 0, DT_REAL, _state, ae_true);
6773  ae_vector_init(&xa, 0, DT_REAL, _state, ae_true);
6774  ae_vector_init(&newtonstep, 0, DT_REAL, _state, ae_true);
6775  ae_vector_init(&g, 0, DT_REAL, _state, ae_true);
6776  ae_vector_init(&pg, 0, DT_REAL, _state, ae_true);
6777  ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
6778  ae_vector_init(&activeconstraints, 0, DT_REAL, _state, ae_true);
6779  ae_vector_init(&tmpk, 0, DT_REAL, _state, ae_true);
6780  ae_vector_init(&colnorms, 0, DT_REAL, _state, ae_true);
6781  ae_vector_init(&p1, 0, DT_INT, _state, ae_true);
6782  ae_vector_init(&p2, 0, DT_INT, _state, ae_true);
6783  _apbuffers_init(&buf, _state, ae_true);
6784  ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
6785  ae_vector_init(&s, 0, DT_REAL, _state, ae_true);
6786  ae_matrix_init(&u, 0, 0, DT_REAL, _state, ae_true);
6787  ae_matrix_init(&vt, 0, 0, DT_REAL, _state, ae_true);
6788 
6789  maxitswithintolerance = 3;
6790  maxarmijoruns = 5;
6791  *qpits = 0;
6792  *gpaits = 0;
6793 
6794  /*
6795  * Initial enforcement of the feasibility with respect to boundary constraints
6796  * NOTE: after this block we assume that boundary constraints are consistent.
6797  */
6798  if( !enforceboundaryconstraints(x, bndl, havebndl, bndu, havebndu, nmain, nslack, _state) )
6799  {
6800  result = ae_false;
6801  ae_frame_leave(_state);
6802  return result;
6803  }
6804  if( k==0 )
6805  {
6806 
6807  /*
6808  * No linear constraints, we can exit right now
6809  */
6810  result = ae_true;
6811  ae_frame_leave(_state);
6812  return result;
6813  }
6814 
6815  /*
6816  * Scale rows of CE in such way that max(CE[i,0..nmain+nslack-1])=1 for any i=0..k-1
6817  */
6818  for(i=0; i<=k-1; i++)
6819  {
6820  v = 0.0;
6821  for(j=0; j<=nmain+nslack-1; j++)
6822  {
6823  v = ae_maxreal(v, ae_fabs(ce->ptr.pp_double[i][j], _state), _state);
6824  }
6825  if( ae_fp_neq(v,0) )
6826  {
6827  v = 1/v;
6828  ae_v_muld(&ce->ptr.pp_double[i][0], 1, ae_v_len(0,nmain+nslack), v);
6829  }
6830  }
6831 
6832  /*
6833  * Allocate temporaries
6834  */
6835  ae_vector_set_length(&xn, nmain+nslack, _state);
6836  ae_vector_set_length(&xa, nmain+nslack, _state);
6837  ae_vector_set_length(&permx, nmain+nslack, _state);
6838  ae_vector_set_length(&g, nmain+nslack, _state);
6839  ae_vector_set_length(&pg, nmain+nslack, _state);
6840  ae_vector_set_length(&tmpk, k, _state);
6841  ae_matrix_set_length(&a, k, nmain+nslack, _state);
6842  ae_vector_set_length(&activeconstraints, nmain+nslack, _state);
6843  ae_vector_set_length(&newtonstep, nmain+nslack, _state);
6844  ae_vector_set_length(&s, nmain+nslack, _state);
6845  ae_vector_set_length(&colnorms, nmain+nslack, _state);
6846  for(i=0; i<=nmain+nslack-1; i++)
6847  {
6848  s.ptr.p_double[i] = 1.0;
6849  colnorms.ptr.p_double[i] = 0.0;
6850  for(j=0; j<=k-1; j++)
6851  {
6852  colnorms.ptr.p_double[i] = colnorms.ptr.p_double[i]+ae_sqr(ce->ptr.pp_double[j][i], _state);
6853  }
6854  }
6855 
6856  /*
6857  * K>0, we have linear equality constraints combined with bound constraints.
6858  *
6859  * Try to find feasible point as minimizer of the quadratic function
6860  * F(x) = 0.5*||CE*x-b||^2 = 0.5*x'*(CE'*CE)*x - (b'*CE)*x + 0.5*b'*b
6861  * subject to boundary constraints given by BL, BU and non-negativity of
6862  * the slack variables. BTW, we drop constant term because it does not
6863  * actually influences on the solution.
6864  *
6865  * Below we will assume that K>0.
6866  */
6867  itswithintolerance = 0;
6868  itscount = 0;
6869  for(;;)
6870  {
6871 
6872  /*
6873  * Stage 0: check for exact convergence
6874  */
6875  converged = ae_true;
6876  feaserr = 0;
6877  for(i=0; i<=k-1; i++)
6878  {
6879 
6880  /*
6881  * Calculate:
6882  * * V - error in the right part
6883  * * MX - maximum term in the left part
6884  *
6885  * Terminate if error in the right part is not greater than 100*Eps*MX.
6886  *
6887  * IMPORTANT: we must perform check for non-strict inequality, i.e. to use <= instead of <.
6888  * it will allow us to easily handle situations with zero rows of CE.
6889  */
6890  mx = 0;
6891  v = -ce->ptr.pp_double[i][nmain+nslack];
6892  for(j=0; j<=nmain+nslack-1; j++)
6893  {
6894  mx = ae_maxreal(mx, ae_fabs(ce->ptr.pp_double[i][j]*x->ptr.p_double[j], _state), _state);
6895  v = v+ce->ptr.pp_double[i][j]*x->ptr.p_double[j];
6896  }
6897  feaserr = feaserr+ae_sqr(v, _state);
6898  converged = converged&&ae_fp_less_eq(ae_fabs(v, _state),100*ae_machineepsilon*mx);
6899  }
6900  feaserr = ae_sqrt(feaserr, _state);
6901  if( converged )
6902  {
6903  result = ae_fp_less_eq(feaserr,epsi);
6904  ae_frame_leave(_state);
6905  return result;
6906  }
6907 
6908  /*
6909  * Stage 1: equality constrained quadratic programming
6910  *
6911  * * treat active bound constraints as equality ones (constraint is considered
6912  * active when we are at the boundary, independently of the antigradient direction)
6913  * * calculate unrestricted Newton step to point XM (which may be infeasible)
6914  * calculate MaxStepLen = largest step in direction of XM which retains feasibility.
6915  * * perform bounded step from X to XN:
6916  * a) XN=XM (if XM is feasible)
6917  * b) XN=X-MaxStepLen*(XM-X) (otherwise)
6918  * * X := XN
6919  * * if XM (Newton step subject to currently active constraints) was feasible, goto Stage 2
6920  * * repeat Stage 1
6921  *
6922  * NOTE 1: in order to solve constrained qudratic subproblem we will have to reorder
6923  * variables in such way that ones corresponding to inactive constraints will
6924  * be first, and active ones will be last in the list. CE and X are now
6925  * [ xi ]
6926  * separated into two parts: CE = [CEi CEa], x = [ ], where CEi/Xi correspond
6927  * [ xa ]
6928  * to INACTIVE constraints, and CEa/Xa correspond to the ACTIVE ones.
6929  *
6930  * Now, instead of F=0.5*x'*(CE'*CE)*x - (b'*CE)*x + 0.5*b'*b, we have
6931  * F(xi) = 0.5*(CEi*xi,CEi*xi) + (CEa*xa-b,CEi*xi) + (0.5*CEa*xa-b,CEa*xa).
6932  * Here xa is considered constant, i.e. we optimize with respect to xi, leaving xa fixed.
6933  *
6934  * We can solve it by performing SVD of CEi and calculating pseudoinverse of the
6935  * Hessian matrix. Of course, we do NOT calculate pseudoinverse explicitly - we
6936  * just use singular vectors to perform implicit multiplication by it.
6937  *
6938  */
6939  for(;;)
6940  {
6941 
6942  /*
6943  * Calculate G - gradient subject to equality constraints,
6944  * multiply it by inverse of the Hessian diagonal to obtain initial
6945  * step vector.
6946  *
6947  * Bound step subject to constraints which can be activated,
6948  * run Armijo search with increasing step size.
6949  * Search is terminated when feasibility error stops to decrease.
6950  *
6951  * NOTE: it is important to test for "stops to decrease" instead
6952  * of "starts to increase" in order to correctly handle cases with
6953  * zero CE.
6954  */
6955  armijobeststep = 0.0;
6956  armijobestfeas = 0.0;
6957  for(i=0; i<=nmain+nslack-1; i++)
6958  {
6959  g.ptr.p_double[i] = 0;
6960  }
6961  for(i=0; i<=k-1; i++)
6962  {
6963  v = ae_v_dotproduct(&ce->ptr.pp_double[i][0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1));
6964  v = v-ce->ptr.pp_double[i][nmain+nslack];
6965  armijobestfeas = armijobestfeas+ae_sqr(v, _state);
6966  ae_v_addd(&g.ptr.p_double[0], 1, &ce->ptr.pp_double[i][0], 1, ae_v_len(0,nmain+nslack-1), v);
6967  }
6968  armijobestfeas = ae_sqrt(armijobestfeas, _state);
6969  for(i=0; i<=nmain-1; i++)
6970  {
6971  if( havebndl->ptr.p_bool[i]&&ae_fp_eq(x->ptr.p_double[i],bndl->ptr.p_double[i]) )
6972  {
6973  g.ptr.p_double[i] = 0.0;
6974  }
6975  if( havebndu->ptr.p_bool[i]&&ae_fp_eq(x->ptr.p_double[i],bndu->ptr.p_double[i]) )
6976  {
6977  g.ptr.p_double[i] = 0.0;
6978  }
6979  }
6980  for(i=0; i<=nslack-1; i++)
6981  {
6982  if( ae_fp_eq(x->ptr.p_double[nmain+i],0.0) )
6983  {
6984  g.ptr.p_double[nmain+i] = 0.0;
6985  }
6986  }
6987  v = 0.0;
6988  for(i=0; i<=nmain+nslack-1; i++)
6989  {
6990  if( ae_fp_neq(ae_sqr(colnorms.ptr.p_double[i], _state),0) )
6991  {
6992  newtonstep.ptr.p_double[i] = -g.ptr.p_double[i]/ae_sqr(colnorms.ptr.p_double[i], _state);
6993  }
6994  else
6995  {
6996  newtonstep.ptr.p_double[i] = 0.0;
6997  }
6998  v = v+ae_sqr(newtonstep.ptr.p_double[i], _state);
6999  }
7000  if( ae_fp_eq(v,0) )
7001  {
7002 
7003  /*
7004  * Constrained gradient is zero, QP iterations are over
7005  */
7006  break;
7007  }
7008  calculatestepbound(x, &newtonstep, 1.0, bndl, havebndl, bndu, havebndu, nmain, nslack, &vartofreeze, &valtofreeze, &maxsteplen, _state);
7009  if( vartofreeze>=0&&ae_fp_eq(maxsteplen,0) )
7010  {
7011 
7012  /*
7013  * Can not perform step, QP iterations are over
7014  */
7015  break;
7016  }
7017  if( vartofreeze>=0 )
7018  {
7019  armijostep = ae_minreal(1.0, maxsteplen, _state);
7020  }
7021  else
7022  {
7023  armijostep = 1;
7024  }
7025  for(;;)
7026  {
7027  ae_v_move(&xa.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1));
7028  ae_v_addd(&xa.ptr.p_double[0], 1, &newtonstep.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1), armijostep);
7029  enforceboundaryconstraints(&xa, bndl, havebndl, bndu, havebndu, nmain, nslack, _state);
7030  feaserr = 0.0;
7031  for(i=0; i<=k-1; i++)
7032  {
7033  v = ae_v_dotproduct(&ce->ptr.pp_double[i][0], 1, &xa.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1));
7034  v = v-ce->ptr.pp_double[i][nmain+nslack];
7035  feaserr = feaserr+ae_sqr(v, _state);
7036  }
7037  feaserr = ae_sqrt(feaserr, _state);
7038  if( ae_fp_greater_eq(feaserr,armijobestfeas) )
7039  {
7040  break;
7041  }
7042  armijobestfeas = feaserr;
7043  armijobeststep = armijostep;
7044  armijostep = 2.0*armijostep;
7045  }
7046  ae_v_addd(&x->ptr.p_double[0], 1, &newtonstep.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1), armijobeststep);
7047  enforceboundaryconstraints(x, bndl, havebndl, bndu, havebndu, nmain, nslack, _state);
7048 
7049  /*
7050  * Determine number of active and free constraints
7051  */
7052  nactive = 0;
7053  for(i=0; i<=nmain-1; i++)
7054  {
7055  activeconstraints.ptr.p_double[i] = 0;
7056  if( havebndl->ptr.p_bool[i]&&ae_fp_eq(x->ptr.p_double[i],bndl->ptr.p_double[i]) )
7057  {
7058  activeconstraints.ptr.p_double[i] = 1;
7059  }
7060  if( havebndu->ptr.p_bool[i]&&ae_fp_eq(x->ptr.p_double[i],bndu->ptr.p_double[i]) )
7061  {
7062  activeconstraints.ptr.p_double[i] = 1;
7063  }
7064  if( ae_fp_greater(activeconstraints.ptr.p_double[i],0) )
7065  {
7066  nactive = nactive+1;
7067  }
7068  }
7069  for(i=0; i<=nslack-1; i++)
7070  {
7071  activeconstraints.ptr.p_double[nmain+i] = 0;
7072  if( ae_fp_eq(x->ptr.p_double[nmain+i],0.0) )
7073  {
7074  activeconstraints.ptr.p_double[nmain+i] = 1;
7075  }
7076  if( ae_fp_greater(activeconstraints.ptr.p_double[nmain+i],0) )
7077  {
7078  nactive = nactive+1;
7079  }
7080  }
7081  nfree = nmain+nslack-nactive;
7082  if( nfree==0 )
7083  {
7084  break;
7085  }
7086  *qpits = *qpits+1;
7087 
7088  /*
7089  * Reorder variables
7090  */
7091  tagsortbuf(&activeconstraints, nmain+nslack, &p1, &p2, &buf, _state);
7092  for(i=0; i<=k-1; i++)
7093  {
7094  for(j=0; j<=nmain+nslack-1; j++)
7095  {
7096  a.ptr.pp_double[i][j] = ce->ptr.pp_double[i][j];
7097  }
7098  }
7099  for(j=0; j<=nmain+nslack-1; j++)
7100  {
7101  permx.ptr.p_double[j] = x->ptr.p_double[j];
7102  }
7103  for(j=0; j<=nmain+nslack-1; j++)
7104  {
7105  if( p2.ptr.p_int[j]!=j )
7106  {
7107  idx0 = p2.ptr.p_int[j];
7108  idx1 = j;
7109  for(i=0; i<=k-1; i++)
7110  {
7111  v = a.ptr.pp_double[i][idx0];
7112  a.ptr.pp_double[i][idx0] = a.ptr.pp_double[i][idx1];
7113  a.ptr.pp_double[i][idx1] = v;
7114  }
7115  v = permx.ptr.p_double[idx0];
7116  permx.ptr.p_double[idx0] = permx.ptr.p_double[idx1];
7117  permx.ptr.p_double[idx1] = v;
7118  }
7119  }
7120 
7121  /*
7122  * Calculate (unprojected) gradient:
7123  * G(xi) = CEi'*(CEi*xi + CEa*xa - b)
7124  */
7125  for(i=0; i<=nfree-1; i++)
7126  {
7127  g.ptr.p_double[i] = 0;
7128  }
7129  for(i=0; i<=k-1; i++)
7130  {
7131  v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &permx.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1));
7132  tmpk.ptr.p_double[i] = v-ce->ptr.pp_double[i][nmain+nslack];
7133  }
7134  for(i=0; i<=k-1; i++)
7135  {
7136  v = tmpk.ptr.p_double[i];
7137  ae_v_addd(&g.ptr.p_double[0], 1, &a.ptr.pp_double[i][0], 1, ae_v_len(0,nfree-1), v);
7138  }
7139 
7140  /*
7141  * Calculate Newton step using SVD of CEi:
7142  * F(xi) = 0.5*xi'*H*xi + g'*xi (Taylor decomposition)
7143  * XN = -H^(-1)*g (new point, solution of the QP subproblem)
7144  * H = CEi'*CEi
7145  * CEi = U*W*V' (SVD of CEi)
7146  * H = V*W^2*V'
7147  * H^(-1) = V*W^(-2)*V'
7148  * step = -V*W^(-2)*V'*g (it is better to perform multiplication from right to left)
7149  *
7150  * NOTE 1: we do NOT need left singular vectors to perform Newton step.
7151  */
7152  nsvd = ae_minint(k, nfree, _state);
7153  if( !rmatrixsvd(&a, k, nfree, 0, 1, 2, &w, &u, &vt, _state) )
7154  {
7155  result = ae_false;
7156  ae_frame_leave(_state);
7157  return result;
7158  }
7159  for(i=0; i<=nsvd-1; i++)
7160  {
7161  v = ae_v_dotproduct(&vt.ptr.pp_double[i][0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,nfree-1));
7162  tmpk.ptr.p_double[i] = v;
7163  }
7164  for(i=0; i<=nsvd-1; i++)
7165  {
7166 
7167  /*
7168  * It is important to have strict ">" in order to correctly
7169  * handle zero singular values.
7170  */
7171  if( ae_fp_greater(ae_sqr(w.ptr.p_double[i], _state),ae_sqr(w.ptr.p_double[0], _state)*(nmain+nslack)*ae_machineepsilon) )
7172  {
7173  tmpk.ptr.p_double[i] = tmpk.ptr.p_double[i]/ae_sqr(w.ptr.p_double[i], _state);
7174  }
7175  else
7176  {
7177  tmpk.ptr.p_double[i] = 0;
7178  }
7179  }
7180  for(i=0; i<=nmain+nslack-1; i++)
7181  {
7182  newtonstep.ptr.p_double[i] = 0;
7183  }
7184  for(i=0; i<=nsvd-1; i++)
7185  {
7186  v = tmpk.ptr.p_double[i];
7187  ae_v_subd(&newtonstep.ptr.p_double[0], 1, &vt.ptr.pp_double[i][0], 1, ae_v_len(0,nfree-1), v);
7188  }
7189  for(j=nmain+nslack-1; j>=0; j--)
7190  {
7191  if( p2.ptr.p_int[j]!=j )
7192  {
7193  idx0 = p2.ptr.p_int[j];
7194  idx1 = j;
7195  v = newtonstep.ptr.p_double[idx0];
7196  newtonstep.ptr.p_double[idx0] = newtonstep.ptr.p_double[idx1];
7197  newtonstep.ptr.p_double[idx1] = v;
7198  }
7199  }
7200 
7201  /*
7202  * NewtonStep contains Newton step subject to active bound constraints.
7203  *
7204  * Such step leads us to the minimizer of the equality constrained F,
7205  * but such minimizer may be infeasible because some constraints which
7206  * are inactive at the initial point can be violated at the solution.
7207  *
7208  * Thus, we perform optimization in two stages:
7209  * a) perform bounded Newton step, i.e. step in the Newton direction
7210  * until activation of the first constraint
7211  * b) in case (MaxStepLen>0)and(MaxStepLen<1), perform additional iteration
7212  * of the Armijo line search in the rest of the Newton direction.
7213  */
7214  calculatestepbound(x, &newtonstep, 1.0, bndl, havebndl, bndu, havebndu, nmain, nslack, &vartofreeze, &valtofreeze, &maxsteplen, _state);
7215  if( vartofreeze>=0&&ae_fp_eq(maxsteplen,0) )
7216  {
7217 
7218  /*
7219  * Activation of the constraints prevent us from performing step,
7220  * QP iterations are over
7221  */
7222  break;
7223  }
7224  if( vartofreeze>=0 )
7225  {
7226  v = ae_minreal(1.0, maxsteplen, _state);
7227  }
7228  else
7229  {
7230  v = 1.0;
7231  }
7232  ae_v_moved(&xn.ptr.p_double[0], 1, &newtonstep.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1), v);
7233  ae_v_add(&xn.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1));
7234  postprocessboundedstep(&xn, x, bndl, havebndl, bndu, havebndu, nmain, nslack, vartofreeze, valtofreeze, v, maxsteplen, _state);
7235  if( ae_fp_greater(maxsteplen,0)&&ae_fp_less(maxsteplen,1) )
7236  {
7237 
7238  /*
7239  * Newton step was restricted by activation of the constraints,
7240  * perform Armijo iteration.
7241  *
7242  * Initial estimate for best step is zero step. We try different
7243  * step sizes, from the 1-MaxStepLen (residual of the full Newton
7244  * step) to progressively smaller and smaller steps.
7245  */
7246  armijobeststep = 0.0;
7247  armijobestfeas = 0.0;
7248  for(i=0; i<=k-1; i++)
7249  {
7250  v = ae_v_dotproduct(&ce->ptr.pp_double[i][0], 1, &xn.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1));
7251  v = v-ce->ptr.pp_double[i][nmain+nslack];
7252  armijobestfeas = armijobestfeas+ae_sqr(v, _state);
7253  }
7254  armijobestfeas = ae_sqrt(armijobestfeas, _state);
7255  armijostep = 1-maxsteplen;
7256  for(j=0; j<=maxarmijoruns-1; j++)
7257  {
7258  ae_v_move(&xa.ptr.p_double[0], 1, &xn.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1));
7259  ae_v_addd(&xa.ptr.p_double[0], 1, &newtonstep.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1), armijostep);
7260  enforceboundaryconstraints(&xa, bndl, havebndl, bndu, havebndu, nmain, nslack, _state);
7261  feaserr = 0.0;
7262  for(i=0; i<=k-1; i++)
7263  {
7264  v = ae_v_dotproduct(&ce->ptr.pp_double[i][0], 1, &xa.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1));
7265  v = v-ce->ptr.pp_double[i][nmain+nslack];
7266  feaserr = feaserr+ae_sqr(v, _state);
7267  }
7268  feaserr = ae_sqrt(feaserr, _state);
7269  if( ae_fp_less(feaserr,armijobestfeas) )
7270  {
7271  armijobestfeas = feaserr;
7272  armijobeststep = armijostep;
7273  }
7274  armijostep = 0.5*armijostep;
7275  }
7276  ae_v_move(&xa.ptr.p_double[0], 1, &xn.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1));
7277  ae_v_addd(&xa.ptr.p_double[0], 1, &newtonstep.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1), armijobeststep);
7278  enforceboundaryconstraints(&xa, bndl, havebndl, bndu, havebndu, nmain, nslack, _state);
7279  }
7280  else
7281  {
7282 
7283  /*
7284  * Armijo iteration is not performed
7285  */
7286  ae_v_move(&xa.ptr.p_double[0], 1, &xn.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1));
7287  }
7288  stage1isover = ae_fp_greater_eq(maxsteplen,1)||ae_fp_eq(maxsteplen,0);
7289 
7290  /*
7291  * Calculate feasibility errors for old and new X.
7292  * These quantinies are used for debugging purposes only.
7293  * However, we can leave them in release code because performance impact is insignificant.
7294  *
7295  * Update X. Exit if needed.
7296  */
7297  feasold = 0;
7298  feasnew = 0;
7299  for(i=0; i<=k-1; i++)
7300  {
7301  v = ae_v_dotproduct(&ce->ptr.pp_double[i][0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1));
7302  feasold = feasold+ae_sqr(v-ce->ptr.pp_double[i][nmain+nslack], _state);
7303  v = ae_v_dotproduct(&ce->ptr.pp_double[i][0], 1, &xa.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1));
7304  feasnew = feasnew+ae_sqr(v-ce->ptr.pp_double[i][nmain+nslack], _state);
7305  }
7306  feasold = ae_sqrt(feasold, _state);
7307  feasnew = ae_sqrt(feasnew, _state);
7308  if( ae_fp_greater_eq(feasnew,feasold) )
7309  {
7310  break;
7311  }
7312  ae_v_move(&x->ptr.p_double[0], 1, &xa.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1));
7313  if( stage1isover )
7314  {
7315  break;
7316  }
7317  }
7318 
7319  /*
7320  * Stage 2: gradient projection algorithm (GPA)
7321  *
7322  * * calculate feasibility error (with respect to linear equality constraints)
7323  * * calculate gradient G of F, project it into feasible area (G => PG)
7324  * * exit if norm(PG) is exactly zero or feasibility error is smaller than EpsC
7325  * * let XM be exact minimum of F along -PG (XM may be infeasible).
7326  * calculate MaxStepLen = largest step in direction of -PG which retains feasibility.
7327  * * perform bounded step from X to XN:
7328  * a) XN=XM (if XM is feasible)
7329  * b) XN=X-MaxStepLen*PG (otherwise)
7330  * * X := XN
7331  * * stop after specified number of iterations or when no new constraints was activated
7332  *
7333  * NOTES:
7334  * * grad(F) = (CE'*CE)*x - (b'*CE)^T
7335  * * CE[i] denotes I-th row of CE
7336  * * XM = X+stp*(-PG) where stp=(grad(F(X)),PG)/(CE*PG,CE*PG).
7337  * Here PG is a projected gradient, but in fact it can be arbitrary non-zero
7338  * direction vector - formula for minimum of F along PG still will be correct.
7339  */
7340  werechangesinconstraints = ae_false;
7341  for(gparuns=1; gparuns<=k; gparuns++)
7342  {
7343 
7344  /*
7345  * calculate feasibility error and G
7346  */
7347  feaserr = 0;
7348  for(i=0; i<=nmain+nslack-1; i++)
7349  {
7350  g.ptr.p_double[i] = 0;
7351  }
7352  for(i=0; i<=k-1; i++)
7353  {
7354 
7355  /*
7356  * G += CE[i]^T * (CE[i]*x-b[i])
7357  */
7358  v = ae_v_dotproduct(&ce->ptr.pp_double[i][0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1));
7359  v = v-ce->ptr.pp_double[i][nmain+nslack];
7360  feaserr = feaserr+ae_sqr(v, _state);
7361  ae_v_addd(&g.ptr.p_double[0], 1, &ce->ptr.pp_double[i][0], 1, ae_v_len(0,nmain+nslack-1), v);
7362  }
7363 
7364  /*
7365  * project G, filter it (strip numerical noise)
7366  */
7367  ae_v_move(&pg.ptr.p_double[0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1));
7368  projectgradientintobc(x, &pg, bndl, havebndl, bndu, havebndu, nmain, nslack, _state);
7369  filterdirection(&pg, x, bndl, havebndl, bndu, havebndu, &s, nmain, nslack, 1.0E-9, _state);
7370  for(i=0; i<=nmain+nslack-1; i++)
7371  {
7372  if( ae_fp_neq(ae_sqr(colnorms.ptr.p_double[i], _state),0) )
7373  {
7374  pg.ptr.p_double[i] = pg.ptr.p_double[i]/ae_sqr(colnorms.ptr.p_double[i], _state);
7375  }
7376  else
7377  {
7378  pg.ptr.p_double[i] = 0.0;
7379  }
7380  }
7381 
7382  /*
7383  * Check GNorm and feasibility.
7384  * Exit when GNorm is exactly zero.
7385  */
7386  pgnorm = ae_v_dotproduct(&pg.ptr.p_double[0], 1, &pg.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1));
7387  feaserr = ae_sqrt(feaserr, _state);
7388  pgnorm = ae_sqrt(pgnorm, _state);
7389  if( ae_fp_eq(pgnorm,0) )
7390  {
7391  result = ae_fp_less_eq(feaserr,epsi);
7392  ae_frame_leave(_state);
7393  return result;
7394  }
7395 
7396  /*
7397  * calculate planned step length
7398  */
7399  vn = ae_v_dotproduct(&g.ptr.p_double[0], 1, &pg.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1));
7400  vd = 0;
7401  for(i=0; i<=k-1; i++)
7402  {
7403  v = ae_v_dotproduct(&ce->ptr.pp_double[i][0], 1, &pg.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1));
7404  vd = vd+ae_sqr(v, _state);
7405  }
7406  stp = vn/vd;
7407 
7408  /*
7409  * Calculate step bound.
7410  * Perform bounded step and post-process it
7411  */
7412  calculatestepbound(x, &pg, -1.0, bndl, havebndl, bndu, havebndu, nmain, nslack, &vartofreeze, &valtofreeze, &maxsteplen, _state);
7413  if( vartofreeze>=0&&ae_fp_eq(maxsteplen,0) )
7414  {
7415  result = ae_false;
7416  ae_frame_leave(_state);
7417  return result;
7418  }
7419  if( vartofreeze>=0 )
7420  {
7421  v = ae_minreal(stp, maxsteplen, _state);
7422  }
7423  else
7424  {
7425  v = stp;
7426  }
7427  ae_v_move(&xn.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1));
7428  ae_v_subd(&xn.ptr.p_double[0], 1, &pg.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1), v);
7429  postprocessboundedstep(&xn, x, bndl, havebndl, bndu, havebndu, nmain, nslack, vartofreeze, valtofreeze, v, maxsteplen, _state);
7430 
7431  /*
7432  * update X
7433  * check stopping criteria
7434  */
7435  werechangesinconstraints = werechangesinconstraints||numberofchangedconstraints(&xn, x, bndl, havebndl, bndu, havebndu, nmain, nslack, _state)>0;
7436  ae_v_move(&x->ptr.p_double[0], 1, &xn.ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1));
7437  *gpaits = *gpaits+1;
7438  if( !werechangesinconstraints )
7439  {
7440  break;
7441  }
7442  }
7443 
7444  /*
7445  * Stage 3: decide to stop algorithm or not to stop
7446  *
7447  * 1. we can stop when last GPA run did NOT changed constraints status.
7448  * It means that we've found final set of the active constraints even
7449  * before GPA made its run. And it means that Newton step moved us to
7450  * the minimum subject to the present constraints.
7451  * Depending on feasibility error, True or False is returned.
7452  */
7453  feaserr = 0;
7454  for(i=0; i<=k-1; i++)
7455  {
7456  v = ae_v_dotproduct(&ce->ptr.pp_double[i][0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,nmain+nslack-1));
7457  v = v-ce->ptr.pp_double[i][nmain+nslack];
7458  feaserr = feaserr+ae_sqr(v, _state);
7459  }
7460  feaserr = ae_sqrt(feaserr, _state);
7461  if( ae_fp_less_eq(feaserr,epsi) )
7462  {
7463  itswithintolerance = itswithintolerance+1;
7464  }
7465  else
7466  {
7467  itswithintolerance = 0;
7468  }
7469  if( !werechangesinconstraints||itswithintolerance>=maxitswithintolerance )
7470  {
7471  result = ae_fp_less_eq(feaserr,epsi);
7472  ae_frame_leave(_state);
7473  return result;
7474  }
7475  itscount = itscount+1;
7476  }
7477  ae_frame_leave(_state);
7478  return result;
7479 }
7480 
7481 
7482 /*************************************************************************
7483  This function check, that input derivatives are right. First it scale
7484 parameters DF0 and DF1 from segment [A;B] to [0;1]. Than it build Hermite
7485 spline and derivative of it in 0,5. Search scale as Max(DF0,DF1, |F0-F1|).
7486 Right derivative has to satisfy condition:
7487  |H-F|/S<=0,01, |H'-F'|/S<=0,01.
7488 
7489 INPUT PARAMETERS:
7490  F0 - function's value in X-TestStep point;
7491  DF0 - derivative's value in X-TestStep point;
7492  F1 - function's value in X+TestStep point;
7493  DF1 - derivative's value in X+TestStep point;
7494  F - testing function's value;
7495  DF - testing derivative's value;
7496  Width- width of verification segment.
7497 
7498 RESULT:
7499  If input derivatives is right then function returns true, else
7500  function returns false.
7501 
7502  -- ALGLIB --
7503  Copyright 29.05.2012 by Bochkanov Sergey
7504 *************************************************************************/
7506  double df0,
7507  double f1,
7508  double df1,
7509  double f,
7510  double df,
7511  double width,
7512  ae_state *_state)
7513 {
7514  double s;
7515  double h;
7516  double dh;
7517  ae_bool result;
7518 
7519 
7520  df = width*df;
7521  df0 = width*df0;
7522  df1 = width*df1;
7523  s = ae_maxreal(ae_maxreal(ae_fabs(df0, _state), ae_fabs(df1, _state), _state), ae_fabs(f1-f0, _state), _state);
7524  h = 0.5*f0+0.125*df0+0.5*f1-0.125*df1;
7525  dh = -1.5*f0-0.25*df0+1.5*f1-0.25*df1;
7526  if( ae_fp_neq(s,0) )
7527  {
7528  if( ae_fp_greater(ae_fabs(h-f, _state)/s,0.001)||ae_fp_greater(ae_fabs(dh-df, _state)/s,0.001) )
7529  {
7530  result = ae_false;
7531  return result;
7532  }
7533  }
7534  else
7535  {
7536  if( ae_fp_neq(h-f,0.0)||ae_fp_neq(dh-df,0.0) )
7537  {
7538  result = ae_false;
7539  return result;
7540  }
7541  }
7542  result = ae_true;
7543  return result;
7544 }
7545 
7546 
7547 
7548 
7549 /*************************************************************************
7550 This subroutine is used to initialize CQM. By default, empty NxN model is
7551 generated, with Alpha=Lambda=Theta=0.0 and zero b.
7552 
7553 Previously allocated buffer variables are reused as much as possible.
7554 
7555  -- ALGLIB --
7556  Copyright 12.06.2012 by Bochkanov Sergey
7557 *************************************************************************/
7559 {
7560  ae_int_t i;
7561 
7562 
7563  s->n = n;
7564  s->k = 0;
7565  s->nfree = n;
7566  s->ecakind = -1;
7567  s->alpha = 0.0;
7568  s->tau = 0.0;
7569  s->theta = 0.0;
7574  bvectorsetlengthatleast(&s->activeset, n, _state);
7575  rvectorsetlengthatleast(&s->xc, n, _state);
7576  rvectorsetlengthatleast(&s->eb, n, _state);
7577  rvectorsetlengthatleast(&s->tq1, n, _state);
7578  rvectorsetlengthatleast(&s->txc, n, _state);
7579  rvectorsetlengthatleast(&s->tb, n, _state);
7580  rvectorsetlengthatleast(&s->b, s->n, _state);
7581  rvectorsetlengthatleast(&s->tk1, s->n, _state);
7582  for(i=0; i<=n-1; i++)
7583  {
7584  s->activeset.ptr.p_bool[i] = ae_false;
7585  s->xc.ptr.p_double[i] = 0.0;
7586  s->b.ptr.p_double[i] = 0.0;
7587  }
7588 }
7589 
7590 
7591 /*************************************************************************
7592 This subroutine changes main quadratic term of the model.
7593 
7594 INPUT PARAMETERS:
7595  S - model
7596  A - NxN matrix, only upper or lower triangle is referenced
7597  IsUpper - True, when matrix is stored in upper triangle
7598  Alpha - multiplier; when Alpha=0, A is not referenced at all
7599 
7600  -- ALGLIB --
7601  Copyright 12.06.2012 by Bochkanov Sergey
7602 *************************************************************************/
7604  /* Real */ ae_matrix* a,
7605  ae_bool isupper,
7606  double alpha,
7607  ae_state *_state)
7608 {
7609  ae_int_t i;
7610  ae_int_t j;
7611  double v;
7612 
7613 
7614  ae_assert(ae_isfinite(alpha, _state)&&ae_fp_greater_eq(alpha,0), "CQMSetA: Alpha<0 or is not finite number", _state);
7615  ae_assert(ae_fp_eq(alpha,0)||isfinitertrmatrix(a, s->n, isupper, _state), "CQMSetA: A is not finite NxN matrix", _state);
7616  s->alpha = alpha;
7617  if( ae_fp_greater(alpha,0) )
7618  {
7619  rmatrixsetlengthatleast(&s->a, s->n, s->n, _state);
7620  rmatrixsetlengthatleast(&s->ecadense, s->n, s->n, _state);
7621  rmatrixsetlengthatleast(&s->tq2dense, s->n, s->n, _state);
7622  for(i=0; i<=s->n-1; i++)
7623  {
7624  for(j=i; j<=s->n-1; j++)
7625  {
7626  if( isupper )
7627  {
7628  v = a->ptr.pp_double[i][j];
7629  }
7630  else
7631  {
7632  v = a->ptr.pp_double[j][i];
7633  }
7634  s->a.ptr.pp_double[i][j] = v;
7635  s->a.ptr.pp_double[j][i] = v;
7636  }
7637  }
7638  }
7640 }
7641 
7642 
7643 /*************************************************************************
7644 This subroutine rewrites diagonal of the main quadratic term of the model
7645 (dense A) by vector Z/Alpha (current value of the Alpha coefficient is
7646 used).
7647 
7648 IMPORTANT: in case model has no dense quadratic term, this function
7649  allocates N*N dense matrix of zeros, and fills its diagonal by
7650  non-zero values.
7651 
7652 INPUT PARAMETERS:
7653  S - model
7654  Z - new diagonal, array[N]
7655 
7656  -- ALGLIB --
7657  Copyright 12.06.2012 by Bochkanov Sergey
7658 *************************************************************************/
7660  /* Real */ ae_vector* z,
7661  ae_state *_state)
7662 {
7663  ae_int_t n;
7664  ae_int_t i;
7665  ae_int_t j;
7666 
7667 
7668  n = s->n;
7669  if( ae_fp_eq(s->alpha,0) )
7670  {
7671  rmatrixsetlengthatleast(&s->a, s->n, s->n, _state);
7672  rmatrixsetlengthatleast(&s->ecadense, s->n, s->n, _state);
7673  rmatrixsetlengthatleast(&s->tq2dense, s->n, s->n, _state);
7674  for(i=0; i<=n-1; i++)
7675  {
7676  for(j=0; j<=n-1; j++)
7677  {
7678  s->a.ptr.pp_double[i][j] = 0.0;
7679  }
7680  }
7681  s->alpha = 1.0;
7682  }
7683  for(i=0; i<=s->n-1; i++)
7684  {
7685  s->a.ptr.pp_double[i][i] = z->ptr.p_double[i]/s->alpha;
7686  }
7688 }
7689 
7690 
7691 /*************************************************************************
7692 This subroutine changes diagonal quadratic term of the model.
7693 
7694 INPUT PARAMETERS:
7695  S - model
7696  D - array[N], semidefinite diagonal matrix
7697  Tau - multiplier; when Tau=0, D is not referenced at all
7698 
7699  -- ALGLIB --
7700  Copyright 12.06.2012 by Bochkanov Sergey
7701 *************************************************************************/
7703  /* Real */ ae_vector* d,
7704  double tau,
7705  ae_state *_state)
7706 {
7707  ae_int_t i;
7708 
7709 
7710  ae_assert(ae_isfinite(tau, _state)&&ae_fp_greater_eq(tau,0), "CQMSetD: Tau<0 or is not finite number", _state);
7711  ae_assert(ae_fp_eq(tau,0)||isfinitevector(d, s->n, _state), "CQMSetD: D is not finite Nx1 vector", _state);
7712  s->tau = tau;
7713  if( ae_fp_greater(tau,0) )
7714  {
7715  rvectorsetlengthatleast(&s->d, s->n, _state);
7716  rvectorsetlengthatleast(&s->ecadiag, s->n, _state);
7717  rvectorsetlengthatleast(&s->tq2diag, s->n, _state);
7718  for(i=0; i<=s->n-1; i++)
7719  {
7720  ae_assert(ae_fp_greater_eq(d->ptr.p_double[i],0), "CQMSetD: D[i]<0", _state);
7721  s->d.ptr.p_double[i] = d->ptr.p_double[i];
7722  }
7723  }
7725 }
7726 
7727 
7728 /*************************************************************************
7729 This subroutine drops main quadratic term A from the model. It is same as
7730 call to CQMSetA() with zero A, but gives better performance because
7731 algorithm knows that matrix is zero and can optimize subsequent
7732 calculations.
7733 
7734 INPUT PARAMETERS:
7735  S - model
7736 
7737  -- ALGLIB --
7738  Copyright 12.06.2012 by Bochkanov Sergey
7739 *************************************************************************/
7741 {
7742 
7743 
7744  s->alpha = 0.0;
7746 }
7747 
7748 
7749 /*************************************************************************
7750 This subroutine changes linear term of the model
7751 
7752  -- ALGLIB --
7753  Copyright 12.06.2012 by Bochkanov Sergey
7754 *************************************************************************/
7756  /* Real */ ae_vector* b,
7757  ae_state *_state)
7758 {
7759  ae_int_t i;
7760 
7761 
7762  ae_assert(isfinitevector(b, s->n, _state), "CQMSetB: B is not finite vector", _state);
7763  rvectorsetlengthatleast(&s->b, s->n, _state);
7764  for(i=0; i<=s->n-1; i++)
7765  {
7766  s->b.ptr.p_double[i] = b->ptr.p_double[i];
7767  }
7769 }
7770 
7771 
7772 /*************************************************************************
7773 This subroutine changes linear term of the model
7774 
7775  -- ALGLIB --
7776  Copyright 12.06.2012 by Bochkanov Sergey
7777 *************************************************************************/
7779  /* Real */ ae_matrix* q,
7780  /* Real */ ae_vector* r,
7781  ae_int_t k,
7782  double theta,
7783  ae_state *_state)
7784 {
7785  ae_int_t i;
7786  ae_int_t j;
7787 
7788 
7789  ae_assert(k>=0, "CQMSetQ: K<0", _state);
7790  ae_assert((k==0||ae_fp_eq(theta,0))||apservisfinitematrix(q, k, s->n, _state), "CQMSetQ: Q is not finite matrix", _state);
7791  ae_assert((k==0||ae_fp_eq(theta,0))||isfinitevector(r, k, _state), "CQMSetQ: R is not finite vector", _state);
7792  ae_assert(ae_isfinite(theta, _state)&&ae_fp_greater_eq(theta,0), "CQMSetQ: Theta<0 or is not finite number", _state);
7793 
7794  /*
7795  * degenerate case: K=0 or Theta=0
7796  */
7797  if( k==0||ae_fp_eq(theta,0) )
7798  {
7799  s->k = 0;
7800  s->theta = 0;
7802  return;
7803  }
7804 
7805  /*
7806  * General case: both Theta>0 and K>0
7807  */
7808  s->k = k;
7809  s->theta = theta;
7810  rmatrixsetlengthatleast(&s->q, s->k, s->n, _state);
7811  rvectorsetlengthatleast(&s->r, s->k, _state);
7812  rmatrixsetlengthatleast(&s->eq, s->k, s->n, _state);
7813  rmatrixsetlengthatleast(&s->eccm, s->k, s->k, _state);
7814  rmatrixsetlengthatleast(&s->tk2, s->k, s->n, _state);
7815  for(i=0; i<=s->k-1; i++)
7816  {
7817  for(j=0; j<=s->n-1; j++)
7818  {
7819  s->q.ptr.pp_double[i][j] = q->ptr.pp_double[i][j];
7820  }
7821  s->r.ptr.p_double[i] = r->ptr.p_double[i];
7822  }
7824 }
7825 
7826 
7827 /*************************************************************************
7828 This subroutine changes active set
7829 
7830 INPUT PARAMETERS
7831  S - model
7832  X - array[N], constraint values
7833  ActiveSet- array[N], active set. If ActiveSet[I]=True, then I-th
7834  variables is constrained to X[I].
7835 
7836  -- ALGLIB --
7837  Copyright 12.06.2012 by Bochkanov Sergey
7838 *************************************************************************/
7840  /* Real */ ae_vector* x,
7841  /* Boolean */ ae_vector* activeset,
7842  ae_state *_state)
7843 {
7844  ae_int_t i;
7845 
7846 
7847  ae_assert(x->cnt>=s->n, "CQMSetActiveSet: Length(X)<N", _state);
7848  ae_assert(activeset->cnt>=s->n, "CQMSetActiveSet: Length(ActiveSet)<N", _state);
7849  for(i=0; i<=s->n-1; i++)
7850  {
7851  s->isactivesetchanged = s->isactivesetchanged||(s->activeset.ptr.p_bool[i]&&!activeset->ptr.p_bool[i]);
7852  s->isactivesetchanged = s->isactivesetchanged||(activeset->ptr.p_bool[i]&&!s->activeset.ptr.p_bool[i]);
7853  s->activeset.ptr.p_bool[i] = activeset->ptr.p_bool[i];
7854  if( activeset->ptr.p_bool[i] )
7855  {
7856  ae_assert(ae_isfinite(x->ptr.p_double[i], _state), "CQMSetActiveSet: X[] contains infinite constraints", _state);
7858  s->xc.ptr.p_double[i] = x->ptr.p_double[i];
7859  }
7860  }
7861 }
7862 
7863 
7864 /*************************************************************************
7865 This subroutine evaluates model at X. Active constraints are ignored.
7866 
7867  -- ALGLIB --
7868  Copyright 12.06.2012 by Bochkanov Sergey
7869 *************************************************************************/
7871  /* Real */ ae_vector* x,
7872  ae_state *_state)
7873 {
7874  ae_int_t n;
7875  ae_int_t i;
7876  ae_int_t j;
7877  double v;
7878  double result;
7879 
7880 
7881  n = s->n;
7882  ae_assert(isfinitevector(x, n, _state), "CQMEval: X is not finite vector", _state);
7883  result = 0.0;
7884 
7885  /*
7886  * main quadratic term
7887  */
7888  if( ae_fp_greater(s->alpha,0) )
7889  {
7890  for(i=0; i<=n-1; i++)
7891  {
7892  for(j=0; j<=n-1; j++)
7893  {
7894  result = result+s->alpha*0.5*x->ptr.p_double[i]*s->a.ptr.pp_double[i][j]*x->ptr.p_double[j];
7895  }
7896  }
7897  }
7898  if( ae_fp_greater(s->tau,0) )
7899  {
7900  for(i=0; i<=n-1; i++)
7901  {
7902  result = result+0.5*ae_sqr(x->ptr.p_double[i], _state)*s->tau*s->d.ptr.p_double[i];
7903  }
7904  }
7905 
7906  /*
7907  * secondary quadratic term
7908  */
7909  if( ae_fp_greater(s->theta,0) )
7910  {
7911  for(i=0; i<=s->k-1; i++)
7912  {
7913  v = ae_v_dotproduct(&s->q.ptr.pp_double[i][0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1));
7914  result = result+0.5*s->theta*ae_sqr(v-s->r.ptr.p_double[i], _state);
7915  }
7916  }
7917 
7918  /*
7919  * linear term
7920  */
7921  for(i=0; i<=s->n-1; i++)
7922  {
7923  result = result+x->ptr.p_double[i]*s->b.ptr.p_double[i];
7924  }
7925  return result;
7926 }
7927 
7928 
7929 /*************************************************************************
7930 This subroutine evaluates model at X. Active constraints are ignored.
7931 It returns:
7932  R - model value
7933  Noise- estimate of the numerical noise in data
7934 
7935  -- ALGLIB --
7936  Copyright 12.06.2012 by Bochkanov Sergey
7937 *************************************************************************/
7939  /* Real */ ae_vector* x,
7940  double* r,
7941  double* noise,
7942  ae_state *_state)
7943 {
7944  ae_int_t n;
7945  ae_int_t i;
7946  ae_int_t j;
7947  double v;
7948  double v2;
7949  double mxq;
7950  double eps;
7951 
7952  *r = 0;
7953  *noise = 0;
7954 
7955  n = s->n;
7956  ae_assert(isfinitevector(x, n, _state), "CQMEval: X is not finite vector", _state);
7957  *r = 0.0;
7958  *noise = 0.0;
7959  eps = 2*ae_machineepsilon;
7960  mxq = 0.0;
7961 
7962  /*
7963  * Main quadratic term.
7964  *
7965  * Noise from the main quadratic term is equal to the
7966  * maximum summand in the term.
7967  */
7968  if( ae_fp_greater(s->alpha,0) )
7969  {
7970  for(i=0; i<=n-1; i++)
7971  {
7972  for(j=0; j<=n-1; j++)
7973  {
7974  v = s->alpha*0.5*x->ptr.p_double[i]*s->a.ptr.pp_double[i][j]*x->ptr.p_double[j];
7975  *r = *r+v;
7976  *noise = ae_maxreal(*noise, eps*ae_fabs(v, _state), _state);
7977  }
7978  }
7979  }
7980  if( ae_fp_greater(s->tau,0) )
7981  {
7982  for(i=0; i<=n-1; i++)
7983  {
7984  v = 0.5*ae_sqr(x->ptr.p_double[i], _state)*s->tau*s->d.ptr.p_double[i];
7985  *r = *r+v;
7986  *noise = ae_maxreal(*noise, eps*ae_fabs(v, _state), _state);
7987  }
7988  }
7989 
7990  /*
7991  * secondary quadratic term
7992  *
7993  * Noise from the secondary quadratic term is estimated as follows:
7994  * * noise in qi*x-r[i] is estimated as
7995  * Eps*MXQ = Eps*max(|r[i]|, |q[i,j]*x[j]|)
7996  * * noise in (qi*x-r[i])^2 is estimated as
7997  * NOISE = (|qi*x-r[i]|+Eps*MXQ)^2-(|qi*x-r[i]|)^2
7998  * = Eps*MXQ*(2*|qi*x-r[i]|+Eps*MXQ)
7999  */
8000  if( ae_fp_greater(s->theta,0) )
8001  {
8002  for(i=0; i<=s->k-1; i++)
8003  {
8004  v = 0.0;
8005  mxq = ae_fabs(s->r.ptr.p_double[i], _state);
8006  for(j=0; j<=n-1; j++)
8007  {
8008  v2 = s->q.ptr.pp_double[i][j]*x->ptr.p_double[j];
8009  v = v+v2;
8010  mxq = ae_maxreal(mxq, ae_fabs(v2, _state), _state);
8011  }
8012  *r = *r+0.5*s->theta*ae_sqr(v-s->r.ptr.p_double[i], _state);
8013  *noise = ae_maxreal(*noise, eps*mxq*(2*ae_fabs(v-s->r.ptr.p_double[i], _state)+eps*mxq), _state);
8014  }
8015  }
8016 
8017  /*
8018  * linear term
8019  */
8020  for(i=0; i<=s->n-1; i++)
8021  {
8022  *r = *r+x->ptr.p_double[i]*s->b.ptr.p_double[i];
8023  *noise = ae_maxreal(*noise, eps*ae_fabs(x->ptr.p_double[i]*s->b.ptr.p_double[i], _state), _state);
8024  }
8025 
8026  /*
8027  * Final update of the noise
8028  */
8029  *noise = n*(*noise);
8030 }
8031 
8032 
8033 /*************************************************************************
8034 This subroutine evaluates gradient of the model; active constraints are
8035 ignored.
8036 
8037 INPUT PARAMETERS:
8038  S - convex model
8039  X - point, array[N]
8040  G - possibly preallocated buffer; resized, if too small
8041 
8042  -- ALGLIB --
8043  Copyright 12.06.2012 by Bochkanov Sergey
8044 *************************************************************************/
8046  /* Real */ ae_vector* x,
8047  /* Real */ ae_vector* g,
8048  ae_state *_state)
8049 {
8050  ae_int_t n;
8051  ae_int_t i;
8052  ae_int_t j;
8053  double v;
8054 
8055 
8056  n = s->n;
8057  ae_assert(isfinitevector(x, n, _state), "CQMEvalGradUnconstrained: X is not finite vector", _state);
8058  rvectorsetlengthatleast(g, n, _state);
8059  for(i=0; i<=n-1; i++)
8060  {
8061  g->ptr.p_double[i] = 0;
8062  }
8063 
8064  /*
8065  * main quadratic term
8066  */
8067  if( ae_fp_greater(s->alpha,0) )
8068  {
8069  for(i=0; i<=n-1; i++)
8070  {
8071  v = 0.0;
8072  for(j=0; j<=n-1; j++)
8073  {
8074  v = v+s->alpha*s->a.ptr.pp_double[i][j]*x->ptr.p_double[j];
8075  }
8076  g->ptr.p_double[i] = g->ptr.p_double[i]+v;
8077  }
8078  }
8079  if( ae_fp_greater(s->tau,0) )
8080  {
8081  for(i=0; i<=n-1; i++)
8082  {
8083  g->ptr.p_double[i] = g->ptr.p_double[i]+x->ptr.p_double[i]*s->tau*s->d.ptr.p_double[i];
8084  }
8085  }
8086 
8087  /*
8088  * secondary quadratic term
8089  */
8090  if( ae_fp_greater(s->theta,0) )
8091  {
8092  for(i=0; i<=s->k-1; i++)
8093  {
8094  v = ae_v_dotproduct(&s->q.ptr.pp_double[i][0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1));
8095  v = s->theta*(v-s->r.ptr.p_double[i]);
8096  ae_v_addd(&g->ptr.p_double[0], 1, &s->q.ptr.pp_double[i][0], 1, ae_v_len(0,n-1), v);
8097  }
8098  }
8099 
8100  /*
8101  * linear term
8102  */
8103  for(i=0; i<=n-1; i++)
8104  {
8105  g->ptr.p_double[i] = g->ptr.p_double[i]+s->b.ptr.p_double[i];
8106  }
8107 }
8108 
8109 
8110 /*************************************************************************
8111 This subroutine evaluates x'*(0.5*alpha*A+tau*D)*x
8112 
8113  -- ALGLIB --
8114  Copyright 12.06.2012 by Bochkanov Sergey
8115 *************************************************************************/
8117  /* Real */ ae_vector* x,
8118  ae_state *_state)
8119 {
8120  ae_int_t n;
8121  ae_int_t i;
8122  ae_int_t j;
8123  double result;
8124 
8125 
8126  n = s->n;
8127  ae_assert(isfinitevector(x, n, _state), "CQMEval: X is not finite vector", _state);
8128  result = 0.0;
8129 
8130  /*
8131  * main quadratic term
8132  */
8133  if( ae_fp_greater(s->alpha,0) )
8134  {
8135  for(i=0; i<=n-1; i++)
8136  {
8137  for(j=0; j<=n-1; j++)
8138  {
8139  result = result+s->alpha*0.5*x->ptr.p_double[i]*s->a.ptr.pp_double[i][j]*x->ptr.p_double[j];
8140  }
8141  }
8142  }
8143  if( ae_fp_greater(s->tau,0) )
8144  {
8145  for(i=0; i<=n-1; i++)
8146  {
8147  result = result+0.5*ae_sqr(x->ptr.p_double[i], _state)*s->tau*s->d.ptr.p_double[i];
8148  }
8149  }
8150  return result;
8151 }
8152 
8153 
8154 /*************************************************************************
8155 This subroutine evaluates (0.5*alpha*A+tau*D)*x
8156 
8157 Y is automatically resized if needed
8158 
8159  -- ALGLIB --
8160  Copyright 12.06.2012 by Bochkanov Sergey
8161 *************************************************************************/
8163  /* Real */ ae_vector* x,
8164  /* Real */ ae_vector* y,
8165  ae_state *_state)
8166 {
8167  ae_int_t n;
8168  ae_int_t i;
8169  double v;
8170 
8171 
8172  n = s->n;
8173  ae_assert(isfinitevector(x, n, _state), "CQMEval: X is not finite vector", _state);
8174  rvectorsetlengthatleast(y, n, _state);
8175 
8176  /*
8177  * main quadratic term
8178  */
8179  for(i=0; i<=n-1; i++)
8180  {
8181  y->ptr.p_double[i] = 0;
8182  }
8183  if( ae_fp_greater(s->alpha,0) )
8184  {
8185  for(i=0; i<=n-1; i++)
8186  {
8187  v = ae_v_dotproduct(&s->a.ptr.pp_double[i][0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1));
8188  y->ptr.p_double[i] = y->ptr.p_double[i]+s->alpha*v;
8189  }
8190  }
8191  if( ae_fp_greater(s->tau,0) )
8192  {
8193  for(i=0; i<=n-1; i++)
8194  {
8195  y->ptr.p_double[i] = y->ptr.p_double[i]+x->ptr.p_double[i]*s->tau*s->d.ptr.p_double[i];
8196  }
8197  }
8198 }
8199 
8200 
8201 /*************************************************************************
8202 This subroutine finds optimum of the model. It returns False on failure
8203 (indefinite/semidefinite matrix). Optimum is found subject to active
8204 constraints.
8205 
8206 INPUT PARAMETERS
8207  S - model
8208  X - possibly preallocated buffer; automatically resized, if
8209  too small enough.
8210 
8211  -- ALGLIB --
8212  Copyright 12.06.2012 by Bochkanov Sergey
8213 *************************************************************************/
8215  /* Real */ ae_vector* x,
8216  ae_state *_state)
8217 {
8218  ae_int_t n;
8219  ae_int_t nfree;
8220  ae_int_t k;
8221  ae_int_t i;
8222  double v;
8223  ae_int_t cidx0;
8224  ae_int_t itidx;
8225  ae_bool result;
8226 
8227 
8228 
8229  /*
8230  * Rebuild internal structures
8231  */
8232  if( !cqmodels_cqmrebuild(s, _state) )
8233  {
8234  result = ae_false;
8235  return result;
8236  }
8237  n = s->n;
8238  k = s->k;
8239  nfree = s->nfree;
8240  result = ae_true;
8241 
8242  /*
8243  * Calculate initial point for the iterative refinement:
8244  * * free components are set to zero
8245  * * constrained components are set to their constrained values
8246  */
8247  rvectorsetlengthatleast(x, n, _state);
8248  for(i=0; i<=n-1; i++)
8249  {
8250  if( s->activeset.ptr.p_bool[i] )
8251  {
8252  x->ptr.p_double[i] = s->xc.ptr.p_double[i];
8253  }
8254  else
8255  {
8256  x->ptr.p_double[i] = 0;
8257  }
8258  }
8259 
8260  /*
8261  * Iterative refinement.
8262  *
8263  * In an ideal world without numerical errors it would be enough
8264  * to make just one Newton step from initial point:
8265  * x_new = -H^(-1)*grad(x=0)
8266  * However, roundoff errors can significantly deteriorate quality
8267  * of the solution. So we have to recalculate gradient and to
8268  * perform Newton steps several times.
8269  *
8270  * Below we perform fixed number of Newton iterations.
8271  */
8272  for(itidx=0; itidx<=cqmodels_newtonrefinementits-1; itidx++)
8273  {
8274 
8275  /*
8276  * Calculate gradient at the current point.
8277  * Move free components of the gradient in the beginning.
8278  */
8279  cqmgradunconstrained(s, x, &s->tmpg, _state);
8280  cidx0 = 0;
8281  for(i=0; i<=n-1; i++)
8282  {
8283  if( !s->activeset.ptr.p_bool[i] )
8284  {
8285  s->tmpg.ptr.p_double[cidx0] = s->tmpg.ptr.p_double[i];
8286  cidx0 = cidx0+1;
8287  }
8288  }
8289 
8290  /*
8291  * Free components of the extrema are calculated in the first NFree elements of TXC.
8292  *
8293  * First, we have to calculate original Newton step, without rank-K perturbations
8294  */
8295  ae_v_moveneg(&s->txc.ptr.p_double[0], 1, &s->tmpg.ptr.p_double[0], 1, ae_v_len(0,nfree-1));
8296  cqmodels_cqmsolveea(s, &s->txc, &s->tmp0, _state);
8297 
8298  /*
8299  * Then, we account for rank-K correction.
8300  * Woodbury matrix identity is used.
8301  */
8302  if( s->k>0&&ae_fp_greater(s->theta,0) )
8303  {
8304  rvectorsetlengthatleast(&s->tmp0, ae_maxint(nfree, k, _state), _state);
8305  rvectorsetlengthatleast(&s->tmp1, ae_maxint(nfree, k, _state), _state);
8306  ae_v_moveneg(&s->tmp1.ptr.p_double[0], 1, &s->tmpg.ptr.p_double[0], 1, ae_v_len(0,nfree-1));
8307  cqmodels_cqmsolveea(s, &s->tmp1, &s->tmp0, _state);
8308  for(i=0; i<=k-1; i++)
8309  {
8310  v = ae_v_dotproduct(&s->eq.ptr.pp_double[i][0], 1, &s->tmp1.ptr.p_double[0], 1, ae_v_len(0,nfree-1));
8311  s->tmp0.ptr.p_double[i] = v;
8312  }
8313  fblscholeskysolve(&s->eccm, 1.0, k, ae_true, &s->tmp0, &s->tmp1, _state);
8314  for(i=0; i<=nfree-1; i++)
8315  {
8316  s->tmp1.ptr.p_double[i] = 0.0;
8317  }
8318  for(i=0; i<=k-1; i++)
8319  {
8320  v = s->tmp0.ptr.p_double[i];
8321  ae_v_addd(&s->tmp1.ptr.p_double[0], 1, &s->eq.ptr.pp_double[i][0], 1, ae_v_len(0,nfree-1), v);
8322  }
8323  cqmodels_cqmsolveea(s, &s->tmp1, &s->tmp0, _state);
8324  ae_v_sub(&s->txc.ptr.p_double[0], 1, &s->tmp1.ptr.p_double[0], 1, ae_v_len(0,nfree-1));
8325  }
8326 
8327  /*
8328  * Unpack components from TXC into X. We pass through all
8329  * free components of X and add our step.
8330  */
8331  cidx0 = 0;
8332  for(i=0; i<=n-1; i++)
8333  {
8334  if( !s->activeset.ptr.p_bool[i] )
8335  {
8336  x->ptr.p_double[i] = x->ptr.p_double[i]+s->txc.ptr.p_double[cidx0];
8337  cidx0 = cidx0+1;
8338  }
8339  }
8340  }
8341  return result;
8342 }
8343 
8344 
8345 /*************************************************************************
8346 This function scales vector by multiplying it by inverse of the diagonal
8347 of the Hessian matrix. It should be used to accelerate steepest descent
8348 phase of the QP solver.
8349 
8350 Although it is called "scale-grad", it can be called for any vector,
8351 whether it is gradient, anti-gradient, or just some vector.
8352 
8353 This function does NOT takes into account current set of constraints, it
8354 just performs matrix-vector multiplication without taking into account
8355 constraints.
8356 
8357 INPUT PARAMETERS:
8358  S - model
8359  X - vector to scale
8360 
8361 OUTPUT PARAMETERS:
8362  X - scaled vector
8363 
8364 NOTE:
8365  when called for non-SPD matrices, it silently skips components of X
8366  which correspond to zero or negative diagonal elements.
8367 
8368 NOTE:
8369  this function uses diagonals of A and D; it ignores Q - rank-K term of
8370  the quadratic model.
8371 
8372  -- ALGLIB --
8373  Copyright 12.06.2012 by Bochkanov Sergey
8374 *************************************************************************/
8376  /* Real */ ae_vector* x,
8377  ae_state *_state)
8378 {
8379  ae_int_t n;
8380  ae_int_t i;
8381  double v;
8382 
8383 
8384  n = s->n;
8385  for(i=0; i<=n-1; i++)
8386  {
8387  v = 0.0;
8388  if( ae_fp_greater(s->alpha,0) )
8389  {
8390  v = v+s->a.ptr.pp_double[i][i];
8391  }
8392  if( ae_fp_greater(s->tau,0) )
8393  {
8394  v = v+s->d.ptr.p_double[i];
8395  }
8396  if( ae_fp_greater(v,0) )
8397  {
8398  x->ptr.p_double[i] = x->ptr.p_double[i]/v;
8399  }
8400  }
8401 }
8402 
8403 
8404 /*************************************************************************
8405 This subroutine calls CQMRebuild() and evaluates model at X subject to
8406 active constraints.
8407 
8408 It is intended for debug purposes only, because it evaluates model by
8409 means of temporaries, which were calculated by CQMRebuild(). The only
8410 purpose of this function is to check correctness of CQMRebuild() by
8411 comparing results of this function with ones obtained by CQMEval(), which
8412 is used as reference point. The idea is that significant deviation in
8413 results of these two functions is evidence of some error in the
8414 CQMRebuild().
8415 
8416 NOTE: suffix T denotes that temporaries marked by T-prefix are used. There
8417  is one more variant of this function, which uses "effective" model
8418  built by CQMRebuild().
8419 
8420 NOTE2: in case CQMRebuild() fails (due to model non-convexity), this
8421  function returns NAN.
8422 
8423  -- ALGLIB --
8424  Copyright 12.06.2012 by Bochkanov Sergey
8425 *************************************************************************/
8427  /* Real */ ae_vector* x,
8428  ae_state *_state)
8429 {
8430  ae_int_t n;
8431  ae_int_t nfree;
8432  ae_int_t i;
8433  ae_int_t j;
8434  double v;
8435  double result;
8436 
8437 
8438  n = s->n;
8439  ae_assert(isfinitevector(x, n, _state), "CQMDebugConstrainedEvalT: X is not finite vector", _state);
8440  if( !cqmodels_cqmrebuild(s, _state) )
8441  {
8442  result = _state->v_nan;
8443  return result;
8444  }
8445  result = 0.0;
8446  nfree = s->nfree;
8447 
8448  /*
8449  * Reorder variables
8450  */
8451  j = 0;
8452  for(i=0; i<=n-1; i++)
8453  {
8454  if( !s->activeset.ptr.p_bool[i] )
8455  {
8456  ae_assert(j<nfree, "CQMDebugConstrainedEvalT: internal error", _state);
8457  s->txc.ptr.p_double[j] = x->ptr.p_double[i];
8458  j = j+1;
8459  }
8460  }
8461 
8462  /*
8463  * TQ2, TQ1, TQ0
8464  *
8465  */
8466  if( ae_fp_greater(s->alpha,0) )
8467  {
8468 
8469  /*
8470  * Dense TQ2
8471  */
8472  for(i=0; i<=nfree-1; i++)
8473  {
8474  for(j=0; j<=nfree-1; j++)
8475  {
8476  result = result+0.5*s->txc.ptr.p_double[i]*s->tq2dense.ptr.pp_double[i][j]*s->txc.ptr.p_double[j];
8477  }
8478  }
8479  }
8480  else
8481  {
8482 
8483  /*
8484  * Diagonal TQ2
8485  */
8486  for(i=0; i<=nfree-1; i++)
8487  {
8488  result = result+0.5*s->tq2diag.ptr.p_double[i]*ae_sqr(s->txc.ptr.p_double[i], _state);
8489  }
8490  }
8491  for(i=0; i<=nfree-1; i++)
8492  {
8493  result = result+s->tq1.ptr.p_double[i]*s->txc.ptr.p_double[i];
8494  }
8495  result = result+s->tq0;
8496 
8497  /*
8498  * TK2, TK1, TK0
8499  */
8500  if( s->k>0&&ae_fp_greater(s->theta,0) )
8501  {
8502  for(i=0; i<=s->k-1; i++)
8503  {
8504  v = 0;
8505  for(j=0; j<=nfree-1; j++)
8506  {
8507  v = v+s->tk2.ptr.pp_double[i][j]*s->txc.ptr.p_double[j];
8508  }
8509  result = result+0.5*ae_sqr(v, _state);
8510  }
8511  for(i=0; i<=nfree-1; i++)
8512  {
8513  result = result+s->tk1.ptr.p_double[i]*s->txc.ptr.p_double[i];
8514  }
8515  result = result+s->tk0;
8516  }
8517 
8518  /*
8519  * TB (Bf and Bc parts)
8520  */
8521  for(i=0; i<=n-1; i++)
8522  {
8523  result = result+s->tb.ptr.p_double[i]*s->txc.ptr.p_double[i];
8524  }
8525  return result;
8526 }
8527 
8528 
8529 /*************************************************************************
8530 This subroutine calls CQMRebuild() and evaluates model at X subject to
8531 active constraints.
8532 
8533 It is intended for debug purposes only, because it evaluates model by
8534 means of "effective" matrices built by CQMRebuild(). The only purpose of
8535 this function is to check correctness of CQMRebuild() by comparing results
8536 of this function with ones obtained by CQMEval(), which is used as
8537 reference point. The idea is that significant deviation in results of
8538 these two functions is evidence of some error in the CQMRebuild().
8539 
8540 NOTE: suffix E denotes that effective matrices. There is one more variant
8541  of this function, which uses temporary matrices built by
8542  CQMRebuild().
8543 
8544 NOTE2: in case CQMRebuild() fails (due to model non-convexity), this
8545  function returns NAN.
8546 
8547  -- ALGLIB --
8548  Copyright 12.06.2012 by Bochkanov Sergey
8549 *************************************************************************/
8551  /* Real */ ae_vector* x,
8552  ae_state *_state)
8553 {
8554  ae_int_t n;
8555  ae_int_t nfree;
8556  ae_int_t i;
8557  ae_int_t j;
8558  double v;
8559  double result;
8560 
8561 
8562  n = s->n;
8563  ae_assert(isfinitevector(x, n, _state), "CQMDebugConstrainedEvalE: X is not finite vector", _state);
8564  if( !cqmodels_cqmrebuild(s, _state) )
8565  {
8566  result = _state->v_nan;
8567  return result;
8568  }
8569  result = 0.0;
8570  nfree = s->nfree;
8571 
8572  /*
8573  * Reorder variables
8574  */
8575  j = 0;
8576  for(i=0; i<=n-1; i++)
8577  {
8578  if( !s->activeset.ptr.p_bool[i] )
8579  {
8580  ae_assert(j<nfree, "CQMDebugConstrainedEvalE: internal error", _state);
8581  s->txc.ptr.p_double[j] = x->ptr.p_double[i];
8582  j = j+1;
8583  }
8584  }
8585 
8586  /*
8587  * ECA
8588  */
8589  ae_assert((s->ecakind==0||s->ecakind==1)||(s->ecakind==-1&&nfree==0), "CQMDebugConstrainedEvalE: unexpected ECAKind", _state);
8590  if( s->ecakind==0 )
8591  {
8592 
8593  /*
8594  * Dense ECA
8595  */
8596  for(i=0; i<=nfree-1; i++)
8597  {
8598  v = 0.0;
8599  for(j=i; j<=nfree-1; j++)
8600  {
8601  v = v+s->ecadense.ptr.pp_double[i][j]*s->txc.ptr.p_double[j];
8602  }
8603  result = result+0.5*ae_sqr(v, _state);
8604  }
8605  }
8606  if( s->ecakind==1 )
8607  {
8608 
8609  /*
8610  * Diagonal ECA
8611  */
8612  for(i=0; i<=nfree-1; i++)
8613  {
8614  result = result+0.5*ae_sqr(s->ecadiag.ptr.p_double[i]*s->txc.ptr.p_double[i], _state);
8615  }
8616  }
8617 
8618  /*
8619  * EQ
8620  */
8621  for(i=0; i<=s->k-1; i++)
8622  {
8623  v = 0.0;
8624  for(j=0; j<=nfree-1; j++)
8625  {
8626  v = v+s->eq.ptr.pp_double[i][j]*s->txc.ptr.p_double[j];
8627  }
8628  result = result+0.5*ae_sqr(v, _state);
8629  }
8630 
8631  /*
8632  * EB
8633  */
8634  for(i=0; i<=nfree-1; i++)
8635  {
8636  result = result+s->eb.ptr.p_double[i]*s->txc.ptr.p_double[i];
8637  }
8638 
8639  /*
8640  * EC
8641  */
8642  result = result+s->ec;
8643  return result;
8644 }
8645 
8646 
8647 /*************************************************************************
8648 Internal function, rebuilds "effective" model subject to constraints.
8649 Returns False on failure (non-SPD main quadratic term)
8650 
8651  -- ALGLIB --
8652  Copyright 10.05.2011 by Bochkanov Sergey
8653 *************************************************************************/
8654 static ae_bool cqmodels_cqmrebuild(convexquadraticmodel* s,
8655  ae_state *_state)
8656 {
8657  ae_int_t n;
8658  ae_int_t nfree;
8659  ae_int_t k;
8660  ae_int_t i;
8661  ae_int_t j;
8662  ae_int_t ridx0;
8663  ae_int_t ridx1;
8664  ae_int_t cidx0;
8665  ae_int_t cidx1;
8666  double v;
8667  ae_bool result;
8668 
8669 
8670  if( ae_fp_eq(s->alpha,0)&&ae_fp_eq(s->tau,0) )
8671  {
8672 
8673  /*
8674  * Non-SPD model, quick exit
8675  */
8676  result = ae_false;
8677  return result;
8678  }
8679  result = ae_true;
8680  n = s->n;
8681  k = s->k;
8682 
8683  /*
8684  * Determine number of free variables.
8685  * Fill TXC - array whose last N-NFree elements store constraints.
8686  */
8687  if( s->isactivesetchanged )
8688  {
8689  s->nfree = 0;
8690  for(i=0; i<=n-1; i++)
8691  {
8692  if( !s->activeset.ptr.p_bool[i] )
8693  {
8694  s->nfree = s->nfree+1;
8695  }
8696  }
8697  j = s->nfree;
8698  for(i=0; i<=n-1; i++)
8699  {
8700  if( s->activeset.ptr.p_bool[i] )
8701  {
8702  s->txc.ptr.p_double[j] = s->xc.ptr.p_double[i];
8703  j = j+1;
8704  }
8705  }
8706  }
8707  nfree = s->nfree;
8708 
8709  /*
8710  * Re-evaluate TQ2/TQ1/TQ0, if needed
8711  */
8713  {
8714 
8715  /*
8716  * Handle cases Alpha>0 and Alpha=0 separately:
8717  * * in the first case we have dense matrix
8718  * * in the second one we have diagonal matrix, which can be
8719  * handled more efficiently
8720  */
8721  if( ae_fp_greater(s->alpha,0) )
8722  {
8723 
8724  /*
8725  * Alpha>0, dense QP
8726  *
8727  * Split variables into two groups - free (F) and constrained (C). Reorder
8728  * variables in such way that free vars come first, constrained are last:
8729  * x = [xf, xc].
8730  *
8731  * Main quadratic term x'*(alpha*A+tau*D)*x now splits into quadratic part,
8732  * linear part and constant part:
8733  * ( alpha*Aff+tau*Df alpha*Afc ) ( xf )
8734  * 0.5*( xf' xc' )*( )*( ) =
8735  * ( alpha*Acf alpha*Acc+tau*Dc ) ( xc )
8736  *
8737  * = 0.5*xf'*(alpha*Aff+tau*Df)*xf + (alpha*Afc*xc)'*xf + 0.5*xc'(alpha*Acc+tau*Dc)*xc
8738  *
8739  * We store these parts into temporary variables:
8740  * * alpha*Aff+tau*Df, alpha*Afc, alpha*Acc+tau*Dc are stored into upper
8741  * triangle of TQ2
8742  * * alpha*Afc*xc is stored into TQ1
8743  * * 0.5*xc'(alpha*Acc+tau*Dc)*xc is stored into TQ0
8744  *
8745  * Below comes first part of the work - generation of TQ2:
8746  * * we pass through rows of A and copy I-th row into upper block (Aff/Afc) or
8747  * lower one (Acf/Acc) of TQ2, depending on presence of X[i] in the active set.
8748  * RIdx0 variable contains current position for insertion into upper block,
8749  * RIdx1 contains current position for insertion into lower one.
8750  * * within each row, we copy J-th element into left half (Aff/Acf) or right
8751  * one (Afc/Acc), depending on presence of X[j] in the active set. CIdx0
8752  * contains current position for insertion into left block, CIdx1 contains
8753  * position for insertion into right one.
8754  * * during copying, we multiply elements by alpha and add diagonal matrix D.
8755  */
8756  ridx0 = 0;
8757  ridx1 = s->nfree;
8758  for(i=0; i<=n-1; i++)
8759  {
8760  cidx0 = 0;
8761  cidx1 = s->nfree;
8762  for(j=0; j<=n-1; j++)
8763  {
8764  if( !s->activeset.ptr.p_bool[i]&&!s->activeset.ptr.p_bool[j] )
8765  {
8766 
8767  /*
8768  * Element belongs to Aff
8769  */
8770  v = s->alpha*s->a.ptr.pp_double[i][j];
8771  if( i==j&&ae_fp_greater(s->tau,0) )
8772  {
8773  v = v+s->tau*s->d.ptr.p_double[i];
8774  }
8775  s->tq2dense.ptr.pp_double[ridx0][cidx0] = v;
8776  }
8777  if( !s->activeset.ptr.p_bool[i]&&s->activeset.ptr.p_bool[j] )
8778  {
8779 
8780  /*
8781  * Element belongs to Afc
8782  */
8783  s->tq2dense.ptr.pp_double[ridx0][cidx1] = s->alpha*s->a.ptr.pp_double[i][j];
8784  }
8785  if( s->activeset.ptr.p_bool[i]&&!s->activeset.ptr.p_bool[j] )
8786  {
8787 
8788  /*
8789  * Element belongs to Acf
8790  */
8791  s->tq2dense.ptr.pp_double[ridx1][cidx0] = s->alpha*s->a.ptr.pp_double[i][j];
8792  }
8793  if( s->activeset.ptr.p_bool[i]&&s->activeset.ptr.p_bool[j] )
8794  {
8795 
8796  /*
8797  * Element belongs to Acc
8798  */
8799  v = s->alpha*s->a.ptr.pp_double[i][j];
8800  if( i==j&&ae_fp_greater(s->tau,0) )
8801  {
8802  v = v+s->tau*s->d.ptr.p_double[i];
8803  }
8804  s->tq2dense.ptr.pp_double[ridx1][cidx1] = v;
8805  }
8806  if( s->activeset.ptr.p_bool[j] )
8807  {
8808  cidx1 = cidx1+1;
8809  }
8810  else
8811  {
8812  cidx0 = cidx0+1;
8813  }
8814  }
8815  if( s->activeset.ptr.p_bool[i] )
8816  {
8817  ridx1 = ridx1+1;
8818  }
8819  else
8820  {
8821  ridx0 = ridx0+1;
8822  }
8823  }
8824 
8825  /*
8826  * Now we have TQ2, and we can evaluate TQ1.
8827  * In the special case when we have Alpha=0, NFree=0 or NFree=N,
8828  * TQ1 is filled by zeros.
8829  */
8830  for(i=0; i<=n-1; i++)
8831  {
8832  s->tq1.ptr.p_double[i] = 0.0;
8833  }
8834  if( s->nfree>0&&s->nfree<n )
8835  {
8836  rmatrixmv(s->nfree, n-s->nfree, &s->tq2dense, 0, s->nfree, 0, &s->txc, s->nfree, &s->tq1, 0, _state);
8837  }
8838 
8839  /*
8840  * And finally, we evaluate TQ0.
8841  */
8842  v = 0.0;
8843  for(i=s->nfree; i<=n-1; i++)
8844  {
8845  for(j=s->nfree; j<=n-1; j++)
8846  {
8847  v = v+0.5*s->txc.ptr.p_double[i]*s->tq2dense.ptr.pp_double[i][j]*s->txc.ptr.p_double[j];
8848  }
8849  }
8850  s->tq0 = v;
8851  }
8852  else
8853  {
8854 
8855  /*
8856  * Alpha=0, diagonal QP
8857  *
8858  * Split variables into two groups - free (F) and constrained (C). Reorder
8859  * variables in such way that free vars come first, constrained are last:
8860  * x = [xf, xc].
8861  *
8862  * Main quadratic term x'*(tau*D)*x now splits into quadratic and constant
8863  * parts:
8864  * ( tau*Df ) ( xf )
8865  * 0.5*( xf' xc' )*( )*( ) =
8866  * ( tau*Dc ) ( xc )
8867  *
8868  * = 0.5*xf'*(tau*Df)*xf + 0.5*xc'(tau*Dc)*xc
8869  *
8870  * We store these parts into temporary variables:
8871  * * tau*Df is stored in TQ2Diag
8872  * * 0.5*xc'(tau*Dc)*xc is stored into TQ0
8873  */
8874  s->tq0 = 0.0;
8875  ridx0 = 0;
8876  for(i=0; i<=n-1; i++)
8877  {
8878  if( !s->activeset.ptr.p_bool[i] )
8879  {
8880  s->tq2diag.ptr.p_double[ridx0] = s->tau*s->d.ptr.p_double[i];
8881  ridx0 = ridx0+1;
8882  }
8883  else
8884  {
8885  s->tq0 = s->tq0+0.5*s->tau*s->d.ptr.p_double[i]*ae_sqr(s->xc.ptr.p_double[i], _state);
8886  }
8887  }
8888  for(i=0; i<=n-1; i++)
8889  {
8890  s->tq1.ptr.p_double[i] = 0.0;
8891  }
8892  }
8893  }
8894 
8895  /*
8896  * Re-evaluate TK2/TK1/TK0, if needed
8897  */
8899  {
8900 
8901  /*
8902  * Split variables into two groups - free (F) and constrained (C). Reorder
8903  * variables in such way that free vars come first, constrained are last:
8904  * x = [xf, xc].
8905  *
8906  * Secondary term theta*(Q*x-r)'*(Q*x-r) now splits into quadratic part,
8907  * linear part and constant part:
8908  * ( ( xf ) )' ( ( xf ) )
8909  * 0.5*theta*( (Qf Qc)'*( ) - r ) * ( (Qf Qc)'*( ) - r ) =
8910  * ( ( xc ) ) ( ( xc ) )
8911  *
8912  * = 0.5*theta*xf'*(Qf'*Qf)*xf + theta*((Qc*xc-r)'*Qf)*xf +
8913  * + theta*(-r'*(Qc*xc-r)-0.5*r'*r+0.5*xc'*Qc'*Qc*xc)
8914  *
8915  * We store these parts into temporary variables:
8916  * * sqrt(theta)*Qf is stored into TK2
8917  * * theta*((Qc*xc-r)'*Qf) is stored into TK1
8918  * * theta*(-r'*(Qc*xc-r)-0.5*r'*r+0.5*xc'*Qc'*Qc*xc) is stored into TK0
8919  *
8920  * We use several other temporaries to store intermediate results:
8921  * * Tmp0 - to store Qc*xc-r
8922  * * Tmp1 - to store Qc*xc
8923  *
8924  * Generation of TK2/TK1/TK0 is performed as follows:
8925  * * we fill TK2/TK1/TK0 (to handle K=0 or Theta=0)
8926  * * other steps are performed only for K>0 and Theta>0
8927  * * we pass through columns of Q and copy I-th column into left block (Qf) or
8928  * right one (Qc) of TK2, depending on presence of X[i] in the active set.
8929  * CIdx0 variable contains current position for insertion into upper block,
8930  * CIdx1 contains current position for insertion into lower one.
8931  * * we calculate Qc*xc-r and store it into Tmp0
8932  * * we calculate TK0 and TK1
8933  * * we multiply leading part of TK2 which stores Qf by sqrt(theta)
8934  * it is important to perform this step AFTER calculation of TK0 and TK1,
8935  * because we need original (non-modified) Qf to calculate TK0 and TK1.
8936  */
8937  for(j=0; j<=n-1; j++)
8938  {
8939  for(i=0; i<=k-1; i++)
8940  {
8941  s->tk2.ptr.pp_double[i][j] = 0.0;
8942  }
8943  s->tk1.ptr.p_double[j] = 0.0;
8944  }
8945  s->tk0 = 0.0;
8946  if( s->k>0&&ae_fp_greater(s->theta,0) )
8947  {
8948 
8949  /*
8950  * Split Q into Qf and Qc
8951  * Calculate Qc*xc-r, store in Tmp0
8952  */
8953  rvectorsetlengthatleast(&s->tmp0, k, _state);
8954  rvectorsetlengthatleast(&s->tmp1, k, _state);
8955  cidx0 = 0;
8956  cidx1 = nfree;
8957  for(i=0; i<=k-1; i++)
8958  {
8959  s->tmp1.ptr.p_double[i] = 0.0;
8960  }
8961  for(j=0; j<=n-1; j++)
8962  {
8963  if( s->activeset.ptr.p_bool[j] )
8964  {
8965  for(i=0; i<=k-1; i++)
8966  {
8967  s->tk2.ptr.pp_double[i][cidx1] = s->q.ptr.pp_double[i][j];
8968  s->tmp1.ptr.p_double[i] = s->tmp1.ptr.p_double[i]+s->q.ptr.pp_double[i][j]*s->txc.ptr.p_double[cidx1];
8969  }
8970  cidx1 = cidx1+1;
8971  }
8972  else
8973  {
8974  for(i=0; i<=k-1; i++)
8975  {
8976  s->tk2.ptr.pp_double[i][cidx0] = s->q.ptr.pp_double[i][j];
8977  }
8978  cidx0 = cidx0+1;
8979  }
8980  }
8981  for(i=0; i<=k-1; i++)
8982  {
8983  s->tmp0.ptr.p_double[i] = s->tmp1.ptr.p_double[i]-s->r.ptr.p_double[i];
8984  }
8985 
8986  /*
8987  * Calculate TK0
8988  */
8989  v = 0.0;
8990  for(i=0; i<=k-1; i++)
8991  {
8992  v = v+s->theta*(0.5*ae_sqr(s->tmp1.ptr.p_double[i], _state)-s->r.ptr.p_double[i]*s->tmp0.ptr.p_double[i]-0.5*ae_sqr(s->r.ptr.p_double[i], _state));
8993  }
8994  s->tk0 = v;
8995 
8996  /*
8997  * Calculate TK1
8998  */
8999  if( nfree>0 )
9000  {
9001  for(i=0; i<=k-1; i++)
9002  {
9003  v = s->theta*s->tmp0.ptr.p_double[i];
9004  ae_v_addd(&s->tk1.ptr.p_double[0], 1, &s->tk2.ptr.pp_double[i][0], 1, ae_v_len(0,nfree-1), v);
9005  }
9006  }
9007 
9008  /*
9009  * Calculate TK2
9010  */
9011  if( nfree>0 )
9012  {
9013  v = ae_sqrt(s->theta, _state);
9014  for(i=0; i<=k-1; i++)
9015  {
9016  ae_v_muld(&s->tk2.ptr.pp_double[i][0], 1, ae_v_len(0,nfree-1), v);
9017  }
9018  }
9019  }
9020  }
9021 
9022  /*
9023  * Re-evaluate TB
9024  */
9026  {
9027  ridx0 = 0;
9028  ridx1 = nfree;
9029  for(i=0; i<=n-1; i++)
9030  {
9031  if( s->activeset.ptr.p_bool[i] )
9032  {
9033  s->tb.ptr.p_double[ridx1] = s->b.ptr.p_double[i];
9034  ridx1 = ridx1+1;
9035  }
9036  else
9037  {
9038  s->tb.ptr.p_double[ridx0] = s->b.ptr.p_double[i];
9039  ridx0 = ridx0+1;
9040  }
9041  }
9042  }
9043 
9044  /*
9045  * Compose ECA: either dense ECA or diagonal ECA
9046  */
9047  if( (s->isactivesetchanged||s->ismaintermchanged)&&nfree>0 )
9048  {
9049  if( ae_fp_greater(s->alpha,0) )
9050  {
9051 
9052  /*
9053  * Dense ECA
9054  */
9055  s->ecakind = 0;
9056  for(i=0; i<=nfree-1; i++)
9057  {
9058  for(j=i; j<=nfree-1; j++)
9059  {
9060  s->ecadense.ptr.pp_double[i][j] = s->tq2dense.ptr.pp_double[i][j];
9061  }
9062  }
9063  if( !spdmatrixcholeskyrec(&s->ecadense, 0, nfree, ae_true, &s->tmp0, _state) )
9064  {
9065  result = ae_false;
9066  return result;
9067  }
9068  }
9069  else
9070  {
9071 
9072  /*
9073  * Diagonal ECA
9074  */
9075  s->ecakind = 1;
9076  for(i=0; i<=nfree-1; i++)
9077  {
9078  if( ae_fp_less(s->tq2diag.ptr.p_double[i],0) )
9079  {
9080  result = ae_false;
9081  return result;
9082  }
9083  s->ecadiag.ptr.p_double[i] = ae_sqrt(s->tq2diag.ptr.p_double[i], _state);
9084  }
9085  }
9086  }
9087 
9088  /*
9089  * Compose EQ
9090  */
9092  {
9093  for(i=0; i<=k-1; i++)
9094  {
9095  for(j=0; j<=nfree-1; j++)
9096  {
9097  s->eq.ptr.pp_double[i][j] = s->tk2.ptr.pp_double[i][j];
9098  }
9099  }
9100  }
9101 
9102  /*
9103  * Calculate ECCM
9104  */
9105  if( ((((s->isactivesetchanged||s->ismaintermchanged)||s->issecondarytermchanged)&&s->k>0)&&ae_fp_greater(s->theta,0))&&nfree>0 )
9106  {
9107 
9108  /*
9109  * Calculate ECCM - Cholesky factor of the "effective" capacitance
9110  * matrix CM = I + EQ*inv(EffectiveA)*EQ'.
9111  *
9112  * We calculate CM as follows:
9113  * CM = I + EQ*inv(EffectiveA)*EQ'
9114  * = I + EQ*ECA^(-1)*ECA^(-T)*EQ'
9115  * = I + (EQ*ECA^(-1))*(EQ*ECA^(-1))'
9116  *
9117  * Then we perform Cholesky decomposition of CM.
9118  */
9119  rmatrixsetlengthatleast(&s->tmp2, k, n, _state);
9120  rmatrixcopy(k, nfree, &s->eq, 0, 0, &s->tmp2, 0, 0, _state);
9121  ae_assert(s->ecakind==0||s->ecakind==1, "CQMRebuild: unexpected ECAKind", _state);
9122  if( s->ecakind==0 )
9123  {
9124  rmatrixrighttrsm(k, nfree, &s->ecadense, 0, 0, ae_true, ae_false, 0, &s->tmp2, 0, 0, _state);
9125  }
9126  if( s->ecakind==1 )
9127  {
9128  for(i=0; i<=k-1; i++)
9129  {
9130  for(j=0; j<=nfree-1; j++)
9131  {
9132  s->tmp2.ptr.pp_double[i][j] = s->tmp2.ptr.pp_double[i][j]/s->ecadiag.ptr.p_double[j];
9133  }
9134  }
9135  }
9136  for(i=0; i<=k-1; i++)
9137  {
9138  for(j=0; j<=k-1; j++)
9139  {
9140  s->eccm.ptr.pp_double[i][j] = 0.0;
9141  }
9142  s->eccm.ptr.pp_double[i][i] = 1.0;
9143  }
9144  rmatrixsyrk(k, nfree, 1.0, &s->tmp2, 0, 0, 0, 1.0, &s->eccm, 0, 0, ae_true, _state);
9145  if( !spdmatrixcholeskyrec(&s->eccm, 0, k, ae_true, &s->tmp0, _state) )
9146  {
9147  result = ae_false;
9148  return result;
9149  }
9150  }
9151 
9152  /*
9153  * Compose EB and EC
9154  *
9155  * NOTE: because these quantities are cheap to compute, we do not
9156  * use caching here.
9157  */
9158  for(i=0; i<=nfree-1; i++)
9159  {
9160  s->eb.ptr.p_double[i] = s->tq1.ptr.p_double[i]+s->tk1.ptr.p_double[i]+s->tb.ptr.p_double[i];
9161  }
9162  s->ec = s->tq0+s->tk0;
9163  for(i=nfree; i<=n-1; i++)
9164  {
9165  s->ec = s->ec+s->tb.ptr.p_double[i]*s->txc.ptr.p_double[i];
9166  }
9167 
9168  /*
9169  * Change cache status - everything is cached
9170  */
9175  return result;
9176 }
9177 
9178 
9179 /*************************************************************************
9180 Internal function, solves system Effective_A*x = b.
9181 It should be called after successful completion of CQMRebuild().
9182 
9183 INPUT PARAMETERS:
9184  S - quadratic model, after call to CQMRebuild()
9185  X - right part B, array[S.NFree]
9186  Tmp - temporary array, automatically reallocated if needed
9187 
9188 OUTPUT PARAMETERS:
9189  X - solution, array[S.NFree]
9190 
9191 NOTE: when called with zero S.NFree, returns silently
9192 NOTE: this function assumes that EA is non-degenerate
9193 
9194  -- ALGLIB --
9195  Copyright 10.05.2011 by Bochkanov Sergey
9196 *************************************************************************/
9197 static void cqmodels_cqmsolveea(convexquadraticmodel* s,
9198  /* Real */ ae_vector* x,
9199  /* Real */ ae_vector* tmp,
9200  ae_state *_state)
9201 {
9202  ae_int_t i;
9203 
9204 
9205  ae_assert((s->ecakind==0||s->ecakind==1)||(s->ecakind==-1&&s->nfree==0), "CQMSolveEA: unexpected ECAKind", _state);
9206  if( s->ecakind==0 )
9207  {
9208 
9209  /*
9210  * Dense ECA, use FBLSCholeskySolve() dense solver.
9211  */
9212  fblscholeskysolve(&s->ecadense, 1.0, s->nfree, ae_true, x, tmp, _state);
9213  }
9214  if( s->ecakind==1 )
9215  {
9216 
9217  /*
9218  * Diagonal ECA
9219  */
9220  for(i=0; i<=s->nfree-1; i++)
9221  {
9222  x->ptr.p_double[i] = x->ptr.p_double[i]/ae_sqr(s->ecadiag.ptr.p_double[i], _state);
9223  }
9224  }
9225 }
9226 
9227 
9228 ae_bool _convexquadraticmodel_init(void* _p, ae_state *_state, ae_bool make_automatic)
9229 {
9231  ae_touch_ptr((void*)p);
9232  if( !ae_matrix_init(&p->a, 0, 0, DT_REAL, _state, make_automatic) )
9233  return ae_false;
9234  if( !ae_matrix_init(&p->q, 0, 0, DT_REAL, _state, make_automatic) )
9235  return ae_false;
9236  if( !ae_vector_init(&p->b, 0, DT_REAL, _state, make_automatic) )
9237  return ae_false;
9238  if( !ae_vector_init(&p->r, 0, DT_REAL, _state, make_automatic) )
9239  return ae_false;
9240  if( !ae_vector_init(&p->xc, 0, DT_REAL, _state, make_automatic) )
9241  return ae_false;
9242  if( !ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic) )
9243  return ae_false;
9244  if( !ae_vector_init(&p->activeset, 0, DT_BOOL, _state, make_automatic) )
9245  return ae_false;
9246  if( !ae_matrix_init(&p->tq2dense, 0, 0, DT_REAL, _state, make_automatic) )
9247  return ae_false;
9248  if( !ae_matrix_init(&p->tk2, 0, 0, DT_REAL, _state, make_automatic) )
9249  return ae_false;
9250  if( !ae_vector_init(&p->tq2diag, 0, DT_REAL, _state, make_automatic) )
9251  return ae_false;
9252  if( !ae_vector_init(&p->tq1, 0, DT_REAL, _state, make_automatic) )
9253  return ae_false;
9254  if( !ae_vector_init(&p->tk1, 0, DT_REAL, _state, make_automatic) )
9255  return ae_false;
9256  if( !ae_vector_init(&p->txc, 0, DT_REAL, _state, make_automatic) )
9257  return ae_false;
9258  if( !ae_vector_init(&p->tb, 0, DT_REAL, _state, make_automatic) )
9259  return ae_false;
9260  if( !ae_matrix_init(&p->ecadense, 0, 0, DT_REAL, _state, make_automatic) )
9261  return ae_false;
9262  if( !ae_matrix_init(&p->eq, 0, 0, DT_REAL, _state, make_automatic) )
9263  return ae_false;
9264  if( !ae_matrix_init(&p->eccm, 0, 0, DT_REAL, _state, make_automatic) )
9265  return ae_false;
9266  if( !ae_vector_init(&p->ecadiag, 0, DT_REAL, _state, make_automatic) )
9267  return ae_false;
9268  if( !ae_vector_init(&p->eb, 0, DT_REAL, _state, make_automatic) )
9269  return ae_false;
9270  if( !ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic) )
9271  return ae_false;
9272  if( !ae_vector_init(&p->tmp1, 0, DT_REAL, _state, make_automatic) )
9273  return ae_false;
9274  if( !ae_vector_init(&p->tmpg, 0, DT_REAL, _state, make_automatic) )
9275  return ae_false;
9276  if( !ae_matrix_init(&p->tmp2, 0, 0, DT_REAL, _state, make_automatic) )
9277  return ae_false;
9278  return ae_true;
9279 }
9280 
9281 
9282 ae_bool _convexquadraticmodel_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
9283 {
9286  dst->n = src->n;
9287  dst->k = src->k;
9288  dst->alpha = src->alpha;
9289  dst->tau = src->tau;
9290  dst->theta = src->theta;
9291  if( !ae_matrix_init_copy(&dst->a, &src->a, _state, make_automatic) )
9292  return ae_false;
9293  if( !ae_matrix_init_copy(&dst->q, &src->q, _state, make_automatic) )
9294  return ae_false;
9295  if( !ae_vector_init_copy(&dst->b, &src->b, _state, make_automatic) )
9296  return ae_false;
9297  if( !ae_vector_init_copy(&dst->r, &src->r, _state, make_automatic) )
9298  return ae_false;
9299  if( !ae_vector_init_copy(&dst->xc, &src->xc, _state, make_automatic) )
9300  return ae_false;
9301  if( !ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic) )
9302  return ae_false;
9303  if( !ae_vector_init_copy(&dst->activeset, &src->activeset, _state, make_automatic) )
9304  return ae_false;
9305  if( !ae_matrix_init_copy(&dst->tq2dense, &src->tq2dense, _state, make_automatic) )
9306  return ae_false;
9307  if( !ae_matrix_init_copy(&dst->tk2, &src->tk2, _state, make_automatic) )
9308  return ae_false;
9309  if( !ae_vector_init_copy(&dst->tq2diag, &src->tq2diag, _state, make_automatic) )
9310  return ae_false;
9311  if( !ae_vector_init_copy(&dst->tq1, &src->tq1, _state, make_automatic) )
9312  return ae_false;
9313  if( !ae_vector_init_copy(&dst->tk1, &src->tk1, _state, make_automatic) )
9314  return ae_false;
9315  dst->tq0 = src->tq0;
9316  dst->tk0 = src->tk0;
9317  if( !ae_vector_init_copy(&dst->txc, &src->txc, _state, make_automatic) )
9318  return ae_false;
9319  if( !ae_vector_init_copy(&dst->tb, &src->tb, _state, make_automatic) )
9320  return ae_false;
9321  dst->nfree = src->nfree;
9322  dst->ecakind = src->ecakind;
9323  if( !ae_matrix_init_copy(&dst->ecadense, &src->ecadense, _state, make_automatic) )
9324  return ae_false;
9325  if( !ae_matrix_init_copy(&dst->eq, &src->eq, _state, make_automatic) )
9326  return ae_false;
9327  if( !ae_matrix_init_copy(&dst->eccm, &src->eccm, _state, make_automatic) )
9328  return ae_false;
9329  if( !ae_vector_init_copy(&dst->ecadiag, &src->ecadiag, _state, make_automatic) )
9330  return ae_false;
9331  if( !ae_vector_init_copy(&dst->eb, &src->eb, _state, make_automatic) )
9332  return ae_false;
9333  dst->ec = src->ec;
9334  if( !ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic) )
9335  return ae_false;
9336  if( !ae_vector_init_copy(&dst->tmp1, &src->tmp1, _state, make_automatic) )
9337  return ae_false;
9338  if( !ae_vector_init_copy(&dst->tmpg, &src->tmpg, _state, make_automatic) )
9339  return ae_false;
9340  if( !ae_matrix_init_copy(&dst->tmp2, &src->tmp2, _state, make_automatic) )
9341  return ae_false;
9346  return ae_true;
9347 }
9348 
9349 
9351 {
9353  ae_touch_ptr((void*)p);
9354  ae_matrix_clear(&p->a);
9355  ae_matrix_clear(&p->q);
9356  ae_vector_clear(&p->b);
9357  ae_vector_clear(&p->r);
9358  ae_vector_clear(&p->xc);
9359  ae_vector_clear(&p->d);
9360  ae_vector_clear(&p->activeset);
9361  ae_matrix_clear(&p->tq2dense);
9362  ae_matrix_clear(&p->tk2);
9363  ae_vector_clear(&p->tq2diag);
9364  ae_vector_clear(&p->tq1);
9365  ae_vector_clear(&p->tk1);
9366  ae_vector_clear(&p->txc);
9367  ae_vector_clear(&p->tb);
9368  ae_matrix_clear(&p->ecadense);
9369  ae_matrix_clear(&p->eq);
9370  ae_matrix_clear(&p->eccm);
9371  ae_vector_clear(&p->ecadiag);
9372  ae_vector_clear(&p->eb);
9373  ae_vector_clear(&p->tmp0);
9374  ae_vector_clear(&p->tmp1);
9375  ae_vector_clear(&p->tmpg);
9376  ae_matrix_clear(&p->tmp2);
9377 }
9378 
9379 
9381 {
9383  ae_touch_ptr((void*)p);
9384  ae_matrix_destroy(&p->a);
9385  ae_matrix_destroy(&p->q);
9386  ae_vector_destroy(&p->b);
9387  ae_vector_destroy(&p->r);
9388  ae_vector_destroy(&p->xc);
9389  ae_vector_destroy(&p->d);
9390  ae_vector_destroy(&p->activeset);
9391  ae_matrix_destroy(&p->tq2dense);
9392  ae_matrix_destroy(&p->tk2);
9393  ae_vector_destroy(&p->tq2diag);
9394  ae_vector_destroy(&p->tq1);
9395  ae_vector_destroy(&p->tk1);
9396  ae_vector_destroy(&p->txc);
9397  ae_vector_destroy(&p->tb);
9398  ae_matrix_destroy(&p->ecadense);
9399  ae_matrix_destroy(&p->eq);
9400  ae_matrix_destroy(&p->eccm);
9401  ae_vector_destroy(&p->ecadiag);
9402  ae_vector_destroy(&p->eb);
9403  ae_vector_destroy(&p->tmp0);
9404  ae_vector_destroy(&p->tmp1);
9405  ae_vector_destroy(&p->tmpg);
9406  ae_matrix_destroy(&p->tmp2);
9407 }
9408 
9409 
9410 
9411 
9412 /*************************************************************************
9413 This subroutine is used to initialize SNNLS solver.
9414 
9415 By default, empty NNLS problem is produced, but we allocated enough space
9416 to store problems with NSMax+NDMax columns and NRMax rows. It is good
9417 place to provide algorithm with initial estimate of the space requirements,
9418 although you may underestimate problem size or even pass zero estimates -
9419 in this case buffer variables will be resized automatically when you set
9420 NNLS problem.
9421 
9422 Previously allocated buffer variables are reused as much as possible. This
9423 function does not clear structure completely, it tries to preserve as much
9424 dynamically allocated memory as possible.
9425 
9426  -- ALGLIB --
9427  Copyright 10.10.2012 by Bochkanov Sergey
9428 *************************************************************************/
9429 void snnlsinit(ae_int_t nsmax,
9430  ae_int_t ndmax,
9431  ae_int_t nrmax,
9432  snnlssolver* s,
9433  ae_state *_state)
9434 {
9435 
9436 
9437  s->ns = 0;
9438  s->nd = 0;
9439  s->nr = 0;
9440  rmatrixsetlengthatleast(&s->densea, nrmax, ndmax, _state);
9441  rmatrixsetlengthatleast(&s->tmpca, nrmax, ndmax, _state);
9442  rmatrixsetlengthatleast(&s->tmpz, ndmax, ndmax, _state);
9443  rvectorsetlengthatleast(&s->b, nrmax, _state);
9444  bvectorsetlengthatleast(&s->nnc, nsmax+ndmax, _state);
9445  s->debugflops = 0.0;
9446  s->debugmaxnewton = 0;
9447  s->refinementits = snnls_iterativerefinementits;
9448 }
9449 
9450 
9451 /*************************************************************************
9452 This subroutine is used to set NNLS problem:
9453 
9454  ( [ 1 | ] [ ] [ ] )^2
9455  ( [ 1 | ] [ ] [ ] )
9456  min ( [ 1 | Ad ] * [ x ] - [ b ] ) s.t. x>=0
9457  ( [ | ] [ ] [ ] )
9458  ( [ | ] [ ] [ ] )
9459 
9460 where:
9461 * identity matrix has NS*NS size (NS<=NR, NS can be zero)
9462 * dense matrix Ad has NR*ND size
9463 * b is NR*1 vector
9464 * x is (NS+ND)*1 vector
9465 * all elements of x are non-negative (this constraint can be removed later
9466  by calling SNNLSDropNNC() function)
9467 
9468 Previously allocated buffer variables are reused as much as possible.
9469 After you set problem, you can solve it with SNNLSSolve().
9470 
9471 INPUT PARAMETERS:
9472  S - SNNLS solver, must be initialized with SNNLSInit() call
9473  A - array[NR,ND], dense part of the system
9474  B - array[NR], right part
9475  NS - size of the sparse part of the system, 0<=NS<=NR
9476  ND - size of the dense part of the system, ND>=0
9477  NR - rows count, NR>0
9478 
9479 NOTE:
9480  1. You can have NS+ND=0, solver will correctly accept such combination
9481  and return empty array as problem solution.
9482 
9483  -- ALGLIB --
9484  Copyright 10.10.2012 by Bochkanov Sergey
9485 *************************************************************************/
9487  /* Real */ ae_matrix* a,
9488  /* Real */ ae_vector* b,
9489  ae_int_t ns,
9490  ae_int_t nd,
9491  ae_int_t nr,
9492  ae_state *_state)
9493 {
9494  ae_int_t i;
9495 
9496 
9497  ae_assert(nd>=0, "SNNLSSetProblem: ND<0", _state);
9498  ae_assert(ns>=0, "SNNLSSetProblem: NS<0", _state);
9499  ae_assert(nr>0, "SNNLSSetProblem: NR<=0", _state);
9500  ae_assert(ns<=nr, "SNNLSSetProblem: NS>NR", _state);
9501  ae_assert(a->rows>=nr||nd==0, "SNNLSSetProblem: rows(A)<NR", _state);
9502  ae_assert(a->cols>=nd, "SNNLSSetProblem: cols(A)<ND", _state);
9503  ae_assert(b->cnt>=nr, "SNNLSSetProblem: length(B)<NR", _state);
9504  ae_assert(apservisfinitematrix(a, nr, nd, _state), "SNNLSSetProblem: A contains INF/NAN", _state);
9505  ae_assert(isfinitevector(b, nr, _state), "SNNLSSetProblem: B contains INF/NAN", _state);
9506 
9507  /*
9508  * Copy problem
9509  */
9510  s->ns = ns;
9511  s->nd = nd;
9512  s->nr = nr;
9513  if( nd>0 )
9514  {
9515  rmatrixsetlengthatleast(&s->densea, nr, nd, _state);
9516  for(i=0; i<=nr-1; i++)
9517  {
9518  ae_v_move(&s->densea.ptr.pp_double[i][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,nd-1));
9519  }
9520  }
9521  rvectorsetlengthatleast(&s->b, nr, _state);
9522  ae_v_move(&s->b.ptr.p_double[0], 1, &b->ptr.p_double[0], 1, ae_v_len(0,nr-1));
9523  bvectorsetlengthatleast(&s->nnc, ns+nd, _state);
9524  for(i=0; i<=ns+nd-1; i++)
9525  {
9526  s->nnc.ptr.p_bool[i] = ae_true;
9527  }
9528 }
9529 
9530 
9531 /*************************************************************************
9532 This subroutine drops non-negativity constraint from the problem set by
9533 SNNLSSetProblem() call. This function must be called AFTER problem is set,
9534 because each SetProblem() call resets constraints to their default state
9535 (all constraints are present).
9536 
9537 INPUT PARAMETERS:
9538  S - SNNLS solver, must be initialized with SNNLSInit() call,
9539  problem must be set with SNNLSSetProblem() call.
9540  Idx - constraint index, 0<=IDX<NS+ND
9541 
9542  -- ALGLIB --
9543  Copyright 10.10.2012 by Bochkanov Sergey
9544 *************************************************************************/
9545 void snnlsdropnnc(snnlssolver* s, ae_int_t idx, ae_state *_state)
9546 {
9547 
9548 
9549  ae_assert(idx>=0, "SNNLSDropNNC: Idx<0", _state);
9550  ae_assert(idx<s->ns+s->nd, "SNNLSDropNNC: Idx>=NS+ND", _state);
9551  s->nnc.ptr.p_bool[idx] = ae_false;
9552 }
9553 
9554 
9555 /*************************************************************************
9556 This subroutine is used to solve NNLS problem.
9557 
9558 INPUT PARAMETERS:
9559  S - SNNLS solver, must be initialized with SNNLSInit() call and
9560  problem must be set up with SNNLSSetProblem() call.
9561  X - possibly preallocated buffer, automatically resized if needed
9562 
9563 OUTPUT PARAMETERS:
9564  X - array[NS+ND], solution
9565 
9566 NOTE:
9567  1. You can have NS+ND=0, solver will correctly accept such combination
9568  and return empty array as problem solution.
9569 
9570  2. Internal field S.DebugFLOPS contains rough estimate of FLOPs used
9571  to solve problem. It can be used for debugging purposes. This field
9572  is real-valued.
9573 
9574  -- ALGLIB --
9575  Copyright 10.10.2012 by Bochkanov Sergey
9576 *************************************************************************/
9577 void snnlssolve(snnlssolver* s,
9578  /* Real */ ae_vector* x,
9579  ae_state *_state)
9580 {
9581  ae_int_t i;
9582  ae_int_t j;
9583  ae_int_t ns;
9584  ae_int_t nd;
9585  ae_int_t nr;
9586  ae_int_t nsc;
9587  ae_int_t ndc;
9588  ae_int_t newtoncnt;
9589  ae_bool terminationneeded;
9590  double eps;
9591  double fcur;
9592  double fprev;
9593  double fcand;
9594  double noiselevel;
9595  double noisetolerance;
9596  double stplen;
9597  double d2;
9598  double d1;
9599  double d0;
9600  ae_bool wasactivation;
9601  ae_int_t rfsits;
9602  double lambdav;
9603  double v0;
9604  double v1;
9605  double v;
9606 
9607 
9608 
9609  /*
9610  * Prepare
9611  */
9612  ns = s->ns;
9613  nd = s->nd;
9614  nr = s->nr;
9615  s->debugflops = 0.0;
9616 
9617  /*
9618  * Handle special cases:
9619  * * NS+ND=0
9620  * * ND=0
9621  */
9622  if( ns+nd==0 )
9623  {
9624  return;
9625  }
9626  if( nd==0 )
9627  {
9628  rvectorsetlengthatleast(x, ns, _state);
9629  for(i=0; i<=ns-1; i++)
9630  {
9631  x->ptr.p_double[i] = s->b.ptr.p_double[i];
9632  if( s->nnc.ptr.p_bool[i] )
9633  {
9634  x->ptr.p_double[i] = ae_maxreal(x->ptr.p_double[i], 0.0, _state);
9635  }
9636  }
9637  return;
9638  }
9639 
9640  /*
9641  * Main cycle of BLEIC-SNNLS algorithm.
9642  * Below we assume that ND>0.
9643  */
9644  rvectorsetlengthatleast(x, ns+nd, _state);
9645  rvectorsetlengthatleast(&s->xn, ns+nd, _state);
9646  rvectorsetlengthatleast(&s->g, ns+nd, _state);
9647  rvectorsetlengthatleast(&s->d, ns+nd, _state);
9648  rvectorsetlengthatleast(&s->r, nr, _state);
9649  rvectorsetlengthatleast(&s->diagaa, nd, _state);
9650  rvectorsetlengthatleast(&s->dx, ns+nd, _state);
9651  for(i=0; i<=ns+nd-1; i++)
9652  {
9653  x->ptr.p_double[i] = 0.0;
9654  }
9655  eps = 2*ae_machineepsilon;
9656  noisetolerance = 10.0;
9657  lambdav = 1.0E6*ae_machineepsilon;
9658  newtoncnt = 0;
9659  for(;;)
9660  {
9661 
9662  /*
9663  * Phase 1: perform steepest descent step.
9664  *
9665  * TerminationNeeded control variable is set on exit from this loop:
9666  * * TerminationNeeded=False in case we have to proceed to Phase 2 (Newton step)
9667  * * TerminationNeeded=True in case we found solution (step along projected gradient is small enough)
9668  *
9669  * Temporaries used:
9670  * * R (I|A)*x-b
9671  *
9672  * NOTE 1. It is assumed that initial point X is feasible. This feasibility
9673  * is retained during all iterations.
9674  */
9675  terminationneeded = ae_false;
9676  for(;;)
9677  {
9678 
9679  /*
9680  * Calculate gradient G and constrained descent direction D
9681  */
9682  for(i=0; i<=nr-1; i++)
9683  {
9684  v = ae_v_dotproduct(&s->densea.ptr.pp_double[i][0], 1, &x->ptr.p_double[ns], 1, ae_v_len(0,nd-1));
9685  if( i<ns )
9686  {
9687  v = v+x->ptr.p_double[i];
9688  }
9689  s->r.ptr.p_double[i] = v-s->b.ptr.p_double[i];
9690  }
9691  for(i=0; i<=ns-1; i++)
9692  {
9693  s->g.ptr.p_double[i] = s->r.ptr.p_double[i];
9694  }
9695  for(i=ns; i<=ns+nd-1; i++)
9696  {
9697  s->g.ptr.p_double[i] = 0.0;
9698  }
9699  for(i=0; i<=nr-1; i++)
9700  {
9701  v = s->r.ptr.p_double[i];
9702  ae_v_addd(&s->g.ptr.p_double[ns], 1, &s->densea.ptr.pp_double[i][0], 1, ae_v_len(ns,ns+nd-1), v);
9703  }
9704  for(i=0; i<=ns+nd-1; i++)
9705  {
9706  if( (s->nnc.ptr.p_bool[i]&&ae_fp_less_eq(x->ptr.p_double[i],0))&&ae_fp_greater(s->g.ptr.p_double[i],0) )
9707  {
9708  s->d.ptr.p_double[i] = 0.0;
9709  }
9710  else
9711  {
9712  s->d.ptr.p_double[i] = -s->g.ptr.p_double[i];
9713  }
9714  }
9715  s->debugflops = s->debugflops+2*2*nr*nd;
9716 
9717  /*
9718  * Build quadratic model of F along descent direction:
9719  * F(x+alpha*d) = D2*alpha^2 + D1*alpha + D0
9720  *
9721  * Estimate numerical noise in the X (noise level is used
9722  * to classify step as singificant or insignificant). Noise
9723  * comes from two sources:
9724  * * noise when calculating rows of (I|A)*x
9725  * * noise when calculating norm of residual
9726  *
9727  * In case function curvature is negative or product of descent
9728  * direction and gradient is non-negative, iterations are terminated.
9729  *
9730  * NOTE: D0 is not actually used, but we prefer to maintain it.
9731  */
9732  fprev = ae_v_dotproduct(&s->r.ptr.p_double[0], 1, &s->r.ptr.p_double[0], 1, ae_v_len(0,nr-1));
9733  fprev = fprev/2;
9734  noiselevel = 0.0;
9735  for(i=0; i<=nr-1; i++)
9736  {
9737 
9738  /*
9739  * Estimate noise introduced by I-th row of (I|A)*x
9740  */
9741  v = 0.0;
9742  if( i<ns )
9743  {
9744  v = eps*x->ptr.p_double[i];
9745  }
9746  for(j=0; j<=nd-1; j++)
9747  {
9748  v = ae_maxreal(v, eps*ae_fabs(s->densea.ptr.pp_double[i][j]*x->ptr.p_double[ns+j], _state), _state);
9749  }
9750  v = 2*ae_fabs(s->r.ptr.p_double[i]*v, _state)+v*v;
9751 
9752  /*
9753  * Add to summary noise in the model
9754  */
9755  noiselevel = noiselevel+v;
9756  }
9757  noiselevel = ae_maxreal(noiselevel, eps*fprev, _state);
9758  d2 = 0.0;
9759  for(i=0; i<=nr-1; i++)
9760  {
9761  v = ae_v_dotproduct(&s->densea.ptr.pp_double[i][0], 1, &s->d.ptr.p_double[ns], 1, ae_v_len(0,nd-1));
9762  if( i<ns )
9763  {
9764  v = v+s->d.ptr.p_double[i];
9765  }
9766  d2 = d2+0.5*ae_sqr(v, _state);
9767  }
9768  v = ae_v_dotproduct(&s->d.ptr.p_double[0], 1, &s->g.ptr.p_double[0], 1, ae_v_len(0,ns+nd-1));
9769  d1 = v;
9770  d0 = fprev;
9771  if( ae_fp_less_eq(d2,0)||ae_fp_greater_eq(d1,0) )
9772  {
9773  terminationneeded = ae_true;
9774  break;
9775  }
9776  s->debugflops = s->debugflops+2*nr*nd;
9777  touchreal(&d0, _state);
9778 
9779  /*
9780  * Perform full (unconstrained) step with length StpLen in direction D.
9781  *
9782  * We can terminate iterations in case one of two criteria is met:
9783  * 1. function change is dominated by noise (or function actually increased
9784  * instead of decreasing)
9785  * 2. relative change in X is small enough
9786  *
9787  * First condition is not enough to guarantee algorithm termination because
9788  * sometimes our noise estimate is too optimistic (say, in situations when
9789  * function value at solition is zero).
9790  */
9791  stplen = -d1/(2*d2);
9792  ae_v_move(&s->xn.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,ns+nd-1));
9793  ae_v_addd(&s->xn.ptr.p_double[0], 1, &s->d.ptr.p_double[0], 1, ae_v_len(0,ns+nd-1), stplen);
9794  fcand = 0.0;
9795  for(i=0; i<=nr-1; i++)
9796  {
9797  v = ae_v_dotproduct(&s->densea.ptr.pp_double[i][0], 1, &s->xn.ptr.p_double[ns], 1, ae_v_len(0,nd-1));
9798  if( i<ns )
9799  {
9800  v = v+s->xn.ptr.p_double[i];
9801  }
9802  fcand = fcand+0.5*ae_sqr(v-s->b.ptr.p_double[i], _state);
9803  }
9804  s->debugflops = s->debugflops+2*nr*nd;
9805  if( ae_fp_greater_eq(fcand,fprev-noiselevel*noisetolerance) )
9806  {
9807  terminationneeded = ae_true;
9808  break;
9809  }
9810  v = 0;
9811  for(i=0; i<=ns+nd-1; i++)
9812  {
9813  v0 = ae_fabs(x->ptr.p_double[i], _state);
9814  v1 = ae_fabs(s->xn.ptr.p_double[i], _state);
9815  if( ae_fp_neq(v0,0)||ae_fp_neq(v1,0) )
9816  {
9817  v = ae_maxreal(v, ae_fabs(x->ptr.p_double[i]-s->xn.ptr.p_double[i], _state)/ae_maxreal(v0, v1, _state), _state);
9818  }
9819  }
9820  if( ae_fp_less_eq(v,eps*noisetolerance) )
9821  {
9822  terminationneeded = ae_true;
9823  break;
9824  }
9825 
9826  /*
9827  * Perform step one more time, now with non-negativity constraints.
9828  *
9829  * NOTE: complicated code below which deals with VarIdx temporary makes
9830  * sure that in case unconstrained step leads us outside of feasible
9831  * area, we activate at least one constraint.
9832  */
9833  wasactivation = snnls_boundedstepandactivation(x, &s->xn, &s->nnc, ns+nd, _state);
9834  fcur = 0.0;
9835  for(i=0; i<=nr-1; i++)
9836  {
9837  v = ae_v_dotproduct(&s->densea.ptr.pp_double[i][0], 1, &x->ptr.p_double[ns], 1, ae_v_len(0,nd-1));
9838  if( i<ns )
9839  {
9840  v = v+x->ptr.p_double[i];
9841  }
9842  fcur = fcur+0.5*ae_sqr(v-s->b.ptr.p_double[i], _state);
9843  }
9844  s->debugflops = s->debugflops+2*nr*nd;
9845 
9846  /*
9847  * Depending on results, decide what to do:
9848  * 1. In case step was performed without activation of constraints,
9849  * we proceed to Newton method
9850  * 2. In case there was activated at least one constraint, we repeat
9851  * steepest descent step.
9852  */
9853  if( !wasactivation )
9854  {
9855 
9856  /*
9857  * Step without activation, proceed to Newton
9858  */
9859  break;
9860  }
9861  }
9862  if( terminationneeded )
9863  {
9864  break;
9865  }
9866 
9867  /*
9868  * Phase 2: Newton method.
9869  */
9870  rvectorsetlengthatleast(&s->cx, ns+nd, _state);
9871  ivectorsetlengthatleast(&s->columnmap, ns+nd, _state);
9872  ivectorsetlengthatleast(&s->rowmap, nr, _state);
9873  rmatrixsetlengthatleast(&s->tmpca, nr, nd, _state);
9874  rmatrixsetlengthatleast(&s->tmpz, nd, nd, _state);
9875  rvectorsetlengthatleast(&s->cborg, nr, _state);
9876  rvectorsetlengthatleast(&s->cb, nr, _state);
9877  terminationneeded = ae_false;
9878  for(;;)
9879  {
9880 
9881  /*
9882  * Prepare equality constrained subproblem with NSC<=NS "sparse"
9883  * variables and NDC<=ND "dense" variables.
9884  *
9885  * First, we reorder variables (columns) and move all unconstrained
9886  * variables "to the left", ColumnMap stores this permutation.
9887  *
9888  * Then, we reorder first NS rows of A and first NS elements of B in
9889  * such way that we still have identity matrix in first NSC columns
9890  * of problem. This permutation is stored in RowMap.
9891  */
9892  nsc = 0;
9893  ndc = 0;
9894  for(i=0; i<=ns-1; i++)
9895  {
9896  if( !(s->nnc.ptr.p_bool[i]&&ae_fp_eq(x->ptr.p_double[i],0)) )
9897  {
9898  s->columnmap.ptr.p_int[nsc] = i;
9899  nsc = nsc+1;
9900  }
9901  }
9902  for(i=ns; i<=ns+nd-1; i++)
9903  {
9904  if( !(s->nnc.ptr.p_bool[i]&&ae_fp_eq(x->ptr.p_double[i],0)) )
9905  {
9906  s->columnmap.ptr.p_int[nsc+ndc] = i;
9907  ndc = ndc+1;
9908  }
9909  }
9910  for(i=0; i<=nsc-1; i++)
9911  {
9912  s->rowmap.ptr.p_int[i] = s->columnmap.ptr.p_int[i];
9913  }
9914  j = nsc;
9915  for(i=0; i<=ns-1; i++)
9916  {
9917  if( s->nnc.ptr.p_bool[i]&&ae_fp_eq(x->ptr.p_double[i],0) )
9918  {
9919  s->rowmap.ptr.p_int[j] = i;
9920  j = j+1;
9921  }
9922  }
9923  for(i=ns; i<=nr-1; i++)
9924  {
9925  s->rowmap.ptr.p_int[i] = i;
9926  }
9927 
9928  /*
9929  * Now, permutations are ready, and we can copy/reorder
9930  * A, B and X to CA, CB and CX.
9931  */
9932  for(i=0; i<=nsc+ndc-1; i++)
9933  {
9934  s->cx.ptr.p_double[i] = x->ptr.p_double[s->columnmap.ptr.p_int[i]];
9935  }
9936  for(i=0; i<=nr-1; i++)
9937  {
9938  for(j=0; j<=ndc-1; j++)
9939  {
9940  s->tmpca.ptr.pp_double[i][j] = s->densea.ptr.pp_double[s->rowmap.ptr.p_int[i]][s->columnmap.ptr.p_int[nsc+j]-ns];
9941  }
9942  s->cb.ptr.p_double[i] = s->b.ptr.p_double[s->rowmap.ptr.p_int[i]];
9943  }
9944 
9945  /*
9946  * Solve equality constrained subproblem.
9947  */
9948  if( ndc>0 )
9949  {
9950 
9951  /*
9952  * NDC>0.
9953  *
9954  * Solve subproblem using Newton-type algorithm. We have a
9955  * NR*(NSC+NDC) linear least squares subproblem
9956  *
9957  * | ( I AU ) ( XU ) ( BU ) |^2
9958  * min | ( ) * ( ) - ( ) |
9959  * | ( 0 AL ) ( XL ) ( BL ) |
9960  *
9961  * where:
9962  * * I is a NSC*NSC identity matrix
9963  * * AU is NSC*NDC dense matrix (first NSC rows of CA)
9964  * * AL is (NR-NSC)*NDC dense matrix (next NR-NSC rows of CA)
9965  * * BU and BL are correspondingly sized parts of CB
9966  *
9967  * After conversion to normal equations and small regularization,
9968  * we get:
9969  *
9970  * ( I AU ) ( XU ) ( BU )
9971  * ( )*( ) = ( )
9972  * ( AU' Y ) ( XL ) ( AU'*BU+AL'*BL )
9973  *
9974  * where Y = AU'*AU + AL'*AL + lambda*diag(AU'*AU+AL'*AL).
9975  *
9976  * With Schur Complement Method this system can be solved in
9977  * O(NR*NDC^2+NDC^3) operations. In order to solve it we multiply
9978  * first row by AU' and subtract it from the second one. As result,
9979  * we get system
9980  *
9981  * Z*XL = AL'*BL, where Z=AL'*AL+lambda*diag(AU'*AU+AL'*AL)
9982  *
9983  * We can easily solve it for XL, and we can get XU as XU = BU-AU*XL.
9984  *
9985  * We will start solution from calculating Cholesky decomposition of Z.
9986  */
9987  for(i=0; i<=nr-1; i++)
9988  {
9989  s->cborg.ptr.p_double[i] = s->cb.ptr.p_double[i];
9990  }
9991  for(i=0; i<=ndc-1; i++)
9992  {
9993  s->diagaa.ptr.p_double[i] = 0;
9994  }
9995  for(i=0; i<=nr-1; i++)
9996  {
9997  for(j=0; j<=ndc-1; j++)
9998  {
9999  s->diagaa.ptr.p_double[j] = s->diagaa.ptr.p_double[j]+ae_sqr(s->tmpca.ptr.pp_double[i][j], _state);
10000  }
10001  }
10002  for(j=0; j<=ndc-1; j++)
10003  {
10004  if( ae_fp_eq(s->diagaa.ptr.p_double[j],0) )
10005  {
10006  s->diagaa.ptr.p_double[j] = 1;
10007  }
10008  }
10009  for(;;)
10010  {
10011 
10012  /*
10013  * NOTE: we try to factorize Z. In case of failure we increase
10014  * regularization parameter and try again.
10015  */
10016  s->debugflops = s->debugflops+2*(nr-nsc)*ae_sqr(ndc, _state)+ae_pow(ndc, 3, _state)/3;
10017  for(i=0; i<=ndc-1; i++)
10018  {
10019  for(j=0; j<=ndc-1; j++)
10020  {
10021  s->tmpz.ptr.pp_double[i][j] = 0.0;
10022  }
10023  }
10024  rmatrixsyrk(ndc, nr-nsc, 1.0, &s->tmpca, nsc, 0, 2, 0.0, &s->tmpz, 0, 0, ae_true, _state);
10025  for(i=0; i<=ndc-1; i++)
10026  {
10027  s->tmpz.ptr.pp_double[i][i] = s->tmpz.ptr.pp_double[i][i]+lambdav*s->diagaa.ptr.p_double[i];
10028  }
10029  if( spdmatrixcholeskyrec(&s->tmpz, 0, ndc, ae_true, &s->tmpcholesky, _state) )
10030  {
10031  break;
10032  }
10033  lambdav = lambdav*10;
10034  }
10035 
10036  /*
10037  * We have Cholesky decomposition of Z, now we can solve system:
10038  * * we start from initial point CX
10039  * * we perform several iterations of refinement:
10040  * * BU_new := BU_orig - XU_cur - AU*XL_cur
10041  * * BL_new := BL_orig - AL*XL_cur
10042  * * solve for BU_new/BL_new, obtain solution dx
10043  * * XU_cur := XU_cur + dx_u
10044  * * XL_cur := XL_cur + dx_l
10045  * * BU_new/BL_new are stored in CB, original right part is
10046  * stored in CBOrg, correction to X is stored in DX, current
10047  * X is stored in CX
10048  */
10049  for(rfsits=1; rfsits<=s->refinementits; rfsits++)
10050  {
10051  for(i=0; i<=nr-1; i++)
10052  {
10053  v = ae_v_dotproduct(&s->tmpca.ptr.pp_double[i][0], 1, &s->cx.ptr.p_double[nsc], 1, ae_v_len(0,ndc-1));
10054  s->cb.ptr.p_double[i] = s->cborg.ptr.p_double[i]-v;
10055  if( i<nsc )
10056  {
10057  s->cb.ptr.p_double[i] = s->cb.ptr.p_double[i]-s->cx.ptr.p_double[i];
10058  }
10059  }
10060  s->debugflops = s->debugflops+2*nr*ndc;
10061  for(i=0; i<=ndc-1; i++)
10062  {
10063  s->dx.ptr.p_double[i] = 0.0;
10064  }
10065  for(i=nsc; i<=nr-1; i++)
10066  {
10067  v = s->cb.ptr.p_double[i];
10068  ae_v_addd(&s->dx.ptr.p_double[0], 1, &s->tmpca.ptr.pp_double[i][0], 1, ae_v_len(0,ndc-1), v);
10069  }
10070  fblscholeskysolve(&s->tmpz, 1.0, ndc, ae_true, &s->dx, &s->tmpcholesky, _state);
10071  s->debugflops = s->debugflops+2*ndc*ndc;
10072  ae_v_add(&s->cx.ptr.p_double[nsc], 1, &s->dx.ptr.p_double[0], 1, ae_v_len(nsc,nsc+ndc-1));
10073  for(i=0; i<=nsc-1; i++)
10074  {
10075  v = ae_v_dotproduct(&s->tmpca.ptr.pp_double[i][0], 1, &s->dx.ptr.p_double[0], 1, ae_v_len(0,ndc-1));
10076  s->cx.ptr.p_double[i] = s->cx.ptr.p_double[i]+s->cb.ptr.p_double[i]-v;
10077  }
10078  s->debugflops = s->debugflops+2*nsc*ndc;
10079  }
10080  }
10081  else
10082  {
10083 
10084  /*
10085  * NDC=0.
10086  *
10087  * We have a NR*NSC linear least squares subproblem
10088  *
10089  * min |XU-BU|^2
10090  *
10091  * solution is easy to find - it is XU=BU!
10092  */
10093  for(i=0; i<=nsc-1; i++)
10094  {
10095  s->cx.ptr.p_double[i] = s->cb.ptr.p_double[i];
10096  }
10097  }
10098  for(i=0; i<=ns+nd-1; i++)
10099  {
10100  s->xn.ptr.p_double[i] = x->ptr.p_double[i];
10101  }
10102  for(i=0; i<=nsc+ndc-1; i++)
10103  {
10104  s->xn.ptr.p_double[s->columnmap.ptr.p_int[i]] = s->cx.ptr.p_double[i];
10105  }
10106  newtoncnt = newtoncnt+1;
10107 
10108  /*
10109  * Step to candidate point.
10110  * If no constraints was added, accept candidate point XN and move to next phase.
10111  * Terminate, if number of Newton iterations exceeded DebugMaxNewton counter.
10112  */
10113  terminationneeded = s->debugmaxnewton>0&&newtoncnt>=s->debugmaxnewton;
10114  if( !snnls_boundedstepandactivation(x, &s->xn, &s->nnc, ns+nd, _state) )
10115  {
10116  break;
10117  }
10118  if( terminationneeded )
10119  {
10120  break;
10121  }
10122  }
10123  if( terminationneeded )
10124  {
10125  break;
10126  }
10127  }
10128 }
10129 
10130 
10131 /*************************************************************************
10132 Having feasible current point XC and possibly infeasible candidate point
10133 XN, this function performs longest step from XC to XN which retains
10134 feasibility. In case XN is found to be infeasible, at least one constraint
10135 is activated.
10136 
10137 For example, if we have:
10138  XC=0.5
10139  XN=-1.2
10140  x>=0
10141 then this function will move us to X=0 and activate constraint "x>=0".
10142 
10143 INPUT PARAMETERS:
10144  XC - current point, must be feasible with respect to
10145  all constraints
10146  XN - candidate point, can be infeasible with respect to some
10147  constraints
10148  NNC - NNC[i] is True when I-th variable is non-negatively
10149  constrained
10150  N - variable count
10151 
10152 OUTPUT PARAMETERS:
10153  XC - new position
10154 
10155 RESULT:
10156  True in case at least one constraint was activated by step
10157 
10158  -- ALGLIB --
10159  Copyright 19.10.2012 by Bochkanov Sergey
10160 *************************************************************************/
10161 static ae_bool snnls_boundedstepandactivation(/* Real */ ae_vector* xc,
10162  /* Real */ ae_vector* xn,
10163  /* Boolean */ ae_vector* nnc,
10164  ae_int_t n,
10165  ae_state *_state)
10166 {
10167  ae_int_t i;
10168  ae_int_t varidx;
10169  double vmax;
10170  double v;
10171  double stplen;
10172  ae_bool result;
10173 
10174 
10175 
10176  /*
10177  * Check constraints.
10178  *
10179  * NOTE: it is important to test for XN[i]<XC[i] (strict inequality,
10180  * allows to handle correctly situations with XC[i]=0 without
10181  * activating already active constraints), but to check for
10182  * XN[i]<=0 (non-strict inequality, correct handling of some
10183  * special cases when unconstrained step ends at the boundary).
10184  */
10185  result = ae_false;
10186  varidx = -1;
10187  vmax = ae_maxrealnumber;
10188  for(i=0; i<=n-1; i++)
10189  {
10190  if( (nnc->ptr.p_bool[i]&&ae_fp_less(xn->ptr.p_double[i],xc->ptr.p_double[i]))&&ae_fp_less_eq(xn->ptr.p_double[i],0.0) )
10191  {
10192  v = vmax;
10193  vmax = safeminposrv(xc->ptr.p_double[i], xc->ptr.p_double[i]-xn->ptr.p_double[i], vmax, _state);
10194  if( ae_fp_less(vmax,v) )
10195  {
10196  varidx = i;
10197  }
10198  }
10199  }
10200  stplen = ae_minreal(vmax, 1.0, _state);
10201 
10202  /*
10203  * Perform step with activation.
10204  *
10205  * NOTE: it is important to use (1-StpLen)*XC + StpLen*XN because
10206  * it allows us to step exactly to XN when StpLen=1, even in
10207  * the presence of numerical errors.
10208  */
10209  for(i=0; i<=n-1; i++)
10210  {
10211  xc->ptr.p_double[i] = (1-stplen)*xc->ptr.p_double[i]+stplen*xn->ptr.p_double[i];
10212  }
10213  if( varidx>=0 )
10214  {
10215  xc->ptr.p_double[varidx] = 0.0;
10216  result = ae_true;
10217  }
10218  for(i=0; i<=n-1; i++)
10219  {
10220  if( nnc->ptr.p_bool[i]&&ae_fp_less(xc->ptr.p_double[i],0.0) )
10221  {
10222  xc->ptr.p_double[i] = 0.0;
10223  result = ae_true;
10224  }
10225  }
10226  return result;
10227 }
10228 
10229 
10230 ae_bool _snnlssolver_init(void* _p, ae_state *_state, ae_bool make_automatic)
10231 {
10232  snnlssolver *p = (snnlssolver*)_p;
10233  ae_touch_ptr((void*)p);
10234  if( !ae_matrix_init(&p->densea, 0, 0, DT_REAL, _state, make_automatic) )
10235  return ae_false;
10236  if( !ae_vector_init(&p->b, 0, DT_REAL, _state, make_automatic) )
10237  return ae_false;
10238  if( !ae_vector_init(&p->nnc, 0, DT_BOOL, _state, make_automatic) )
10239  return ae_false;
10240  if( !ae_vector_init(&p->xn, 0, DT_REAL, _state, make_automatic) )
10241  return ae_false;
10242  if( !ae_matrix_init(&p->tmpz, 0, 0, DT_REAL, _state, make_automatic) )
10243  return ae_false;
10244  if( !ae_matrix_init(&p->tmpca, 0, 0, DT_REAL, _state, make_automatic) )
10245  return ae_false;
10246  if( !ae_vector_init(&p->g, 0, DT_REAL, _state, make_automatic) )
10247  return ae_false;
10248  if( !ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic) )
10249  return ae_false;
10250  if( !ae_vector_init(&p->dx, 0, DT_REAL, _state, make_automatic) )
10251  return ae_false;
10252  if( !ae_vector_init(&p->diagaa, 0, DT_REAL, _state, make_automatic) )
10253  return ae_false;
10254  if( !ae_vector_init(&p->cb, 0, DT_REAL, _state, make_automatic) )
10255  return ae_false;
10256  if( !ae_vector_init(&p->cx, 0, DT_REAL, _state, make_automatic) )
10257  return ae_false;
10258  if( !ae_vector_init(&p->cborg, 0, DT_REAL, _state, make_automatic) )
10259  return ae_false;
10260  if( !ae_vector_init(&p->columnmap, 0, DT_INT, _state, make_automatic) )
10261  return ae_false;
10262  if( !ae_vector_init(&p->rowmap, 0, DT_INT, _state, make_automatic) )
10263  return ae_false;
10264  if( !ae_vector_init(&p->tmpcholesky, 0, DT_REAL, _state, make_automatic) )
10265  return ae_false;
10266  if( !ae_vector_init(&p->r, 0, DT_REAL, _state, make_automatic) )
10267  return ae_false;
10268  return ae_true;
10269 }
10270 
10271 
10272 ae_bool _snnlssolver_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
10273 {
10274  snnlssolver *dst = (snnlssolver*)_dst;
10275  snnlssolver *src = (snnlssolver*)_src;
10276  dst->ns = src->ns;
10277  dst->nd = src->nd;
10278  dst->nr = src->nr;
10279  if( !ae_matrix_init_copy(&dst->densea, &src->densea, _state, make_automatic) )
10280  return ae_false;
10281  if( !ae_vector_init_copy(&dst->b, &src->b, _state, make_automatic) )
10282  return ae_false;
10283  if( !ae_vector_init_copy(&dst->nnc, &src->nnc, _state, make_automatic) )
10284  return ae_false;
10285  dst->refinementits = src->refinementits;
10286  dst->debugflops = src->debugflops;
10287  dst->debugmaxnewton = src->debugmaxnewton;
10288  if( !ae_vector_init_copy(&dst->xn, &src->xn, _state, make_automatic) )
10289  return ae_false;
10290  if( !ae_matrix_init_copy(&dst->tmpz, &src->tmpz, _state, make_automatic) )
10291  return ae_false;
10292  if( !ae_matrix_init_copy(&dst->tmpca, &src->tmpca, _state, make_automatic) )
10293  return ae_false;
10294  if( !ae_vector_init_copy(&dst->g, &src->g, _state, make_automatic) )
10295  return ae_false;
10296  if( !ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic) )
10297  return ae_false;
10298  if( !ae_vector_init_copy(&dst->dx, &src->dx, _state, make_automatic) )
10299  return ae_false;
10300  if( !ae_vector_init_copy(&dst->diagaa, &src->diagaa, _state, make_automatic) )
10301  return ae_false;
10302  if( !ae_vector_init_copy(&dst->cb, &src->cb, _state, make_automatic) )
10303  return ae_false;
10304  if( !ae_vector_init_copy(&dst->cx, &src->cx, _state, make_automatic) )
10305  return ae_false;
10306  if( !ae_vector_init_copy(&dst->cborg, &src->cborg, _state, make_automatic) )
10307  return ae_false;
10308  if( !ae_vector_init_copy(&dst->columnmap, &src->columnmap, _state, make_automatic) )
10309  return ae_false;
10310  if( !ae_vector_init_copy(&dst->rowmap, &src->rowmap, _state, make_automatic) )
10311  return ae_false;
10312  if( !ae_vector_init_copy(&dst->tmpcholesky, &src->tmpcholesky, _state, make_automatic) )
10313  return ae_false;
10314  if( !ae_vector_init_copy(&dst->r, &src->r, _state, make_automatic) )
10315  return ae_false;
10316  return ae_true;
10317 }
10318 
10319 
10320 void _snnlssolver_clear(void* _p)
10321 {
10322  snnlssolver *p = (snnlssolver*)_p;
10323  ae_touch_ptr((void*)p);
10324  ae_matrix_clear(&p->densea);
10325  ae_vector_clear(&p->b);
10326  ae_vector_clear(&p->nnc);
10327  ae_vector_clear(&p->xn);
10328  ae_matrix_clear(&p->tmpz);
10329  ae_matrix_clear(&p->tmpca);
10330  ae_vector_clear(&p->g);
10331  ae_vector_clear(&p->d);
10332  ae_vector_clear(&p->dx);
10333  ae_vector_clear(&p->diagaa);
10334  ae_vector_clear(&p->cb);
10335  ae_vector_clear(&p->cx);
10336  ae_vector_clear(&p->cborg);
10337  ae_vector_clear(&p->columnmap);
10338  ae_vector_clear(&p->rowmap);
10339  ae_vector_clear(&p->tmpcholesky);
10340  ae_vector_clear(&p->r);
10341 }
10342 
10343 
10344 void _snnlssolver_destroy(void* _p)
10345 {
10346  snnlssolver *p = (snnlssolver*)_p;
10347  ae_touch_ptr((void*)p);
10348  ae_matrix_destroy(&p->densea);
10349  ae_vector_destroy(&p->b);
10350  ae_vector_destroy(&p->nnc);
10351  ae_vector_destroy(&p->xn);
10352  ae_matrix_destroy(&p->tmpz);
10353  ae_matrix_destroy(&p->tmpca);
10354  ae_vector_destroy(&p->g);
10355  ae_vector_destroy(&p->d);
10356  ae_vector_destroy(&p->dx);
10357  ae_vector_destroy(&p->diagaa);
10358  ae_vector_destroy(&p->cb);
10359  ae_vector_destroy(&p->cx);
10360  ae_vector_destroy(&p->cborg);
10361  ae_vector_destroy(&p->columnmap);
10362  ae_vector_destroy(&p->rowmap);
10363  ae_vector_destroy(&p->tmpcholesky);
10364  ae_vector_destroy(&p->r);
10365 }
10366 
10367 
10368 
10369 
10370 /*************************************************************************
10371 This subroutine is used to initialize active set. By default, empty
10372 N-variable model with no constraints is generated. Previously allocated
10373 buffer variables are reused as much as possible.
10374 
10375 Two use cases for this object are described below.
10376 
10377 CASE 1 - STEEPEST DESCENT:
10378 
10379  SASInit()
10380  repeat:
10381  SASReactivateConstraints()
10382  SASDescentDirection()
10383  SASExploreDirection()
10384  SASMoveTo()
10385  until convergence
10386 
10387 CASE 1 - PRECONDITIONED STEEPEST DESCENT:
10388 
10389  SASInit()
10390  repeat:
10391  SASReactivateConstraintsPrec()
10392  SASDescentDirectionPrec()
10393  SASExploreDirection()
10394  SASMoveTo()
10395  until convergence
10396 
10397  -- ALGLIB --
10398  Copyright 21.12.2012 by Bochkanov Sergey
10399 *************************************************************************/
10400 void sasinit(ae_int_t n, sactiveset* s, ae_state *_state)
10401 {
10402  ae_int_t i;
10403 
10404 
10405  s->n = n;
10406  s->algostate = 0;
10407 
10408  /*
10409  * Constraints
10410  */
10411  s->constraintschanged = ae_true;
10412  s->nec = 0;
10413  s->nic = 0;
10414  rvectorsetlengthatleast(&s->bndl, n, _state);
10415  bvectorsetlengthatleast(&s->hasbndl, n, _state);
10416  rvectorsetlengthatleast(&s->bndu, n, _state);
10417  bvectorsetlengthatleast(&s->hasbndu, n, _state);
10418  for(i=0; i<=n-1; i++)
10419  {
10420  s->bndl.ptr.p_double[i] = _state->v_neginf;
10421  s->bndu.ptr.p_double[i] = _state->v_posinf;
10422  s->hasbndl.ptr.p_bool[i] = ae_false;
10423  s->hasbndu.ptr.p_bool[i] = ae_false;
10424  }
10425 
10426  /*
10427  * current point, scale
10428  */
10429  s->hasxc = ae_false;
10430  rvectorsetlengthatleast(&s->xc, n, _state);
10431  rvectorsetlengthatleast(&s->s, n, _state);
10432  rvectorsetlengthatleast(&s->h, n, _state);
10433  for(i=0; i<=n-1; i++)
10434  {
10435  s->xc.ptr.p_double[i] = 0.0;
10436  s->s.ptr.p_double[i] = 1.0;
10437  s->h.ptr.p_double[i] = 1.0;
10438  }
10439 
10440  /*
10441  * Other
10442  */
10443  rvectorsetlengthatleast(&s->unitdiagonal, n, _state);
10444  for(i=0; i<=n-1; i++)
10445  {
10446  s->unitdiagonal.ptr.p_double[i] = 1.0;
10447  }
10448 }
10449 
10450 
10451 /*************************************************************************
10452 This function sets scaling coefficients for SAS object.
10453 
10454 ALGLIB optimizers use scaling matrices to test stopping conditions (step
10455 size and gradient are scaled before comparison with tolerances). Scale of
10456 the I-th variable is a translation invariant measure of:
10457 a) "how large" the variable is
10458 b) how large the step should be to make significant changes in the function
10459 
10460 During orthogonalization phase, scale is used to calculate drop tolerances
10461 (whether vector is significantly non-zero or not).
10462 
10463 INPUT PARAMETERS:
10464  State - structure stores algorithm state
10465  S - array[N], non-zero scaling coefficients
10466  S[i] may be negative, sign doesn't matter.
10467 
10468  -- ALGLIB --
10469  Copyright 21.12.2012 by Bochkanov Sergey
10470 *************************************************************************/
10471 void sassetscale(sactiveset* state,
10472  /* Real */ ae_vector* s,
10473  ae_state *_state)
10474 {
10475  ae_int_t i;
10476 
10477 
10478  ae_assert(state->algostate==0, "SASSetScale: you may change scale only in modification mode", _state);
10479  ae_assert(s->cnt>=state->n, "SASSetScale: Length(S)<N", _state);
10480  for(i=0; i<=state->n-1; i++)
10481  {
10482  ae_assert(ae_isfinite(s->ptr.p_double[i], _state), "SASSetScale: S contains infinite or NAN elements", _state);
10483  ae_assert(ae_fp_neq(s->ptr.p_double[i],0), "SASSetScale: S contains zero elements", _state);
10484  }
10485  for(i=0; i<=state->n-1; i++)
10486  {
10487  state->s.ptr.p_double[i] = ae_fabs(s->ptr.p_double[i], _state);
10488  }
10489 }
10490 
10491 
10492 /*************************************************************************
10493 Modification of the preconditioner: diagonal of approximate Hessian is
10494 used.
10495 
10496 INPUT PARAMETERS:
10497  State - structure which stores algorithm state
10498  D - diagonal of the approximate Hessian, array[0..N-1],
10499  (if larger, only leading N elements are used).
10500 
10501 NOTE 1: D[i] should be positive. Exception will be thrown otherwise.
10502 
10503 NOTE 2: you should pass diagonal of approximate Hessian - NOT ITS INVERSE.
10504 
10505  -- ALGLIB --
10506  Copyright 21.12.2012 by Bochkanov Sergey
10507 *************************************************************************/
10508 void sassetprecdiag(sactiveset* state,
10509  /* Real */ ae_vector* d,
10510  ae_state *_state)
10511 {
10512  ae_int_t i;
10513 
10514 
10515  ae_assert(state->algostate==0, "SASSetPrecDiag: you may change preconditioner only in modification mode", _state);
10516  ae_assert(d->cnt>=state->n, "SASSetPrecDiag: D is too short", _state);
10517  for(i=0; i<=state->n-1; i++)
10518  {
10519  ae_assert(ae_isfinite(d->ptr.p_double[i], _state), "SASSetPrecDiag: D contains infinite or NAN elements", _state);
10520  ae_assert(ae_fp_greater(d->ptr.p_double[i],0), "SASSetPrecDiag: D contains non-positive elements", _state);
10521  }
10522  for(i=0; i<=state->n-1; i++)
10523  {
10524  state->h.ptr.p_double[i] = d->ptr.p_double[i];
10525  }
10526 }
10527 
10528 
10529 /*************************************************************************
10530 This function sets/changes boundary constraints.
10531 
10532 INPUT PARAMETERS:
10533  State - structure stores algorithm state
10534  BndL - lower bounds, array[N].
10535  If some (all) variables are unbounded, you may specify
10536  very small number or -INF.
10537  BndU - upper bounds, array[N].
10538  If some (all) variables are unbounded, you may specify
10539  very large number or +INF.
10540 
10541 NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case I-th
10542 variable will be "frozen" at X[i]=BndL[i]=BndU[i].
10543 
10544  -- ALGLIB --
10545  Copyright 21.12.2012 by Bochkanov Sergey
10546 *************************************************************************/
10547 void sassetbc(sactiveset* state,
10548  /* Real */ ae_vector* bndl,
10549  /* Real */ ae_vector* bndu,
10550  ae_state *_state)
10551 {
10552  ae_int_t i;
10553  ae_int_t n;
10554 
10555 
10556  ae_assert(state->algostate==0, "SASSetBC: you may change constraints only in modification mode", _state);
10557  n = state->n;
10558  ae_assert(bndl->cnt>=n, "SASSetBC: Length(BndL)<N", _state);
10559  ae_assert(bndu->cnt>=n, "SASSetBC: Length(BndU)<N", _state);
10560  for(i=0; i<=n-1; i++)
10561  {
10562  ae_assert(ae_isfinite(bndl->ptr.p_double[i], _state)||ae_isneginf(bndl->ptr.p_double[i], _state), "SASSetBC: BndL contains NAN or +INF", _state);
10563  ae_assert(ae_isfinite(bndu->ptr.p_double[i], _state)||ae_isposinf(bndu->ptr.p_double[i], _state), "SASSetBC: BndL contains NAN or -INF", _state);
10564  state->bndl.ptr.p_double[i] = bndl->ptr.p_double[i];
10565  state->hasbndl.ptr.p_bool[i] = ae_isfinite(bndl->ptr.p_double[i], _state);
10566  state->bndu.ptr.p_double[i] = bndu->ptr.p_double[i];
10567  state->hasbndu.ptr.p_bool[i] = ae_isfinite(bndu->ptr.p_double[i], _state);
10568  }
10569  state->constraintschanged = ae_true;
10570 }
10571 
10572 
10573 /*************************************************************************
10574 This function sets linear constraints for SAS object.
10575 
10576 Linear constraints are inactive by default (after initial creation).
10577 
10578 INPUT PARAMETERS:
10579  State - SAS structure
10580  C - linear constraints, array[K,N+1].
10581  Each row of C represents one constraint, either equality
10582  or inequality (see below):
10583  * first N elements correspond to coefficients,
10584  * last element corresponds to the right part.
10585  All elements of C (including right part) must be finite.
10586  CT - type of constraints, array[K]:
10587  * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1]
10588  * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1]
10589  * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1]
10590  K - number of equality/inequality constraints, K>=0
10591 
10592 NOTE 1: linear (non-bound) constraints are satisfied only approximately:
10593 * there always exists some minor violation (about Epsilon in magnitude)
10594  due to rounding errors
10595 * numerical differentiation, if used, may lead to function evaluations
10596  outside of the feasible area, because algorithm does NOT change
10597  numerical differentiation formula according to linear constraints.
10598 If you want constraints to be satisfied exactly, try to reformulate your
10599 problem in such manner that all constraints will become boundary ones
10600 (this kind of constraints is always satisfied exactly, both in the final
10601 solution and in all intermediate points).
10602 
10603  -- ALGLIB --
10604  Copyright 28.11.2010 by Bochkanov Sergey
10605 *************************************************************************/
10606 void sassetlc(sactiveset* state,
10607  /* Real */ ae_matrix* c,
10608  /* Integer */ ae_vector* ct,
10609  ae_int_t k,
10610  ae_state *_state)
10611 {
10612  ae_int_t n;
10613  ae_int_t i;
10614 
10615 
10616  ae_assert(state->algostate==0, "SASSetLC: you may change constraints only in modification mode", _state);
10617  n = state->n;
10618 
10619  /*
10620  * First, check for errors in the inputs
10621  */
10622  ae_assert(k>=0, "SASSetLC: K<0", _state);
10623  ae_assert(c->cols>=n+1||k==0, "SASSetLC: Cols(C)<N+1", _state);
10624  ae_assert(c->rows>=k, "SASSetLC: Rows(C)<K", _state);
10625  ae_assert(ct->cnt>=k, "SASSetLC: Length(CT)<K", _state);
10626  ae_assert(apservisfinitematrix(c, k, n+1, _state), "SASSetLC: C contains infinite or NaN values!", _state);
10627 
10628  /*
10629  * Handle zero K
10630  */
10631  if( k==0 )
10632  {
10633  state->nec = 0;
10634  state->nic = 0;
10635  state->constraintschanged = ae_true;
10636  return;
10637  }
10638 
10639  /*
10640  * Equality constraints are stored first, in the upper
10641  * NEC rows of State.CLEIC matrix. Inequality constraints
10642  * are stored in the next NIC rows.
10643  *
10644  * NOTE: we convert inequality constraints to the form
10645  * A*x<=b before copying them.
10646  */
10647  rmatrixsetlengthatleast(&state->cleic, k, n+1, _state);
10648  state->nec = 0;
10649  state->nic = 0;
10650  for(i=0; i<=k-1; i++)
10651  {
10652  if( ct->ptr.p_int[i]==0 )
10653  {
10654  ae_v_move(&state->cleic.ptr.pp_double[state->nec][0], 1, &c->ptr.pp_double[i][0], 1, ae_v_len(0,n));
10655  state->nec = state->nec+1;
10656  }
10657  }
10658  for(i=0; i<=k-1; i++)
10659  {
10660  if( ct->ptr.p_int[i]!=0 )
10661  {
10662  if( ct->ptr.p_int[i]>0 )
10663  {
10664  ae_v_moveneg(&state->cleic.ptr.pp_double[state->nec+state->nic][0], 1, &c->ptr.pp_double[i][0], 1, ae_v_len(0,n));
10665  }
10666  else
10667  {
10668  ae_v_move(&state->cleic.ptr.pp_double[state->nec+state->nic][0], 1, &c->ptr.pp_double[i][0], 1, ae_v_len(0,n));
10669  }
10670  state->nic = state->nic+1;
10671  }
10672  }
10673 
10674  /*
10675  * Mark state as changed
10676  */
10677  state->constraintschanged = ae_true;
10678 }
10679 
10680 
10681 /*************************************************************************
10682 Another variation of SASSetLC(), which accepts linear constraints using
10683 another representation.
10684 
10685 Linear constraints are inactive by default (after initial creation).
10686 
10687 INPUT PARAMETERS:
10688  State - SAS structure
10689  CLEIC - linear constraints, array[NEC+NIC,N+1].
10690  Each row of C represents one constraint:
10691  * first N elements correspond to coefficients,
10692  * last element corresponds to the right part.
10693  First NEC rows store equality constraints, next NIC - are
10694  inequality ones.
10695  All elements of C (including right part) must be finite.
10696  NEC - number of equality constraints, NEC>=0
10697  NIC - number of inequality constraints, NIC>=0
10698 
10699 NOTE 1: linear (non-bound) constraints are satisfied only approximately:
10700 * there always exists some minor violation (about Epsilon in magnitude)
10701  due to rounding errors
10702 * numerical differentiation, if used, may lead to function evaluations
10703  outside of the feasible area, because algorithm does NOT change
10704  numerical differentiation formula according to linear constraints.
10705 If you want constraints to be satisfied exactly, try to reformulate your
10706 problem in such manner that all constraints will become boundary ones
10707 (this kind of constraints is always satisfied exactly, both in the final
10708 solution and in all intermediate points).
10709 
10710  -- ALGLIB --
10711  Copyright 28.11.2010 by Bochkanov Sergey
10712 *************************************************************************/
10713 void sassetlcx(sactiveset* state,
10714  /* Real */ ae_matrix* cleic,
10715  ae_int_t nec,
10716  ae_int_t nic,
10717  ae_state *_state)
10718 {
10719  ae_int_t n;
10720  ae_int_t i;
10721  ae_int_t j;
10722 
10723 
10724  ae_assert(state->algostate==0, "SASSetLCX: you may change constraints only in modification mode", _state);
10725  n = state->n;
10726 
10727  /*
10728  * First, check for errors in the inputs
10729  */
10730  ae_assert(nec>=0, "SASSetLCX: NEC<0", _state);
10731  ae_assert(nic>=0, "SASSetLCX: NIC<0", _state);
10732  ae_assert(cleic->cols>=n+1||nec+nic==0, "SASSetLCX: Cols(CLEIC)<N+1", _state);
10733  ae_assert(cleic->rows>=nec+nic, "SASSetLCX: Rows(CLEIC)<NEC+NIC", _state);
10734  ae_assert(apservisfinitematrix(cleic, nec+nic, n+1, _state), "SASSetLCX: CLEIC contains infinite or NaN values!", _state);
10735 
10736  /*
10737  * Store constraints
10738  */
10739  rmatrixsetlengthatleast(&state->cleic, nec+nic, n+1, _state);
10740  state->nec = nec;
10741  state->nic = nic;
10742  for(i=0; i<=nec+nic-1; i++)
10743  {
10744  for(j=0; j<=n; j++)
10745  {
10746  state->cleic.ptr.pp_double[i][j] = cleic->ptr.pp_double[i][j];
10747  }
10748  }
10749 
10750  /*
10751  * Mark state as changed
10752  */
10753  state->constraintschanged = ae_true;
10754 }
10755 
10756 
10757 /*************************************************************************
10758 This subroutine turns on optimization mode:
10759 1. feasibility in X is enforced (in case X=S.XC and constraints have not
10760  changed, algorithm just uses X without any modifications at all)
10761 2. constraints are marked as "candidate" or "inactive"
10762 
10763 INPUT PARAMETERS:
10764  S - active set object
10765  X - initial point (candidate), array[N]. It is expected that X
10766  contains only finite values (we do not check it).
10767 
10768 OUTPUT PARAMETERS:
10769  S - state is changed
10770  X - initial point can be changed to enforce feasibility
10771 
10772 RESULT:
10773  True in case feasible point was found (mode was changed to "optimization")
10774  False in case no feasible point was found (mode was not changed)
10775 
10776  -- ALGLIB --
10777  Copyright 21.12.2012 by Bochkanov Sergey
10778 *************************************************************************/
10779 ae_bool sasstartoptimization(sactiveset* state,
10780  /* Real */ ae_vector* x,
10781  ae_state *_state)
10782 {
10783  ae_int_t n;
10784  ae_int_t nec;
10785  ae_int_t nic;
10786  ae_int_t i;
10787  ae_int_t j;
10788  double v;
10789  ae_bool result;
10790 
10791 
10792  ae_assert(state->algostate==0, "SASStartOptimization: already in optimization mode", _state);
10793  result = ae_false;
10794  n = state->n;
10795  nec = state->nec;
10796  nic = state->nic;
10797 
10798  /*
10799  * Enforce feasibility and calculate set of "candidate"/"active" constraints.
10800  * Always active equality constraints are marked as "active", all other constraints
10801  * are marked as "candidate".
10802  */
10803  ivectorsetlengthatleast(&state->activeset, n+nec+nic, _state);
10804  for(i=0; i<=n-1; i++)
10805  {
10806  if( state->hasbndl.ptr.p_bool[i]&&state->hasbndu.ptr.p_bool[i] )
10807  {
10808  if( ae_fp_greater(state->bndl.ptr.p_double[i],state->bndu.ptr.p_double[i]) )
10809  {
10810  return result;
10811  }
10812  }
10813  }
10814  ae_v_move(&state->xc.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1));
10815  if( state->nec+state->nic>0 )
10816  {
10817 
10818  /*
10819  * General linear constraints are present; general code is used.
10820  */
10821  rvectorsetlengthatleast(&state->tmp0, n, _state);
10822  rvectorsetlengthatleast(&state->tmpfeas, n+state->nic, _state);
10823  rmatrixsetlengthatleast(&state->tmpm0, state->nec+state->nic, n+state->nic+1, _state);
10824  for(i=0; i<=state->nec+state->nic-1; i++)
10825  {
10826  ae_v_move(&state->tmpm0.ptr.pp_double[i][0], 1, &state->cleic.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
10827  for(j=n; j<=n+state->nic-1; j++)
10828  {
10829  state->tmpm0.ptr.pp_double[i][j] = 0;
10830  }
10831  if( i>=state->nec )
10832  {
10833  state->tmpm0.ptr.pp_double[i][n+i-state->nec] = 1.0;
10834  }
10835  state->tmpm0.ptr.pp_double[i][n+state->nic] = state->cleic.ptr.pp_double[i][n];
10836  }
10837  ae_v_move(&state->tmpfeas.ptr.p_double[0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
10838  for(i=0; i<=state->nic-1; i++)
10839  {
10840  v = ae_v_dotproduct(&state->cleic.ptr.pp_double[i+state->nec][0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
10841  state->tmpfeas.ptr.p_double[i+n] = ae_maxreal(state->cleic.ptr.pp_double[i+state->nec][n]-v, 0.0, _state);
10842  }
10843  if( !findfeasiblepoint(&state->tmpfeas, &state->bndl, &state->hasbndl, &state->bndu, &state->hasbndu, n, state->nic, &state->tmpm0, state->nec+state->nic, 1.0E-6, &i, &j, _state) )
10844  {
10845  return result;
10846  }
10847  ae_v_move(&state->xc.ptr.p_double[0], 1, &state->tmpfeas.ptr.p_double[0], 1, ae_v_len(0,n-1));
10848  for(i=0; i<=n-1; i++)
10849  {
10850  if( (state->hasbndl.ptr.p_bool[i]&&state->hasbndu.ptr.p_bool[i])&&ae_fp_eq(state->bndl.ptr.p_double[i],state->bndu.ptr.p_double[i]) )
10851  {
10852  state->activeset.ptr.p_int[i] = 1;
10853  continue;
10854  }
10855  if( (state->hasbndl.ptr.p_bool[i]&&ae_fp_eq(state->xc.ptr.p_double[i],state->bndl.ptr.p_double[i]))||(state->hasbndu.ptr.p_bool[i]&&ae_fp_eq(state->xc.ptr.p_double[i],state->bndu.ptr.p_double[i])) )
10856  {
10857  state->activeset.ptr.p_int[i] = 0;
10858  continue;
10859  }
10860  state->activeset.ptr.p_int[i] = -1;
10861  }
10862  for(i=0; i<=state->nec-1; i++)
10863  {
10864  state->activeset.ptr.p_int[n+i] = 1;
10865  }
10866  for(i=0; i<=state->nic-1; i++)
10867  {
10868  if( ae_fp_eq(state->tmpfeas.ptr.p_double[n+i],0) )
10869  {
10870  state->activeset.ptr.p_int[n+state->nec+i] = 0;
10871  }
10872  else
10873  {
10874  state->activeset.ptr.p_int[n+state->nec+i] = -1;
10875  }
10876  }
10877  }
10878  else
10879  {
10880 
10881  /*
10882  * Only bound constraints are present, quick code can be used
10883  */
10884  for(i=0; i<=n-1; i++)
10885  {
10886  state->activeset.ptr.p_int[i] = -1;
10887  if( (state->hasbndl.ptr.p_bool[i]&&state->hasbndu.ptr.p_bool[i])&&ae_fp_eq(state->bndl.ptr.p_double[i],state->bndu.ptr.p_double[i]) )
10888  {
10889  state->activeset.ptr.p_int[i] = 1;
10890  state->xc.ptr.p_double[i] = state->bndl.ptr.p_double[i];
10891  continue;
10892  }
10893  if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less_eq(state->xc.ptr.p_double[i],state->bndl.ptr.p_double[i]) )
10894  {
10895  state->xc.ptr.p_double[i] = state->bndl.ptr.p_double[i];
10896  state->activeset.ptr.p_int[i] = 0;
10897  continue;
10898  }
10899  if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater_eq(state->xc.ptr.p_double[i],state->bndu.ptr.p_double[i]) )
10900  {
10901  state->xc.ptr.p_double[i] = state->bndu.ptr.p_double[i];
10902  state->activeset.ptr.p_int[i] = 0;
10903  continue;
10904  }
10905  }
10906  }
10907 
10908  /*
10909  * Change state, allocate temporaries
10910  */
10911  result = ae_true;
10912  state->algostate = 1;
10913  state->basisisready = ae_false;
10914  state->hasxc = ae_true;
10915  rmatrixsetlengthatleast(&state->pbasis, ae_minint(nec+nic, n, _state), n+1, _state);
10916  rmatrixsetlengthatleast(&state->ibasis, ae_minint(nec+nic, n, _state), n+1, _state);
10917  rmatrixsetlengthatleast(&state->sbasis, ae_minint(nec+nic, n, _state), n+1, _state);
10918  return result;
10919 }
10920 
10921 
10922 /*************************************************************************
10923 This function explores search direction and calculates bound for step as
10924 well as information for activation of constraints.
10925 
10926 INPUT PARAMETERS:
10927  State - SAS structure which stores current point and all other
10928  active set related information
10929  D - descent direction to explore
10930 
10931 OUTPUT PARAMETERS:
10932  StpMax - upper limit on step length imposed by yet inactive
10933  constraints. Can be zero in case some constraints
10934  can be activated by zero step. Equal to some large
10935  value in case step is unlimited.
10936  CIdx - -1 for unlimited step, in [0,N+NEC+NIC) in case of
10937  limited step.
10938  VVal - value which is assigned to X[CIdx] during activation.
10939  For CIdx<0 or CIdx>=N some dummy value is assigned to
10940  this parameter.
10941 *************************************************************************/
10942 void sasexploredirection(sactiveset* state,
10943  /* Real */ ae_vector* d,
10944  double* stpmax,
10945  ae_int_t* cidx,
10946  double* vval,
10947  ae_state *_state)
10948 {
10949  ae_int_t n;
10950  ae_int_t nec;
10951  ae_int_t nic;
10952  ae_int_t i;
10953  double prevmax;
10954  double vc;
10955  double vd;
10956 
10957  *stpmax = 0;
10958  *cidx = 0;
10959  *vval = 0;
10960 
10961  ae_assert(state->algostate==1, "SASExploreDirection: is not in optimization mode", _state);
10962  n = state->n;
10963  nec = state->nec;
10964  nic = state->nic;
10965  *cidx = -1;
10966  *vval = 0;
10967  *stpmax = 1.0E50;
10968  for(i=0; i<=n-1; i++)
10969  {
10970  if( state->activeset.ptr.p_int[i]<=0 )
10971  {
10972  ae_assert(!state->hasbndl.ptr.p_bool[i]||ae_fp_greater_eq(state->xc.ptr.p_double[i],state->bndl.ptr.p_double[i]), "SASExploreDirection: internal error - infeasible X", _state);
10973  ae_assert(!state->hasbndu.ptr.p_bool[i]||ae_fp_less_eq(state->xc.ptr.p_double[i],state->bndu.ptr.p_double[i]), "SASExploreDirection: internal error - infeasible X", _state);
10974  if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less(d->ptr.p_double[i],0) )
10975  {
10976  prevmax = *stpmax;
10977  *stpmax = safeminposrv(state->xc.ptr.p_double[i]-state->bndl.ptr.p_double[i], -d->ptr.p_double[i], *stpmax, _state);
10978  if( ae_fp_less(*stpmax,prevmax) )
10979  {
10980  *cidx = i;
10981  *vval = state->bndl.ptr.p_double[i];
10982  }
10983  }
10984  if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater(d->ptr.p_double[i],0) )
10985  {
10986  prevmax = *stpmax;
10987  *stpmax = safeminposrv(state->bndu.ptr.p_double[i]-state->xc.ptr.p_double[i], d->ptr.p_double[i], *stpmax, _state);
10988  if( ae_fp_less(*stpmax,prevmax) )
10989  {
10990  *cidx = i;
10991  *vval = state->bndu.ptr.p_double[i];
10992  }
10993  }
10994  }
10995  }
10996  for(i=nec; i<=nec+nic-1; i++)
10997  {
10998  if( state->activeset.ptr.p_int[n+i]<=0 )
10999  {
11000  vc = ae_v_dotproduct(&state->cleic.ptr.pp_double[i][0], 1, &state->xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
11001  vc = vc-state->cleic.ptr.pp_double[i][n];
11002  vd = ae_v_dotproduct(&state->cleic.ptr.pp_double[i][0], 1, &d->ptr.p_double[0], 1, ae_v_len(0,n-1));
11003  if( ae_fp_less_eq(vd,0) )
11004  {
11005  continue;
11006  }
11007  if( ae_fp_less(vc,0) )
11008  {
11009 
11010  /*
11011  * XC is strictly feasible with respect to I-th constraint,
11012  * we can perform non-zero step because there is non-zero distance
11013  * between XC and bound.
11014  */
11015  prevmax = *stpmax;
11016  *stpmax = safeminposrv(-vc, vd, *stpmax, _state);
11017  if( ae_fp_less(*stpmax,prevmax) )
11018  {
11019  *cidx = n+i;
11020  }
11021  }
11022  else
11023  {
11024 
11025  /*
11026  * XC is at the boundary (or slightly beyond it), and step vector
11027  * points beyond the boundary.
11028  *
11029  * The only thing we can do is to perform zero step and activate
11030  * I-th constraint.
11031  */
11032  *stpmax = 0;
11033  *cidx = n+i;
11034  }
11035  }
11036  }
11037 }
11038 
11039 
11040 /*************************************************************************
11041 This subroutine moves current point to XN, in the direction previously
11042 explored with SASExploreDirection() function.
11043 
11044 Step may activate one constraint. It is assumed than XN is approximately
11045 feasible (small error as large as several ulps is possible). Strict
11046 feasibility with respect to bound constraints is enforced during
11047 activation, feasibility with respect to general linear constraints is not
11048 enforced.
11049 
11050 INPUT PARAMETERS:
11051  S - active set object
11052  XN - new point.
11053  NeedAct - True in case one constraint needs activation
11054  CIdx - index of constraint, in [0,N+NEC+NIC).
11055  Ignored if NeedAct is false.
11056  This value is calculated by SASExploreDirection().
11057  CVal - for CIdx in [0,N) this field stores value which is
11058  assigned to XC[CIdx] during activation. CVal is ignored in
11059  other cases.
11060  This value is calculated by SASExploreDirection().
11061 
11062 OUTPUT PARAMETERS:
11063  S - current point and list of active constraints are changed.
11064 
11065 RESULT:
11066  >0, in case at least one inactive non-candidate constraint was activated
11067  =0, in case only "candidate" constraints were activated
11068  <0, in case no constraints were activated by the step
11069 
11070 NOTE: in general case State.XC<>XN because activation of constraints may
11071  slightly change current point (to enforce feasibility).
11072 
11073  -- ALGLIB --
11074  Copyright 21.12.2012 by Bochkanov Sergey
11075 *************************************************************************/
11076 ae_int_t sasmoveto(sactiveset* state,
11077  /* Real */ ae_vector* xn,
11078  ae_bool needact,
11079  ae_int_t cidx,
11080  double cval,
11081  ae_state *_state)
11082 {
11083  ae_int_t n;
11084  ae_int_t nec;
11085  ae_int_t nic;
11086  ae_int_t i;
11087  ae_bool wasactivation;
11088  ae_int_t result;
11089 
11090 
11091  ae_assert(state->algostate==1, "SASMoveTo: is not in optimization mode", _state);
11092  n = state->n;
11093  nec = state->nec;
11094  nic = state->nic;
11095 
11096  /*
11097  * Save previous state, update current point
11098  */
11099  rvectorsetlengthatleast(&state->mtx, n, _state);
11100  ivectorsetlengthatleast(&state->mtas, n+nec+nic, _state);
11101  for(i=0; i<=n-1; i++)
11102  {
11103  state->mtx.ptr.p_double[i] = state->xc.ptr.p_double[i];
11104  state->xc.ptr.p_double[i] = xn->ptr.p_double[i];
11105  }
11106  for(i=0; i<=n+nec+nic-1; i++)
11107  {
11108  state->mtas.ptr.p_int[i] = state->activeset.ptr.p_int[i];
11109  }
11110 
11111  /*
11112  * Activate constraints
11113  */
11114  wasactivation = ae_false;
11115  if( needact )
11116  {
11117 
11118  /*
11119  * Activation
11120  */
11121  ae_assert(cidx>=0&&cidx<n+nec+nic, "SASMoveTo: incorrect CIdx", _state);
11122  if( cidx<n )
11123  {
11124 
11125  /*
11126  * CIdx in [0,N-1] means that bound constraint was activated.
11127  * We activate it explicitly to avoid situation when roundoff-error
11128  * prevents us from moving EXACTLY to x=CVal.
11129  */
11130  state->xc.ptr.p_double[cidx] = cval;
11131  }
11132  state->activeset.ptr.p_int[cidx] = 1;
11133  wasactivation = ae_true;
11134  }
11135  for(i=0; i<=n-1; i++)
11136  {
11137 
11138  /*
11139  * Post-check (some constraints may be activated because of numerical errors)
11140  */
11141  if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less(state->xc.ptr.p_double[i],state->bndl.ptr.p_double[i]) )
11142  {
11143  state->xc.ptr.p_double[i] = state->bndl.ptr.p_double[i];
11144  state->activeset.ptr.p_int[i] = 1;
11145  wasactivation = ae_true;
11146  }
11147  if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater(state->xc.ptr.p_double[i],state->bndu.ptr.p_double[i]) )
11148  {
11149  state->xc.ptr.p_double[i] = state->bndu.ptr.p_double[i];
11150  state->activeset.ptr.p_int[i] = 1;
11151  wasactivation = ae_true;
11152  }
11153  }
11154 
11155  /*
11156  * Determine return status:
11157  * * -1 in case no constraints were activated
11158  * * 0 in case only "candidate" constraints were activated
11159  * * +1 in case at least one "non-candidate" constraint was activated
11160  */
11161  if( wasactivation )
11162  {
11163 
11164  /*
11165  * Step activated one/several constraints, but sometimes it is spurious
11166  * activation - RecalculateConstraints() tells us that constraint is
11167  * inactive (negative Largrange multiplier), but step activates it
11168  * because of numerical noise.
11169  *
11170  * This block of code checks whether step activated truly new constraints
11171  * (ones which were not in the active set at the solution):
11172  *
11173  * * for non-boundary constraint it is enough to check that previous value
11174  * of ActiveSet[i] is negative (=far from boundary), and new one is
11175  * positive (=we are at the boundary, constraint is activated).
11176  *
11177  * * for boundary constraints previous criterion won't work. Each variable
11178  * has two constraints, and simply checking their status is not enough -
11179  * we have to correctly identify cases when we leave one boundary
11180  * (PrevActiveSet[i]=0) and move to another boundary (ActiveSet[i]>0).
11181  * Such cases can be identified if we compare previous X with new X.
11182  *
11183  * In case only "candidate" constraints were activated, result variable
11184  * is set to 0. In case at least one new constraint was activated, result
11185  * is set to 1.
11186  */
11187  result = 0;
11188  for(i=0; i<=n-1; i++)
11189  {
11190  if( state->activeset.ptr.p_int[i]>0&&ae_fp_neq(state->xc.ptr.p_double[i],state->mtx.ptr.p_double[i]) )
11191  {
11192  result = 1;
11193  }
11194  }
11195  for(i=n; i<=n+state->nec+state->nic-1; i++)
11196  {
11197  if( state->mtas.ptr.p_int[i]<0&&state->activeset.ptr.p_int[i]>0 )
11198  {
11199  result = 1;
11200  }
11201  }
11202  }
11203  else
11204  {
11205 
11206  /*
11207  * No activation, return -1
11208  */
11209  result = -1;
11210  }
11211 
11212  /*
11213  * Invalidate basis
11214  */
11215  state->basisisready = ae_false;
11216  return result;
11217 }
11218 
11219 
11220 /*************************************************************************
11221 This subroutine performs immediate activation of one constraint:
11222 * "immediate" means that we do not have to move to activate it
11223 * in case boundary constraint is activated, we enforce current point to be
11224  exactly at the boundary
11225 
11226 INPUT PARAMETERS:
11227  S - active set object
11228  CIdx - index of constraint, in [0,N+NEC+NIC).
11229  This value is calculated by SASExploreDirection().
11230  CVal - for CIdx in [0,N) this field stores value which is
11231  assigned to XC[CIdx] during activation. CVal is ignored in
11232  other cases.
11233  This value is calculated by SASExploreDirection().
11234 
11235  -- ALGLIB --
11236  Copyright 21.12.2012 by Bochkanov Sergey
11237 *************************************************************************/
11238 void sasimmediateactivation(sactiveset* state,
11239  ae_int_t cidx,
11240  double cval,
11241  ae_state *_state)
11242 {
11243 
11244 
11245  ae_assert(state->algostate==1, "SASMoveTo: is not in optimization mode", _state);
11246  if( cidx<state->n )
11247  {
11248  state->xc.ptr.p_double[cidx] = cval;
11249  }
11250  state->activeset.ptr.p_int[cidx] = 1;
11251  state->basisisready = ae_false;
11252 }
11253 
11254 
11255 /*************************************************************************
11256 This subroutine calculates descent direction subject to current active set.
11257 
11258 INPUT PARAMETERS:
11259  S - active set object
11260  G - array[N], gradient
11261  D - possibly prealocated buffer;
11262  automatically resized if needed.
11263 
11264 OUTPUT PARAMETERS:
11265  D - descent direction projected onto current active set.
11266  Components of D which correspond to active boundary
11267  constraints are forced to be exactly zero.
11268  In case D is non-zero, it is normalized to have unit norm.
11269 
11270 NOTE: in case active set has N active constraints (or more), descent
11271  direction is forced to be exactly zero.
11272 
11273  -- ALGLIB --
11274  Copyright 21.12.2012 by Bochkanov Sergey
11275 *************************************************************************/
11276 void sasconstraineddescent(sactiveset* state,
11277  /* Real */ ae_vector* g,
11278  /* Real */ ae_vector* d,
11279  ae_state *_state)
11280 {
11281 
11282 
11283  ae_assert(state->algostate==1, "SASConstrainedDescent: is not in optimization mode", _state);
11284  sasrebuildbasis(state, _state);
11285  sactivesets_constraineddescent(state, g, &state->unitdiagonal, &state->ibasis, ae_true, d, _state);
11286 }
11287 
11288 
11289 /*************************************************************************
11290 This subroutine calculates preconditioned descent direction subject to
11291 current active set.
11292 
11293 INPUT PARAMETERS:
11294  S - active set object
11295  G - array[N], gradient
11296  D - possibly prealocated buffer;
11297  automatically resized if needed.
11298 
11299 OUTPUT PARAMETERS:
11300  D - descent direction projected onto current active set.
11301  Components of D which correspond to active boundary
11302  constraints are forced to be exactly zero.
11303  In case D is non-zero, it is normalized to have unit norm.
11304 
11305 NOTE: in case active set has N active constraints (or more), descent
11306  direction is forced to be exactly zero.
11307 
11308  -- ALGLIB --
11309  Copyright 21.12.2012 by Bochkanov Sergey
11310 *************************************************************************/
11311 void sasconstraineddescentprec(sactiveset* state,
11312  /* Real */ ae_vector* g,
11313  /* Real */ ae_vector* d,
11314  ae_state *_state)
11315 {
11316 
11317 
11318  ae_assert(state->algostate==1, "SASConstrainedDescentPrec: is not in optimization mode", _state);
11319  sasrebuildbasis(state, _state);
11320  sactivesets_constraineddescent(state, g, &state->h, &state->pbasis, ae_true, d, _state);
11321 }
11322 
11323 
11324 /*************************************************************************
11325 This subroutine calculates product of direction vector and preconditioner
11326 multiplied subject to current active set.
11327 
11328 INPUT PARAMETERS:
11329  S - active set object
11330  D - array[N], direction
11331 
11332 OUTPUT PARAMETERS:
11333  D - preconditioned direction projected onto current active set.
11334  Components of D which correspond to active boundary
11335  constraints are forced to be exactly zero.
11336 
11337 NOTE: in case active set has N active constraints (or more), descent
11338  direction is forced to be exactly zero.
11339 
11340  -- ALGLIB --
11341  Copyright 21.12.2012 by Bochkanov Sergey
11342 *************************************************************************/
11343 void sasconstraineddirection(sactiveset* state,
11344  /* Real */ ae_vector* d,
11345  ae_state *_state)
11346 {
11347  ae_int_t i;
11348 
11349 
11350  ae_assert(state->algostate==1, "SASConstrainedAntigradientPrec: is not in optimization mode", _state);
11351  sasrebuildbasis(state, _state);
11352  sactivesets_constraineddescent(state, d, &state->unitdiagonal, &state->ibasis, ae_false, &state->cdtmp, _state);
11353  for(i=0; i<=state->n-1; i++)
11354  {
11355  d->ptr.p_double[i] = -state->cdtmp.ptr.p_double[i];
11356  }
11357 }
11358 
11359 
11360 /*************************************************************************
11361 This subroutine calculates product of direction vector and preconditioner
11362 multiplied subject to current active set.
11363 
11364 INPUT PARAMETERS:
11365  S - active set object
11366  D - array[N], direction
11367 
11368 OUTPUT PARAMETERS:
11369  D - preconditioned direction projected onto current active set.
11370  Components of D which correspond to active boundary
11371  constraints are forced to be exactly zero.
11372 
11373 NOTE: in case active set has N active constraints (or more), descent
11374  direction is forced to be exactly zero.
11375 
11376  -- ALGLIB --
11377  Copyright 21.12.2012 by Bochkanov Sergey
11378 *************************************************************************/
11379 void sasconstraineddirectionprec(sactiveset* state,
11380  /* Real */ ae_vector* d,
11381  ae_state *_state)
11382 {
11383  ae_int_t i;
11384 
11385 
11386  ae_assert(state->algostate==1, "SASConstrainedAntigradientPrec: is not in optimization mode", _state);
11387  sasrebuildbasis(state, _state);
11388  sactivesets_constraineddescent(state, d, &state->h, &state->pbasis, ae_false, &state->cdtmp, _state);
11389  for(i=0; i<=state->n-1; i++)
11390  {
11391  d->ptr.p_double[i] = -state->cdtmp.ptr.p_double[i];
11392  }
11393 }
11394 
11395 
11396 /*************************************************************************
11397 This subroutine performs correction of some (possibly infeasible) point
11398 with respect to a) current active set, b) all boundary constraints, both
11399 active and inactive:
11400 
11401 0) we calculate L1 penalty term for violation of active linear constraints
11402  (one which is returned by SASActiveLCPenalty1() function).
11403 1) first, it performs projection (orthogonal with respect to scale matrix
11404  S) of X into current active set: X -> X1.
11405 2) next, we perform projection with respect to ALL boundary constraints
11406  which are violated at X1: X1 -> X2.
11407 3) X is replaced by X2.
11408 
11409 The idea is that this function can preserve and enforce feasibility during
11410 optimization, and additional penalty parameter can be used to prevent algo
11411 from leaving feasible set because of rounding errors.
11412 
11413 INPUT PARAMETERS:
11414  S - active set object
11415  X - array[N], candidate point
11416 
11417 OUTPUT PARAMETERS:
11418  X - "improved" candidate point:
11419  a) feasible with respect to all boundary constraints
11420  b) feasibility with respect to active set is retained at
11421  good level.
11422  Penalty - penalty term, which can be added to function value if user
11423  wants to penalize violation of constraints (recommended).
11424 
11425 NOTE: this function is not intended to find exact projection (i.e. best
11426  approximation) of X into feasible set. It just improves situation a
11427  bit.
11428  Regular use of this function will help you to retain feasibility
11429  - if you already have something to start with and constrain your
11430  steps is such way that the only source of infeasibility are roundoff
11431  errors.
11432 
11433  -- ALGLIB --
11434  Copyright 21.12.2012 by Bochkanov Sergey
11435 *************************************************************************/
11436 void sascorrection(sactiveset* state,
11437  /* Real */ ae_vector* x,
11438  double* penalty,
11439  ae_state *_state)
11440 {
11441  ae_int_t i;
11442  ae_int_t j;
11443  ae_int_t n;
11444  double v;
11445 
11446  *penalty = 0;
11447 
11448  ae_assert(state->algostate==1, "SASCorrection: is not in optimization mode", _state);
11449  sasrebuildbasis(state, _state);
11450  n = state->n;
11451  rvectorsetlengthatleast(&state->corrtmp, n, _state);
11452 
11453  /*
11454  * Calculate penalty term.
11455  */
11456  *penalty = sasactivelcpenalty1(state, x, _state);
11457 
11458  /*
11459  * Perform projection 1.
11460  *
11461  * This projecton is given by:
11462  *
11463  * x_proj = x - S*S*As'*(As*x-b)
11464  *
11465  * where x is original x before projection, S is a scale matrix,
11466  * As is a matrix of equality constraints (active set) which were
11467  * orthogonalized with respect to inner product given by S (i.e. we
11468  * have As*S*S'*As'=I), b is a right part of the orthogonalized
11469  * constraints.
11470  *
11471  * NOTE: you can verify that x_proj is strictly feasible w.r.t.
11472  * active set by multiplying it by As - you will get
11473  * As*x_proj = As*x - As*x + b = b.
11474  *
11475  * This formula for projection can be obtained by solving
11476  * following minimization problem.
11477  *
11478  * min ||inv(S)*(x_proj-x)||^2 s.t. As*x_proj=b
11479  *
11480  */
11481  ae_v_move(&state->corrtmp.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1));
11482  for(i=0; i<=state->basissize-1; i++)
11483  {
11484  v = -state->sbasis.ptr.pp_double[i][n];
11485  for(j=0; j<=n-1; j++)
11486  {
11487  v = v+state->sbasis.ptr.pp_double[i][j]*state->corrtmp.ptr.p_double[j];
11488  }
11489  for(j=0; j<=n-1; j++)
11490  {
11491  state->corrtmp.ptr.p_double[j] = state->corrtmp.ptr.p_double[j]-v*state->sbasis.ptr.pp_double[i][j]*ae_sqr(state->s.ptr.p_double[j], _state);
11492  }
11493  }
11494  for(i=0; i<=n-1; i++)
11495  {
11496  if( state->activeset.ptr.p_int[i]>0 )
11497  {
11498  state->corrtmp.ptr.p_double[i] = state->xc.ptr.p_double[i];
11499  }
11500  }
11501 
11502  /*
11503  * Perform projection 2
11504  */
11505  for(i=0; i<=n-1; i++)
11506  {
11507  x->ptr.p_double[i] = state->corrtmp.ptr.p_double[i];
11508  if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less(x->ptr.p_double[i],state->bndl.ptr.p_double[i]) )
11509  {
11510  x->ptr.p_double[i] = state->bndl.ptr.p_double[i];
11511  }
11512  if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater(x->ptr.p_double[i],state->bndu.ptr.p_double[i]) )
11513  {
11514  x->ptr.p_double[i] = state->bndu.ptr.p_double[i];
11515  }
11516  }
11517 }
11518 
11519 
11520 /*************************************************************************
11521 This subroutine returns L1 penalty for violation of active general linear
11522 constraints (violation of boundary or inactive linear constraints is not
11523 added to penalty).
11524 
11525 Penalty term is equal to:
11526 
11527  Penalty = SUM( Abs((C_i*x-R_i)/Alpha_i) )
11528 
11529 Here:
11530 * summation is performed for I=0...NEC+NIC-1, ActiveSet[N+I]>0
11531  (only for rows of CLEIC which are in active set)
11532 * C_i is I-th row of CLEIC
11533 * R_i is corresponding right part
11534 * S is a scale matrix
11535 * Alpha_i = ||S*C_i|| - is a scaling coefficient which "normalizes"
11536  I-th summation term according to its scale.
11537 
11538 INPUT PARAMETERS:
11539  S - active set object
11540  X - array[N], candidate point
11541 
11542  -- ALGLIB --
11543  Copyright 21.12.2012 by Bochkanov Sergey
11544 *************************************************************************/
11545 double sasactivelcpenalty1(sactiveset* state,
11546  /* Real */ ae_vector* x,
11547  ae_state *_state)
11548 {
11549  ae_int_t i;
11550  ae_int_t j;
11551  ae_int_t n;
11552  ae_int_t nec;
11553  ae_int_t nic;
11554  double v;
11555  double alpha;
11556  double p;
11557  double result;
11558 
11559 
11560  ae_assert(state->algostate==1, "SASActiveLCPenalty1: is not in optimization mode", _state);
11561  sasrebuildbasis(state, _state);
11562  n = state->n;
11563  nec = state->nec;
11564  nic = state->nic;
11565 
11566  /*
11567  * Calculate penalty term.
11568  */
11569  result = 0;
11570  for(i=0; i<=nec+nic-1; i++)
11571  {
11572  if( state->activeset.ptr.p_int[n+i]>0 )
11573  {
11574  alpha = 0;
11575  p = -state->cleic.ptr.pp_double[i][n];
11576  for(j=0; j<=n-1; j++)
11577  {
11578  v = state->cleic.ptr.pp_double[i][j];
11579  p = p+v*x->ptr.p_double[j];
11580  alpha = alpha+ae_sqr(v*state->s.ptr.p_double[j], _state);
11581  }
11582  alpha = ae_sqrt(alpha, _state);
11583  if( ae_fp_neq(alpha,0) )
11584  {
11585  result = result+ae_fabs(p/alpha, _state);
11586  }
11587  }
11588  }
11589  return result;
11590 }
11591 
11592 
11593 /*************************************************************************
11594 This subroutine calculates scaled norm of vector after projection onto
11595 subspace of active constraints. Most often this function is used to test
11596 stopping conditions.
11597 
11598 INPUT PARAMETERS:
11599  S - active set object
11600  D - vector whose norm is calculated
11601 
11602 RESULT:
11603  Vector norm (after projection and scaling)
11604 
11605 NOTE: projection is performed first, scaling is performed after projection
11606 
11607  -- ALGLIB --
11608  Copyright 21.12.2012 by Bochkanov Sergey
11609 *************************************************************************/
11610 double sasscaledconstrainednorm(sactiveset* state,
11611  /* Real */ ae_vector* d,
11612  ae_state *_state)
11613 {
11614  ae_int_t i;
11615  ae_int_t n;
11616  double v;
11617  double result;
11618 
11619 
11620  ae_assert(state->algostate==1, "SASMoveTo: is not in optimization mode", _state);
11621  n = state->n;
11622  rvectorsetlengthatleast(&state->scntmp, n, _state);
11623 
11624  /*
11625  * Prepare basis (if needed)
11626  */
11627  sasrebuildbasis(state, _state);
11628 
11629  /*
11630  * Calculate descent direction
11631  */
11632  for(i=0; i<=n-1; i++)
11633  {
11634  if( state->activeset.ptr.p_int[i]>0 )
11635  {
11636  state->scntmp.ptr.p_double[i] = 0;
11637  }
11638  else
11639  {
11640  state->scntmp.ptr.p_double[i] = d->ptr.p_double[i];
11641  }
11642  }
11643  for(i=0; i<=state->basissize-1; i++)
11644  {
11645  v = ae_v_dotproduct(&state->ibasis.ptr.pp_double[i][0], 1, &state->scntmp.ptr.p_double[0], 1, ae_v_len(0,n-1));
11646  ae_v_subd(&state->scntmp.ptr.p_double[0], 1, &state->ibasis.ptr.pp_double[i][0], 1, ae_v_len(0,n-1), v);
11647  }
11648  v = 0.0;
11649  for(i=0; i<=n-1; i++)
11650  {
11651  v = v+ae_sqr(state->s.ptr.p_double[i]*state->scntmp.ptr.p_double[i], _state);
11652  }
11653  result = ae_sqrt(v, _state);
11654  return result;
11655 }
11656 
11657 
11658 /*************************************************************************
11659 This subroutine turns off optimization mode.
11660 
11661 INPUT PARAMETERS:
11662  S - active set object
11663 
11664 OUTPUT PARAMETERS:
11665  S - state is changed
11666 
11667 NOTE: this function can be called many times for optimizer which was
11668  already stopped.
11669 
11670  -- ALGLIB --
11671  Copyright 21.12.2012 by Bochkanov Sergey
11672 *************************************************************************/
11673 void sasstopoptimization(sactiveset* state, ae_state *_state)
11674 {
11675 
11676 
11677  state->algostate = 0;
11678 }
11679 
11680 
11681 /*************************************************************************
11682 This function recalculates constraints - activates and deactivates them
11683 according to gradient value at current point. Algorithm assumes that we
11684 want to make steepest descent step from current point; constraints are
11685 activated and deactivated in such way that we won't violate any constraint
11686 by steepest descent step.
11687 
11688 After call to this function active set is ready to try steepest descent
11689 step (SASDescentDirection-SASExploreDirection-SASMoveTo).
11690 
11691 Only already "active" and "candidate" elements of ActiveSet are examined;
11692 constraints which are not active are not examined.
11693 
11694 INPUT PARAMETERS:
11695  State - active set object
11696  GC - array[N], gradient at XC
11697 
11698 OUTPUT PARAMETERS:
11699  State - active set object, with new set of constraint
11700 
11701  -- ALGLIB --
11702  Copyright 26.09.2012 by Bochkanov Sergey
11703 *************************************************************************/
11704 void sasreactivateconstraints(sactiveset* state,
11705  /* Real */ ae_vector* gc,
11706  ae_state *_state)
11707 {
11708 
11709 
11710  ae_assert(state->algostate==1, "SASReactivateConstraints: must be in optimization mode", _state);
11711  sactivesets_reactivateconstraints(state, gc, &state->unitdiagonal, _state);
11712 }
11713 
11714 
11715 /*************************************************************************
11716 This function recalculates constraints - activates and deactivates them
11717 according to gradient value at current point.
11718 
11719 Algorithm assumes that we want to make Quasi-Newton step from current
11720 point with diagonal Quasi-Newton matrix H. Constraints are activated and
11721 deactivated in such way that we won't violate any constraint by step.
11722 
11723 After call to this function active set is ready to try preconditioned
11724 steepest descent step (SASDescentDirection-SASExploreDirection-SASMoveTo).
11725 
11726 Only already "active" and "candidate" elements of ActiveSet are examined;
11727 constraints which are not active are not examined.
11728 
11729 INPUT PARAMETERS:
11730  State - active set object
11731  GC - array[N], gradient at XC
11732 
11733 OUTPUT PARAMETERS:
11734  State - active set object, with new set of constraint
11735 
11736  -- ALGLIB --
11737  Copyright 26.09.2012 by Bochkanov Sergey
11738 *************************************************************************/
11739 void sasreactivateconstraintsprec(sactiveset* state,
11740  /* Real */ ae_vector* gc,
11741  ae_state *_state)
11742 {
11743 
11744 
11745  ae_assert(state->algostate==1, "SASReactivateConstraintsPrec: must be in optimization mode", _state);
11746  sactivesets_reactivateconstraints(state, gc, &state->h, _state);
11747 }
11748 
11749 
11750 /*************************************************************************
11751 This function builds three orthonormal basises for current active set:
11752 * P-orthogonal one, which is orthogonalized with inner product
11753  (x,y) = x'*P*y, where P=inv(H) is current preconditioner
11754 * S-orthogonal one, which is orthogonalized with inner product
11755  (x,y) = x'*S'*S*y, where S is diagonal scaling matrix
11756 * I-orthogonal one, which is orthogonalized with standard dot product
11757 
11758 NOTE: all sets of orthogonal vectors are guaranteed to have same size.
11759  P-orthogonal basis is built first, I/S-orthogonal basises are forced
11760  to have same number of vectors as P-orthogonal one (padded by zero
11761  vectors if needed).
11762 
11763 NOTE: this function tracks changes in active set; first call will result
11764  in reorthogonalization
11765 
11766 INPUT PARAMETERS:
11767  State - active set object
11768  H - diagonal preconditioner, H[i]>0
11769 
11770 OUTPUT PARAMETERS:
11771  State - active set object with new basis
11772 
11773  -- ALGLIB --
11774  Copyright 20.06.2012 by Bochkanov Sergey
11775 *************************************************************************/
11776 void sasrebuildbasis(sactiveset* state, ae_state *_state)
11777 {
11778  ae_int_t n;
11779  ae_int_t nec;
11780  ae_int_t nic;
11781  ae_int_t i;
11782  ae_int_t j;
11783  ae_int_t t;
11784  ae_int_t nactivelin;
11785  ae_int_t nactivebnd;
11786  double v;
11787  double vmax;
11788  ae_int_t kmax;
11789 
11790 
11791  if( state->basisisready )
11792  {
11793  return;
11794  }
11795  n = state->n;
11796  nec = state->nec;
11797  nic = state->nic;
11798  rmatrixsetlengthatleast(&state->tmpbasis, nec+nic, n+1, _state);
11799  state->basissize = 0;
11800  state->basisisready = ae_true;
11801 
11802  /*
11803  * Determine number of active boundary and non-boundary
11804  * constraints, move them to TmpBasis. Quick exit if no
11805  * non-boundary constraints were detected.
11806  */
11807  nactivelin = 0;
11808  nactivebnd = 0;
11809  for(i=0; i<=nec+nic-1; i++)
11810  {
11811  if( state->activeset.ptr.p_int[n+i]>0 )
11812  {
11813  nactivelin = nactivelin+1;
11814  }
11815  }
11816  for(j=0; j<=n-1; j++)
11817  {
11818  if( state->activeset.ptr.p_int[j]>0 )
11819  {
11820  nactivebnd = nactivebnd+1;
11821  }
11822  }
11823  if( nactivelin==0 )
11824  {
11825  return;
11826  }
11827 
11828  /*
11829  * Orthogonalize linear constraints (inner product is given by preconditioner)
11830  * with respect to each other and boundary ones:
11831  * * normalize all constraints
11832  * * orthogonalize with respect to boundary ones
11833  * * repeat:
11834  * * if basisSize+nactivebnd=n - TERMINATE
11835  * * choose largest row from TmpBasis
11836  * * if row norm is too small - TERMINATE
11837  * * add row to basis, normalize
11838  * * remove from TmpBasis, orthogonalize other constraints with respect to this one
11839  */
11840  nactivelin = 0;
11841  for(i=0; i<=nec+nic-1; i++)
11842  {
11843  if( state->activeset.ptr.p_int[n+i]>0 )
11844  {
11845  ae_v_move(&state->tmpbasis.ptr.pp_double[nactivelin][0], 1, &state->cleic.ptr.pp_double[i][0], 1, ae_v_len(0,n));
11846  nactivelin = nactivelin+1;
11847  }
11848  }
11849  for(i=0; i<=nactivelin-1; i++)
11850  {
11851  v = 0.0;
11852  for(j=0; j<=n-1; j++)
11853  {
11854  v = v+ae_sqr(state->tmpbasis.ptr.pp_double[i][j], _state)/state->h.ptr.p_double[j];
11855  }
11856  if( ae_fp_greater(v,0) )
11857  {
11858  v = 1/ae_sqrt(v, _state);
11859  for(j=0; j<=n; j++)
11860  {
11861  state->tmpbasis.ptr.pp_double[i][j] = state->tmpbasis.ptr.pp_double[i][j]*v;
11862  }
11863  }
11864  }
11865  for(j=0; j<=n-1; j++)
11866  {
11867  if( state->activeset.ptr.p_int[j]>0 )
11868  {
11869  for(i=0; i<=nactivelin-1; i++)
11870  {
11871  state->tmpbasis.ptr.pp_double[i][n] = state->tmpbasis.ptr.pp_double[i][n]-state->tmpbasis.ptr.pp_double[i][j]*state->xc.ptr.p_double[j];
11872  state->tmpbasis.ptr.pp_double[i][j] = 0.0;
11873  }
11874  }
11875  }
11876  while(state->basissize+nactivebnd<n)
11877  {
11878 
11879  /*
11880  * Find largest vector, add to basis
11881  */
11882  vmax = -1;
11883  kmax = -1;
11884  for(i=0; i<=nactivelin-1; i++)
11885  {
11886  v = 0.0;
11887  for(j=0; j<=n-1; j++)
11888  {
11889  v = v+ae_sqr(state->tmpbasis.ptr.pp_double[i][j], _state)/state->h.ptr.p_double[j];
11890  }
11891  v = ae_sqrt(v, _state);
11892  if( ae_fp_greater(v,vmax) )
11893  {
11894  vmax = v;
11895  kmax = i;
11896  }
11897  }
11898  if( ae_fp_less(vmax,1.0E4*ae_machineepsilon) )
11899  {
11900  break;
11901  }
11902  v = 1/vmax;
11903  ae_v_moved(&state->pbasis.ptr.pp_double[state->basissize][0], 1, &state->tmpbasis.ptr.pp_double[kmax][0], 1, ae_v_len(0,n), v);
11904  state->basissize = state->basissize+1;
11905 
11906  /*
11907  * Reorthogonalize other vectors with respect to chosen one.
11908  * Remove it from the array.
11909  */
11910  for(i=0; i<=nactivelin-1; i++)
11911  {
11912  if( i!=kmax )
11913  {
11914  v = 0;
11915  for(j=0; j<=n-1; j++)
11916  {
11917  v = v+state->pbasis.ptr.pp_double[state->basissize-1][j]*state->tmpbasis.ptr.pp_double[i][j]/state->h.ptr.p_double[j];
11918  }
11919  ae_v_subd(&state->tmpbasis.ptr.pp_double[i][0], 1, &state->pbasis.ptr.pp_double[state->basissize-1][0], 1, ae_v_len(0,n), v);
11920  }
11921  }
11922  for(j=0; j<=n; j++)
11923  {
11924  state->tmpbasis.ptr.pp_double[kmax][j] = 0;
11925  }
11926  }
11927 
11928  /*
11929  * Orthogonalize linear constraints using traditional dot product
11930  * with respect to each other and boundary ones.
11931  *
11932  * NOTE: we force basis size to be equal to one which was computed
11933  * at the previous step, with preconditioner-based inner product.
11934  */
11935  nactivelin = 0;
11936  for(i=0; i<=nec+nic-1; i++)
11937  {
11938  if( state->activeset.ptr.p_int[n+i]>0 )
11939  {
11940  ae_v_move(&state->tmpbasis.ptr.pp_double[nactivelin][0], 1, &state->cleic.ptr.pp_double[i][0], 1, ae_v_len(0,n));
11941  nactivelin = nactivelin+1;
11942  }
11943  }
11944  for(i=0; i<=nactivelin-1; i++)
11945  {
11946  v = 0.0;
11947  for(j=0; j<=n-1; j++)
11948  {
11949  v = v+ae_sqr(state->tmpbasis.ptr.pp_double[i][j], _state);
11950  }
11951  if( ae_fp_greater(v,0) )
11952  {
11953  v = 1/ae_sqrt(v, _state);
11954  for(j=0; j<=n; j++)
11955  {
11956  state->tmpbasis.ptr.pp_double[i][j] = state->tmpbasis.ptr.pp_double[i][j]*v;
11957  }
11958  }
11959  }
11960  for(j=0; j<=n-1; j++)
11961  {
11962  if( state->activeset.ptr.p_int[j]>0 )
11963  {
11964  for(i=0; i<=nactivelin-1; i++)
11965  {
11966  state->tmpbasis.ptr.pp_double[i][n] = state->tmpbasis.ptr.pp_double[i][n]-state->tmpbasis.ptr.pp_double[i][j]*state->xc.ptr.p_double[j];
11967  state->tmpbasis.ptr.pp_double[i][j] = 0.0;
11968  }
11969  }
11970  }
11971  for(t=0; t<=state->basissize-1; t++)
11972  {
11973 
11974  /*
11975  * Find largest vector, add to basis.
11976  */
11977  vmax = -1;
11978  kmax = -1;
11979  for(i=0; i<=nactivelin-1; i++)
11980  {
11981  v = 0.0;
11982  for(j=0; j<=n-1; j++)
11983  {
11984  v = v+ae_sqr(state->tmpbasis.ptr.pp_double[i][j], _state);
11985  }
11986  v = ae_sqrt(v, _state);
11987  if( ae_fp_greater(v,vmax) )
11988  {
11989  vmax = v;
11990  kmax = i;
11991  }
11992  }
11993  if( ae_fp_eq(vmax,0) )
11994  {
11995  for(j=0; j<=n; j++)
11996  {
11997  state->ibasis.ptr.pp_double[t][j] = 0.0;
11998  }
11999  continue;
12000  }
12001  v = 1/vmax;
12002  ae_v_moved(&state->ibasis.ptr.pp_double[t][0], 1, &state->tmpbasis.ptr.pp_double[kmax][0], 1, ae_v_len(0,n), v);
12003 
12004  /*
12005  * Reorthogonalize other vectors with respect to chosen one.
12006  * Remove it from the array.
12007  */
12008  for(i=0; i<=nactivelin-1; i++)
12009  {
12010  if( i!=kmax )
12011  {
12012  v = 0;
12013  for(j=0; j<=n-1; j++)
12014  {
12015  v = v+state->ibasis.ptr.pp_double[t][j]*state->tmpbasis.ptr.pp_double[i][j];
12016  }
12017  ae_v_subd(&state->tmpbasis.ptr.pp_double[i][0], 1, &state->ibasis.ptr.pp_double[t][0], 1, ae_v_len(0,n), v);
12018  }
12019  }
12020  for(j=0; j<=n; j++)
12021  {
12022  state->tmpbasis.ptr.pp_double[kmax][j] = 0;
12023  }
12024  }
12025 
12026  /*
12027  * Orthogonalize linear constraints using inner product given by
12028  * scale matrix.
12029  *
12030  * NOTE: we force basis size to be equal to one which was computed
12031  * with preconditioner-based inner product.
12032  */
12033  nactivelin = 0;
12034  for(i=0; i<=nec+nic-1; i++)
12035  {
12036  if( state->activeset.ptr.p_int[n+i]>0 )
12037  {
12038  ae_v_move(&state->tmpbasis.ptr.pp_double[nactivelin][0], 1, &state->cleic.ptr.pp_double[i][0], 1, ae_v_len(0,n));
12039  nactivelin = nactivelin+1;
12040  }
12041  }
12042  for(i=0; i<=nactivelin-1; i++)
12043  {
12044  v = 0.0;
12045  for(j=0; j<=n-1; j++)
12046  {
12047  v = v+ae_sqr(state->tmpbasis.ptr.pp_double[i][j]*state->s.ptr.p_double[j], _state);
12048  }
12049  if( ae_fp_greater(v,0) )
12050  {
12051  v = 1/ae_sqrt(v, _state);
12052  for(j=0; j<=n; j++)
12053  {
12054  state->tmpbasis.ptr.pp_double[i][j] = state->tmpbasis.ptr.pp_double[i][j]*v;
12055  }
12056  }
12057  }
12058  for(j=0; j<=n-1; j++)
12059  {
12060  if( state->activeset.ptr.p_int[j]>0 )
12061  {
12062  for(i=0; i<=nactivelin-1; i++)
12063  {
12064  state->tmpbasis.ptr.pp_double[i][n] = state->tmpbasis.ptr.pp_double[i][n]-state->tmpbasis.ptr.pp_double[i][j]*state->xc.ptr.p_double[j];
12065  state->tmpbasis.ptr.pp_double[i][j] = 0.0;
12066  }
12067  }
12068  }
12069  for(t=0; t<=state->basissize-1; t++)
12070  {
12071 
12072  /*
12073  * Find largest vector, add to basis.
12074  */
12075  vmax = -1;
12076  kmax = -1;
12077  for(i=0; i<=nactivelin-1; i++)
12078  {
12079  v = 0.0;
12080  for(j=0; j<=n-1; j++)
12081  {
12082  v = v+ae_sqr(state->tmpbasis.ptr.pp_double[i][j]*state->s.ptr.p_double[j], _state);
12083  }
12084  v = ae_sqrt(v, _state);
12085  if( ae_fp_greater(v,vmax) )
12086  {
12087  vmax = v;
12088  kmax = i;
12089  }
12090  }
12091  if( ae_fp_eq(vmax,0) )
12092  {
12093  for(j=0; j<=n; j++)
12094  {
12095  state->sbasis.ptr.pp_double[t][j] = 0.0;
12096  }
12097  continue;
12098  }
12099  v = 1/vmax;
12100  ae_v_moved(&state->sbasis.ptr.pp_double[t][0], 1, &state->tmpbasis.ptr.pp_double[kmax][0], 1, ae_v_len(0,n), v);
12101 
12102  /*
12103  * Reorthogonalize other vectors with respect to chosen one.
12104  * Remove it from the array.
12105  */
12106  for(i=0; i<=nactivelin-1; i++)
12107  {
12108  if( i!=kmax )
12109  {
12110  v = 0;
12111  for(j=0; j<=n-1; j++)
12112  {
12113  v = v+state->sbasis.ptr.pp_double[t][j]*state->tmpbasis.ptr.pp_double[i][j]*ae_sqr(state->s.ptr.p_double[j], _state);
12114  }
12115  ae_v_subd(&state->tmpbasis.ptr.pp_double[i][0], 1, &state->sbasis.ptr.pp_double[t][0], 1, ae_v_len(0,n), v);
12116  }
12117  }
12118  for(j=0; j<=n; j++)
12119  {
12120  state->tmpbasis.ptr.pp_double[kmax][j] = 0;
12121  }
12122  }
12123 }
12124 
12125 
12126 /*************************************************************************
12127 This subroutine calculates preconditioned descent direction subject to
12128 current active set.
12129 
12130 INPUT PARAMETERS:
12131  State - active set object
12132  G - array[N], gradient
12133  H - array[N], Hessian matrix
12134  HA - active constraints orthogonalized in such way
12135  that HA*inv(H)*HA'= I.
12136  Normalize- whether we need normalized descent or not
12137  D - possibly preallocated buffer; automatically resized.
12138 
12139 OUTPUT PARAMETERS:
12140  D - descent direction projected onto current active set.
12141  Components of D which correspond to active boundary
12142  constraints are forced to be exactly zero.
12143  In case D is non-zero and Normalize is True, it is
12144  normalized to have unit norm.
12145 
12146  -- ALGLIB --
12147  Copyright 21.12.2012 by Bochkanov Sergey
12148 *************************************************************************/
12149 static void sactivesets_constraineddescent(sactiveset* state,
12150  /* Real */ ae_vector* g,
12151  /* Real */ ae_vector* h,
12152  /* Real */ ae_matrix* ha,
12153  ae_bool normalize,
12154  /* Real */ ae_vector* d,
12155  ae_state *_state)
12156 {
12157  ae_int_t i;
12158  ae_int_t j;
12159  ae_int_t n;
12160  double v;
12161  ae_int_t nactive;
12162 
12163 
12164  ae_assert(state->algostate==1, "SAS: internal error in ConstrainedDescent() - not in optimization mode", _state);
12165  ae_assert(state->basisisready, "SAS: internal error in ConstrainedDescent() - no basis", _state);
12166  n = state->n;
12167  rvectorsetlengthatleast(d, n, _state);
12168 
12169  /*
12170  * Calculate preconditioned constrained descent direction:
12171  *
12172  * d := -inv(H)*( g - HA'*(HA*inv(H)*g) )
12173  *
12174  * Formula above always gives direction which is orthogonal to rows of HA.
12175  * You can verify it by multiplication of both sides by HA[i] (I-th row),
12176  * taking into account that HA*inv(H)*HA'= I (by definition of HA - it is
12177  * orthogonal basis with inner product given by inv(H)).
12178  */
12179  nactive = 0;
12180  for(i=0; i<=n-1; i++)
12181  {
12182  if( state->activeset.ptr.p_int[i]>0 )
12183  {
12184  d->ptr.p_double[i] = 0;
12185  nactive = nactive+1;
12186  }
12187  else
12188  {
12189  d->ptr.p_double[i] = g->ptr.p_double[i];
12190  }
12191  }
12192  for(i=0; i<=state->basissize-1; i++)
12193  {
12194  v = 0.0;
12195  for(j=0; j<=n-1; j++)
12196  {
12197  v = v+ha->ptr.pp_double[i][j]*d->ptr.p_double[j]/h->ptr.p_double[j];
12198  }
12199  ae_v_subd(&d->ptr.p_double[0], 1, &ha->ptr.pp_double[i][0], 1, ae_v_len(0,n-1), v);
12200  nactive = nactive+1;
12201  }
12202  v = 0.0;
12203  for(i=0; i<=n-1; i++)
12204  {
12205  if( state->activeset.ptr.p_int[i]>0 )
12206  {
12207  d->ptr.p_double[i] = 0;
12208  }
12209  else
12210  {
12211  d->ptr.p_double[i] = -d->ptr.p_double[i]/h->ptr.p_double[i];
12212  v = v+ae_sqr(d->ptr.p_double[i], _state);
12213  }
12214  }
12215  v = ae_sqrt(v, _state);
12216  if( nactive>=n )
12217  {
12218  v = 0;
12219  for(i=0; i<=n-1; i++)
12220  {
12221  d->ptr.p_double[i] = 0;
12222  }
12223  }
12224  if( normalize&&ae_fp_greater(v,0) )
12225  {
12226  for(i=0; i<=n-1; i++)
12227  {
12228  d->ptr.p_double[i] = d->ptr.p_double[i]/v;
12229  }
12230  }
12231 }
12232 
12233 
12234 /*************************************************************************
12235 This function recalculates constraints - activates and deactivates them
12236 according to gradient value at current point.
12237 
12238 Algorithm assumes that we want to make Quasi-Newton step from current
12239 point with diagonal Quasi-Newton matrix H. Constraints are activated and
12240 deactivated in such way that we won't violate any constraint by step.
12241 
12242 Only already "active" and "candidate" elements of ActiveSet are examined;
12243 constraints which are not active are not examined.
12244 
12245 INPUT PARAMETERS:
12246  State - active set object
12247  GC - array[N], gradient at XC
12248  H - array[N], Hessian matrix
12249 
12250 OUTPUT PARAMETERS:
12251  State - active set object, with new set of constraint
12252 
12253  -- ALGLIB --
12254  Copyright 26.09.2012 by Bochkanov Sergey
12255 *************************************************************************/
12256 static void sactivesets_reactivateconstraints(sactiveset* state,
12257  /* Real */ ae_vector* gc,
12258  /* Real */ ae_vector* h,
12259  ae_state *_state)
12260 {
12261  ae_int_t n;
12262  ae_int_t nec;
12263  ae_int_t nic;
12264  ae_int_t i;
12265  ae_int_t j;
12266  ae_int_t idx0;
12267  ae_int_t idx1;
12268  double v;
12269  ae_int_t nactivebnd;
12270  ae_int_t nactivelin;
12271  ae_int_t nactiveconstraints;
12272  double rowscale;
12273 
12274 
12275  ae_assert(state->algostate==1, "SASReactivateConstraintsPrec: must be in optimization mode", _state);
12276 
12277  /*
12278  * Prepare
12279  */
12280  n = state->n;
12281  nec = state->nec;
12282  nic = state->nic;
12283  state->basisisready = ae_false;
12284 
12285  /*
12286  * Handle important special case - no linear constraints,
12287  * only boundary constraints are present
12288  */
12289  if( nec+nic==0 )
12290  {
12291  for(i=0; i<=n-1; i++)
12292  {
12293  if( (state->hasbndl.ptr.p_bool[i]&&state->hasbndu.ptr.p_bool[i])&&ae_fp_eq(state->bndl.ptr.p_double[i],state->bndu.ptr.p_double[i]) )
12294  {
12295  state->activeset.ptr.p_int[i] = 1;
12296  continue;
12297  }
12298  if( (state->hasbndl.ptr.p_bool[i]&&ae_fp_eq(state->xc.ptr.p_double[i],state->bndl.ptr.p_double[i]))&&ae_fp_greater_eq(gc->ptr.p_double[i],0) )
12299  {
12300  state->activeset.ptr.p_int[i] = 1;
12301  continue;
12302  }
12303  if( (state->hasbndu.ptr.p_bool[i]&&ae_fp_eq(state->xc.ptr.p_double[i],state->bndu.ptr.p_double[i]))&&ae_fp_less_eq(gc->ptr.p_double[i],0) )
12304  {
12305  state->activeset.ptr.p_int[i] = 1;
12306  continue;
12307  }
12308  state->activeset.ptr.p_int[i] = -1;
12309  }
12310  return;
12311  }
12312 
12313  /*
12314  * General case.
12315  * Allocate temporaries.
12316  */
12317  rvectorsetlengthatleast(&state->rctmpg, n, _state);
12318  rvectorsetlengthatleast(&state->rctmprightpart, n, _state);
12319  rvectorsetlengthatleast(&state->rctmps, n, _state);
12320  rmatrixsetlengthatleast(&state->rctmpdense0, n, nec+nic, _state);
12321  rmatrixsetlengthatleast(&state->rctmpdense1, n, nec+nic, _state);
12322  bvectorsetlengthatleast(&state->rctmpisequality, n+nec+nic, _state);
12323  ivectorsetlengthatleast(&state->rctmpconstraintidx, n+nec+nic, _state);
12324 
12325  /*
12326  * Calculate descent direction
12327  */
12328  ae_v_moveneg(&state->rctmpg.ptr.p_double[0], 1, &gc->ptr.p_double[0], 1, ae_v_len(0,n-1));
12329 
12330  /*
12331  * Determine candidates to the active set.
12332  *
12333  * After this block constraints become either "inactive" (ActiveSet[i]<0)
12334  * or "candidates" (ActiveSet[i]=0). Previously active constraints always
12335  * become "candidates".
12336  */
12337  for(i=0; i<=n+nec+nic-1; i++)
12338  {
12339  if( state->activeset.ptr.p_int[i]>0 )
12340  {
12341  state->activeset.ptr.p_int[i] = 0;
12342  }
12343  else
12344  {
12345  state->activeset.ptr.p_int[i] = -1;
12346  }
12347  }
12348  nactiveconstraints = 0;
12349  nactivebnd = 0;
12350  nactivelin = 0;
12351  for(i=0; i<=n-1; i++)
12352  {
12353 
12354  /*
12355  * Activate boundary constraints:
12356  * * copy constraint index to RCTmpConstraintIdx
12357  * * set corresponding element of ActiveSet[] to "candidate"
12358  * * fill RCTmpS by either +1 (lower bound) or -1 (upper bound)
12359  * * set RCTmpIsEquality to False (BndL<BndU) or True (BndL=BndU)
12360  * * increase counters
12361  */
12362  if( (state->hasbndl.ptr.p_bool[i]&&state->hasbndu.ptr.p_bool[i])&&ae_fp_eq(state->bndl.ptr.p_double[i],state->bndu.ptr.p_double[i]) )
12363  {
12364 
12365  /*
12366  * Equality constraint is activated
12367  */
12368  state->rctmpconstraintidx.ptr.p_int[nactiveconstraints] = i;
12369  state->activeset.ptr.p_int[i] = 0;
12370  state->rctmps.ptr.p_double[i] = 1.0;
12371  state->rctmpisequality.ptr.p_bool[nactiveconstraints] = ae_true;
12372  nactiveconstraints = nactiveconstraints+1;
12373  nactivebnd = nactivebnd+1;
12374  continue;
12375  }
12376  if( state->hasbndl.ptr.p_bool[i]&&ae_fp_eq(state->xc.ptr.p_double[i],state->bndl.ptr.p_double[i]) )
12377  {
12378 
12379  /*
12380  * Lower bound is activated
12381  */
12382  state->rctmpconstraintidx.ptr.p_int[nactiveconstraints] = i;
12383  state->activeset.ptr.p_int[i] = 0;
12384  state->rctmps.ptr.p_double[i] = -1.0;
12385  state->rctmpisequality.ptr.p_bool[nactiveconstraints] = ae_false;
12386  nactiveconstraints = nactiveconstraints+1;
12387  nactivebnd = nactivebnd+1;
12388  continue;
12389  }
12390  if( state->hasbndu.ptr.p_bool[i]&&ae_fp_eq(state->xc.ptr.p_double[i],state->bndu.ptr.p_double[i]) )
12391  {
12392 
12393  /*
12394  * Upper bound is activated
12395  */
12396  state->rctmpconstraintidx.ptr.p_int[nactiveconstraints] = i;
12397  state->activeset.ptr.p_int[i] = 0;
12398  state->rctmps.ptr.p_double[i] = 1.0;
12399  state->rctmpisequality.ptr.p_bool[nactiveconstraints] = ae_false;
12400  nactiveconstraints = nactiveconstraints+1;
12401  nactivebnd = nactivebnd+1;
12402  continue;
12403  }
12404  }
12405  for(i=0; i<=nec+nic-1; i++)
12406  {
12407  if( i>=nec )
12408  {
12409 
12410  /*
12411  * Inequality constraints are skipped if we too far away from
12412  * the boundary.
12413  */
12414  rowscale = 0.0;
12415  v = -state->cleic.ptr.pp_double[i][n];
12416  for(j=0; j<=n-1; j++)
12417  {
12418  v = v+state->cleic.ptr.pp_double[i][j]*state->xc.ptr.p_double[j];
12419  rowscale = ae_maxreal(rowscale, ae_fabs(state->cleic.ptr.pp_double[i][j]*state->s.ptr.p_double[j], _state), _state);
12420  }
12421  if( ae_fp_less_eq(v,-1.0E5*ae_machineepsilon*rowscale) )
12422  {
12423 
12424  /*
12425  * NOTE: it is important to check for non-strict inequality
12426  * because we have to correctly handle zero constraint
12427  * 0*x<=0
12428  */
12429  continue;
12430  }
12431  }
12432  ae_v_move(&state->rctmpdense0.ptr.pp_double[0][nactivelin], state->rctmpdense0.stride, &state->cleic.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
12433  state->rctmpconstraintidx.ptr.p_int[nactiveconstraints] = n+i;
12434  state->activeset.ptr.p_int[n+i] = 0;
12435  state->rctmpisequality.ptr.p_bool[nactiveconstraints] = i<nec;
12436  nactiveconstraints = nactiveconstraints+1;
12437  nactivelin = nactivelin+1;
12438  }
12439 
12440  /*
12441  * Skip if no "candidate" constraints was found
12442  */
12443  if( nactiveconstraints==0 )
12444  {
12445  for(i=0; i<=n-1; i++)
12446  {
12447  if( (state->hasbndl.ptr.p_bool[i]&&state->hasbndu.ptr.p_bool[i])&&ae_fp_eq(state->bndl.ptr.p_double[i],state->bndu.ptr.p_double[i]) )
12448  {
12449  state->activeset.ptr.p_int[i] = 1;
12450  continue;
12451  }
12452  if( (state->hasbndl.ptr.p_bool[i]&&ae_fp_eq(state->xc.ptr.p_double[i],state->bndl.ptr.p_double[i]))&&ae_fp_greater_eq(gc->ptr.p_double[i],0) )
12453  {
12454  state->activeset.ptr.p_int[i] = 1;
12455  continue;
12456  }
12457  if( (state->hasbndu.ptr.p_bool[i]&&ae_fp_eq(state->xc.ptr.p_double[i],state->bndu.ptr.p_double[i]))&&ae_fp_less_eq(gc->ptr.p_double[i],0) )
12458  {
12459  state->activeset.ptr.p_int[i] = 1;
12460  continue;
12461  }
12462  }
12463  return;
12464  }
12465 
12466  /*
12467  * General case.
12468  *
12469  * APPROACH TO CONSTRAINTS ACTIVATION/DEACTIVATION
12470  *
12471  * We have NActiveConstraints "candidates": NActiveBnd boundary candidates,
12472  * NActiveLin linear candidates. Indexes of boundary constraints are stored
12473  * in RCTmpConstraintIdx[0:NActiveBnd-1], indexes of linear ones are stored
12474  * in RCTmpConstraintIdx[NActiveBnd:NActiveBnd+NActiveLin-1]. Some of the
12475  * constraints are equality ones, some are inequality - as specified by
12476  * RCTmpIsEquality[i].
12477  *
12478  * Now we have to determine active subset of "candidates" set. In order to
12479  * do so we solve following constrained minimization problem:
12480  * ( )^2
12481  * min ( SUM(lambda[i]*A[i]) + G )
12482  * ( )
12483  * Here:
12484  * * G is a gradient (column vector)
12485  * * A[i] is a column vector, linear (left) part of I-th constraint.
12486  * I=0..NActiveConstraints-1, first NActiveBnd elements of A are just
12487  * subset of identity matrix (boundary constraints), next NActiveLin
12488  * elements are subset of rows of the matrix of general linear constraints.
12489  * * lambda[i] is a Lagrange multiplier corresponding to I-th constraint
12490  *
12491  * NOTE: for preconditioned setting A is replaced by A*H^(-0.5), G is
12492  * replaced by G*H^(-0.5). We apply this scaling at the last stage,
12493  * before passing data to NNLS solver.
12494  *
12495  * Minimization is performed subject to non-negativity constraints on
12496  * lambda[i] corresponding to inequality constraints. Inequality constraints
12497  * which correspond to non-zero lambda are activated, equality constraints
12498  * are always considered active.
12499  *
12500  * Informally speaking, we "decompose" descent direction -G and represent
12501  * it as sum of constraint vectors and "residual" part (which is equal to
12502  * the actual descent direction subject to constraints).
12503  *
12504  * SOLUTION OF THE NNLS PROBLEM
12505  *
12506  * We solve this optimization problem with Non-Negative Least Squares solver,
12507  * which can efficiently solve least squares problems of the form
12508  *
12509  * ( [ I | AU ] )^2
12510  * min ( [ | ]*x-b ) s.t. non-negativity constraints on some x[i]
12511  * ( [ 0 | AL ] )
12512  *
12513  * In order to use this solver we have to rearrange rows of A[] and G in
12514  * such way that first NActiveBnd columns of A store identity matrix (before
12515  * sorting non-zero elements are randomly distributed in the first NActiveBnd
12516  * columns of A, during sorting we move them to first NActiveBnd rows).
12517  *
12518  * Then we create instance of NNLS solver (we reuse instance left from the
12519  * previous run of the optimization problem) and solve NNLS problem.
12520  */
12521  idx0 = 0;
12522  idx1 = nactivebnd;
12523  for(i=0; i<=n-1; i++)
12524  {
12525  if( state->activeset.ptr.p_int[i]>=0 )
12526  {
12527  v = 1/ae_sqrt(h->ptr.p_double[i], _state);
12528  for(j=0; j<=nactivelin-1; j++)
12529  {
12530  state->rctmpdense1.ptr.pp_double[idx0][j] = state->rctmpdense0.ptr.pp_double[i][j]/state->rctmps.ptr.p_double[i]*v;
12531  }
12532  state->rctmprightpart.ptr.p_double[idx0] = state->rctmpg.ptr.p_double[i]/state->rctmps.ptr.p_double[i]*v;
12533  idx0 = idx0+1;
12534  }
12535  else
12536  {
12537  v = 1/ae_sqrt(h->ptr.p_double[i], _state);
12538  for(j=0; j<=nactivelin-1; j++)
12539  {
12540  state->rctmpdense1.ptr.pp_double[idx1][j] = state->rctmpdense0.ptr.pp_double[i][j]*v;
12541  }
12542  state->rctmprightpart.ptr.p_double[idx1] = state->rctmpg.ptr.p_double[i]*v;
12543  idx1 = idx1+1;
12544  }
12545  }
12546  snnlsinit(n, nec+nic, n, &state->solver, _state);
12547  snnlssetproblem(&state->solver, &state->rctmpdense1, &state->rctmprightpart, nactivebnd, nactiveconstraints-nactivebnd, n, _state);
12548  for(i=0; i<=nactiveconstraints-1; i++)
12549  {
12550  if( state->rctmpisequality.ptr.p_bool[i] )
12551  {
12552  snnlsdropnnc(&state->solver, i, _state);
12553  }
12554  }
12555  snnlssolve(&state->solver, &state->rctmplambdas, _state);
12556 
12557  /*
12558  * After solution of the problem we activate equality constraints (always active)
12559  * and inequality constraints with non-zero Lagrange multipliers. Then we reorthogonalize
12560  * active constraints.
12561  */
12562  for(i=0; i<=nactiveconstraints-1; i++)
12563  {
12564  if( state->rctmpisequality.ptr.p_bool[i]||ae_fp_greater(state->rctmplambdas.ptr.p_double[i],0) )
12565  {
12566  state->activeset.ptr.p_int[state->rctmpconstraintidx.ptr.p_int[i]] = 1;
12567  }
12568  else
12569  {
12570  state->activeset.ptr.p_int[state->rctmpconstraintidx.ptr.p_int[i]] = 0;
12571  }
12572  }
12573  sasrebuildbasis(state, _state);
12574 }
12575 
12576 
12577 ae_bool _sactiveset_init(void* _p, ae_state *_state, ae_bool make_automatic)
12578 {
12579  sactiveset *p = (sactiveset*)_p;
12580  ae_touch_ptr((void*)p);
12581  if( !ae_vector_init(&p->xc, 0, DT_REAL, _state, make_automatic) )
12582  return ae_false;
12583  if( !ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic) )
12584  return ae_false;
12585  if( !ae_vector_init(&p->h, 0, DT_REAL, _state, make_automatic) )
12586  return ae_false;
12587  if( !ae_vector_init(&p->activeset, 0, DT_INT, _state, make_automatic) )
12588  return ae_false;
12589  if( !ae_matrix_init(&p->sbasis, 0, 0, DT_REAL, _state, make_automatic) )
12590  return ae_false;
12591  if( !ae_matrix_init(&p->pbasis, 0, 0, DT_REAL, _state, make_automatic) )
12592  return ae_false;
12593  if( !ae_matrix_init(&p->ibasis, 0, 0, DT_REAL, _state, make_automatic) )
12594  return ae_false;
12595  if( !ae_vector_init(&p->hasbndl, 0, DT_BOOL, _state, make_automatic) )
12596  return ae_false;
12597  if( !ae_vector_init(&p->hasbndu, 0, DT_BOOL, _state, make_automatic) )
12598  return ae_false;
12599  if( !ae_vector_init(&p->bndl, 0, DT_REAL, _state, make_automatic) )
12600  return ae_false;
12601  if( !ae_vector_init(&p->bndu, 0, DT_REAL, _state, make_automatic) )
12602  return ae_false;
12603  if( !ae_matrix_init(&p->cleic, 0, 0, DT_REAL, _state, make_automatic) )
12604  return ae_false;
12605  if( !ae_vector_init(&p->mtx, 0, DT_REAL, _state, make_automatic) )
12606  return ae_false;
12607  if( !ae_vector_init(&p->mtas, 0, DT_INT, _state, make_automatic) )
12608  return ae_false;
12609  if( !ae_vector_init(&p->cdtmp, 0, DT_REAL, _state, make_automatic) )
12610  return ae_false;
12611  if( !ae_vector_init(&p->corrtmp, 0, DT_REAL, _state, make_automatic) )
12612  return ae_false;
12613  if( !ae_vector_init(&p->unitdiagonal, 0, DT_REAL, _state, make_automatic) )
12614  return ae_false;
12615  if( !_snnlssolver_init(&p->solver, _state, make_automatic) )
12616  return ae_false;
12617  if( !ae_vector_init(&p->scntmp, 0, DT_REAL, _state, make_automatic) )
12618  return ae_false;
12619  if( !ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic) )
12620  return ae_false;
12621  if( !ae_vector_init(&p->tmpfeas, 0, DT_REAL, _state, make_automatic) )
12622  return ae_false;
12623  if( !ae_matrix_init(&p->tmpm0, 0, 0, DT_REAL, _state, make_automatic) )
12624  return ae_false;
12625  if( !ae_vector_init(&p->rctmps, 0, DT_REAL, _state, make_automatic) )
12626  return ae_false;
12627  if( !ae_vector_init(&p->rctmpg, 0, DT_REAL, _state, make_automatic) )
12628  return ae_false;
12629  if( !ae_vector_init(&p->rctmprightpart, 0, DT_REAL, _state, make_automatic) )
12630  return ae_false;
12631  if( !ae_matrix_init(&p->rctmpdense0, 0, 0, DT_REAL, _state, make_automatic) )
12632  return ae_false;
12633  if( !ae_matrix_init(&p->rctmpdense1, 0, 0, DT_REAL, _state, make_automatic) )
12634  return ae_false;
12635  if( !ae_vector_init(&p->rctmpisequality, 0, DT_BOOL, _state, make_automatic) )
12636  return ae_false;
12637  if( !ae_vector_init(&p->rctmpconstraintidx, 0, DT_INT, _state, make_automatic) )
12638  return ae_false;
12639  if( !ae_vector_init(&p->rctmplambdas, 0, DT_REAL, _state, make_automatic) )
12640  return ae_false;
12641  if( !ae_matrix_init(&p->tmpbasis, 0, 0, DT_REAL, _state, make_automatic) )
12642  return ae_false;
12643  return ae_true;
12644 }
12645 
12646 
12647 ae_bool _sactiveset_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
12648 {
12649  sactiveset *dst = (sactiveset*)_dst;
12650  sactiveset *src = (sactiveset*)_src;
12651  dst->n = src->n;
12652  dst->algostate = src->algostate;
12653  if( !ae_vector_init_copy(&dst->xc, &src->xc, _state, make_automatic) )
12654  return ae_false;
12655  dst->hasxc = src->hasxc;
12656  if( !ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic) )
12657  return ae_false;
12658  if( !ae_vector_init_copy(&dst->h, &src->h, _state, make_automatic) )
12659  return ae_false;
12660  if( !ae_vector_init_copy(&dst->activeset, &src->activeset, _state, make_automatic) )
12661  return ae_false;
12662  dst->basisisready = src->basisisready;
12663  if( !ae_matrix_init_copy(&dst->sbasis, &src->sbasis, _state, make_automatic) )
12664  return ae_false;
12665  if( !ae_matrix_init_copy(&dst->pbasis, &src->pbasis, _state, make_automatic) )
12666  return ae_false;
12667  if( !ae_matrix_init_copy(&dst->ibasis, &src->ibasis, _state, make_automatic) )
12668  return ae_false;
12669  dst->basissize = src->basissize;
12670  dst->constraintschanged = src->constraintschanged;
12671  if( !ae_vector_init_copy(&dst->hasbndl, &src->hasbndl, _state, make_automatic) )
12672  return ae_false;
12673  if( !ae_vector_init_copy(&dst->hasbndu, &src->hasbndu, _state, make_automatic) )
12674  return ae_false;
12675  if( !ae_vector_init_copy(&dst->bndl, &src->bndl, _state, make_automatic) )
12676  return ae_false;
12677  if( !ae_vector_init_copy(&dst->bndu, &src->bndu, _state, make_automatic) )
12678  return ae_false;
12679  if( !ae_matrix_init_copy(&dst->cleic, &src->cleic, _state, make_automatic) )
12680  return ae_false;
12681  dst->nec = src->nec;
12682  dst->nic = src->nic;
12683  if( !ae_vector_init_copy(&dst->mtx, &src->mtx, _state, make_automatic) )
12684  return ae_false;
12685  if( !ae_vector_init_copy(&dst->mtas, &src->mtas, _state, make_automatic) )
12686  return ae_false;
12687  if( !ae_vector_init_copy(&dst->cdtmp, &src->cdtmp, _state, make_automatic) )
12688  return ae_false;
12689  if( !ae_vector_init_copy(&dst->corrtmp, &src->corrtmp, _state, make_automatic) )
12690  return ae_false;
12691  if( !ae_vector_init_copy(&dst->unitdiagonal, &src->unitdiagonal, _state, make_automatic) )
12692  return ae_false;
12693  if( !_snnlssolver_init_copy(&dst->solver, &src->solver, _state, make_automatic) )
12694  return ae_false;
12695  if( !ae_vector_init_copy(&dst->scntmp, &src->scntmp, _state, make_automatic) )
12696  return ae_false;
12697  if( !ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic) )
12698  return ae_false;
12699  if( !ae_vector_init_copy(&dst->tmpfeas, &src->tmpfeas, _state, make_automatic) )
12700  return ae_false;
12701  if( !ae_matrix_init_copy(&dst->tmpm0, &src->tmpm0, _state, make_automatic) )
12702  return ae_false;
12703  if( !ae_vector_init_copy(&dst->rctmps, &src->rctmps, _state, make_automatic) )
12704  return ae_false;
12705  if( !ae_vector_init_copy(&dst->rctmpg, &src->rctmpg, _state, make_automatic) )
12706  return ae_false;
12707  if( !ae_vector_init_copy(&dst->rctmprightpart, &src->rctmprightpart, _state, make_automatic) )
12708  return ae_false;
12709  if( !ae_matrix_init_copy(&dst->rctmpdense0, &src->rctmpdense0, _state, make_automatic) )
12710  return ae_false;
12711  if( !ae_matrix_init_copy(&dst->rctmpdense1, &src->rctmpdense1, _state, make_automatic) )
12712  return ae_false;
12713  if( !ae_vector_init_copy(&dst->rctmpisequality, &src->rctmpisequality, _state, make_automatic) )
12714  return ae_false;
12715  if( !ae_vector_init_copy(&dst->rctmpconstraintidx, &src->rctmpconstraintidx, _state, make_automatic) )
12716  return ae_false;
12717  if( !ae_vector_init_copy(&dst->rctmplambdas, &src->rctmplambdas, _state, make_automatic) )
12718  return ae_false;
12719  if( !ae_matrix_init_copy(&dst->tmpbasis, &src->tmpbasis, _state, make_automatic) )
12720  return ae_false;
12721  return ae_true;
12722 }
12723 
12724 
12725 void _sactiveset_clear(void* _p)
12726 {
12727  sactiveset *p = (sactiveset*)_p;
12728  ae_touch_ptr((void*)p);
12729  ae_vector_clear(&p->xc);
12730  ae_vector_clear(&p->s);
12731  ae_vector_clear(&p->h);
12732  ae_vector_clear(&p->activeset);
12733  ae_matrix_clear(&p->sbasis);
12734  ae_matrix_clear(&p->pbasis);
12735  ae_matrix_clear(&p->ibasis);
12736  ae_vector_clear(&p->hasbndl);
12737  ae_vector_clear(&p->hasbndu);
12738  ae_vector_clear(&p->bndl);
12739  ae_vector_clear(&p->bndu);
12740  ae_matrix_clear(&p->cleic);
12741  ae_vector_clear(&p->mtx);
12742  ae_vector_clear(&p->mtas);
12743  ae_vector_clear(&p->cdtmp);
12744  ae_vector_clear(&p->corrtmp);
12745  ae_vector_clear(&p->unitdiagonal);
12746  _snnlssolver_clear(&p->solver);
12747  ae_vector_clear(&p->scntmp);
12748  ae_vector_clear(&p->tmp0);
12749  ae_vector_clear(&p->tmpfeas);
12750  ae_matrix_clear(&p->tmpm0);
12751  ae_vector_clear(&p->rctmps);
12752  ae_vector_clear(&p->rctmpg);
12753  ae_vector_clear(&p->rctmprightpart);
12754  ae_matrix_clear(&p->rctmpdense0);
12755  ae_matrix_clear(&p->rctmpdense1);
12756  ae_vector_clear(&p->rctmpisequality);
12757  ae_vector_clear(&p->rctmpconstraintidx);
12758  ae_vector_clear(&p->rctmplambdas);
12759  ae_matrix_clear(&p->tmpbasis);
12760 }
12761 
12762 
12763 void _sactiveset_destroy(void* _p)
12764 {
12765  sactiveset *p = (sactiveset*)_p;
12766  ae_touch_ptr((void*)p);
12767  ae_vector_destroy(&p->xc);
12768  ae_vector_destroy(&p->s);
12769  ae_vector_destroy(&p->h);
12770  ae_vector_destroy(&p->activeset);
12771  ae_matrix_destroy(&p->sbasis);
12772  ae_matrix_destroy(&p->pbasis);
12773  ae_matrix_destroy(&p->ibasis);
12774  ae_vector_destroy(&p->hasbndl);
12775  ae_vector_destroy(&p->hasbndu);
12776  ae_vector_destroy(&p->bndl);
12777  ae_vector_destroy(&p->bndu);
12778  ae_matrix_destroy(&p->cleic);
12779  ae_vector_destroy(&p->mtx);
12780  ae_vector_destroy(&p->mtas);
12781  ae_vector_destroy(&p->cdtmp);
12782  ae_vector_destroy(&p->corrtmp);
12783  ae_vector_destroy(&p->unitdiagonal);
12784  _snnlssolver_destroy(&p->solver);
12785  ae_vector_destroy(&p->scntmp);
12786  ae_vector_destroy(&p->tmp0);
12787  ae_vector_destroy(&p->tmpfeas);
12788  ae_matrix_destroy(&p->tmpm0);
12789  ae_vector_destroy(&p->rctmps);
12790  ae_vector_destroy(&p->rctmpg);
12791  ae_vector_destroy(&p->rctmprightpart);
12792  ae_matrix_destroy(&p->rctmpdense0);
12793  ae_matrix_destroy(&p->rctmpdense1);
12794  ae_vector_destroy(&p->rctmpisequality);
12795  ae_vector_destroy(&p->rctmpconstraintidx);
12796  ae_vector_destroy(&p->rctmplambdas);
12797  ae_matrix_destroy(&p->tmpbasis);
12798 }
12799 
12800 
12801 
12802 
12803 /*************************************************************************
12804  NONLINEAR CONJUGATE GRADIENT METHOD
12805 
12806 DESCRIPTION:
12807 The subroutine minimizes function F(x) of N arguments by using one of the
12808 nonlinear conjugate gradient methods.
12809 
12810 These CG methods are globally convergent (even on non-convex functions) as
12811 long as grad(f) is Lipschitz continuous in a some neighborhood of the
12812 L = { x : f(x)<=f(x0) }.
12813 
12814 
12815 REQUIREMENTS:
12816 Algorithm will request following information during its operation:
12817 * function value F and its gradient G (simultaneously) at given point X
12818 
12819 
12820 USAGE:
12821 1. User initializes algorithm state with MinCGCreate() call
12822 2. User tunes solver parameters with MinCGSetCond(), MinCGSetStpMax() and
12823  other functions
12824 3. User calls MinCGOptimize() function which takes algorithm state and
12825  pointer (delegate, etc.) to callback function which calculates F/G.
12826 4. User calls MinCGResults() to get solution
12827 5. Optionally, user may call MinCGRestartFrom() to solve another problem
12828  with same N but another starting point and/or another function.
12829  MinCGRestartFrom() allows to reuse already initialized structure.
12830 
12831 
12832 INPUT PARAMETERS:
12833  N - problem dimension, N>0:
12834  * if given, only leading N elements of X are used
12835  * if not given, automatically determined from size of X
12836  X - starting point, array[0..N-1].
12837 
12838 OUTPUT PARAMETERS:
12839  State - structure which stores algorithm state
12840 
12841  -- ALGLIB --
12842  Copyright 25.03.2010 by Bochkanov Sergey
12843 *************************************************************************/
12844 void mincgcreate(ae_int_t n,
12845  /* Real */ ae_vector* x,
12846  mincgstate* state,
12847  ae_state *_state)
12848 {
12849 
12850  _mincgstate_clear(state);
12851 
12852  ae_assert(n>=1, "MinCGCreate: N too small!", _state);
12853  ae_assert(x->cnt>=n, "MinCGCreate: Length(X)<N!", _state);
12854  ae_assert(isfinitevector(x, n, _state), "MinCGCreate: X contains infinite or NaN values!", _state);
12855  mincg_mincginitinternal(n, 0.0, state, _state);
12856  mincgrestartfrom(state, x, _state);
12857 }
12858 
12859 
12860 /*************************************************************************
12861 The subroutine is finite difference variant of MinCGCreate(). It uses
12862 finite differences in order to differentiate target function.
12863 
12864 Description below contains information which is specific to this function
12865 only. We recommend to read comments on MinCGCreate() in order to get more
12866 information about creation of CG optimizer.
12867 
12868 INPUT PARAMETERS:
12869  N - problem dimension, N>0:
12870  * if given, only leading N elements of X are used
12871  * if not given, automatically determined from size of X
12872  X - starting point, array[0..N-1].
12873  DiffStep- differentiation step, >0
12874 
12875 OUTPUT PARAMETERS:
12876  State - structure which stores algorithm state
12877 
12878 NOTES:
12879 1. algorithm uses 4-point central formula for differentiation.
12880 2. differentiation step along I-th axis is equal to DiffStep*S[I] where
12881  S[] is scaling vector which can be set by MinCGSetScale() call.
12882 3. we recommend you to use moderate values of differentiation step. Too
12883  large step will result in too large truncation errors, while too small
12884  step will result in too large numerical errors. 1.0E-6 can be good
12885  value to start with.
12886 4. Numerical differentiation is very inefficient - one gradient
12887  calculation needs 4*N function evaluations. This function will work for
12888  any N - either small (1...10), moderate (10...100) or large (100...).
12889  However, performance penalty will be too severe for any N's except for
12890  small ones.
12891  We should also say that code which relies on numerical differentiation
12892  is less robust and precise. L-BFGS needs exact gradient values.
12893  Imprecise gradient may slow down convergence, especially on highly
12894  nonlinear problems.
12895  Thus we recommend to use this function for fast prototyping on small-
12896  dimensional problems only, and to implement analytical gradient as soon
12897  as possible.
12898 
12899  -- ALGLIB --
12900  Copyright 16.05.2011 by Bochkanov Sergey
12901 *************************************************************************/
12902 void mincgcreatef(ae_int_t n,
12903  /* Real */ ae_vector* x,
12904  double diffstep,
12905  mincgstate* state,
12906  ae_state *_state)
12907 {
12908 
12909  _mincgstate_clear(state);
12910 
12911  ae_assert(n>=1, "MinCGCreateF: N too small!", _state);
12912  ae_assert(x->cnt>=n, "MinCGCreateF: Length(X)<N!", _state);
12913  ae_assert(isfinitevector(x, n, _state), "MinCGCreateF: X contains infinite or NaN values!", _state);
12914  ae_assert(ae_isfinite(diffstep, _state), "MinCGCreateF: DiffStep is infinite or NaN!", _state);
12915  ae_assert(ae_fp_greater(diffstep,0), "MinCGCreateF: DiffStep is non-positive!", _state);
12916  mincg_mincginitinternal(n, diffstep, state, _state);
12917  mincgrestartfrom(state, x, _state);
12918 }
12919 
12920 
12921 /*************************************************************************
12922 This function sets stopping conditions for CG optimization algorithm.
12923 
12924 INPUT PARAMETERS:
12925  State - structure which stores algorithm state
12926  EpsG - >=0
12927  The subroutine finishes its work if the condition
12928  |v|<EpsG is satisfied, where:
12929  * |.| means Euclidian norm
12930  * v - scaled gradient vector, v[i]=g[i]*s[i]
12931  * g - gradient
12932  * s - scaling coefficients set by MinCGSetScale()
12933  EpsF - >=0
12934  The subroutine finishes its work if on k+1-th iteration
12935  the condition |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1}
12936  is satisfied.
12937  EpsX - >=0
12938  The subroutine finishes its work if on k+1-th iteration
12939  the condition |v|<=EpsX is fulfilled, where:
12940  * |.| means Euclidian norm
12941  * v - scaled step vector, v[i]=dx[i]/s[i]
12942  * dx - ste pvector, dx=X(k+1)-X(k)
12943  * s - scaling coefficients set by MinCGSetScale()
12944  MaxIts - maximum number of iterations. If MaxIts=0, the number of
12945  iterations is unlimited.
12946 
12947 Passing EpsG=0, EpsF=0, EpsX=0 and MaxIts=0 (simultaneously) will lead to
12948 automatic stopping criterion selection (small EpsX).
12949 
12950  -- ALGLIB --
12951  Copyright 02.04.2010 by Bochkanov Sergey
12952 *************************************************************************/
12953 void mincgsetcond(mincgstate* state,
12954  double epsg,
12955  double epsf,
12956  double epsx,
12957  ae_int_t maxits,
12958  ae_state *_state)
12959 {
12960 
12961 
12962  ae_assert(ae_isfinite(epsg, _state), "MinCGSetCond: EpsG is not finite number!", _state);
12963  ae_assert(ae_fp_greater_eq(epsg,0), "MinCGSetCond: negative EpsG!", _state);
12964  ae_assert(ae_isfinite(epsf, _state), "MinCGSetCond: EpsF is not finite number!", _state);
12965  ae_assert(ae_fp_greater_eq(epsf,0), "MinCGSetCond: negative EpsF!", _state);
12966  ae_assert(ae_isfinite(epsx, _state), "MinCGSetCond: EpsX is not finite number!", _state);
12967  ae_assert(ae_fp_greater_eq(epsx,0), "MinCGSetCond: negative EpsX!", _state);
12968  ae_assert(maxits>=0, "MinCGSetCond: negative MaxIts!", _state);
12969  if( ((ae_fp_eq(epsg,0)&&ae_fp_eq(epsf,0))&&ae_fp_eq(epsx,0))&&maxits==0 )
12970  {
12971  epsx = 1.0E-6;
12972  }
12973  state->epsg = epsg;
12974  state->epsf = epsf;
12975  state->epsx = epsx;
12976  state->maxits = maxits;
12977 }
12978 
12979 
12980 /*************************************************************************
12981 This function sets scaling coefficients for CG optimizer.
12982 
12983 ALGLIB optimizers use scaling matrices to test stopping conditions (step
12984 size and gradient are scaled before comparison with tolerances). Scale of
12985 the I-th variable is a translation invariant measure of:
12986 a) "how large" the variable is
12987 b) how large the step should be to make significant changes in the function
12988 
12989 Scaling is also used by finite difference variant of CG optimizer - step
12990 along I-th axis is equal to DiffStep*S[I].
12991 
12992 In most optimizers (and in the CG too) scaling is NOT a form of
12993 preconditioning. It just affects stopping conditions. You should set
12994 preconditioner by separate call to one of the MinCGSetPrec...() functions.
12995 
12996 There is special preconditioning mode, however, which uses scaling
12997 coefficients to form diagonal preconditioning matrix. You can turn this
12998 mode on, if you want. But you should understand that scaling is not the
12999 same thing as preconditioning - these are two different, although related
13000 forms of tuning solver.
13001 
13002 INPUT PARAMETERS:
13003  State - structure stores algorithm state
13004  S - array[N], non-zero scaling coefficients
13005  S[i] may be negative, sign doesn't matter.
13006 
13007  -- ALGLIB --
13008  Copyright 14.01.2011 by Bochkanov Sergey
13009 *************************************************************************/
13010 void mincgsetscale(mincgstate* state,
13011  /* Real */ ae_vector* s,
13012  ae_state *_state)
13013 {
13014  ae_int_t i;
13015 
13016 
13017  ae_assert(s->cnt>=state->n, "MinCGSetScale: Length(S)<N", _state);
13018  for(i=0; i<=state->n-1; i++)
13019  {
13020  ae_assert(ae_isfinite(s->ptr.p_double[i], _state), "MinCGSetScale: S contains infinite or NAN elements", _state);
13021  ae_assert(ae_fp_neq(s->ptr.p_double[i],0), "MinCGSetScale: S contains zero elements", _state);
13022  state->s.ptr.p_double[i] = ae_fabs(s->ptr.p_double[i], _state);
13023  }
13024 }
13025 
13026 
13027 /*************************************************************************
13028 This function turns on/off reporting.
13029 
13030 INPUT PARAMETERS:
13031  State - structure which stores algorithm state
13032  NeedXRep- whether iteration reports are needed or not
13033 
13034 If NeedXRep is True, algorithm will call rep() callback function if it is
13035 provided to MinCGOptimize().
13036 
13037  -- ALGLIB --
13038  Copyright 02.04.2010 by Bochkanov Sergey
13039 *************************************************************************/
13040 void mincgsetxrep(mincgstate* state, ae_bool needxrep, ae_state *_state)
13041 {
13042 
13043 
13044  state->xrep = needxrep;
13045 }
13046 
13047 
13048 /*************************************************************************
13049 This function turns on/off line search reports.
13050 These reports are described in more details in developer-only comments on
13051 MinCGState object.
13052 
13053 INPUT PARAMETERS:
13054  State - structure which stores algorithm state
13055  NeedDRep- whether line search reports are needed or not
13056 
13057 This function is intended for private use only. Turning it on artificially
13058 may cause program failure.
13059 
13060  -- ALGLIB --
13061  Copyright 02.04.2010 by Bochkanov Sergey
13062 *************************************************************************/
13063 void mincgsetdrep(mincgstate* state, ae_bool needdrep, ae_state *_state)
13064 {
13065 
13066 
13067  state->drep = needdrep;
13068 }
13069 
13070 
13071 /*************************************************************************
13072 This function sets CG algorithm.
13073 
13074 INPUT PARAMETERS:
13075  State - structure which stores algorithm state
13076  CGType - algorithm type:
13077  * -1 automatic selection of the best algorithm
13078  * 0 DY (Dai and Yuan) algorithm
13079  * 1 Hybrid DY-HS algorithm
13080 
13081  -- ALGLIB --
13082  Copyright 02.04.2010 by Bochkanov Sergey
13083 *************************************************************************/
13084 void mincgsetcgtype(mincgstate* state, ae_int_t cgtype, ae_state *_state)
13085 {
13086 
13087 
13088  ae_assert(cgtype>=-1&&cgtype<=1, "MinCGSetCGType: incorrect CGType!", _state);
13089  if( cgtype==-1 )
13090  {
13091  cgtype = 1;
13092  }
13093  state->cgtype = cgtype;
13094 }
13095 
13096 
13097 /*************************************************************************
13098 This function sets maximum step length
13099 
13100 INPUT PARAMETERS:
13101  State - structure which stores algorithm state
13102  StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't
13103  want to limit step length.
13104 
13105 Use this subroutine when you optimize target function which contains exp()
13106 or other fast growing functions, and optimization algorithm makes too
13107 large steps which leads to overflow. This function allows us to reject
13108 steps that are too large (and therefore expose us to the possible
13109 overflow) without actually calculating function value at the x+stp*d.
13110 
13111  -- ALGLIB --
13112  Copyright 02.04.2010 by Bochkanov Sergey
13113 *************************************************************************/
13114 void mincgsetstpmax(mincgstate* state, double stpmax, ae_state *_state)
13115 {
13116 
13117 
13118  ae_assert(ae_isfinite(stpmax, _state), "MinCGSetStpMax: StpMax is not finite!", _state);
13119  ae_assert(ae_fp_greater_eq(stpmax,0), "MinCGSetStpMax: StpMax<0!", _state);
13120  state->stpmax = stpmax;
13121 }
13122 
13123 
13124 /*************************************************************************
13125 This function allows to suggest initial step length to the CG algorithm.
13126 
13127 Suggested step length is used as starting point for the line search. It
13128 can be useful when you have badly scaled problem, i.e. when ||grad||
13129 (which is used as initial estimate for the first step) is many orders of
13130 magnitude different from the desired step.
13131 
13132 Line search may fail on such problems without good estimate of initial
13133 step length. Imagine, for example, problem with ||grad||=10^50 and desired
13134 step equal to 0.1 Line search function will use 10^50 as initial step,
13135 then it will decrease step length by 2 (up to 20 attempts) and will get
13136 10^44, which is still too large.
13137 
13138 This function allows us to tell than line search should be started from
13139 some moderate step length, like 1.0, so algorithm will be able to detect
13140 desired step length in a several searches.
13141 
13142 Default behavior (when no step is suggested) is to use preconditioner, if
13143 it is available, to generate initial estimate of step length.
13144 
13145 This function influences only first iteration of algorithm. It should be
13146 called between MinCGCreate/MinCGRestartFrom() call and MinCGOptimize call.
13147 Suggested step is ignored if you have preconditioner.
13148 
13149 INPUT PARAMETERS:
13150  State - structure used to store algorithm state.
13151  Stp - initial estimate of the step length.
13152  Can be zero (no estimate).
13153 
13154  -- ALGLIB --
13155  Copyright 30.07.2010 by Bochkanov Sergey
13156 *************************************************************************/
13157 void mincgsuggeststep(mincgstate* state, double stp, ae_state *_state)
13158 {
13159 
13160 
13161  ae_assert(ae_isfinite(stp, _state), "MinCGSuggestStep: Stp is infinite or NAN", _state);
13162  ae_assert(ae_fp_greater_eq(stp,0), "MinCGSuggestStep: Stp<0", _state);
13163  state->suggestedstep = stp;
13164 }
13165 
13166 
13167 /*************************************************************************
13168 Modification of the preconditioner: preconditioning is turned off.
13169 
13170 INPUT PARAMETERS:
13171  State - structure which stores algorithm state
13172 
13173 NOTE: you can change preconditioner "on the fly", during algorithm
13174 iterations.
13175 
13176  -- ALGLIB --
13177  Copyright 13.10.2010 by Bochkanov Sergey
13178 *************************************************************************/
13179 void mincgsetprecdefault(mincgstate* state, ae_state *_state)
13180 {
13181 
13182 
13183  state->prectype = 0;
13184  state->innerresetneeded = ae_true;
13185 }
13186 
13187 
13188 /*************************************************************************
13189 Modification of the preconditioner: diagonal of approximate Hessian is
13190 used.
13191 
13192 INPUT PARAMETERS:
13193  State - structure which stores algorithm state
13194  D - diagonal of the approximate Hessian, array[0..N-1],
13195  (if larger, only leading N elements are used).
13196 
13197 NOTE: you can change preconditioner "on the fly", during algorithm
13198 iterations.
13199 
13200 NOTE 2: D[i] should be positive. Exception will be thrown otherwise.
13201 
13202 NOTE 3: you should pass diagonal of approximate Hessian - NOT ITS INVERSE.
13203 
13204  -- ALGLIB --
13205  Copyright 13.10.2010 by Bochkanov Sergey
13206 *************************************************************************/
13207 void mincgsetprecdiag(mincgstate* state,
13208  /* Real */ ae_vector* d,
13209  ae_state *_state)
13210 {
13211  ae_int_t i;
13212 
13213 
13214  ae_assert(d->cnt>=state->n, "MinCGSetPrecDiag: D is too short", _state);
13215  for(i=0; i<=state->n-1; i++)
13216  {
13217  ae_assert(ae_isfinite(d->ptr.p_double[i], _state), "MinCGSetPrecDiag: D contains infinite or NAN elements", _state);
13218  ae_assert(ae_fp_greater(d->ptr.p_double[i],0), "MinCGSetPrecDiag: D contains non-positive elements", _state);
13219  }
13220  mincgsetprecdiagfast(state, d, _state);
13221 }
13222 
13223 
13224 /*************************************************************************
13225 Modification of the preconditioner: scale-based diagonal preconditioning.
13226 
13227 This preconditioning mode can be useful when you don't have approximate
13228 diagonal of Hessian, but you know that your variables are badly scaled
13229 (for example, one variable is in [1,10], and another in [1000,100000]),
13230 and most part of the ill-conditioning comes from different scales of vars.
13231 
13232 In this case simple scale-based preconditioner, with H[i] = 1/(s[i]^2),
13233 can greatly improve convergence.
13234 
13235 IMPRTANT: you should set scale of your variables with MinCGSetScale() call
13236 (before or after MinCGSetPrecScale() call). Without knowledge of the scale
13237 of your variables scale-based preconditioner will be just unit matrix.
13238 
13239 INPUT PARAMETERS:
13240  State - structure which stores algorithm state
13241 
13242 NOTE: you can change preconditioner "on the fly", during algorithm
13243 iterations.
13244 
13245  -- ALGLIB --
13246  Copyright 13.10.2010 by Bochkanov Sergey
13247 *************************************************************************/
13248 void mincgsetprecscale(mincgstate* state, ae_state *_state)
13249 {
13250 
13251 
13252  state->prectype = 3;
13253  state->innerresetneeded = ae_true;
13254 }
13255 
13256 
13257 /*************************************************************************
13258 NOTES:
13259 
13260 1. This function has two different implementations: one which uses exact
13261  (analytical) user-supplied gradient, and one which uses function value
13262  only and numerically differentiates function in order to obtain
13263  gradient.
13264 
13265  Depending on the specific function used to create optimizer object
13266  (either MinCGCreate() for analytical gradient or MinCGCreateF() for
13267  numerical differentiation) you should choose appropriate variant of
13268  MinCGOptimize() - one which accepts function AND gradient or one which
13269  accepts function ONLY.
13270 
13271  Be careful to choose variant of MinCGOptimize() which corresponds to
13272  your optimization scheme! Table below lists different combinations of
13273  callback (function/gradient) passed to MinCGOptimize() and specific
13274  function used to create optimizer.
13275 
13276 
13277  | USER PASSED TO MinCGOptimize()
13278  CREATED WITH | function only | function and gradient
13279  ------------------------------------------------------------
13280  MinCGCreateF() | work FAIL
13281  MinCGCreate() | FAIL work
13282 
13283  Here "FAIL" denotes inappropriate combinations of optimizer creation
13284  function and MinCGOptimize() version. Attemps to use such combination
13285  (for example, to create optimizer with MinCGCreateF() and to pass
13286  gradient information to MinCGOptimize()) will lead to exception being
13287  thrown. Either you did not pass gradient when it WAS needed or you
13288  passed gradient when it was NOT needed.
13289 
13290  -- ALGLIB --
13291  Copyright 20.04.2009 by Bochkanov Sergey
13292 *************************************************************************/
13293 ae_bool mincgiteration(mincgstate* state, ae_state *_state)
13294 {
13295  ae_int_t n;
13296  ae_int_t i;
13297  double betak;
13298  double v;
13299  double vv;
13300  ae_bool result;
13301 
13302 
13303 
13304  /*
13305  * Reverse communication preparations
13306  * I know it looks ugly, but it works the same way
13307  * anywhere from C++ to Python.
13308  *
13309  * This code initializes locals by:
13310  * * random values determined during code
13311  * generation - on first subroutine call
13312  * * values from previous call - on subsequent calls
13313  */
13314  if( state->rstate.stage>=0 )
13315  {
13316  n = state->rstate.ia.ptr.p_int[0];
13317  i = state->rstate.ia.ptr.p_int[1];
13318  betak = state->rstate.ra.ptr.p_double[0];
13319  v = state->rstate.ra.ptr.p_double[1];
13320  vv = state->rstate.ra.ptr.p_double[2];
13321  }
13322  else
13323  {
13324  n = -983;
13325  i = -989;
13326  betak = -834;
13327  v = 900;
13328  vv = -287;
13329  }
13330  if( state->rstate.stage==0 )
13331  {
13332  goto lbl_0;
13333  }
13334  if( state->rstate.stage==1 )
13335  {
13336  goto lbl_1;
13337  }
13338  if( state->rstate.stage==2 )
13339  {
13340  goto lbl_2;
13341  }
13342  if( state->rstate.stage==3 )
13343  {
13344  goto lbl_3;
13345  }
13346  if( state->rstate.stage==4 )
13347  {
13348  goto lbl_4;
13349  }
13350  if( state->rstate.stage==5 )
13351  {
13352  goto lbl_5;
13353  }
13354  if( state->rstate.stage==6 )
13355  {
13356  goto lbl_6;
13357  }
13358  if( state->rstate.stage==7 )
13359  {
13360  goto lbl_7;
13361  }
13362  if( state->rstate.stage==8 )
13363  {
13364  goto lbl_8;
13365  }
13366  if( state->rstate.stage==9 )
13367  {
13368  goto lbl_9;
13369  }
13370  if( state->rstate.stage==10 )
13371  {
13372  goto lbl_10;
13373  }
13374  if( state->rstate.stage==11 )
13375  {
13376  goto lbl_11;
13377  }
13378  if( state->rstate.stage==12 )
13379  {
13380  goto lbl_12;
13381  }
13382  if( state->rstate.stage==13 )
13383  {
13384  goto lbl_13;
13385  }
13386  if( state->rstate.stage==14 )
13387  {
13388  goto lbl_14;
13389  }
13390  if( state->rstate.stage==15 )
13391  {
13392  goto lbl_15;
13393  }
13394  if( state->rstate.stage==16 )
13395  {
13396  goto lbl_16;
13397  }
13398  if( state->rstate.stage==17 )
13399  {
13400  goto lbl_17;
13401  }
13402  if( state->rstate.stage==18 )
13403  {
13404  goto lbl_18;
13405  }
13406  if( state->rstate.stage==19 )
13407  {
13408  goto lbl_19;
13409  }
13410 
13411  /*
13412  * Routine body
13413  */
13414 
13415  /*
13416  * Prepare
13417  */
13418  n = state->n;
13419  state->repterminationtype = 0;
13420  state->repiterationscount = 0;
13421  state->repvaridx = -1;
13422  state->repnfev = 0;
13423  state->debugrestartscount = 0;
13424 
13425  /*
13426  * Check, that transferred derivative value is right
13427  */
13428  mincg_clearrequestfields(state, _state);
13429  if( !(ae_fp_eq(state->diffstep,0)&&ae_fp_greater(state->teststep,0)) )
13430  {
13431  goto lbl_20;
13432  }
13433  state->needfg = ae_true;
13434  i = 0;
13435 lbl_22:
13436  if( i>n-1 )
13437  {
13438  goto lbl_24;
13439  }
13440  v = state->x.ptr.p_double[i];
13441  state->x.ptr.p_double[i] = v-state->teststep*state->s.ptr.p_double[i];
13442  state->rstate.stage = 0;
13443  goto lbl_rcomm;
13444 lbl_0:
13445  state->fm1 = state->f;
13446  state->fp1 = state->g.ptr.p_double[i];
13447  state->x.ptr.p_double[i] = v+state->teststep*state->s.ptr.p_double[i];
13448  state->rstate.stage = 1;
13449  goto lbl_rcomm;
13450 lbl_1:
13451  state->fm2 = state->f;
13452  state->fp2 = state->g.ptr.p_double[i];
13453  state->x.ptr.p_double[i] = v;
13454  state->rstate.stage = 2;
13455  goto lbl_rcomm;
13456 lbl_2:
13457 
13458  /*
13459  * 2*State.TestStep - scale parameter
13460  * width of segment [Xi-TestStep;Xi+TestStep]
13461  */
13462  if( !derivativecheck(state->fm1, state->fp1, state->fm2, state->fp2, state->f, state->g.ptr.p_double[i], 2*state->teststep, _state) )
13463  {
13464  state->repvaridx = i;
13465  state->repterminationtype = -7;
13466  result = ae_false;
13467  return result;
13468  }
13469  i = i+1;
13470  goto lbl_22;
13471 lbl_24:
13472  state->needfg = ae_false;
13473 lbl_20:
13474 
13475  /*
13476  * Preparations continue:
13477  * * set XK
13478  * * calculate F/G
13479  * * set DK to -G
13480  * * powerup algo (it may change preconditioner)
13481  * * apply preconditioner to DK
13482  * * report update of X
13483  * * check stopping conditions for G
13484  */
13485  ae_v_move(&state->xk.ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,n-1));
13486  state->terminationneeded = ae_false;
13487  mincg_clearrequestfields(state, _state);
13488  if( ae_fp_neq(state->diffstep,0) )
13489  {
13490  goto lbl_25;
13491  }
13492  state->needfg = ae_true;
13493  state->rstate.stage = 3;
13494  goto lbl_rcomm;
13495 lbl_3:
13496  state->needfg = ae_false;
13497  goto lbl_26;
13498 lbl_25:
13499  state->needf = ae_true;
13500  state->rstate.stage = 4;
13501  goto lbl_rcomm;
13502 lbl_4:
13503  state->fbase = state->f;
13504  i = 0;
13505 lbl_27:
13506  if( i>n-1 )
13507  {
13508  goto lbl_29;
13509  }
13510  v = state->x.ptr.p_double[i];
13511  state->x.ptr.p_double[i] = v-state->diffstep*state->s.ptr.p_double[i];
13512  state->rstate.stage = 5;
13513  goto lbl_rcomm;
13514 lbl_5:
13515  state->fm2 = state->f;
13516  state->x.ptr.p_double[i] = v-0.5*state->diffstep*state->s.ptr.p_double[i];
13517  state->rstate.stage = 6;
13518  goto lbl_rcomm;
13519 lbl_6:
13520  state->fm1 = state->f;
13521  state->x.ptr.p_double[i] = v+0.5*state->diffstep*state->s.ptr.p_double[i];
13522  state->rstate.stage = 7;
13523  goto lbl_rcomm;
13524 lbl_7:
13525  state->fp1 = state->f;
13526  state->x.ptr.p_double[i] = v+state->diffstep*state->s.ptr.p_double[i];
13527  state->rstate.stage = 8;
13528  goto lbl_rcomm;
13529 lbl_8:
13530  state->fp2 = state->f;
13531  state->x.ptr.p_double[i] = v;
13532  state->g.ptr.p_double[i] = (8*(state->fp1-state->fm1)-(state->fp2-state->fm2))/(6*state->diffstep*state->s.ptr.p_double[i]);
13533  i = i+1;
13534  goto lbl_27;
13535 lbl_29:
13536  state->f = state->fbase;
13537  state->needf = ae_false;
13538 lbl_26:
13539  if( !state->drep )
13540  {
13541  goto lbl_30;
13542  }
13543 
13544  /*
13545  * Report algorithm powerup (if needed)
13546  */
13547  mincg_clearrequestfields(state, _state);
13548  state->algpowerup = ae_true;
13549  state->rstate.stage = 9;
13550  goto lbl_rcomm;
13551 lbl_9:
13552  state->algpowerup = ae_false;
13553 lbl_30:
13554  trimprepare(state->f, &state->trimthreshold, _state);
13555  ae_v_moveneg(&state->dk.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1));
13556  mincg_preconditionedmultiply(state, &state->dk, &state->work0, &state->work1, _state);
13557  if( !state->xrep )
13558  {
13559  goto lbl_32;
13560  }
13561  mincg_clearrequestfields(state, _state);
13562  state->xupdated = ae_true;
13563  state->rstate.stage = 10;
13564  goto lbl_rcomm;
13565 lbl_10:
13566  state->xupdated = ae_false;
13567 lbl_32:
13568  if( state->terminationneeded )
13569  {
13570  ae_v_move(&state->xn.ptr.p_double[0], 1, &state->xk.ptr.p_double[0], 1, ae_v_len(0,n-1));
13571  state->repterminationtype = 8;
13572  result = ae_false;
13573  return result;
13574  }
13575  v = 0;
13576  for(i=0; i<=n-1; i++)
13577  {
13578  v = v+ae_sqr(state->g.ptr.p_double[i]*state->s.ptr.p_double[i], _state);
13579  }
13580  if( ae_fp_less_eq(ae_sqrt(v, _state),state->epsg) )
13581  {
13582  ae_v_move(&state->xn.ptr.p_double[0], 1, &state->xk.ptr.p_double[0], 1, ae_v_len(0,n-1));
13583  state->repterminationtype = 4;
13584  result = ae_false;
13585  return result;
13586  }
13587  state->repnfev = 1;
13588  state->k = 0;
13589  state->fold = state->f;
13590 
13591  /*
13592  * Choose initial step.
13593  * Apply preconditioner, if we have something other than default.
13594  */
13595  if( state->prectype==2||state->prectype==3 )
13596  {
13597 
13598  /*
13599  * because we use preconditioner, step length must be equal
13600  * to the norm of DK
13601  */
13602  v = ae_v_dotproduct(&state->dk.ptr.p_double[0], 1, &state->dk.ptr.p_double[0], 1, ae_v_len(0,n-1));
13603  state->lastgoodstep = ae_sqrt(v, _state);
13604  }
13605  else
13606  {
13607 
13608  /*
13609  * No preconditioner is used, we try to use suggested step
13610  */
13611  if( ae_fp_greater(state->suggestedstep,0) )
13612  {
13613  state->lastgoodstep = state->suggestedstep;
13614  }
13615  else
13616  {
13617  state->lastgoodstep = 1.0;
13618  }
13619  }
13620 
13621  /*
13622  * Main cycle
13623  */
13624  state->rstimer = mincg_rscountdownlen;
13625 lbl_34:
13626  if( ae_false )
13627  {
13628  goto lbl_35;
13629  }
13630 
13631  /*
13632  * * clear reset flag
13633  * * clear termination flag
13634  * * store G[k] for later calculation of Y[k]
13635  * * prepare starting point and direction and step length for line search
13636  */
13637  state->innerresetneeded = ae_false;
13638  state->terminationneeded = ae_false;
13639  ae_v_moveneg(&state->yk.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1));
13640  ae_v_move(&state->d.ptr.p_double[0], 1, &state->dk.ptr.p_double[0], 1, ae_v_len(0,n-1));
13641  ae_v_move(&state->x.ptr.p_double[0], 1, &state->xk.ptr.p_double[0], 1, ae_v_len(0,n-1));
13642  state->mcstage = 0;
13643  state->stp = 1.0;
13644  linminnormalized(&state->d, &state->stp, n, _state);
13645  if( ae_fp_neq(state->lastgoodstep,0) )
13646  {
13647  state->stp = state->lastgoodstep;
13648  }
13649  state->curstpmax = state->stpmax;
13650 
13651  /*
13652  * Report beginning of line search (if needed)
13653  * Terminate algorithm, if user request was detected
13654  */
13655  if( !state->drep )
13656  {
13657  goto lbl_36;
13658  }
13659  mincg_clearrequestfields(state, _state);
13660  state->lsstart = ae_true;
13661  state->rstate.stage = 11;
13662  goto lbl_rcomm;
13663 lbl_11:
13664  state->lsstart = ae_false;
13665 lbl_36:
13666  if( state->terminationneeded )
13667  {
13668  ae_v_move(&state->xn.ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,n-1));
13669  state->repterminationtype = 8;
13670  result = ae_false;
13671  return result;
13672  }
13673 
13674  /*
13675  * Minimization along D
13676  */
13677  mcsrch(n, &state->x, &state->f, &state->g, &state->d, &state->stp, state->curstpmax, mincg_gtol, &state->mcinfo, &state->nfev, &state->work0, &state->lstate, &state->mcstage, _state);
13678 lbl_38:
13679  if( state->mcstage==0 )
13680  {
13681  goto lbl_39;
13682  }
13683 
13684  /*
13685  * Calculate function/gradient using either
13686  * analytical gradient supplied by user
13687  * or finite difference approximation.
13688  *
13689  * "Trim" function in order to handle near-singularity points.
13690  */
13691  mincg_clearrequestfields(state, _state);
13692  if( ae_fp_neq(state->diffstep,0) )
13693  {
13694  goto lbl_40;
13695  }
13696  state->needfg = ae_true;
13697  state->rstate.stage = 12;
13698  goto lbl_rcomm;
13699 lbl_12:
13700  state->needfg = ae_false;
13701  goto lbl_41;
13702 lbl_40:
13703  state->needf = ae_true;
13704  state->rstate.stage = 13;
13705  goto lbl_rcomm;
13706 lbl_13:
13707  state->fbase = state->f;
13708  i = 0;
13709 lbl_42:
13710  if( i>n-1 )
13711  {
13712  goto lbl_44;
13713  }
13714  v = state->x.ptr.p_double[i];
13715  state->x.ptr.p_double[i] = v-state->diffstep*state->s.ptr.p_double[i];
13716  state->rstate.stage = 14;
13717  goto lbl_rcomm;
13718 lbl_14:
13719  state->fm2 = state->f;
13720  state->x.ptr.p_double[i] = v-0.5*state->diffstep*state->s.ptr.p_double[i];
13721  state->rstate.stage = 15;
13722  goto lbl_rcomm;
13723 lbl_15:
13724  state->fm1 = state->f;
13725  state->x.ptr.p_double[i] = v+0.5*state->diffstep*state->s.ptr.p_double[i];
13726  state->rstate.stage = 16;
13727  goto lbl_rcomm;
13728 lbl_16:
13729  state->fp1 = state->f;
13730  state->x.ptr.p_double[i] = v+state->diffstep*state->s.ptr.p_double[i];
13731  state->rstate.stage = 17;
13732  goto lbl_rcomm;
13733 lbl_17:
13734  state->fp2 = state->f;
13735  state->x.ptr.p_double[i] = v;
13736  state->g.ptr.p_double[i] = (8*(state->fp1-state->fm1)-(state->fp2-state->fm2))/(6*state->diffstep*state->s.ptr.p_double[i]);
13737  i = i+1;
13738  goto lbl_42;
13739 lbl_44:
13740  state->f = state->fbase;
13741  state->needf = ae_false;
13742 lbl_41:
13743  trimfunction(&state->f, &state->g, n, state->trimthreshold, _state);
13744 
13745  /*
13746  * Call MCSRCH again
13747  */
13748  mcsrch(n, &state->x, &state->f, &state->g, &state->d, &state->stp, state->curstpmax, mincg_gtol, &state->mcinfo, &state->nfev, &state->work0, &state->lstate, &state->mcstage, _state);
13749  goto lbl_38;
13750 lbl_39:
13751 
13752  /*
13753  * * report end of line search
13754  * * store current point to XN
13755  * * report iteration
13756  * * terminate algorithm if user request was detected
13757  */
13758  if( !state->drep )
13759  {
13760  goto lbl_45;
13761  }
13762 
13763  /*
13764  * Report end of line search (if needed)
13765  */
13766  mincg_clearrequestfields(state, _state);
13767  state->lsend = ae_true;
13768  state->rstate.stage = 18;
13769  goto lbl_rcomm;
13770 lbl_18:
13771  state->lsend = ae_false;
13772 lbl_45:
13773  ae_v_move(&state->xn.ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,n-1));
13774  if( !state->xrep )
13775  {
13776  goto lbl_47;
13777  }
13778  mincg_clearrequestfields(state, _state);
13779  state->xupdated = ae_true;
13780  state->rstate.stage = 19;
13781  goto lbl_rcomm;
13782 lbl_19:
13783  state->xupdated = ae_false;
13784 lbl_47:
13785  if( state->terminationneeded )
13786  {
13787  ae_v_move(&state->xn.ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,n-1));
13788  state->repterminationtype = 8;
13789  result = ae_false;
13790  return result;
13791  }
13792 
13793  /*
13794  * Line search is finished.
13795  * * calculate BetaK
13796  * * calculate DN
13797  * * update timers
13798  * * calculate step length:
13799  * * LastScaledStep is ALWAYS calculated because it is used in the stopping criteria
13800  * * LastGoodStep is updated only when MCINFO is equal to 1 (Wolfe conditions hold).
13801  * See below for more explanation.
13802  */
13803  if( state->mcinfo==1&&!state->innerresetneeded )
13804  {
13805 
13806  /*
13807  * Standard Wolfe conditions hold
13808  * Calculate Y[K] and D[K]'*Y[K]
13809  */
13810  ae_v_add(&state->yk.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1));
13811  vv = ae_v_dotproduct(&state->yk.ptr.p_double[0], 1, &state->dk.ptr.p_double[0], 1, ae_v_len(0,n-1));
13812 
13813  /*
13814  * Calculate BetaK according to DY formula
13815  */
13816  v = mincg_preconditionedmultiply2(state, &state->g, &state->g, &state->work0, &state->work1, _state);
13817  state->betady = v/vv;
13818 
13819  /*
13820  * Calculate BetaK according to HS formula
13821  */
13822  v = mincg_preconditionedmultiply2(state, &state->g, &state->yk, &state->work0, &state->work1, _state);
13823  state->betahs = v/vv;
13824 
13825  /*
13826  * Choose BetaK
13827  */
13828  if( state->cgtype==0 )
13829  {
13830  betak = state->betady;
13831  }
13832  if( state->cgtype==1 )
13833  {
13834  betak = ae_maxreal(0, ae_minreal(state->betady, state->betahs, _state), _state);
13835  }
13836  }
13837  else
13838  {
13839 
13840  /*
13841  * Something is wrong (may be function is too wild or too flat)
13842  * or we just have to restart algo.
13843  *
13844  * We'll set BetaK=0, which will restart CG algorithm.
13845  * We can stop later (during normal checks) if stopping conditions are met.
13846  */
13847  betak = 0;
13848  state->debugrestartscount = state->debugrestartscount+1;
13849  }
13850  if( state->repiterationscount>0&&state->repiterationscount%(3+n)==0 )
13851  {
13852 
13853  /*
13854  * clear Beta every N iterations
13855  */
13856  betak = 0;
13857  }
13858  if( state->mcinfo==1||state->mcinfo==5 )
13859  {
13860  state->rstimer = mincg_rscountdownlen;
13861  }
13862  else
13863  {
13864  state->rstimer = state->rstimer-1;
13865  }
13866  ae_v_moveneg(&state->dn.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1));
13867  mincg_preconditionedmultiply(state, &state->dn, &state->work0, &state->work1, _state);
13868  ae_v_addd(&state->dn.ptr.p_double[0], 1, &state->dk.ptr.p_double[0], 1, ae_v_len(0,n-1), betak);
13869  state->lastscaledstep = 0.0;
13870  for(i=0; i<=n-1; i++)
13871  {
13872  state->lastscaledstep = state->lastscaledstep+ae_sqr(state->d.ptr.p_double[i]/state->s.ptr.p_double[i], _state);
13873  }
13874  state->lastscaledstep = state->stp*ae_sqrt(state->lastscaledstep, _state);
13875  if( state->mcinfo==1 )
13876  {
13877 
13878  /*
13879  * Step is good (Wolfe conditions hold), update LastGoodStep.
13880  *
13881  * This check for MCINFO=1 is essential because sometimes in the
13882  * constrained optimization setting we may take very short steps
13883  * (like 1E-15) because we were very close to boundary of the
13884  * feasible area. Such short step does not mean that we've converged
13885  * to the solution - it was so short because we were close to the
13886  * boundary and there was a limit on step length.
13887  *
13888  * So having such short step is quite normal situation. However, we
13889  * should NOT start next iteration from step whose initial length is
13890  * estimated as 1E-15 because it may lead to the failure of the
13891  * linear minimizer (step is too short, function does not changes,
13892  * line search stagnates).
13893  */
13894  state->lastgoodstep = 0;
13895  for(i=0; i<=n-1; i++)
13896  {
13897  state->lastgoodstep = state->lastgoodstep+ae_sqr(state->d.ptr.p_double[i], _state);
13898  }
13899  state->lastgoodstep = state->stp*ae_sqrt(state->lastgoodstep, _state);
13900  }
13901 
13902  /*
13903  * Update information.
13904  * Check stopping conditions.
13905  */
13906  state->repnfev = state->repnfev+state->nfev;
13907  state->repiterationscount = state->repiterationscount+1;
13908  if( state->repiterationscount>=state->maxits&&state->maxits>0 )
13909  {
13910 
13911  /*
13912  * Too many iterations
13913  */
13914  state->repterminationtype = 5;
13915  result = ae_false;
13916  return result;
13917  }
13918  v = 0;
13919  for(i=0; i<=n-1; i++)
13920  {
13921  v = v+ae_sqr(state->g.ptr.p_double[i]*state->s.ptr.p_double[i], _state);
13922  }
13923  if( ae_fp_less_eq(ae_sqrt(v, _state),state->epsg) )
13924  {
13925 
13926  /*
13927  * Gradient is small enough
13928  */
13929  state->repterminationtype = 4;
13930  result = ae_false;
13931  return result;
13932  }
13933  if( !state->innerresetneeded )
13934  {
13935 
13936  /*
13937  * These conditions are checked only when no inner reset was requested by user
13938  */
13939  if( ae_fp_less_eq(state->fold-state->f,state->epsf*ae_maxreal(ae_fabs(state->fold, _state), ae_maxreal(ae_fabs(state->f, _state), 1.0, _state), _state)) )
13940  {
13941 
13942  /*
13943  * F(k+1)-F(k) is small enough
13944  */
13945  state->repterminationtype = 1;
13946  result = ae_false;
13947  return result;
13948  }
13949  if( ae_fp_less_eq(state->lastscaledstep,state->epsx) )
13950  {
13951 
13952  /*
13953  * X(k+1)-X(k) is small enough
13954  */
13955  state->repterminationtype = 2;
13956  result = ae_false;
13957  return result;
13958  }
13959  }
13960  if( state->rstimer<=0 )
13961  {
13962 
13963  /*
13964  * Too many subsequent restarts
13965  */
13966  state->repterminationtype = 7;
13967  result = ae_false;
13968  return result;
13969  }
13970 
13971  /*
13972  * Shift Xk/Dk, update other information
13973  */
13974  ae_v_move(&state->xk.ptr.p_double[0], 1, &state->xn.ptr.p_double[0], 1, ae_v_len(0,n-1));
13975  ae_v_move(&state->dk.ptr.p_double[0], 1, &state->dn.ptr.p_double[0], 1, ae_v_len(0,n-1));
13976  state->fold = state->f;
13977  state->k = state->k+1;
13978  goto lbl_34;
13979 lbl_35:
13980  result = ae_false;
13981  return result;
13982 
13983  /*
13984  * Saving state
13985  */
13986 lbl_rcomm:
13987  result = ae_true;
13988  state->rstate.ia.ptr.p_int[0] = n;
13989  state->rstate.ia.ptr.p_int[1] = i;
13990  state->rstate.ra.ptr.p_double[0] = betak;
13991  state->rstate.ra.ptr.p_double[1] = v;
13992  state->rstate.ra.ptr.p_double[2] = vv;
13993  return result;
13994 }
13995 
13996 
13997 /*************************************************************************
13998 Conjugate gradient results
13999 
14000 INPUT PARAMETERS:
14001  State - algorithm state
14002 
14003 OUTPUT PARAMETERS:
14004  X - array[0..N-1], solution
14005  Rep - optimization report:
14006  * Rep.TerminationType completion code:
14007  * -7 gradient verification failed.
14008  See MinCGSetGradientCheck() for more information.
14009  * 1 relative function improvement is no more than
14010  EpsF.
14011  * 2 relative step is no more than EpsX.
14012  * 4 gradient norm is no more than EpsG
14013  * 5 MaxIts steps was taken
14014  * 7 stopping conditions are too stringent,
14015  further improvement is impossible,
14016  we return best X found so far
14017  * 8 terminated by user
14018  * Rep.IterationsCount contains iterations count
14019  * NFEV contains number of function calculations
14020 
14021  -- ALGLIB --
14022  Copyright 20.04.2009 by Bochkanov Sergey
14023 *************************************************************************/
14024 void mincgresults(mincgstate* state,
14025  /* Real */ ae_vector* x,
14026  mincgreport* rep,
14027  ae_state *_state)
14028 {
14029 
14030  ae_vector_clear(x);
14031  _mincgreport_clear(rep);
14032 
14033  mincgresultsbuf(state, x, rep, _state);
14034 }
14035 
14036 
14037 /*************************************************************************
14038 Conjugate gradient results
14039 
14040 Buffered implementation of MinCGResults(), which uses pre-allocated buffer
14041 to store X[]. If buffer size is too small, it resizes buffer. It is
14042 intended to be used in the inner cycles of performance critical algorithms
14043 where array reallocation penalty is too large to be ignored.
14044 
14045  -- ALGLIB --
14046  Copyright 20.04.2009 by Bochkanov Sergey
14047 *************************************************************************/
14048 void mincgresultsbuf(mincgstate* state,
14049  /* Real */ ae_vector* x,
14050  mincgreport* rep,
14051  ae_state *_state)
14052 {
14053 
14054 
14055  if( x->cnt<state->n )
14056  {
14057  ae_vector_set_length(x, state->n, _state);
14058  }
14059  ae_v_move(&x->ptr.p_double[0], 1, &state->xn.ptr.p_double[0], 1, ae_v_len(0,state->n-1));
14060  rep->iterationscount = state->repiterationscount;
14061  rep->nfev = state->repnfev;
14062  rep->varidx = state->repvaridx;
14063  rep->terminationtype = state->repterminationtype;
14064 }
14065 
14066 
14067 /*************************************************************************
14068 This subroutine restarts CG algorithm from new point. All optimization
14069 parameters are left unchanged.
14070 
14071 This function allows to solve multiple optimization problems (which
14072 must have same number of dimensions) without object reallocation penalty.
14073 
14074 INPUT PARAMETERS:
14075  State - structure used to store algorithm state.
14076  X - new starting point.
14077 
14078  -- ALGLIB --
14079  Copyright 30.07.2010 by Bochkanov Sergey
14080 *************************************************************************/
14081 void mincgrestartfrom(mincgstate* state,
14082  /* Real */ ae_vector* x,
14083  ae_state *_state)
14084 {
14085 
14086 
14087  ae_assert(x->cnt>=state->n, "MinCGRestartFrom: Length(X)<N!", _state);
14088  ae_assert(isfinitevector(x, state->n, _state), "MinCGCreate: X contains infinite or NaN values!", _state);
14089  ae_v_move(&state->x.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,state->n-1));
14090  mincgsuggeststep(state, 0.0, _state);
14091  ae_vector_set_length(&state->rstate.ia, 1+1, _state);
14092  ae_vector_set_length(&state->rstate.ra, 2+1, _state);
14093  state->rstate.stage = -1;
14094  mincg_clearrequestfields(state, _state);
14095 }
14096 
14097 
14098 /*************************************************************************
14099 Faster version of MinCGSetPrecDiag(), for time-critical parts of code,
14100 without safety checks.
14101 
14102  -- ALGLIB --
14103  Copyright 13.10.2010 by Bochkanov Sergey
14104 *************************************************************************/
14105 void mincgsetprecdiagfast(mincgstate* state,
14106  /* Real */ ae_vector* d,
14107  ae_state *_state)
14108 {
14109  ae_int_t i;
14110 
14111 
14112  rvectorsetlengthatleast(&state->diagh, state->n, _state);
14113  rvectorsetlengthatleast(&state->diaghl2, state->n, _state);
14114  state->prectype = 2;
14115  state->vcnt = 0;
14116  state->innerresetneeded = ae_true;
14117  for(i=0; i<=state->n-1; i++)
14118  {
14119  state->diagh.ptr.p_double[i] = d->ptr.p_double[i];
14120  state->diaghl2.ptr.p_double[i] = 0.0;
14121  }
14122 }
14123 
14124 
14125 /*************************************************************************
14126 This function sets low-rank preconditioner for Hessian matrix H=D+V'*C*V,
14127 where:
14128 * H is a Hessian matrix, which is approximated by D/V/C
14129 * D=D1+D2 is a diagonal matrix, which includes two positive definite terms:
14130  * constant term D1 (is not updated or infrequently updated)
14131  * variable term D2 (can be cheaply updated from iteration to iteration)
14132 * V is a low-rank correction
14133 * C is a diagonal factor of low-rank correction
14134 
14135 Preconditioner P is calculated using approximate Woodburry formula:
14136  P = D^(-1) - D^(-1)*V'*(C^(-1)+V*D1^(-1)*V')^(-1)*V*D^(-1)
14137  = D^(-1) - D^(-1)*VC'*VC*D^(-1),
14138 where
14139  VC = sqrt(B)*V
14140  B = (C^(-1)+V*D1^(-1)*V')^(-1)
14141 
14142 Note that B is calculated using constant term (D1) only, which allows us
14143 to update D2 without recalculation of B or VC. Such preconditioner is
14144 exact when D2 is zero. When D2 is non-zero, it is only approximation, but
14145 very good and cheap one.
14146 
14147 This function accepts D1, V, C.
14148 D2 is set to zero by default.
14149 
14150 Cost of this update is O(N*VCnt*VCnt), but D2 can be updated in just O(N)
14151 by MinCGSetPrecVarPart.
14152 
14153  -- ALGLIB --
14154  Copyright 13.10.2010 by Bochkanov Sergey
14155 *************************************************************************/
14156 void mincgsetpreclowrankfast(mincgstate* state,
14157  /* Real */ ae_vector* d1,
14158  /* Real */ ae_vector* c,
14159  /* Real */ ae_matrix* v,
14160  ae_int_t vcnt,
14161  ae_state *_state)
14162 {
14163  ae_frame _frame_block;
14164  ae_int_t i;
14165  ae_int_t j;
14166  ae_int_t k;
14167  ae_int_t n;
14168  double t;
14169  ae_matrix b;
14170 
14171  ae_frame_make(_state, &_frame_block);
14172  ae_matrix_init(&b, 0, 0, DT_REAL, _state, ae_true);
14173 
14174  if( vcnt==0 )
14175  {
14176  mincgsetprecdiagfast(state, d1, _state);
14177  ae_frame_leave(_state);
14178  return;
14179  }
14180  n = state->n;
14181  ae_matrix_set_length(&b, vcnt, vcnt, _state);
14182  rvectorsetlengthatleast(&state->diagh, n, _state);
14183  rvectorsetlengthatleast(&state->diaghl2, n, _state);
14184  rmatrixsetlengthatleast(&state->vcorr, vcnt, n, _state);
14185  state->prectype = 2;
14186  state->vcnt = vcnt;
14187  state->innerresetneeded = ae_true;
14188  for(i=0; i<=n-1; i++)
14189  {
14190  state->diagh.ptr.p_double[i] = d1->ptr.p_double[i];
14191  state->diaghl2.ptr.p_double[i] = 0.0;
14192  }
14193  for(i=0; i<=vcnt-1; i++)
14194  {
14195  for(j=i; j<=vcnt-1; j++)
14196  {
14197  t = 0;
14198  for(k=0; k<=n-1; k++)
14199  {
14200  t = t+v->ptr.pp_double[i][k]*v->ptr.pp_double[j][k]/d1->ptr.p_double[k];
14201  }
14202  b.ptr.pp_double[i][j] = t;
14203  }
14204  b.ptr.pp_double[i][i] = b.ptr.pp_double[i][i]+1.0/c->ptr.p_double[i];
14205  }
14206  if( !spdmatrixcholeskyrec(&b, 0, vcnt, ae_true, &state->work0, _state) )
14207  {
14208  state->vcnt = 0;
14209  ae_frame_leave(_state);
14210  return;
14211  }
14212  for(i=0; i<=vcnt-1; i++)
14213  {
14214  ae_v_move(&state->vcorr.ptr.pp_double[i][0], 1, &v->ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
14215  for(j=0; j<=i-1; j++)
14216  {
14217  t = b.ptr.pp_double[j][i];
14218  ae_v_subd(&state->vcorr.ptr.pp_double[i][0], 1, &state->vcorr.ptr.pp_double[j][0], 1, ae_v_len(0,n-1), t);
14219  }
14220  t = 1/b.ptr.pp_double[i][i];
14221  ae_v_muld(&state->vcorr.ptr.pp_double[i][0], 1, ae_v_len(0,n-1), t);
14222  }
14223  ae_frame_leave(_state);
14224 }
14225 
14226 
14227 /*************************************************************************
14228 This function updates variable part (diagonal matrix D2)
14229 of low-rank preconditioner.
14230 
14231 This update is very cheap and takes just O(N) time.
14232 
14233 It has no effect with default preconditioner.
14234 
14235  -- ALGLIB --
14236  Copyright 13.10.2010 by Bochkanov Sergey
14237 *************************************************************************/
14238 void mincgsetprecvarpart(mincgstate* state,
14239  /* Real */ ae_vector* d2,
14240  ae_state *_state)
14241 {
14242  ae_int_t i;
14243  ae_int_t n;
14244 
14245 
14246  n = state->n;
14247  for(i=0; i<=n-1; i++)
14248  {
14249  state->diaghl2.ptr.p_double[i] = d2->ptr.p_double[i];
14250  }
14251 }
14252 
14253 
14254 /*************************************************************************
14255 
14256 This subroutine turns on verification of the user-supplied analytic
14257 gradient:
14258 * user calls this subroutine before optimization begins
14259 * MinCGOptimize() is called
14260 * prior to actual optimization, for each component of parameters being
14261  optimized X[i] algorithm performs following steps:
14262  * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i],
14263  where X[i] is i-th component of the initial point and S[i] is a scale
14264  of i-th parameter
14265  * F(X) is evaluated at these trial points
14266  * we perform one more evaluation in the middle point of the interval
14267  * we build cubic model using function values and derivatives at trial
14268  points and we compare its prediction with actual value in the middle
14269  point
14270  * in case difference between prediction and actual value is higher than
14271  some predetermined threshold, algorithm stops with completion code -7;
14272  Rep.VarIdx is set to index of the parameter with incorrect derivative.
14273 * after verification is over, algorithm proceeds to the actual optimization.
14274 
14275 NOTE 1: verification needs N (parameters count) gradient evaluations. It
14276  is very costly and you should use it only for low dimensional
14277  problems, when you want to be sure that you've correctly
14278  calculated analytic derivatives. You should not use it in the
14279  production code (unless you want to check derivatives provided by
14280  some third party).
14281 
14282 NOTE 2: you should carefully choose TestStep. Value which is too large
14283  (so large that function behaviour is significantly non-cubic) will
14284  lead to false alarms. You may use different step for different
14285  parameters by means of setting scale with MinCGSetScale().
14286 
14287 NOTE 3: this function may lead to false positives. In case it reports that
14288  I-th derivative was calculated incorrectly, you may decrease test
14289  step and try one more time - maybe your function changes too
14290  sharply and your step is too large for such rapidly chanding
14291  function.
14292 
14293 INPUT PARAMETERS:
14294  State - structure used to store algorithm state
14295  TestStep - verification step:
14296  * TestStep=0 turns verification off
14297  * TestStep>0 activates verification
14298 
14299  -- ALGLIB --
14300  Copyright 31.05.2012 by Bochkanov Sergey
14301 *************************************************************************/
14302 void mincgsetgradientcheck(mincgstate* state,
14303  double teststep,
14304  ae_state *_state)
14305 {
14306 
14307 
14308  ae_assert(ae_isfinite(teststep, _state), "MinCGSetGradientCheck: TestStep contains NaN or Infinite", _state);
14309  ae_assert(ae_fp_greater_eq(teststep,0), "MinCGSetGradientCheck: invalid argument TestStep(TestStep<0)", _state);
14310  state->teststep = teststep;
14311 }
14312 
14313 
14314 /*************************************************************************
14315 Clears request fileds (to be sure that we don't forgot to clear something)
14316 *************************************************************************/
14317 static void mincg_clearrequestfields(mincgstate* state, ae_state *_state)
14318 {
14319 
14320 
14321  state->needf = ae_false;
14322  state->needfg = ae_false;
14323  state->xupdated = ae_false;
14324  state->lsstart = ae_false;
14325  state->lsend = ae_false;
14326  state->algpowerup = ae_false;
14327 }
14328 
14329 
14330 /*************************************************************************
14331 This function calculates preconditioned product H^(-1)*x and stores result
14332 back into X. Work0[] and Work1[] are used as temporaries (size must be at
14333 least N; this function doesn't allocate arrays).
14334 
14335  -- ALGLIB --
14336  Copyright 13.10.2010 by Bochkanov Sergey
14337 *************************************************************************/
14338 static void mincg_preconditionedmultiply(mincgstate* state,
14339  /* Real */ ae_vector* x,
14340  /* Real */ ae_vector* work0,
14341  /* Real */ ae_vector* work1,
14342  ae_state *_state)
14343 {
14344  ae_int_t i;
14345  ae_int_t n;
14346  ae_int_t vcnt;
14347  double v;
14348 
14349 
14350  n = state->n;
14351  vcnt = state->vcnt;
14352  if( state->prectype==0 )
14353  {
14354  return;
14355  }
14356  if( state->prectype==3 )
14357  {
14358  for(i=0; i<=n-1; i++)
14359  {
14360  x->ptr.p_double[i] = x->ptr.p_double[i]*state->s.ptr.p_double[i]*state->s.ptr.p_double[i];
14361  }
14362  return;
14363  }
14364  ae_assert(state->prectype==2, "MinCG: internal error (unexpected PrecType)", _state);
14365 
14366  /*
14367  * handle part common for VCnt=0 and VCnt<>0
14368  */
14369  for(i=0; i<=n-1; i++)
14370  {
14371  x->ptr.p_double[i] = x->ptr.p_double[i]/(state->diagh.ptr.p_double[i]+state->diaghl2.ptr.p_double[i]);
14372  }
14373 
14374  /*
14375  * if VCnt>0
14376  */
14377  if( vcnt>0 )
14378  {
14379  for(i=0; i<=vcnt-1; i++)
14380  {
14381  v = ae_v_dotproduct(&state->vcorr.ptr.pp_double[i][0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1));
14382  work0->ptr.p_double[i] = v;
14383  }
14384  for(i=0; i<=n-1; i++)
14385  {
14386  work1->ptr.p_double[i] = 0;
14387  }
14388  for(i=0; i<=vcnt-1; i++)
14389  {
14390  v = work0->ptr.p_double[i];
14391  ae_v_addd(&state->work1.ptr.p_double[0], 1, &state->vcorr.ptr.pp_double[i][0], 1, ae_v_len(0,n-1), v);
14392  }
14393  for(i=0; i<=n-1; i++)
14394  {
14395  x->ptr.p_double[i] = x->ptr.p_double[i]-state->work1.ptr.p_double[i]/(state->diagh.ptr.p_double[i]+state->diaghl2.ptr.p_double[i]);
14396  }
14397  }
14398 }
14399 
14400 
14401 /*************************************************************************
14402 This function calculates preconditioned product x'*H^(-1)*y. Work0[] and
14403 Work1[] are used as temporaries (size must be at least N; this function
14404 doesn't allocate arrays).
14405 
14406  -- ALGLIB --
14407  Copyright 13.10.2010 by Bochkanov Sergey
14408 *************************************************************************/
14409 static double mincg_preconditionedmultiply2(mincgstate* state,
14410  /* Real */ ae_vector* x,
14411  /* Real */ ae_vector* y,
14412  /* Real */ ae_vector* work0,
14413  /* Real */ ae_vector* work1,
14414  ae_state *_state)
14415 {
14416  ae_int_t i;
14417  ae_int_t n;
14418  ae_int_t vcnt;
14419  double v0;
14420  double v1;
14421  double result;
14422 
14423 
14424  n = state->n;
14425  vcnt = state->vcnt;
14426 
14427  /*
14428  * no preconditioning
14429  */
14430  if( state->prectype==0 )
14431  {
14432  v0 = ae_v_dotproduct(&x->ptr.p_double[0], 1, &y->ptr.p_double[0], 1, ae_v_len(0,n-1));
14433  result = v0;
14434  return result;
14435  }
14436  if( state->prectype==3 )
14437  {
14438  result = 0;
14439  for(i=0; i<=n-1; i++)
14440  {
14441  result = result+x->ptr.p_double[i]*state->s.ptr.p_double[i]*state->s.ptr.p_double[i]*y->ptr.p_double[i];
14442  }
14443  return result;
14444  }
14445  ae_assert(state->prectype==2, "MinCG: internal error (unexpected PrecType)", _state);
14446 
14447  /*
14448  * low rank preconditioning
14449  */
14450  result = 0.0;
14451  for(i=0; i<=n-1; i++)
14452  {
14453  result = result+x->ptr.p_double[i]*y->ptr.p_double[i]/(state->diagh.ptr.p_double[i]+state->diaghl2.ptr.p_double[i]);
14454  }
14455  if( vcnt>0 )
14456  {
14457  for(i=0; i<=n-1; i++)
14458  {
14459  work0->ptr.p_double[i] = x->ptr.p_double[i]/(state->diagh.ptr.p_double[i]+state->diaghl2.ptr.p_double[i]);
14460  work1->ptr.p_double[i] = y->ptr.p_double[i]/(state->diagh.ptr.p_double[i]+state->diaghl2.ptr.p_double[i]);
14461  }
14462  for(i=0; i<=vcnt-1; i++)
14463  {
14464  v0 = ae_v_dotproduct(&work0->ptr.p_double[0], 1, &state->vcorr.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
14465  v1 = ae_v_dotproduct(&work1->ptr.p_double[0], 1, &state->vcorr.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
14466  result = result-v0*v1;
14467  }
14468  }
14469  return result;
14470 }
14471 
14472 
14473 /*************************************************************************
14474 Internal initialization subroutine
14475 
14476  -- ALGLIB --
14477  Copyright 16.05.2011 by Bochkanov Sergey
14478 *************************************************************************/
14479 static void mincg_mincginitinternal(ae_int_t n,
14480  double diffstep,
14481  mincgstate* state,
14482  ae_state *_state)
14483 {
14484  ae_int_t i;
14485 
14486 
14487 
14488  /*
14489  * Initialize
14490  */
14491  state->teststep = 0;
14492  state->n = n;
14493  state->diffstep = diffstep;
14494  mincgsetcond(state, 0, 0, 0, 0, _state);
14495  mincgsetxrep(state, ae_false, _state);
14496  mincgsetdrep(state, ae_false, _state);
14497  mincgsetstpmax(state, 0, _state);
14498  mincgsetcgtype(state, -1, _state);
14499  mincgsetprecdefault(state, _state);
14500  ae_vector_set_length(&state->xk, n, _state);
14501  ae_vector_set_length(&state->dk, n, _state);
14502  ae_vector_set_length(&state->xn, n, _state);
14503  ae_vector_set_length(&state->dn, n, _state);
14504  ae_vector_set_length(&state->x, n, _state);
14505  ae_vector_set_length(&state->d, n, _state);
14506  ae_vector_set_length(&state->g, n, _state);
14507  ae_vector_set_length(&state->work0, n, _state);
14508  ae_vector_set_length(&state->work1, n, _state);
14509  ae_vector_set_length(&state->yk, n, _state);
14510  ae_vector_set_length(&state->s, n, _state);
14511  for(i=0; i<=n-1; i++)
14512  {
14513  state->s.ptr.p_double[i] = 1.0;
14514  }
14515 }
14516 
14517 
14518 ae_bool _mincgstate_init(void* _p, ae_state *_state, ae_bool make_automatic)
14519 {
14520  mincgstate *p = (mincgstate*)_p;
14521  ae_touch_ptr((void*)p);
14522  if( !ae_vector_init(&p->diagh, 0, DT_REAL, _state, make_automatic) )
14523  return ae_false;
14524  if( !ae_vector_init(&p->diaghl2, 0, DT_REAL, _state, make_automatic) )
14525  return ae_false;
14526  if( !ae_matrix_init(&p->vcorr, 0, 0, DT_REAL, _state, make_automatic) )
14527  return ae_false;
14528  if( !ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic) )
14529  return ae_false;
14530  if( !ae_vector_init(&p->xk, 0, DT_REAL, _state, make_automatic) )
14531  return ae_false;
14532  if( !ae_vector_init(&p->dk, 0, DT_REAL, _state, make_automatic) )
14533  return ae_false;
14534  if( !ae_vector_init(&p->xn, 0, DT_REAL, _state, make_automatic) )
14535  return ae_false;
14536  if( !ae_vector_init(&p->dn, 0, DT_REAL, _state, make_automatic) )
14537  return ae_false;
14538  if( !ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic) )
14539  return ae_false;
14540  if( !ae_vector_init(&p->yk, 0, DT_REAL, _state, make_automatic) )
14541  return ae_false;
14542  if( !ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic) )
14543  return ae_false;
14544  if( !ae_vector_init(&p->g, 0, DT_REAL, _state, make_automatic) )
14545  return ae_false;
14546  if( !_rcommstate_init(&p->rstate, _state, make_automatic) )
14547  return ae_false;
14548  if( !_linminstate_init(&p->lstate, _state, make_automatic) )
14549  return ae_false;
14550  if( !ae_vector_init(&p->work0, 0, DT_REAL, _state, make_automatic) )
14551  return ae_false;
14552  if( !ae_vector_init(&p->work1, 0, DT_REAL, _state, make_automatic) )
14553  return ae_false;
14554  return ae_true;
14555 }
14556 
14557 
14558 ae_bool _mincgstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
14559 {
14560  mincgstate *dst = (mincgstate*)_dst;
14561  mincgstate *src = (mincgstate*)_src;
14562  dst->n = src->n;
14563  dst->epsg = src->epsg;
14564  dst->epsf = src->epsf;
14565  dst->epsx = src->epsx;
14566  dst->maxits = src->maxits;
14567  dst->stpmax = src->stpmax;
14568  dst->suggestedstep = src->suggestedstep;
14569  dst->xrep = src->xrep;
14570  dst->drep = src->drep;
14571  dst->cgtype = src->cgtype;
14572  dst->prectype = src->prectype;
14573  if( !ae_vector_init_copy(&dst->diagh, &src->diagh, _state, make_automatic) )
14574  return ae_false;
14575  if( !ae_vector_init_copy(&dst->diaghl2, &src->diaghl2, _state, make_automatic) )
14576  return ae_false;
14577  if( !ae_matrix_init_copy(&dst->vcorr, &src->vcorr, _state, make_automatic) )
14578  return ae_false;
14579  dst->vcnt = src->vcnt;
14580  if( !ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic) )
14581  return ae_false;
14582  dst->diffstep = src->diffstep;
14583  dst->nfev = src->nfev;
14584  dst->mcstage = src->mcstage;
14585  dst->k = src->k;
14586  if( !ae_vector_init_copy(&dst->xk, &src->xk, _state, make_automatic) )
14587  return ae_false;
14588  if( !ae_vector_init_copy(&dst->dk, &src->dk, _state, make_automatic) )
14589  return ae_false;
14590  if( !ae_vector_init_copy(&dst->xn, &src->xn, _state, make_automatic) )
14591  return ae_false;
14592  if( !ae_vector_init_copy(&dst->dn, &src->dn, _state, make_automatic) )
14593  return ae_false;
14594  if( !ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic) )
14595  return ae_false;
14596  dst->fold = src->fold;
14597  dst->stp = src->stp;
14598  dst->curstpmax = src->curstpmax;
14599  if( !ae_vector_init_copy(&dst->yk, &src->yk, _state, make_automatic) )
14600  return ae_false;
14601  dst->lastgoodstep = src->lastgoodstep;
14602  dst->lastscaledstep = src->lastscaledstep;
14603  dst->mcinfo = src->mcinfo;
14604  dst->innerresetneeded = src->innerresetneeded;
14605  dst->terminationneeded = src->terminationneeded;
14606  dst->trimthreshold = src->trimthreshold;
14607  dst->rstimer = src->rstimer;
14608  if( !ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic) )
14609  return ae_false;
14610  dst->f = src->f;
14611  if( !ae_vector_init_copy(&dst->g, &src->g, _state, make_automatic) )
14612  return ae_false;
14613  dst->needf = src->needf;
14614  dst->needfg = src->needfg;
14615  dst->xupdated = src->xupdated;
14616  dst->algpowerup = src->algpowerup;
14617  dst->lsstart = src->lsstart;
14618  dst->lsend = src->lsend;
14619  dst->teststep = src->teststep;
14620  if( !_rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic) )
14621  return ae_false;
14622  dst->repiterationscount = src->repiterationscount;
14623  dst->repnfev = src->repnfev;
14624  dst->repvaridx = src->repvaridx;
14625  dst->repterminationtype = src->repterminationtype;
14626  dst->debugrestartscount = src->debugrestartscount;
14627  if( !_linminstate_init_copy(&dst->lstate, &src->lstate, _state, make_automatic) )
14628  return ae_false;
14629  dst->fbase = src->fbase;
14630  dst->fm2 = src->fm2;
14631  dst->fm1 = src->fm1;
14632  dst->fp1 = src->fp1;
14633  dst->fp2 = src->fp2;
14634  dst->betahs = src->betahs;
14635  dst->betady = src->betady;
14636  if( !ae_vector_init_copy(&dst->work0, &src->work0, _state, make_automatic) )
14637  return ae_false;
14638  if( !ae_vector_init_copy(&dst->work1, &src->work1, _state, make_automatic) )
14639  return ae_false;
14640  return ae_true;
14641 }
14642 
14643 
14644 void _mincgstate_clear(void* _p)
14645 {
14646  mincgstate *p = (mincgstate*)_p;
14647  ae_touch_ptr((void*)p);
14648  ae_vector_clear(&p->diagh);
14649  ae_vector_clear(&p->diaghl2);
14650  ae_matrix_clear(&p->vcorr);
14651  ae_vector_clear(&p->s);
14652  ae_vector_clear(&p->xk);
14653  ae_vector_clear(&p->dk);
14654  ae_vector_clear(&p->xn);
14655  ae_vector_clear(&p->dn);
14656  ae_vector_clear(&p->d);
14657  ae_vector_clear(&p->yk);
14658  ae_vector_clear(&p->x);
14659  ae_vector_clear(&p->g);
14660  _rcommstate_clear(&p->rstate);
14661  _linminstate_clear(&p->lstate);
14662  ae_vector_clear(&p->work0);
14663  ae_vector_clear(&p->work1);
14664 }
14665 
14666 
14667 void _mincgstate_destroy(void* _p)
14668 {
14669  mincgstate *p = (mincgstate*)_p;
14670  ae_touch_ptr((void*)p);
14671  ae_vector_destroy(&p->diagh);
14672  ae_vector_destroy(&p->diaghl2);
14673  ae_matrix_destroy(&p->vcorr);
14674  ae_vector_destroy(&p->s);
14675  ae_vector_destroy(&p->xk);
14676  ae_vector_destroy(&p->dk);
14677  ae_vector_destroy(&p->xn);
14678  ae_vector_destroy(&p->dn);
14679  ae_vector_destroy(&p->d);
14680  ae_vector_destroy(&p->yk);
14681  ae_vector_destroy(&p->x);
14682  ae_vector_destroy(&p->g);
14683  _rcommstate_destroy(&p->rstate);
14684  _linminstate_destroy(&p->lstate);
14685  ae_vector_destroy(&p->work0);
14686  ae_vector_destroy(&p->work1);
14687 }
14688 
14689 
14690 ae_bool _mincgreport_init(void* _p, ae_state *_state, ae_bool make_automatic)
14691 {
14692  mincgreport *p = (mincgreport*)_p;
14693  ae_touch_ptr((void*)p);
14694  return ae_true;
14695 }
14696 
14697 
14698 ae_bool _mincgreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
14699 {
14700  mincgreport *dst = (mincgreport*)_dst;
14701  mincgreport *src = (mincgreport*)_src;
14702  dst->iterationscount = src->iterationscount;
14703  dst->nfev = src->nfev;
14704  dst->varidx = src->varidx;
14705  dst->terminationtype = src->terminationtype;
14706  return ae_true;
14707 }
14708 
14709 
14710 void _mincgreport_clear(void* _p)
14711 {
14712  mincgreport *p = (mincgreport*)_p;
14713  ae_touch_ptr((void*)p);
14714 }
14715 
14716 
14717 void _mincgreport_destroy(void* _p)
14718 {
14719  mincgreport *p = (mincgreport*)_p;
14720  ae_touch_ptr((void*)p);
14721 }
14722 
14723 
14724 
14725 
14726 /*************************************************************************
14727  BOUND CONSTRAINED OPTIMIZATION
14728  WITH ADDITIONAL LINEAR EQUALITY AND INEQUALITY CONSTRAINTS
14729 
14730 DESCRIPTION:
14731 The subroutine minimizes function F(x) of N arguments subject to any
14732 combination of:
14733 * bound constraints
14734 * linear inequality constraints
14735 * linear equality constraints
14736 
14737 REQUIREMENTS:
14738 * user must provide function value and gradient
14739 * starting point X0 must be feasible or
14740  not too far away from the feasible set
14741 * grad(f) must be Lipschitz continuous on a level set:
14742  L = { x : f(x)<=f(x0) }
14743 * function must be defined everywhere on the feasible set F
14744 
14745 USAGE:
14746 
14747 Constrained optimization if far more complex than the unconstrained one.
14748 Here we give very brief outline of the BLEIC optimizer. We strongly recommend
14749 you to read examples in the ALGLIB Reference Manual and to read ALGLIB User Guide
14750 on optimization, which is available at http://www.alglib.net/optimization/
14751 
14752 1. User initializes algorithm state with MinBLEICCreate() call
14753 
14754 2. USer adds boundary and/or linear constraints by calling
14755  MinBLEICSetBC() and MinBLEICSetLC() functions.
14756 
14757 3. User sets stopping conditions with MinBLEICSetCond().
14758 
14759 4. User calls MinBLEICOptimize() function which takes algorithm state and
14760  pointer (delegate, etc.) to callback function which calculates F/G.
14761 
14762 5. User calls MinBLEICResults() to get solution
14763 
14764 6. Optionally user may call MinBLEICRestartFrom() to solve another problem
14765  with same N but another starting point.
14766  MinBLEICRestartFrom() allows to reuse already initialized structure.
14767 
14768 
14769 INPUT PARAMETERS:
14770  N - problem dimension, N>0:
14771  * if given, only leading N elements of X are used
14772  * if not given, automatically determined from size ofX
14773  X - starting point, array[N]:
14774  * it is better to set X to a feasible point
14775  * but X can be infeasible, in which case algorithm will try
14776  to find feasible point first, using X as initial
14777  approximation.
14778 
14779 OUTPUT PARAMETERS:
14780  State - structure stores algorithm state
14781 
14782  -- ALGLIB --
14783  Copyright 28.11.2010 by Bochkanov Sergey
14784 *************************************************************************/
14785 void minbleiccreate(ae_int_t n,
14786  /* Real */ ae_vector* x,
14787  minbleicstate* state,
14788  ae_state *_state)
14789 {
14790  ae_frame _frame_block;
14791  ae_matrix c;
14792  ae_vector ct;
14793 
14794  ae_frame_make(_state, &_frame_block);
14795  _minbleicstate_clear(state);
14796  ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true);
14797  ae_vector_init(&ct, 0, DT_INT, _state, ae_true);
14798 
14799  ae_assert(n>=1, "MinBLEICCreate: N<1", _state);
14800  ae_assert(x->cnt>=n, "MinBLEICCreate: Length(X)<N", _state);
14801  ae_assert(isfinitevector(x, n, _state), "MinBLEICCreate: X contains infinite or NaN values!", _state);
14802  minbleic_minbleicinitinternal(n, x, 0.0, state, _state);
14803  ae_frame_leave(_state);
14804 }
14805 
14806 
14807 /*************************************************************************
14808 The subroutine is finite difference variant of MinBLEICCreate(). It uses
14809 finite differences in order to differentiate target function.
14810 
14811 Description below contains information which is specific to this function
14812 only. We recommend to read comments on MinBLEICCreate() in order to get
14813 more information about creation of BLEIC optimizer.
14814 
14815 INPUT PARAMETERS:
14816  N - problem dimension, N>0:
14817  * if given, only leading N elements of X are used
14818  * if not given, automatically determined from size of X
14819  X - starting point, array[0..N-1].
14820  DiffStep- differentiation step, >0
14821 
14822 OUTPUT PARAMETERS:
14823  State - structure which stores algorithm state
14824 
14825 NOTES:
14826 1. algorithm uses 4-point central formula for differentiation.
14827 2. differentiation step along I-th axis is equal to DiffStep*S[I] where
14828  S[] is scaling vector which can be set by MinBLEICSetScale() call.
14829 3. we recommend you to use moderate values of differentiation step. Too
14830  large step will result in too large truncation errors, while too small
14831  step will result in too large numerical errors. 1.0E-6 can be good
14832  value to start with.
14833 4. Numerical differentiation is very inefficient - one gradient
14834  calculation needs 4*N function evaluations. This function will work for
14835  any N - either small (1...10), moderate (10...100) or large (100...).
14836  However, performance penalty will be too severe for any N's except for
14837  small ones.
14838  We should also say that code which relies on numerical differentiation
14839  is less robust and precise. CG needs exact gradient values. Imprecise
14840  gradient may slow down convergence, especially on highly nonlinear
14841  problems.
14842  Thus we recommend to use this function for fast prototyping on small-
14843  dimensional problems only, and to implement analytical gradient as soon
14844  as possible.
14845 
14846  -- ALGLIB --
14847  Copyright 16.05.2011 by Bochkanov Sergey
14848 *************************************************************************/
14849 void minbleiccreatef(ae_int_t n,
14850  /* Real */ ae_vector* x,
14851  double diffstep,
14852  minbleicstate* state,
14853  ae_state *_state)
14854 {
14855  ae_frame _frame_block;
14856  ae_matrix c;
14857  ae_vector ct;
14858 
14859  ae_frame_make(_state, &_frame_block);
14860  _minbleicstate_clear(state);
14861  ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true);
14862  ae_vector_init(&ct, 0, DT_INT, _state, ae_true);
14863 
14864  ae_assert(n>=1, "MinBLEICCreateF: N<1", _state);
14865  ae_assert(x->cnt>=n, "MinBLEICCreateF: Length(X)<N", _state);
14866  ae_assert(isfinitevector(x, n, _state), "MinBLEICCreateF: X contains infinite or NaN values!", _state);
14867  ae_assert(ae_isfinite(diffstep, _state), "MinBLEICCreateF: DiffStep is infinite or NaN!", _state);
14868  ae_assert(ae_fp_greater(diffstep,0), "MinBLEICCreateF: DiffStep is non-positive!", _state);
14869  minbleic_minbleicinitinternal(n, x, diffstep, state, _state);
14870  ae_frame_leave(_state);
14871 }
14872 
14873 
14874 /*************************************************************************
14875 This function sets boundary constraints for BLEIC optimizer.
14876 
14877 Boundary constraints are inactive by default (after initial creation).
14878 They are preserved after algorithm restart with MinBLEICRestartFrom().
14879 
14880 INPUT PARAMETERS:
14881  State - structure stores algorithm state
14882  BndL - lower bounds, array[N].
14883  If some (all) variables are unbounded, you may specify
14884  very small number or -INF.
14885  BndU - upper bounds, array[N].
14886  If some (all) variables are unbounded, you may specify
14887  very large number or +INF.
14888 
14889 NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case I-th
14890 variable will be "frozen" at X[i]=BndL[i]=BndU[i].
14891 
14892 NOTE 2: this solver has following useful properties:
14893 * bound constraints are always satisfied exactly
14894 * function is evaluated only INSIDE area specified by bound constraints,
14895  even when numerical differentiation is used (algorithm adjusts nodes
14896  according to boundary constraints)
14897 
14898  -- ALGLIB --
14899  Copyright 28.11.2010 by Bochkanov Sergey
14900 *************************************************************************/
14901 void minbleicsetbc(minbleicstate* state,
14902  /* Real */ ae_vector* bndl,
14903  /* Real */ ae_vector* bndu,
14904  ae_state *_state)
14905 {
14906  ae_int_t i;
14907  ae_int_t n;
14908 
14909 
14910  n = state->nmain;
14911  ae_assert(bndl->cnt>=n, "MinBLEICSetBC: Length(BndL)<N", _state);
14912  ae_assert(bndu->cnt>=n, "MinBLEICSetBC: Length(BndU)<N", _state);
14913  for(i=0; i<=n-1; i++)
14914  {
14915  ae_assert(ae_isfinite(bndl->ptr.p_double[i], _state)||ae_isneginf(bndl->ptr.p_double[i], _state), "MinBLEICSetBC: BndL contains NAN or +INF", _state);
14916  ae_assert(ae_isfinite(bndu->ptr.p_double[i], _state)||ae_isposinf(bndu->ptr.p_double[i], _state), "MinBLEICSetBC: BndL contains NAN or -INF", _state);
14917  state->bndl.ptr.p_double[i] = bndl->ptr.p_double[i];
14918  state->hasbndl.ptr.p_bool[i] = ae_isfinite(bndl->ptr.p_double[i], _state);
14919  state->bndu.ptr.p_double[i] = bndu->ptr.p_double[i];
14920  state->hasbndu.ptr.p_bool[i] = ae_isfinite(bndu->ptr.p_double[i], _state);
14921  }
14922  sassetbc(&state->sas, bndl, bndu, _state);
14923 }
14924 
14925 
14926 /*************************************************************************
14927 This function sets linear constraints for BLEIC optimizer.
14928 
14929 Linear constraints are inactive by default (after initial creation).
14930 They are preserved after algorithm restart with MinBLEICRestartFrom().
14931 
14932 INPUT PARAMETERS:
14933  State - structure previously allocated with MinBLEICCreate call.
14934  C - linear constraints, array[K,N+1].
14935  Each row of C represents one constraint, either equality
14936  or inequality (see below):
14937  * first N elements correspond to coefficients,
14938  * last element corresponds to the right part.
14939  All elements of C (including right part) must be finite.
14940  CT - type of constraints, array[K]:
14941  * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1]
14942  * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1]
14943  * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1]
14944  K - number of equality/inequality constraints, K>=0:
14945  * if given, only leading K elements of C/CT are used
14946  * if not given, automatically determined from sizes of C/CT
14947 
14948 NOTE 1: linear (non-bound) constraints are satisfied only approximately:
14949 * there always exists some minor violation (about Epsilon in magnitude)
14950  due to rounding errors
14951 * numerical differentiation, if used, may lead to function evaluations
14952  outside of the feasible area, because algorithm does NOT change
14953  numerical differentiation formula according to linear constraints.
14954 If you want constraints to be satisfied exactly, try to reformulate your
14955 problem in such manner that all constraints will become boundary ones
14956 (this kind of constraints is always satisfied exactly, both in the final
14957 solution and in all intermediate points).
14958 
14959  -- ALGLIB --
14960  Copyright 28.11.2010 by Bochkanov Sergey
14961 *************************************************************************/
14962 void minbleicsetlc(minbleicstate* state,
14963  /* Real */ ae_matrix* c,
14964  /* Integer */ ae_vector* ct,
14965  ae_int_t k,
14966  ae_state *_state)
14967 {
14968  ae_int_t n;
14969  ae_int_t i;
14970  ae_int_t j;
14971  double v;
14972 
14973 
14974  n = state->nmain;
14975 
14976  /*
14977  * First, check for errors in the inputs
14978  */
14979  ae_assert(k>=0, "MinBLEICSetLC: K<0", _state);
14980  ae_assert(c->cols>=n+1||k==0, "MinBLEICSetLC: Cols(C)<N+1", _state);
14981  ae_assert(c->rows>=k, "MinBLEICSetLC: Rows(C)<K", _state);
14982  ae_assert(ct->cnt>=k, "MinBLEICSetLC: Length(CT)<K", _state);
14983  ae_assert(apservisfinitematrix(c, k, n+1, _state), "MinBLEICSetLC: C contains infinite or NaN values!", _state);
14984 
14985  /*
14986  * Handle zero K
14987  */
14988  if( k==0 )
14989  {
14990  state->nec = 0;
14991  state->nic = 0;
14992  return;
14993  }
14994 
14995  /*
14996  * Equality constraints are stored first, in the upper
14997  * NEC rows of State.CLEIC matrix. Inequality constraints
14998  * are stored in the next NIC rows.
14999  *
15000  * NOTE: we convert inequality constraints to the form
15001  * A*x<=b before copying them.
15002  */
15003  rmatrixsetlengthatleast(&state->cleic, k, n+1, _state);
15004  state->nec = 0;
15005  state->nic = 0;
15006  for(i=0; i<=k-1; i++)
15007  {
15008  if( ct->ptr.p_int[i]==0 )
15009  {
15010  ae_v_move(&state->cleic.ptr.pp_double[state->nec][0], 1, &c->ptr.pp_double[i][0], 1, ae_v_len(0,n));
15011  state->nec = state->nec+1;
15012  }
15013  }
15014  for(i=0; i<=k-1; i++)
15015  {
15016  if( ct->ptr.p_int[i]!=0 )
15017  {
15018  if( ct->ptr.p_int[i]>0 )
15019  {
15020  ae_v_moveneg(&state->cleic.ptr.pp_double[state->nec+state->nic][0], 1, &c->ptr.pp_double[i][0], 1, ae_v_len(0,n));
15021  }
15022  else
15023  {
15024  ae_v_move(&state->cleic.ptr.pp_double[state->nec+state->nic][0], 1, &c->ptr.pp_double[i][0], 1, ae_v_len(0,n));
15025  }
15026  state->nic = state->nic+1;
15027  }
15028  }
15029 
15030  /*
15031  * Normalize rows of State.CLEIC: each row must have unit norm.
15032  * Norm is calculated using first N elements (i.e. right part is
15033  * not counted when we calculate norm).
15034  */
15035  for(i=0; i<=k-1; i++)
15036  {
15037  v = 0;
15038  for(j=0; j<=n-1; j++)
15039  {
15040  v = v+ae_sqr(state->cleic.ptr.pp_double[i][j], _state);
15041  }
15042  if( ae_fp_eq(v,0) )
15043  {
15044  continue;
15045  }
15046  v = 1/ae_sqrt(v, _state);
15047  ae_v_muld(&state->cleic.ptr.pp_double[i][0], 1, ae_v_len(0,n), v);
15048  }
15049  sassetlc(&state->sas, c, ct, k, _state);
15050 }
15051 
15052 
15053 /*************************************************************************
15054 This function sets stopping conditions for the optimizer.
15055 
15056 INPUT PARAMETERS:
15057  State - structure which stores algorithm state
15058  EpsG - >=0
15059  The subroutine finishes its work if the condition
15060  |v|<EpsG is satisfied, where:
15061  * |.| means Euclidian norm
15062  * v - scaled gradient vector, v[i]=g[i]*s[i]
15063  * g - gradient
15064  * s - scaling coefficients set by MinBLEICSetScale()
15065  EpsF - >=0
15066  The subroutine finishes its work if on k+1-th iteration
15067  the condition |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1}
15068  is satisfied.
15069  EpsX - >=0
15070  The subroutine finishes its work if on k+1-th iteration
15071  the condition |v|<=EpsX is fulfilled, where:
15072  * |.| means Euclidian norm
15073  * v - scaled step vector, v[i]=dx[i]/s[i]
15074  * dx - step vector, dx=X(k+1)-X(k)
15075  * s - scaling coefficients set by MinBLEICSetScale()
15076  MaxIts - maximum number of iterations. If MaxIts=0, the number of
15077  iterations is unlimited.
15078 
15079 Passing EpsG=0, EpsF=0 and EpsX=0 and MaxIts=0 (simultaneously) will lead
15080 to automatic stopping criterion selection.
15081 
15082 NOTE: when SetCond() called with non-zero MaxIts, BLEIC solver may perform
15083  slightly more than MaxIts iterations. I.e., MaxIts sets non-strict
15084  limit on iterations count.
15085 
15086  -- ALGLIB --
15087  Copyright 28.11.2010 by Bochkanov Sergey
15088 *************************************************************************/
15089 void minbleicsetcond(minbleicstate* state,
15090  double epsg,
15091  double epsf,
15092  double epsx,
15093  ae_int_t maxits,
15094  ae_state *_state)
15095 {
15096 
15097 
15098  ae_assert(ae_isfinite(epsg, _state), "MinBLEICSetCond: EpsG is not finite number", _state);
15099  ae_assert(ae_fp_greater_eq(epsg,0), "MinBLEICSetCond: negative EpsG", _state);
15100  ae_assert(ae_isfinite(epsf, _state), "MinBLEICSetCond: EpsF is not finite number", _state);
15101  ae_assert(ae_fp_greater_eq(epsf,0), "MinBLEICSetCond: negative EpsF", _state);
15102  ae_assert(ae_isfinite(epsx, _state), "MinBLEICSetCond: EpsX is not finite number", _state);
15103  ae_assert(ae_fp_greater_eq(epsx,0), "MinBLEICSetCond: negative EpsX", _state);
15104  ae_assert(maxits>=0, "MinBLEICSetCond: negative MaxIts!", _state);
15105  if( ((ae_fp_eq(epsg,0)&&ae_fp_eq(epsf,0))&&ae_fp_eq(epsx,0))&&maxits==0 )
15106  {
15107  epsx = 1.0E-6;
15108  }
15109  state->epsg = epsg;
15110  state->epsf = epsf;
15111  state->epsx = epsx;
15112  state->maxits = maxits;
15113 }
15114 
15115 
15116 /*************************************************************************
15117 This function sets scaling coefficients for BLEIC optimizer.
15118 
15119 ALGLIB optimizers use scaling matrices to test stopping conditions (step
15120 size and gradient are scaled before comparison with tolerances). Scale of
15121 the I-th variable is a translation invariant measure of:
15122 a) "how large" the variable is
15123 b) how large the step should be to make significant changes in the function
15124 
15125 Scaling is also used by finite difference variant of the optimizer - step
15126 along I-th axis is equal to DiffStep*S[I].
15127 
15128 In most optimizers (and in the BLEIC too) scaling is NOT a form of
15129 preconditioning. It just affects stopping conditions. You should set
15130 preconditioner by separate call to one of the MinBLEICSetPrec...()
15131 functions.
15132 
15133 There is a special preconditioning mode, however, which uses scaling
15134 coefficients to form diagonal preconditioning matrix. You can turn this
15135 mode on, if you want. But you should understand that scaling is not the
15136 same thing as preconditioning - these are two different, although related
15137 forms of tuning solver.
15138 
15139 INPUT PARAMETERS:
15140  State - structure stores algorithm state
15141  S - array[N], non-zero scaling coefficients
15142  S[i] may be negative, sign doesn't matter.
15143 
15144  -- ALGLIB --
15145  Copyright 14.01.2011 by Bochkanov Sergey
15146 *************************************************************************/
15147 void minbleicsetscale(minbleicstate* state,
15148  /* Real */ ae_vector* s,
15149  ae_state *_state)
15150 {
15151  ae_int_t i;
15152 
15153 
15154  ae_assert(s->cnt>=state->nmain, "MinBLEICSetScale: Length(S)<N", _state);
15155  for(i=0; i<=state->nmain-1; i++)
15156  {
15157  ae_assert(ae_isfinite(s->ptr.p_double[i], _state), "MinBLEICSetScale: S contains infinite or NAN elements", _state);
15158  ae_assert(ae_fp_neq(s->ptr.p_double[i],0), "MinBLEICSetScale: S contains zero elements", _state);
15159  state->s.ptr.p_double[i] = ae_fabs(s->ptr.p_double[i], _state);
15160  }
15161  sassetscale(&state->sas, s, _state);
15162 }
15163 
15164 
15165 /*************************************************************************
15166 Modification of the preconditioner: preconditioning is turned off.
15167 
15168 INPUT PARAMETERS:
15169  State - structure which stores algorithm state
15170 
15171  -- ALGLIB --
15172  Copyright 13.10.2010 by Bochkanov Sergey
15173 *************************************************************************/
15174 void minbleicsetprecdefault(minbleicstate* state, ae_state *_state)
15175 {
15176 
15177 
15178  state->prectype = 0;
15179 }
15180 
15181 
15182 /*************************************************************************
15183 Modification of the preconditioner: diagonal of approximate Hessian is
15184 used.
15185 
15186 INPUT PARAMETERS:
15187  State - structure which stores algorithm state
15188  D - diagonal of the approximate Hessian, array[0..N-1],
15189  (if larger, only leading N elements are used).
15190 
15191 NOTE 1: D[i] should be positive. Exception will be thrown otherwise.
15192 
15193 NOTE 2: you should pass diagonal of approximate Hessian - NOT ITS INVERSE.
15194 
15195  -- ALGLIB --
15196  Copyright 13.10.2010 by Bochkanov Sergey
15197 *************************************************************************/
15198 void minbleicsetprecdiag(minbleicstate* state,
15199  /* Real */ ae_vector* d,
15200  ae_state *_state)
15201 {
15202  ae_int_t i;
15203 
15204 
15205  ae_assert(d->cnt>=state->nmain, "MinBLEICSetPrecDiag: D is too short", _state);
15206  for(i=0; i<=state->nmain-1; i++)
15207  {
15208  ae_assert(ae_isfinite(d->ptr.p_double[i], _state), "MinBLEICSetPrecDiag: D contains infinite or NAN elements", _state);
15209  ae_assert(ae_fp_greater(d->ptr.p_double[i],0), "MinBLEICSetPrecDiag: D contains non-positive elements", _state);
15210  }
15211  rvectorsetlengthatleast(&state->diagh, state->nmain, _state);
15212  state->prectype = 2;
15213  for(i=0; i<=state->nmain-1; i++)
15214  {
15215  state->diagh.ptr.p_double[i] = d->ptr.p_double[i];
15216  }
15217 }
15218 
15219 
15220 /*************************************************************************
15221 Modification of the preconditioner: scale-based diagonal preconditioning.
15222 
15223 This preconditioning mode can be useful when you don't have approximate
15224 diagonal of Hessian, but you know that your variables are badly scaled
15225 (for example, one variable is in [1,10], and another in [1000,100000]),
15226 and most part of the ill-conditioning comes from different scales of vars.
15227 
15228 In this case simple scale-based preconditioner, with H[i] = 1/(s[i]^2),
15229 can greatly improve convergence.
15230 
15231 IMPRTANT: you should set scale of your variables with MinBLEICSetScale()
15232 call (before or after MinBLEICSetPrecScale() call). Without knowledge of
15233 the scale of your variables scale-based preconditioner will be just unit
15234 matrix.
15235 
15236 INPUT PARAMETERS:
15237  State - structure which stores algorithm state
15238 
15239  -- ALGLIB --
15240  Copyright 13.10.2010 by Bochkanov Sergey
15241 *************************************************************************/
15242 void minbleicsetprecscale(minbleicstate* state, ae_state *_state)
15243 {
15244 
15245 
15246  state->prectype = 3;
15247 }
15248 
15249 
15250 /*************************************************************************
15251 This function turns on/off reporting.
15252 
15253 INPUT PARAMETERS:
15254  State - structure which stores algorithm state
15255  NeedXRep- whether iteration reports are needed or not
15256 
15257 If NeedXRep is True, algorithm will call rep() callback function if it is
15258 provided to MinBLEICOptimize().
15259 
15260  -- ALGLIB --
15261  Copyright 28.11.2010 by Bochkanov Sergey
15262 *************************************************************************/
15263 void minbleicsetxrep(minbleicstate* state,
15264  ae_bool needxrep,
15265  ae_state *_state)
15266 {
15267 
15268 
15269  state->xrep = needxrep;
15270 }
15271 
15272 
15273 /*************************************************************************
15274 This function turns on/off line search reports.
15275 These reports are described in more details in developer-only comments on
15276 MinBLEICState object.
15277 
15278 INPUT PARAMETERS:
15279  State - structure which stores algorithm state
15280  NeedDRep- whether line search reports are needed or not
15281 
15282 This function is intended for private use only. Turning it on artificially
15283 may cause program failure.
15284 
15285  -- ALGLIB --
15286  Copyright 02.04.2010 by Bochkanov Sergey
15287 *************************************************************************/
15288 void minbleicsetdrep(minbleicstate* state,
15289  ae_bool needdrep,
15290  ae_state *_state)
15291 {
15292 
15293 
15294  state->drep = needdrep;
15295 }
15296 
15297 
15298 /*************************************************************************
15299 This function sets maximum step length
15300 
15301 IMPORTANT: this feature is hard to combine with preconditioning. You can't
15302 set upper limit on step length, when you solve optimization problem with
15303 linear (non-boundary) constraints AND preconditioner turned on.
15304 
15305 When non-boundary constraints are present, you have to either a) use
15306 preconditioner, or b) use upper limit on step length. YOU CAN'T USE BOTH!
15307 In this case algorithm will terminate with appropriate error code.
15308 
15309 INPUT PARAMETERS:
15310  State - structure which stores algorithm state
15311  StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't
15312  want to limit step length.
15313 
15314 Use this subroutine when you optimize target function which contains exp()
15315 or other fast growing functions, and optimization algorithm makes too
15316 large steps which lead to overflow. This function allows us to reject
15317 steps that are too large (and therefore expose us to the possible
15318 overflow) without actually calculating function value at the x+stp*d.
15319 
15320  -- ALGLIB --
15321  Copyright 02.04.2010 by Bochkanov Sergey
15322 *************************************************************************/
15323 void minbleicsetstpmax(minbleicstate* state,
15324  double stpmax,
15325  ae_state *_state)
15326 {
15327 
15328 
15329  ae_assert(ae_isfinite(stpmax, _state), "MinBLEICSetStpMax: StpMax is not finite!", _state);
15330  ae_assert(ae_fp_greater_eq(stpmax,0), "MinBLEICSetStpMax: StpMax<0!", _state);
15331  state->stpmax = stpmax;
15332 }
15333 
15334 
15335 /*************************************************************************
15336 NOTES:
15337 
15338 1. This function has two different implementations: one which uses exact
15339  (analytical) user-supplied gradient, and one which uses function value
15340  only and numerically differentiates function in order to obtain
15341  gradient.
15342 
15343  Depending on the specific function used to create optimizer object
15344  (either MinBLEICCreate() for analytical gradient or MinBLEICCreateF()
15345  for numerical differentiation) you should choose appropriate variant of
15346  MinBLEICOptimize() - one which accepts function AND gradient or one
15347  which accepts function ONLY.
15348 
15349  Be careful to choose variant of MinBLEICOptimize() which corresponds to
15350  your optimization scheme! Table below lists different combinations of
15351  callback (function/gradient) passed to MinBLEICOptimize() and specific
15352  function used to create optimizer.
15353 
15354 
15355  | USER PASSED TO MinBLEICOptimize()
15356  CREATED WITH | function only | function and gradient
15357  ------------------------------------------------------------
15358  MinBLEICCreateF() | work FAIL
15359  MinBLEICCreate() | FAIL work
15360 
15361  Here "FAIL" denotes inappropriate combinations of optimizer creation
15362  function and MinBLEICOptimize() version. Attemps to use such
15363  combination (for example, to create optimizer with MinBLEICCreateF()
15364  and to pass gradient information to MinCGOptimize()) will lead to
15365  exception being thrown. Either you did not pass gradient when it WAS
15366  needed or you passed gradient when it was NOT needed.
15367 
15368  -- ALGLIB --
15369  Copyright 28.11.2010 by Bochkanov Sergey
15370 *************************************************************************/
15371 ae_bool minbleiciteration(minbleicstate* state, ae_state *_state)
15372 {
15373  ae_int_t n;
15374  ae_int_t m;
15375  ae_int_t i;
15376  ae_int_t j;
15377  double v;
15378  double vv;
15379  ae_int_t badbfgsits;
15380  ae_bool b;
15381  ae_int_t nextaction;
15382  ae_int_t mcinfo;
15383  ae_int_t actstatus;
15384  ae_int_t ic;
15385  double penalty;
15386  double ginit;
15387  double gdecay;
15388  ae_bool result;
15389 
15390 
15391 
15392  /*
15393  * Reverse communication preparations
15394  * I know it looks ugly, but it works the same way
15395  * anywhere from C++ to Python.
15396  *
15397  * This code initializes locals by:
15398  * * random values determined during code
15399  * generation - on first subroutine call
15400  * * values from previous call - on subsequent calls
15401  */
15402  if( state->rstate.stage>=0 )
15403  {
15404  n = state->rstate.ia.ptr.p_int[0];
15405  m = state->rstate.ia.ptr.p_int[1];
15406  i = state->rstate.ia.ptr.p_int[2];
15407  j = state->rstate.ia.ptr.p_int[3];
15408  badbfgsits = state->rstate.ia.ptr.p_int[4];
15409  nextaction = state->rstate.ia.ptr.p_int[5];
15410  mcinfo = state->rstate.ia.ptr.p_int[6];
15411  actstatus = state->rstate.ia.ptr.p_int[7];
15412  ic = state->rstate.ia.ptr.p_int[8];
15413  b = state->rstate.ba.ptr.p_bool[0];
15414  v = state->rstate.ra.ptr.p_double[0];
15415  vv = state->rstate.ra.ptr.p_double[1];
15416  penalty = state->rstate.ra.ptr.p_double[2];
15417  ginit = state->rstate.ra.ptr.p_double[3];
15418  gdecay = state->rstate.ra.ptr.p_double[4];
15419  }
15420  else
15421  {
15422  n = -983;
15423  m = -989;
15424  i = -834;
15425  j = 900;
15426  badbfgsits = -287;
15427  nextaction = 364;
15428  mcinfo = 214;
15429  actstatus = -338;
15430  ic = -686;
15431  b = ae_false;
15432  v = 585;
15433  vv = 497;
15434  penalty = -271;
15435  ginit = -581;
15436  gdecay = 745;
15437  }
15438  if( state->rstate.stage==0 )
15439  {
15440  goto lbl_0;
15441  }
15442  if( state->rstate.stage==1 )
15443  {
15444  goto lbl_1;
15445  }
15446  if( state->rstate.stage==2 )
15447  {
15448  goto lbl_2;
15449  }
15450  if( state->rstate.stage==3 )
15451  {
15452  goto lbl_3;
15453  }
15454  if( state->rstate.stage==4 )
15455  {
15456  goto lbl_4;
15457  }
15458  if( state->rstate.stage==5 )
15459  {
15460  goto lbl_5;
15461  }
15462  if( state->rstate.stage==6 )
15463  {
15464  goto lbl_6;
15465  }
15466  if( state->rstate.stage==7 )
15467  {
15468  goto lbl_7;
15469  }
15470  if( state->rstate.stage==8 )
15471  {
15472  goto lbl_8;
15473  }
15474  if( state->rstate.stage==9 )
15475  {
15476  goto lbl_9;
15477  }
15478  if( state->rstate.stage==10 )
15479  {
15480  goto lbl_10;
15481  }
15482  if( state->rstate.stage==11 )
15483  {
15484  goto lbl_11;
15485  }
15486  if( state->rstate.stage==12 )
15487  {
15488  goto lbl_12;
15489  }
15490  if( state->rstate.stage==13 )
15491  {
15492  goto lbl_13;
15493  }
15494  if( state->rstate.stage==14 )
15495  {
15496  goto lbl_14;
15497  }
15498  if( state->rstate.stage==15 )
15499  {
15500  goto lbl_15;
15501  }
15502  if( state->rstate.stage==16 )
15503  {
15504  goto lbl_16;
15505  }
15506  if( state->rstate.stage==17 )
15507  {
15508  goto lbl_17;
15509  }
15510  if( state->rstate.stage==18 )
15511  {
15512  goto lbl_18;
15513  }
15514  if( state->rstate.stage==19 )
15515  {
15516  goto lbl_19;
15517  }
15518  if( state->rstate.stage==20 )
15519  {
15520  goto lbl_20;
15521  }
15522  if( state->rstate.stage==21 )
15523  {
15524  goto lbl_21;
15525  }
15526  if( state->rstate.stage==22 )
15527  {
15528  goto lbl_22;
15529  }
15530  if( state->rstate.stage==23 )
15531  {
15532  goto lbl_23;
15533  }
15534  if( state->rstate.stage==24 )
15535  {
15536  goto lbl_24;
15537  }
15538  if( state->rstate.stage==25 )
15539  {
15540  goto lbl_25;
15541  }
15542  if( state->rstate.stage==26 )
15543  {
15544  goto lbl_26;
15545  }
15546  if( state->rstate.stage==27 )
15547  {
15548  goto lbl_27;
15549  }
15550  if( state->rstate.stage==28 )
15551  {
15552  goto lbl_28;
15553  }
15554  if( state->rstate.stage==29 )
15555  {
15556  goto lbl_29;
15557  }
15558  if( state->rstate.stage==30 )
15559  {
15560  goto lbl_30;
15561  }
15562  if( state->rstate.stage==31 )
15563  {
15564  goto lbl_31;
15565  }
15566  if( state->rstate.stage==32 )
15567  {
15568  goto lbl_32;
15569  }
15570  if( state->rstate.stage==33 )
15571  {
15572  goto lbl_33;
15573  }
15574  if( state->rstate.stage==34 )
15575  {
15576  goto lbl_34;
15577  }
15578  if( state->rstate.stage==35 )
15579  {
15580  goto lbl_35;
15581  }
15582  if( state->rstate.stage==36 )
15583  {
15584  goto lbl_36;
15585  }
15586  if( state->rstate.stage==37 )
15587  {
15588  goto lbl_37;
15589  }
15590  if( state->rstate.stage==38 )
15591  {
15592  goto lbl_38;
15593  }
15594  if( state->rstate.stage==39 )
15595  {
15596  goto lbl_39;
15597  }
15598  if( state->rstate.stage==40 )
15599  {
15600  goto lbl_40;
15601  }
15602  if( state->rstate.stage==41 )
15603  {
15604  goto lbl_41;
15605  }
15606 
15607  /*
15608  * Routine body
15609  */
15610 
15611  /*
15612  * Algorithm parameters:
15613  * * M number of L-BFGS corrections.
15614  * This coefficient remains fixed during iterations.
15615  * * GDecay desired decrease of constrained gradient during L-BFGS iterations.
15616  * This coefficient is decreased after each L-BFGS round until
15617  * it reaches minimum decay.
15618  */
15619  m = ae_minint(5, state->nmain, _state);
15620  gdecay = minbleic_initialdecay;
15621 
15622  /*
15623  * Init
15624  */
15625  n = state->nmain;
15626  state->repterminationtype = 0;
15627  state->repinneriterationscount = 0;
15628  state->repouteriterationscount = 0;
15629  state->repnfev = 0;
15630  state->repvaridx = -1;
15631  state->repdebugeqerr = 0.0;
15632  state->repdebugfs = _state->v_nan;
15633  state->repdebugff = _state->v_nan;
15634  state->repdebugdx = _state->v_nan;
15635  if( ae_fp_neq(state->stpmax,0)&&state->prectype!=0 )
15636  {
15637  state->repterminationtype = -10;
15638  result = ae_false;
15639  return result;
15640  }
15641  rvectorsetlengthatleast(&state->rho, m, _state);
15642  rvectorsetlengthatleast(&state->theta, m, _state);
15643  rmatrixsetlengthatleast(&state->yk, m, n, _state);
15644  rmatrixsetlengthatleast(&state->sk, m, n, _state);
15645 
15646  /*
15647  * Fill TmpPrec with current preconditioner
15648  */
15649  rvectorsetlengthatleast(&state->tmpprec, n, _state);
15650  for(i=0; i<=n-1; i++)
15651  {
15652  if( state->prectype==2 )
15653  {
15654  state->tmpprec.ptr.p_double[i] = state->diagh.ptr.p_double[i];
15655  continue;
15656  }
15657  if( state->prectype==3 )
15658  {
15659  state->tmpprec.ptr.p_double[i] = 1/ae_sqr(state->s.ptr.p_double[i], _state);
15660  continue;
15661  }
15662  state->tmpprec.ptr.p_double[i] = 1;
15663  }
15664  sassetprecdiag(&state->sas, &state->tmpprec, _state);
15665 
15666  /*
15667  * Start optimization
15668  */
15669  if( !sasstartoptimization(&state->sas, &state->xstart, _state) )
15670  {
15671  state->repterminationtype = -3;
15672  result = ae_false;
15673  return result;
15674  }
15675 
15676  /*
15677  * Check correctness of user-supplied gradient
15678  */
15679  if( !(ae_fp_eq(state->diffstep,0)&&ae_fp_greater(state->teststep,0)) )
15680  {
15681  goto lbl_42;
15682  }
15683  minbleic_clearrequestfields(state, _state);
15684  ae_v_move(&state->x.ptr.p_double[0], 1, &state->sas.xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
15685  state->needfg = ae_true;
15686  i = 0;
15687 lbl_44:
15688  if( i>n-1 )
15689  {
15690  goto lbl_46;
15691  }
15692  ae_assert(!state->hasbndl.ptr.p_bool[i]||ae_fp_greater_eq(state->sas.xc.ptr.p_double[i],state->bndl.ptr.p_double[i]), "MinBLEICIteration: internal error(State.X is out of bounds)", _state);
15693  ae_assert(!state->hasbndu.ptr.p_bool[i]||ae_fp_less_eq(state->sas.xc.ptr.p_double[i],state->bndu.ptr.p_double[i]), "MinBLEICIteration: internal error(State.X is out of bounds)", _state);
15694  v = state->x.ptr.p_double[i];
15695  state->x.ptr.p_double[i] = v-state->teststep*state->s.ptr.p_double[i];
15696  if( state->hasbndl.ptr.p_bool[i] )
15697  {
15698  state->x.ptr.p_double[i] = ae_maxreal(state->x.ptr.p_double[i], state->bndl.ptr.p_double[i], _state);
15699  }
15700  state->xm1 = state->x.ptr.p_double[i];
15701  state->rstate.stage = 0;
15702  goto lbl_rcomm;
15703 lbl_0:
15704  state->fm1 = state->f;
15705  state->gm1 = state->g.ptr.p_double[i];
15706  state->x.ptr.p_double[i] = v+state->teststep*state->s.ptr.p_double[i];
15707  if( state->hasbndu.ptr.p_bool[i] )
15708  {
15709  state->x.ptr.p_double[i] = ae_minreal(state->x.ptr.p_double[i], state->bndu.ptr.p_double[i], _state);
15710  }
15711  state->xp1 = state->x.ptr.p_double[i];
15712  state->rstate.stage = 1;
15713  goto lbl_rcomm;
15714 lbl_1:
15715  state->fp1 = state->f;
15716  state->gp1 = state->g.ptr.p_double[i];
15717  state->x.ptr.p_double[i] = (state->xm1+state->xp1)/2;
15718  if( state->hasbndl.ptr.p_bool[i] )
15719  {
15720  state->x.ptr.p_double[i] = ae_maxreal(state->x.ptr.p_double[i], state->bndl.ptr.p_double[i], _state);
15721  }
15722  if( state->hasbndu.ptr.p_bool[i] )
15723  {
15724  state->x.ptr.p_double[i] = ae_minreal(state->x.ptr.p_double[i], state->bndu.ptr.p_double[i], _state);
15725  }
15726  state->rstate.stage = 2;
15727  goto lbl_rcomm;
15728 lbl_2:
15729  state->x.ptr.p_double[i] = v;
15730  if( !derivativecheck(state->fm1, state->gm1, state->fp1, state->gp1, state->f, state->g.ptr.p_double[i], state->xp1-state->xm1, _state) )
15731  {
15732  state->repvaridx = i;
15733  state->repterminationtype = -7;
15734  sasstopoptimization(&state->sas, _state);
15735  result = ae_false;
15736  return result;
15737  }
15738  i = i+1;
15739  goto lbl_44;
15740 lbl_46:
15741  state->needfg = ae_false;
15742 lbl_42:
15743 
15744  /*
15745  * Main cycle of BLEIC-PG algorithm
15746  */
15747  state->repterminationtype = 4;
15748  badbfgsits = 0;
15749  state->lastgoodstep = 0;
15750  state->lastscaledgoodstep = 0;
15751  state->maxscaledgrad = 0;
15752  state->nonmonotoniccnt = n+state->nic;
15753  ae_v_move(&state->x.ptr.p_double[0], 1, &state->sas.xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
15754  minbleic_clearrequestfields(state, _state);
15755  if( ae_fp_neq(state->diffstep,0) )
15756  {
15757  goto lbl_47;
15758  }
15759  state->needfg = ae_true;
15760  state->rstate.stage = 3;
15761  goto lbl_rcomm;
15762 lbl_3:
15763  state->needfg = ae_false;
15764  goto lbl_48;
15765 lbl_47:
15766  state->needf = ae_true;
15767  state->rstate.stage = 4;
15768  goto lbl_rcomm;
15769 lbl_4:
15770  state->needf = ae_false;
15771 lbl_48:
15772  state->fc = state->f;
15773  trimprepare(state->f, &state->trimthreshold, _state);
15774  state->repnfev = state->repnfev+1;
15775  if( !state->xrep )
15776  {
15777  goto lbl_49;
15778  }
15779 
15780  /*
15781  * Report current point
15782  */
15783  ae_v_move(&state->x.ptr.p_double[0], 1, &state->sas.xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
15784  state->f = state->fc;
15785  state->xupdated = ae_true;
15786  state->rstate.stage = 5;
15787  goto lbl_rcomm;
15788 lbl_5:
15789  state->xupdated = ae_false;
15790 lbl_49:
15791 lbl_51:
15792  if( ae_false )
15793  {
15794  goto lbl_52;
15795  }
15796 
15797  /*
15798  * Phase 1
15799  *
15800  * (a) calculate unconstrained gradient
15801  * (b) determine active set
15802  * (c) update MaxScaledGrad
15803  */
15804  ae_v_move(&state->x.ptr.p_double[0], 1, &state->sas.xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
15805  minbleic_clearrequestfields(state, _state);
15806  if( ae_fp_neq(state->diffstep,0) )
15807  {
15808  goto lbl_53;
15809  }
15810 
15811  /*
15812  * Analytic gradient
15813  */
15814  state->needfg = ae_true;
15815  state->rstate.stage = 6;
15816  goto lbl_rcomm;
15817 lbl_6:
15818  state->needfg = ae_false;
15819  goto lbl_54;
15820 lbl_53:
15821 
15822  /*
15823  * Numerical differentiation
15824  */
15825  state->needf = ae_true;
15826  state->rstate.stage = 7;
15827  goto lbl_rcomm;
15828 lbl_7:
15829  state->fbase = state->f;
15830  i = 0;
15831 lbl_55:
15832  if( i>n-1 )
15833  {
15834  goto lbl_57;
15835  }
15836  v = state->x.ptr.p_double[i];
15837  b = ae_false;
15838  if( state->hasbndl.ptr.p_bool[i] )
15839  {
15840  b = b||ae_fp_less(v-state->diffstep*state->s.ptr.p_double[i],state->bndl.ptr.p_double[i]);
15841  }
15842  if( state->hasbndu.ptr.p_bool[i] )
15843  {
15844  b = b||ae_fp_greater(v+state->diffstep*state->s.ptr.p_double[i],state->bndu.ptr.p_double[i]);
15845  }
15846  if( b )
15847  {
15848  goto lbl_58;
15849  }
15850  state->x.ptr.p_double[i] = v-state->diffstep*state->s.ptr.p_double[i];
15851  state->rstate.stage = 8;
15852  goto lbl_rcomm;
15853 lbl_8:
15854  state->fm2 = state->f;
15855  state->x.ptr.p_double[i] = v-0.5*state->diffstep*state->s.ptr.p_double[i];
15856  state->rstate.stage = 9;
15857  goto lbl_rcomm;
15858 lbl_9:
15859  state->fm1 = state->f;
15860  state->x.ptr.p_double[i] = v+0.5*state->diffstep*state->s.ptr.p_double[i];
15861  state->rstate.stage = 10;
15862  goto lbl_rcomm;
15863 lbl_10:
15864  state->fp1 = state->f;
15865  state->x.ptr.p_double[i] = v+state->diffstep*state->s.ptr.p_double[i];
15866  state->rstate.stage = 11;
15867  goto lbl_rcomm;
15868 lbl_11:
15869  state->fp2 = state->f;
15870  state->g.ptr.p_double[i] = (8*(state->fp1-state->fm1)-(state->fp2-state->fm2))/(6*state->diffstep*state->s.ptr.p_double[i]);
15871  goto lbl_59;
15872 lbl_58:
15873  state->xm1 = v-state->diffstep*state->s.ptr.p_double[i];
15874  state->xp1 = v+state->diffstep*state->s.ptr.p_double[i];
15875  if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less(state->xm1,state->bndl.ptr.p_double[i]) )
15876  {
15877  state->xm1 = state->bndl.ptr.p_double[i];
15878  }
15879  if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater(state->xp1,state->bndu.ptr.p_double[i]) )
15880  {
15881  state->xp1 = state->bndu.ptr.p_double[i];
15882  }
15883  state->x.ptr.p_double[i] = state->xm1;
15884  state->rstate.stage = 12;
15885  goto lbl_rcomm;
15886 lbl_12:
15887  state->fm1 = state->f;
15888  state->x.ptr.p_double[i] = state->xp1;
15889  state->rstate.stage = 13;
15890  goto lbl_rcomm;
15891 lbl_13:
15892  state->fp1 = state->f;
15893  if( ae_fp_neq(state->xm1,state->xp1) )
15894  {
15895  state->g.ptr.p_double[i] = (state->fp1-state->fm1)/(state->xp1-state->xm1);
15896  }
15897  else
15898  {
15899  state->g.ptr.p_double[i] = 0;
15900  }
15901 lbl_59:
15902  state->x.ptr.p_double[i] = v;
15903  i = i+1;
15904  goto lbl_55;
15905 lbl_57:
15906  state->f = state->fbase;
15907  state->needf = ae_false;
15908 lbl_54:
15909  state->fc = state->f;
15910  ae_v_move(&state->gc.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1));
15911  sasreactivateconstraintsprec(&state->sas, &state->gc, _state);
15912  v = 0.0;
15913  for(i=0; i<=n-1; i++)
15914  {
15915  v = v+ae_sqr(state->gc.ptr.p_double[i]*state->s.ptr.p_double[i], _state);
15916  }
15917  state->maxscaledgrad = ae_maxreal(state->maxscaledgrad, ae_sqrt(v, _state), _state);
15918 
15919  /*
15920  * Phase 2: perform steepest descent step.
15921  *
15922  * NextAction control variable is set on exit from this loop:
15923  * * NextAction>0 in case we have to proceed to Phase 3 (L-BFGS step)
15924  * * NextAction<0 in case we have to proceed to Phase 1 (recalculate active set)
15925  * * NextAction=0 in case we found solution (step size or function change are small enough)
15926  */
15927  nextaction = 0;
15928 lbl_60:
15929  if( ae_false )
15930  {
15931  goto lbl_61;
15932  }
15933 
15934  /*
15935  * Check gradient-based stopping criteria
15936  */
15937  if( ae_fp_less_eq(sasscaledconstrainednorm(&state->sas, &state->gc, _state),state->epsg) )
15938  {
15939 
15940  /*
15941  * Gradient is small enough, stop iterations
15942  */
15943  state->repterminationtype = 4;
15944  nextaction = 0;
15945  goto lbl_61;
15946  }
15947 
15948  /*
15949  * Calculate normalized constrained descent direction, store to D.
15950  * Try to use previous scaled step length as initial estimate for new step.
15951  *
15952  * NOTE: D can be exactly zero, in this case Stp is set to 1.0
15953  */
15954  sasconstraineddescentprec(&state->sas, &state->gc, &state->d, _state);
15955  v = 0;
15956  for(i=0; i<=n-1; i++)
15957  {
15958  v = v+ae_sqr(state->d.ptr.p_double[i]/state->s.ptr.p_double[i], _state);
15959  }
15960  v = ae_sqrt(v, _state);
15961  if( ae_fp_greater(state->lastscaledgoodstep,0)&&ae_fp_greater(v,0) )
15962  {
15963  state->stp = state->lastscaledgoodstep/v;
15964  }
15965  else
15966  {
15967  state->stp = 1.0;
15968  }
15969 
15970  /*
15971  * Calculate bound on step length.
15972  * Enforce user-supplied limit on step length.
15973  */
15974  sasexploredirection(&state->sas, &state->d, &state->curstpmax, &state->cidx, &state->cval, _state);
15975  state->activationstep = state->curstpmax;
15976  if( state->cidx>=0&&ae_fp_eq(state->activationstep,0) )
15977  {
15978  sasimmediateactivation(&state->sas, state->cidx, state->cval, _state);
15979  goto lbl_60;
15980  }
15981  if( ae_fp_greater(state->stpmax,0) )
15982  {
15983  state->curstpmax = ae_minreal(state->curstpmax, state->stpmax, _state);
15984  }
15985 
15986  /*
15987  * Report beginning of line search (if requested by caller).
15988  * See description of the MinBLEICState for more information
15989  * about fields accessible to caller.
15990  *
15991  * Caller may do following:
15992  * * change State.Stp and load better initial estimate of
15993  * the step length.
15994  */
15995  if( !state->drep )
15996  {
15997  goto lbl_62;
15998  }
15999  minbleic_clearrequestfields(state, _state);
16000  state->lsstart = ae_true;
16001  state->lbfgssearch = ae_false;
16002  state->boundedstep = state->cidx>=0;
16003  ae_v_move(&state->x.ptr.p_double[0], 1, &state->sas.xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
16004  ae_v_move(&state->g.ptr.p_double[0], 1, &state->gc.ptr.p_double[0], 1, ae_v_len(0,n-1));
16005  state->f = state->fc;
16006  state->rstate.stage = 14;
16007  goto lbl_rcomm;
16008 lbl_14:
16009  state->lsstart = ae_false;
16010 lbl_62:
16011 
16012  /*
16013  * Perform optimization of F along XC+alpha*D.
16014  */
16015  state->mcstage = 0;
16016  ae_v_move(&state->xn.ptr.p_double[0], 1, &state->sas.xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
16017  ae_v_move(&state->gn.ptr.p_double[0], 1, &state->gc.ptr.p_double[0], 1, ae_v_len(0,n-1));
16018  state->fn = state->fc;
16019  mcsrch(n, &state->xn, &state->fn, &state->gn, &state->d, &state->stp, state->curstpmax, minbleic_gtol, &mcinfo, &state->nfev, &state->work, &state->lstate, &state->mcstage, _state);
16020 lbl_64:
16021  if( state->mcstage==0 )
16022  {
16023  goto lbl_65;
16024  }
16025 
16026  /*
16027  * Enforce constraints (correction) in XN.
16028  * Copy current point from XN to X.
16029  */
16030  sascorrection(&state->sas, &state->xn, &penalty, _state);
16031  for(i=0; i<=n-1; i++)
16032  {
16033  state->x.ptr.p_double[i] = state->xn.ptr.p_double[i];
16034  }
16035 
16036  /*
16037  * Gradient, either user-provided or numerical differentiation
16038  */
16039  minbleic_clearrequestfields(state, _state);
16040  if( ae_fp_neq(state->diffstep,0) )
16041  {
16042  goto lbl_66;
16043  }
16044 
16045  /*
16046  * Analytic gradient
16047  */
16048  state->needfg = ae_true;
16049  state->rstate.stage = 15;
16050  goto lbl_rcomm;
16051 lbl_15:
16052  state->needfg = ae_false;
16053  state->repnfev = state->repnfev+1;
16054  goto lbl_67;
16055 lbl_66:
16056 
16057  /*
16058  * Numerical differentiation
16059  */
16060  state->needf = ae_true;
16061  state->rstate.stage = 16;
16062  goto lbl_rcomm;
16063 lbl_16:
16064  state->fbase = state->f;
16065  i = 0;
16066 lbl_68:
16067  if( i>n-1 )
16068  {
16069  goto lbl_70;
16070  }
16071  v = state->x.ptr.p_double[i];
16072  b = ae_false;
16073  if( state->hasbndl.ptr.p_bool[i] )
16074  {
16075  b = b||ae_fp_less(v-state->diffstep*state->s.ptr.p_double[i],state->bndl.ptr.p_double[i]);
16076  }
16077  if( state->hasbndu.ptr.p_bool[i] )
16078  {
16079  b = b||ae_fp_greater(v+state->diffstep*state->s.ptr.p_double[i],state->bndu.ptr.p_double[i]);
16080  }
16081  if( b )
16082  {
16083  goto lbl_71;
16084  }
16085  state->x.ptr.p_double[i] = v-state->diffstep*state->s.ptr.p_double[i];
16086  state->rstate.stage = 17;
16087  goto lbl_rcomm;
16088 lbl_17:
16089  state->fm2 = state->f;
16090  state->x.ptr.p_double[i] = v-0.5*state->diffstep*state->s.ptr.p_double[i];
16091  state->rstate.stage = 18;
16092  goto lbl_rcomm;
16093 lbl_18:
16094  state->fm1 = state->f;
16095  state->x.ptr.p_double[i] = v+0.5*state->diffstep*state->s.ptr.p_double[i];
16096  state->rstate.stage = 19;
16097  goto lbl_rcomm;
16098 lbl_19:
16099  state->fp1 = state->f;
16100  state->x.ptr.p_double[i] = v+state->diffstep*state->s.ptr.p_double[i];
16101  state->rstate.stage = 20;
16102  goto lbl_rcomm;
16103 lbl_20:
16104  state->fp2 = state->f;
16105  state->g.ptr.p_double[i] = (8*(state->fp1-state->fm1)-(state->fp2-state->fm2))/(6*state->diffstep*state->s.ptr.p_double[i]);
16106  state->repnfev = state->repnfev+4;
16107  goto lbl_72;
16108 lbl_71:
16109  state->xm1 = v-state->diffstep*state->s.ptr.p_double[i];
16110  state->xp1 = v+state->diffstep*state->s.ptr.p_double[i];
16111  if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less(state->xm1,state->bndl.ptr.p_double[i]) )
16112  {
16113  state->xm1 = state->bndl.ptr.p_double[i];
16114  }
16115  if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater(state->xp1,state->bndu.ptr.p_double[i]) )
16116  {
16117  state->xp1 = state->bndu.ptr.p_double[i];
16118  }
16119  state->x.ptr.p_double[i] = state->xm1;
16120  state->rstate.stage = 21;
16121  goto lbl_rcomm;
16122 lbl_21:
16123  state->fm1 = state->f;
16124  state->x.ptr.p_double[i] = state->xp1;
16125  state->rstate.stage = 22;
16126  goto lbl_rcomm;
16127 lbl_22:
16128  state->fp1 = state->f;
16129  if( ae_fp_neq(state->xm1,state->xp1) )
16130  {
16131  state->g.ptr.p_double[i] = (state->fp1-state->fm1)/(state->xp1-state->xm1);
16132  }
16133  else
16134  {
16135  state->g.ptr.p_double[i] = 0;
16136  }
16137  state->repnfev = state->repnfev+2;
16138 lbl_72:
16139  state->x.ptr.p_double[i] = v;
16140  i = i+1;
16141  goto lbl_68;
16142 lbl_70:
16143  state->f = state->fbase;
16144  state->needf = ae_false;
16145 lbl_67:
16146 
16147  /*
16148  * Back to MCSRCH
16149  *
16150  * NOTE: penalty term from correction is added to FN in order
16151  * to penalize increase in infeasibility.
16152  */
16153  state->fn = state->f+minbleic_penaltyfactor*state->maxscaledgrad*penalty;
16154  ae_v_move(&state->gn.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1));
16155  trimfunction(&state->fn, &state->gn, n, state->trimthreshold, _state);
16156  mcsrch(n, &state->xn, &state->fn, &state->gn, &state->d, &state->stp, state->curstpmax, minbleic_gtol, &mcinfo, &state->nfev, &state->work, &state->lstate, &state->mcstage, _state);
16157  goto lbl_64;
16158 lbl_65:
16159 
16160  /*
16161  * Handle possible failure of the line search
16162  */
16163  if( mcinfo!=1&&mcinfo!=5 )
16164  {
16165 
16166  /*
16167  * We can not find step which decreases function value. We have
16168  * two possibilities:
16169  * (a) numerical properties of the function do not allow us to
16170  * find good solution.
16171  * (b) we are close to activation of some constraint, and it is
16172  * so close that step which activates it leads to change in
16173  * target function which is smaller than numerical noise.
16174  *
16175  * Optimization algorithm must be able to handle case (b), because
16176  * inability to handle it will cause failure when algorithm
16177  * started very close to boundary of the feasible area.
16178  *
16179  * In order to correctly handle such cases we allow limited amount
16180  * of small steps which increase function value.
16181  */
16182  v = 0.0;
16183  for(i=0; i<=n-1; i++)
16184  {
16185  v = v+ae_sqr(state->d.ptr.p_double[i]*state->curstpmax/state->s.ptr.p_double[i], _state);
16186  }
16187  v = ae_sqrt(v, _state);
16188  if( (state->cidx>=0&&ae_fp_less_eq(v,minbleic_maxnonmonotoniclen))&&state->nonmonotoniccnt>0 )
16189  {
16190 
16191  /*
16192  * We enforce non-monotonic step:
16193  * * Stp := CurStpMax
16194  * * MCINFO := 5
16195  * * XN := XC+CurStpMax*D
16196  * * non-monotonic counter is decreased
16197  */
16198  state->stp = state->curstpmax;
16199  mcinfo = 5;
16200  v = state->curstpmax;
16201  ae_v_move(&state->xn.ptr.p_double[0], 1, &state->sas.xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
16202  ae_v_addd(&state->xn.ptr.p_double[0], 1, &state->d.ptr.p_double[0], 1, ae_v_len(0,n-1), v);
16203  state->nonmonotoniccnt = state->nonmonotoniccnt-1;
16204  }
16205  else
16206  {
16207 
16208  /*
16209  * Numerical properties of the function does not allow us to solve problem
16210  */
16211  state->repterminationtype = 7;
16212  nextaction = 0;
16213  goto lbl_61;
16214  }
16215  }
16216 
16217  /*
16218  * Current point is updated.
16219  */
16220  ae_v_move(&state->xp.ptr.p_double[0], 1, &state->sas.xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
16221  ae_v_move(&state->gp.ptr.p_double[0], 1, &state->gc.ptr.p_double[0], 1, ae_v_len(0,n-1));
16222  state->fp = state->fc;
16223  actstatus = sasmoveto(&state->sas, &state->xn, state->cidx>=0&&ae_fp_greater_eq(state->stp,state->activationstep), state->cidx, state->cval, _state);
16224  ae_v_move(&state->gc.ptr.p_double[0], 1, &state->gn.ptr.p_double[0], 1, ae_v_len(0,n-1));
16225  state->fc = state->fn;
16226  state->repinneriterationscount = state->repinneriterationscount+1;
16227  if( !state->xrep )
16228  {
16229  goto lbl_73;
16230  }
16231  ae_v_move(&state->x.ptr.p_double[0], 1, &state->sas.xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
16232  minbleic_clearrequestfields(state, _state);
16233  state->xupdated = ae_true;
16234  state->rstate.stage = 23;
16235  goto lbl_rcomm;
16236 lbl_23:
16237  state->xupdated = ae_false;
16238 lbl_73:
16239 
16240  /*
16241  * Check for stopping.
16242  *
16243  * Step, gradient and function-based stopping criteria are tested only
16244  * for steps which satisfy Wolfe conditions.
16245  *
16246  * MaxIts-based stopping condition is checked for all steps
16247  */
16248  if( mcinfo==1 )
16249  {
16250 
16251  /*
16252  * Step is small enough
16253  */
16254  v = 0;
16255  vv = 0;
16256  for(i=0; i<=n-1; i++)
16257  {
16258  v = v+ae_sqr((state->sas.xc.ptr.p_double[i]-state->xp.ptr.p_double[i])/state->s.ptr.p_double[i], _state);
16259  vv = vv+ae_sqr(state->sas.xc.ptr.p_double[i]-state->xp.ptr.p_double[i], _state);
16260  }
16261  v = ae_sqrt(v, _state);
16262  vv = ae_sqrt(vv, _state);
16263  if( ae_fp_less_eq(v,state->epsx) )
16264  {
16265  state->repterminationtype = 2;
16266  nextaction = 0;
16267  goto lbl_61;
16268  }
16269  state->lastgoodstep = vv;
16270  minbleic_updateestimateofgoodstep(&state->lastscaledgoodstep, v, _state);
16271 
16272  /*
16273  * Function change is small enough
16274  */
16275  if( ae_fp_less_eq(ae_fabs(state->fp-state->fc, _state),state->epsf*ae_maxreal(ae_fabs(state->fc, _state), ae_maxreal(ae_fabs(state->fp, _state), 1.0, _state), _state)) )
16276  {
16277 
16278  /*
16279  * Function change is small enough
16280  */
16281  state->repterminationtype = 1;
16282  nextaction = 0;
16283  goto lbl_61;
16284  }
16285  }
16286  if( state->maxits>0&&state->repinneriterationscount>=state->maxits )
16287  {
16288 
16289  /*
16290  * Required number of iterations was performed
16291  */
16292  state->repterminationtype = 5;
16293  nextaction = 0;
16294  goto lbl_61;
16295  }
16296 
16297  /*
16298  * Decide where to move:
16299  * * in case only "candidate" constraints were activated, repeat stage 2
16300  * * in case no constraints was activated, move to stage 3
16301  * * otherwise, move to stage 1 (re-evaluation of the active set)
16302  */
16303  if( actstatus==0 )
16304  {
16305  goto lbl_60;
16306  }
16307  if( actstatus<0 )
16308  {
16309  nextaction = 1;
16310  }
16311  else
16312  {
16313  nextaction = -1;
16314  }
16315  goto lbl_61;
16316  goto lbl_60;
16317 lbl_61:
16318  if( nextaction<0 )
16319  {
16320  goto lbl_51;
16321  }
16322  if( nextaction==0 )
16323  {
16324  goto lbl_52;
16325  }
16326 
16327  /*
16328  * Phase 3: L-BFGS step
16329  */
16330  ae_v_move(&state->x.ptr.p_double[0], 1, &state->sas.xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
16331  minbleic_clearrequestfields(state, _state);
16332  if( ae_fp_neq(state->diffstep,0) )
16333  {
16334  goto lbl_75;
16335  }
16336 
16337  /*
16338  * Analytic gradient
16339  */
16340  state->needfg = ae_true;
16341  state->rstate.stage = 24;
16342  goto lbl_rcomm;
16343 lbl_24:
16344  state->needfg = ae_false;
16345  state->repnfev = state->repnfev+1;
16346  goto lbl_76;
16347 lbl_75:
16348 
16349  /*
16350  * Numerical differentiation
16351  */
16352  state->needf = ae_true;
16353  state->rstate.stage = 25;
16354  goto lbl_rcomm;
16355 lbl_25:
16356  state->fbase = state->f;
16357  i = 0;
16358 lbl_77:
16359  if( i>n-1 )
16360  {
16361  goto lbl_79;
16362  }
16363  v = state->x.ptr.p_double[i];
16364  b = ae_false;
16365  if( state->hasbndl.ptr.p_bool[i] )
16366  {
16367  b = b||ae_fp_less(v-state->diffstep*state->s.ptr.p_double[i],state->bndl.ptr.p_double[i]);
16368  }
16369  if( state->hasbndu.ptr.p_bool[i] )
16370  {
16371  b = b||ae_fp_greater(v+state->diffstep*state->s.ptr.p_double[i],state->bndu.ptr.p_double[i]);
16372  }
16373  if( b )
16374  {
16375  goto lbl_80;
16376  }
16377  state->x.ptr.p_double[i] = v-state->diffstep*state->s.ptr.p_double[i];
16378  state->rstate.stage = 26;
16379  goto lbl_rcomm;
16380 lbl_26:
16381  state->fm2 = state->f;
16382  state->x.ptr.p_double[i] = v-0.5*state->diffstep*state->s.ptr.p_double[i];
16383  state->rstate.stage = 27;
16384  goto lbl_rcomm;
16385 lbl_27:
16386  state->fm1 = state->f;
16387  state->x.ptr.p_double[i] = v+0.5*state->diffstep*state->s.ptr.p_double[i];
16388  state->rstate.stage = 28;
16389  goto lbl_rcomm;
16390 lbl_28:
16391  state->fp1 = state->f;
16392  state->x.ptr.p_double[i] = v+state->diffstep*state->s.ptr.p_double[i];
16393  state->rstate.stage = 29;
16394  goto lbl_rcomm;
16395 lbl_29:
16396  state->fp2 = state->f;
16397  state->g.ptr.p_double[i] = (8*(state->fp1-state->fm1)-(state->fp2-state->fm2))/(6*state->diffstep*state->s.ptr.p_double[i]);
16398  state->repnfev = state->repnfev+4;
16399  goto lbl_81;
16400 lbl_80:
16401  state->xm1 = v-state->diffstep*state->s.ptr.p_double[i];
16402  state->xp1 = v+state->diffstep*state->s.ptr.p_double[i];
16403  if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less(state->xm1,state->bndl.ptr.p_double[i]) )
16404  {
16405  state->xm1 = state->bndl.ptr.p_double[i];
16406  }
16407  if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater(state->xp1,state->bndu.ptr.p_double[i]) )
16408  {
16409  state->xp1 = state->bndu.ptr.p_double[i];
16410  }
16411  state->x.ptr.p_double[i] = state->xm1;
16412  state->rstate.stage = 30;
16413  goto lbl_rcomm;
16414 lbl_30:
16415  state->fm1 = state->f;
16416  state->x.ptr.p_double[i] = state->xp1;
16417  state->rstate.stage = 31;
16418  goto lbl_rcomm;
16419 lbl_31:
16420  state->fp1 = state->f;
16421  if( ae_fp_neq(state->xm1,state->xp1) )
16422  {
16423  state->g.ptr.p_double[i] = (state->fp1-state->fm1)/(state->xp1-state->xm1);
16424  }
16425  else
16426  {
16427  state->g.ptr.p_double[i] = 0;
16428  }
16429  state->repnfev = state->repnfev+2;
16430 lbl_81:
16431  state->x.ptr.p_double[i] = v;
16432  i = i+1;
16433  goto lbl_77;
16434 lbl_79:
16435  state->f = state->fbase;
16436  state->needf = ae_false;
16437 lbl_76:
16438  state->fc = state->f;
16439  trimprepare(state->fc, &state->trimthreshold, _state);
16440  ae_v_move(&state->gc.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1));
16441  ae_v_moveneg(&state->d.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1));
16442  sasconstraineddirection(&state->sas, &state->gc, _state);
16443  sasconstraineddirectionprec(&state->sas, &state->d, _state);
16444  ginit = 0.0;
16445  for(i=0; i<=n-1; i++)
16446  {
16447  ginit = ginit+ae_sqr(state->gc.ptr.p_double[i]*state->s.ptr.p_double[i], _state);
16448  }
16449  ginit = ae_sqrt(ginit, _state);
16450  state->k = 0;
16451 lbl_82:
16452  if( state->k>n )
16453  {
16454  goto lbl_83;
16455  }
16456 
16457  /*
16458  * Main cycle: prepare to 1-D line search
16459  */
16460  state->p = state->k%m;
16461  state->q = ae_minint(state->k, m-1, _state);
16462 
16463  /*
16464  * Store X[k], G[k]
16465  */
16466  ae_v_moveneg(&state->sk.ptr.pp_double[state->p][0], 1, &state->sas.xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
16467  ae_v_moveneg(&state->yk.ptr.pp_double[state->p][0], 1, &state->gc.ptr.p_double[0], 1, ae_v_len(0,n-1));
16468 
16469  /*
16470  * Try to use previous scaled step length as initial estimate for new step.
16471  */
16472  v = 0;
16473  for(i=0; i<=n-1; i++)
16474  {
16475  v = v+ae_sqr(state->d.ptr.p_double[i]/state->s.ptr.p_double[i], _state);
16476  }
16477  v = ae_sqrt(v, _state);
16478  if( ae_fp_greater(state->lastscaledgoodstep,0)&&ae_fp_greater(v,0) )
16479  {
16480  state->stp = state->lastscaledgoodstep/v;
16481  }
16482  else
16483  {
16484  state->stp = 1.0;
16485  }
16486 
16487  /*
16488  * Calculate bound on step length
16489  */
16490  sasexploredirection(&state->sas, &state->d, &state->curstpmax, &state->cidx, &state->cval, _state);
16491  state->activationstep = state->curstpmax;
16492  if( state->cidx>=0&&ae_fp_eq(state->activationstep,0) )
16493  {
16494  goto lbl_83;
16495  }
16496  if( ae_fp_greater(state->stpmax,0) )
16497  {
16498  v = ae_v_dotproduct(&state->d.ptr.p_double[0], 1, &state->d.ptr.p_double[0], 1, ae_v_len(0,n-1));
16499  v = ae_sqrt(v, _state);
16500  if( ae_fp_greater(v,0) )
16501  {
16502  state->curstpmax = ae_minreal(state->curstpmax, state->stpmax/v, _state);
16503  }
16504  }
16505 
16506  /*
16507  * Report beginning of line search (if requested by caller).
16508  * See description of the MinBLEICState for more information
16509  * about fields accessible to caller.
16510  *
16511  * Caller may do following:
16512  * * change State.Stp and load better initial estimate of
16513  * the step length.
16514  * Caller may not terminate algorithm.
16515  */
16516  if( !state->drep )
16517  {
16518  goto lbl_84;
16519  }
16520  minbleic_clearrequestfields(state, _state);
16521  state->lsstart = ae_true;
16522  state->lbfgssearch = ae_true;
16523  state->boundedstep = state->cidx>=0;
16524  ae_v_move(&state->x.ptr.p_double[0], 1, &state->sas.xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
16525  state->rstate.stage = 32;
16526  goto lbl_rcomm;
16527 lbl_32:
16528  state->lsstart = ae_false;
16529 lbl_84:
16530 
16531  /*
16532  * Minimize F(x+alpha*d)
16533  */
16534  ae_v_move(&state->xn.ptr.p_double[0], 1, &state->sas.xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
16535  ae_v_move(&state->gn.ptr.p_double[0], 1, &state->gc.ptr.p_double[0], 1, ae_v_len(0,n-1));
16536  state->fn = state->fc;
16537  state->mcstage = 0;
16538  mcsrch(n, &state->xn, &state->fn, &state->gn, &state->d, &state->stp, state->curstpmax, minbleic_gtol, &mcinfo, &state->nfev, &state->work, &state->lstate, &state->mcstage, _state);
16539 lbl_86:
16540  if( state->mcstage==0 )
16541  {
16542  goto lbl_87;
16543  }
16544 
16545  /*
16546  * Perform correction (constraints are enforced)
16547  * Copy XN to X
16548  */
16549  sascorrection(&state->sas, &state->xn, &penalty, _state);
16550  for(i=0; i<=n-1; i++)
16551  {
16552  state->x.ptr.p_double[i] = state->xn.ptr.p_double[i];
16553  }
16554 
16555  /*
16556  * Gradient, either user-provided or numerical differentiation
16557  */
16558  minbleic_clearrequestfields(state, _state);
16559  if( ae_fp_neq(state->diffstep,0) )
16560  {
16561  goto lbl_88;
16562  }
16563 
16564  /*
16565  * Analytic gradient
16566  */
16567  state->needfg = ae_true;
16568  state->rstate.stage = 33;
16569  goto lbl_rcomm;
16570 lbl_33:
16571  state->needfg = ae_false;
16572  state->repnfev = state->repnfev+1;
16573  goto lbl_89;
16574 lbl_88:
16575 
16576  /*
16577  * Numerical differentiation
16578  */
16579  state->needf = ae_true;
16580  state->rstate.stage = 34;
16581  goto lbl_rcomm;
16582 lbl_34:
16583  state->fbase = state->f;
16584  i = 0;
16585 lbl_90:
16586  if( i>n-1 )
16587  {
16588  goto lbl_92;
16589  }
16590  v = state->x.ptr.p_double[i];
16591  b = ae_false;
16592  if( state->hasbndl.ptr.p_bool[i] )
16593  {
16594  b = b||ae_fp_less(v-state->diffstep*state->s.ptr.p_double[i],state->bndl.ptr.p_double[i]);
16595  }
16596  if( state->hasbndu.ptr.p_bool[i] )
16597  {
16598  b = b||ae_fp_greater(v+state->diffstep*state->s.ptr.p_double[i],state->bndu.ptr.p_double[i]);
16599  }
16600  if( b )
16601  {
16602  goto lbl_93;
16603  }
16604  state->x.ptr.p_double[i] = v-state->diffstep*state->s.ptr.p_double[i];
16605  state->rstate.stage = 35;
16606  goto lbl_rcomm;
16607 lbl_35:
16608  state->fm2 = state->f;
16609  state->x.ptr.p_double[i] = v-0.5*state->diffstep*state->s.ptr.p_double[i];
16610  state->rstate.stage = 36;
16611  goto lbl_rcomm;
16612 lbl_36:
16613  state->fm1 = state->f;
16614  state->x.ptr.p_double[i] = v+0.5*state->diffstep*state->s.ptr.p_double[i];
16615  state->rstate.stage = 37;
16616  goto lbl_rcomm;
16617 lbl_37:
16618  state->fp1 = state->f;
16619  state->x.ptr.p_double[i] = v+state->diffstep*state->s.ptr.p_double[i];
16620  state->rstate.stage = 38;
16621  goto lbl_rcomm;
16622 lbl_38:
16623  state->fp2 = state->f;
16624  state->g.ptr.p_double[i] = (8*(state->fp1-state->fm1)-(state->fp2-state->fm2))/(6*state->diffstep*state->s.ptr.p_double[i]);
16625  state->repnfev = state->repnfev+4;
16626  goto lbl_94;
16627 lbl_93:
16628  state->xm1 = v-state->diffstep*state->s.ptr.p_double[i];
16629  state->xp1 = v+state->diffstep*state->s.ptr.p_double[i];
16630  if( state->hasbndl.ptr.p_bool[i]&&ae_fp_less(state->xm1,state->bndl.ptr.p_double[i]) )
16631  {
16632  state->xm1 = state->bndl.ptr.p_double[i];
16633  }
16634  if( state->hasbndu.ptr.p_bool[i]&&ae_fp_greater(state->xp1,state->bndu.ptr.p_double[i]) )
16635  {
16636  state->xp1 = state->bndu.ptr.p_double[i];
16637  }
16638  state->x.ptr.p_double[i] = state->xm1;
16639  state->rstate.stage = 39;
16640  goto lbl_rcomm;
16641 lbl_39:
16642  state->fm1 = state->f;
16643  state->x.ptr.p_double[i] = state->xp1;
16644  state->rstate.stage = 40;
16645  goto lbl_rcomm;
16646 lbl_40:
16647  state->fp1 = state->f;
16648  if( ae_fp_neq(state->xm1,state->xp1) )
16649  {
16650  state->g.ptr.p_double[i] = (state->fp1-state->fm1)/(state->xp1-state->xm1);
16651  }
16652  else
16653  {
16654  state->g.ptr.p_double[i] = 0;
16655  }
16656  state->repnfev = state->repnfev+2;
16657 lbl_94:
16658  state->x.ptr.p_double[i] = v;
16659  i = i+1;
16660  goto lbl_90;
16661 lbl_92:
16662  state->f = state->fbase;
16663  state->needf = ae_false;
16664 lbl_89:
16665 
16666  /*
16667  * Back to MCSRCH
16668  *
16669  * NOTE: penalty term from correction is added to FN in order
16670  * to penalize increase in infeasibility.
16671  */
16672  state->fn = state->f+minbleic_penaltyfactor*state->maxscaledgrad*penalty;
16673  ae_v_move(&state->gn.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1));
16674  sasconstraineddirection(&state->sas, &state->gn, _state);
16675  trimfunction(&state->fn, &state->gn, n, state->trimthreshold, _state);
16676  mcsrch(n, &state->xn, &state->fn, &state->gn, &state->d, &state->stp, state->curstpmax, minbleic_gtol, &mcinfo, &state->nfev, &state->work, &state->lstate, &state->mcstage, _state);
16677  goto lbl_86;
16678 lbl_87:
16679  ae_v_add(&state->sk.ptr.pp_double[state->p][0], 1, &state->xn.ptr.p_double[0], 1, ae_v_len(0,n-1));
16680  ae_v_add(&state->yk.ptr.pp_double[state->p][0], 1, &state->gn.ptr.p_double[0], 1, ae_v_len(0,n-1));
16681 
16682  /*
16683  * Handle possible failure of the line search
16684  */
16685  if( mcinfo!=1&&mcinfo!=5 )
16686  {
16687  goto lbl_83;
16688  }
16689 
16690  /*
16691  * Current point is updated.
16692  */
16693  ae_v_move(&state->xp.ptr.p_double[0], 1, &state->sas.xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
16694  ae_v_move(&state->gp.ptr.p_double[0], 1, &state->gc.ptr.p_double[0], 1, ae_v_len(0,n-1));
16695  state->fp = state->fc;
16696  actstatus = sasmoveto(&state->sas, &state->xn, state->cidx>=0&&ae_fp_greater_eq(state->stp,state->activationstep), state->cidx, state->cval, _state);
16697  ae_v_move(&state->gc.ptr.p_double[0], 1, &state->gn.ptr.p_double[0], 1, ae_v_len(0,n-1));
16698  state->fc = state->fn;
16699  if( !state->xrep )
16700  {
16701  goto lbl_95;
16702  }
16703  ae_v_move(&state->x.ptr.p_double[0], 1, &state->sas.xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
16704  minbleic_clearrequestfields(state, _state);
16705  state->xupdated = ae_true;
16706  state->rstate.stage = 41;
16707  goto lbl_rcomm;
16708 lbl_41:
16709  state->xupdated = ae_false;
16710 lbl_95:
16711  state->repinneriterationscount = state->repinneriterationscount+1;
16712 
16713  /*
16714  * Update length of the good step
16715  */
16716  if( mcinfo==1 )
16717  {
16718  v = 0;
16719  vv = 0;
16720  for(i=0; i<=n-1; i++)
16721  {
16722  v = v+ae_sqr((state->sas.xc.ptr.p_double[i]-state->xp.ptr.p_double[i])/state->s.ptr.p_double[i], _state);
16723  vv = vv+ae_sqr(state->sas.xc.ptr.p_double[i]-state->xp.ptr.p_double[i], _state);
16724  }
16725  state->lastgoodstep = ae_sqrt(vv, _state);
16726  minbleic_updateestimateofgoodstep(&state->lastscaledgoodstep, ae_sqrt(v, _state), _state);
16727  }
16728 
16729  /*
16730  * Termination of the L-BFGS algorithm:
16731  * a) line search was performed with activation of constraint
16732  * b) scaled gradient decreased below GDecay
16733  * c) iterations counter >= MaxIts
16734  */
16735  if( actstatus>=0 )
16736  {
16737  goto lbl_83;
16738  }
16739  v = 0.0;
16740  for(i=0; i<=n-1; i++)
16741  {
16742  v = v+ae_sqr(state->gc.ptr.p_double[i]*state->s.ptr.p_double[i], _state);
16743  }
16744  if( ae_fp_less(ae_sqrt(v, _state),gdecay*ginit) )
16745  {
16746  goto lbl_83;
16747  }
16748  if( state->maxits>0&&state->repinneriterationscount>=state->maxits )
16749  {
16750  goto lbl_83;
16751  }
16752 
16753  /*
16754  * Update L-BFGS model:
16755  * * calculate Rho[k]
16756  * * calculate d(k+1) = -H(k+1)*g(k+1)
16757  * (use constrained preconditioner to perform multiplication)
16758  */
16759  v = ae_v_dotproduct(&state->yk.ptr.pp_double[state->p][0], 1, &state->sk.ptr.pp_double[state->p][0], 1, ae_v_len(0,n-1));
16760  vv = ae_v_dotproduct(&state->yk.ptr.pp_double[state->p][0], 1, &state->yk.ptr.pp_double[state->p][0], 1, ae_v_len(0,n-1));
16761  if( ae_fp_eq(v,0)||ae_fp_eq(vv,0) )
16762  {
16763  goto lbl_83;
16764  }
16765  state->rho.ptr.p_double[state->p] = 1/v;
16766  ae_v_move(&state->work.ptr.p_double[0], 1, &state->gn.ptr.p_double[0], 1, ae_v_len(0,n-1));
16767  for(i=state->k; i>=state->k-state->q; i--)
16768  {
16769  ic = i%m;
16770  v = ae_v_dotproduct(&state->sk.ptr.pp_double[ic][0], 1, &state->work.ptr.p_double[0], 1, ae_v_len(0,n-1));
16771  state->theta.ptr.p_double[ic] = v;
16772  vv = v*state->rho.ptr.p_double[ic];
16773  ae_v_subd(&state->work.ptr.p_double[0], 1, &state->yk.ptr.pp_double[ic][0], 1, ae_v_len(0,n-1), vv);
16774  }
16775  sasconstraineddirectionprec(&state->sas, &state->work, _state);
16776  for(i=state->k-state->q; i<=state->k; i++)
16777  {
16778  ic = i%m;
16779  v = ae_v_dotproduct(&state->yk.ptr.pp_double[ic][0], 1, &state->work.ptr.p_double[0], 1, ae_v_len(0,n-1));
16780  vv = state->rho.ptr.p_double[ic]*(-v+state->theta.ptr.p_double[ic]);
16781  ae_v_addd(&state->work.ptr.p_double[0], 1, &state->sk.ptr.pp_double[ic][0], 1, ae_v_len(0,n-1), vv);
16782  }
16783  ae_v_moveneg(&state->d.ptr.p_double[0], 1, &state->work.ptr.p_double[0], 1, ae_v_len(0,n-1));
16784  state->k = state->k+1;
16785  goto lbl_82;
16786 lbl_83:
16787 
16788  /*
16789  * Decrease decay coefficient. Subsequent L-BFGS stages will
16790  * have more stringent stopping criteria.
16791  */
16792  gdecay = ae_maxreal(gdecay*minbleic_decaycorrection, minbleic_mindecay, _state);
16793  goto lbl_51;
16794 lbl_52:
16795  sasstopoptimization(&state->sas, _state);
16796  state->repouteriterationscount = 1;
16797  result = ae_false;
16798  return result;
16799 
16800  /*
16801  * Saving state
16802  */
16803 lbl_rcomm:
16804  result = ae_true;
16805  state->rstate.ia.ptr.p_int[0] = n;
16806  state->rstate.ia.ptr.p_int[1] = m;
16807  state->rstate.ia.ptr.p_int[2] = i;
16808  state->rstate.ia.ptr.p_int[3] = j;
16809  state->rstate.ia.ptr.p_int[4] = badbfgsits;
16810  state->rstate.ia.ptr.p_int[5] = nextaction;
16811  state->rstate.ia.ptr.p_int[6] = mcinfo;
16812  state->rstate.ia.ptr.p_int[7] = actstatus;
16813  state->rstate.ia.ptr.p_int[8] = ic;
16814  state->rstate.ba.ptr.p_bool[0] = b;
16815  state->rstate.ra.ptr.p_double[0] = v;
16816  state->rstate.ra.ptr.p_double[1] = vv;
16817  state->rstate.ra.ptr.p_double[2] = penalty;
16818  state->rstate.ra.ptr.p_double[3] = ginit;
16819  state->rstate.ra.ptr.p_double[4] = gdecay;
16820  return result;
16821 }
16822 
16823 
16824 /*************************************************************************
16825 BLEIC results
16826 
16827 INPUT PARAMETERS:
16828  State - algorithm state
16829 
16830 OUTPUT PARAMETERS:
16831  X - array[0..N-1], solution
16832  Rep - optimization report. You should check Rep.TerminationType
16833  in order to distinguish successful termination from
16834  unsuccessful one:
16835  * -7 gradient verification failed.
16836  See MinBLEICSetGradientCheck() for more information.
16837  * -3 inconsistent constraints. Feasible point is
16838  either nonexistent or too hard to find. Try to
16839  restart optimizer with better initial approximation
16840  * 1 relative function improvement is no more than EpsF.
16841  * 2 scaled step is no more than EpsX.
16842  * 4 scaled gradient norm is no more than EpsG.
16843  * 5 MaxIts steps was taken
16844  More information about fields of this structure can be
16845  found in the comments on MinBLEICReport datatype.
16846 
16847  -- ALGLIB --
16848  Copyright 28.11.2010 by Bochkanov Sergey
16849 *************************************************************************/
16850 void minbleicresults(minbleicstate* state,
16851  /* Real */ ae_vector* x,
16852  minbleicreport* rep,
16853  ae_state *_state)
16854 {
16855 
16856  ae_vector_clear(x);
16857  _minbleicreport_clear(rep);
16858 
16859  minbleicresultsbuf(state, x, rep, _state);
16860 }
16861 
16862 
16863 /*************************************************************************
16864 BLEIC results
16865 
16866 Buffered implementation of MinBLEICResults() which uses pre-allocated buffer
16867 to store X[]. If buffer size is too small, it resizes buffer. It is
16868 intended to be used in the inner cycles of performance critical algorithms
16869 where array reallocation penalty is too large to be ignored.
16870 
16871  -- ALGLIB --
16872  Copyright 28.11.2010 by Bochkanov Sergey
16873 *************************************************************************/
16874 void minbleicresultsbuf(minbleicstate* state,
16875  /* Real */ ae_vector* x,
16876  minbleicreport* rep,
16877  ae_state *_state)
16878 {
16879  ae_int_t i;
16880 
16881 
16882  if( x->cnt<state->nmain )
16883  {
16884  ae_vector_set_length(x, state->nmain, _state);
16885  }
16886  rep->iterationscount = state->repinneriterationscount;
16887  rep->inneriterationscount = state->repinneriterationscount;
16888  rep->outeriterationscount = state->repouteriterationscount;
16889  rep->nfev = state->repnfev;
16890  rep->varidx = state->repvaridx;
16891  rep->terminationtype = state->repterminationtype;
16892  if( state->repterminationtype>0 )
16893  {
16894  ae_v_move(&x->ptr.p_double[0], 1, &state->sas.xc.ptr.p_double[0], 1, ae_v_len(0,state->nmain-1));
16895  }
16896  else
16897  {
16898  for(i=0; i<=state->nmain-1; i++)
16899  {
16900  x->ptr.p_double[i] = _state->v_nan;
16901  }
16902  }
16903  rep->debugeqerr = state->repdebugeqerr;
16904  rep->debugfs = state->repdebugfs;
16905  rep->debugff = state->repdebugff;
16906  rep->debugdx = state->repdebugdx;
16907  rep->debugfeasqpits = state->repdebugfeasqpits;
16908  rep->debugfeasgpaits = state->repdebugfeasgpaits;
16909 }
16910 
16911 
16912 /*************************************************************************
16913 This subroutine restarts algorithm from new point.
16914 All optimization parameters (including constraints) are left unchanged.
16915 
16916 This function allows to solve multiple optimization problems (which
16917 must have same number of dimensions) without object reallocation penalty.
16918 
16919 INPUT PARAMETERS:
16920  State - structure previously allocated with MinBLEICCreate call.
16921  X - new starting point.
16922 
16923  -- ALGLIB --
16924  Copyright 28.11.2010 by Bochkanov Sergey
16925 *************************************************************************/
16926 void minbleicrestartfrom(minbleicstate* state,
16927  /* Real */ ae_vector* x,
16928  ae_state *_state)
16929 {
16930  ae_int_t n;
16931 
16932 
16933  n = state->nmain;
16934 
16935  /*
16936  * First, check for errors in the inputs
16937  */
16938  ae_assert(x->cnt>=n, "MinBLEICRestartFrom: Length(X)<N", _state);
16939  ae_assert(isfinitevector(x, n, _state), "MinBLEICRestartFrom: X contains infinite or NaN values!", _state);
16940 
16941  /*
16942  * Set XC
16943  */
16944  ae_v_move(&state->xstart.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1));
16945 
16946  /*
16947  * prepare RComm facilities
16948  */
16949  ae_vector_set_length(&state->rstate.ia, 8+1, _state);
16950  ae_vector_set_length(&state->rstate.ba, 0+1, _state);
16951  ae_vector_set_length(&state->rstate.ra, 4+1, _state);
16952  state->rstate.stage = -1;
16953  minbleic_clearrequestfields(state, _state);
16954  sasstopoptimization(&state->sas, _state);
16955 }
16956 
16957 
16958 /*************************************************************************
16959 This subroutine finalizes internal structures after emergency termination
16960 from State.LSStart report (see comments on MinBLEICState for more information).
16961 
16962 INPUT PARAMETERS:
16963  State - structure after exit from LSStart report
16964 
16965  -- ALGLIB --
16966  Copyright 28.11.2010 by Bochkanov Sergey
16967 *************************************************************************/
16968 void minbleicemergencytermination(minbleicstate* state, ae_state *_state)
16969 {
16970 
16971 
16972  sasstopoptimization(&state->sas, _state);
16973 }
16974 
16975 
16976 /*************************************************************************
16977 This subroutine turns on verification of the user-supplied analytic
16978 gradient:
16979 * user calls this subroutine before optimization begins
16980 * MinBLEICOptimize() is called
16981 * prior to actual optimization, for each component of parameters being
16982  optimized X[i] algorithm performs following steps:
16983  * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i],
16984  where X[i] is i-th component of the initial point and S[i] is a scale
16985  of i-th parameter
16986  * if needed, steps are bounded with respect to constraints on X[]
16987  * F(X) is evaluated at these trial points
16988  * we perform one more evaluation in the middle point of the interval
16989  * we build cubic model using function values and derivatives at trial
16990  points and we compare its prediction with actual value in the middle
16991  point
16992  * in case difference between prediction and actual value is higher than
16993  some predetermined threshold, algorithm stops with completion code -7;
16994  Rep.VarIdx is set to index of the parameter with incorrect derivative.
16995 * after verification is over, algorithm proceeds to the actual optimization.
16996 
16997 NOTE 1: verification needs N (parameters count) gradient evaluations. It
16998  is very costly and you should use it only for low dimensional
16999  problems, when you want to be sure that you've correctly
17000  calculated analytic derivatives. You should not use it in the
17001  production code (unless you want to check derivatives provided by
17002  some third party).
17003 
17004 NOTE 2: you should carefully choose TestStep. Value which is too large
17005  (so large that function behaviour is significantly non-cubic) will
17006  lead to false alarms. You may use different step for different
17007  parameters by means of setting scale with MinBLEICSetScale().
17008 
17009 NOTE 3: this function may lead to false positives. In case it reports that
17010  I-th derivative was calculated incorrectly, you may decrease test
17011  step and try one more time - maybe your function changes too
17012  sharply and your step is too large for such rapidly chanding
17013  function.
17014 
17015 INPUT PARAMETERS:
17016  State - structure used to store algorithm state
17017  TestStep - verification step:
17018  * TestStep=0 turns verification off
17019  * TestStep>0 activates verification
17020 
17021  -- ALGLIB --
17022  Copyright 15.06.2012 by Bochkanov Sergey
17023 *************************************************************************/
17024 void minbleicsetgradientcheck(minbleicstate* state,
17025  double teststep,
17026  ae_state *_state)
17027 {
17028 
17029 
17030  ae_assert(ae_isfinite(teststep, _state), "MinBLEICSetGradientCheck: TestStep contains NaN or Infinite", _state);
17031  ae_assert(ae_fp_greater_eq(teststep,0), "MinBLEICSetGradientCheck: invalid argument TestStep(TestStep<0)", _state);
17032  state->teststep = teststep;
17033 }
17034 
17035 
17036 /*************************************************************************
17037 Clears request fileds (to be sure that we don't forget to clear something)
17038 *************************************************************************/
17039 static void minbleic_clearrequestfields(minbleicstate* state,
17040  ae_state *_state)
17041 {
17042 
17043 
17044  state->needf = ae_false;
17045  state->needfg = ae_false;
17046  state->xupdated = ae_false;
17047  state->lsstart = ae_false;
17048 }
17049 
17050 
17051 /*************************************************************************
17052 Internal initialization subroutine
17053 *************************************************************************/
17054 static void minbleic_minbleicinitinternal(ae_int_t n,
17055  /* Real */ ae_vector* x,
17056  double diffstep,
17057  minbleicstate* state,
17058  ae_state *_state)
17059 {
17060  ae_frame _frame_block;
17061  ae_int_t i;
17062  ae_matrix c;
17063  ae_vector ct;
17064 
17065  ae_frame_make(_state, &_frame_block);
17066  ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true);
17067  ae_vector_init(&ct, 0, DT_INT, _state, ae_true);
17068 
17069 
17070  /*
17071  * Initialize
17072  */
17073  state->teststep = 0;
17074  state->nmain = n;
17075  state->diffstep = diffstep;
17076  sasinit(n, &state->sas, _state);
17077  ae_vector_set_length(&state->bndl, n, _state);
17078  ae_vector_set_length(&state->hasbndl, n, _state);
17079  ae_vector_set_length(&state->bndu, n, _state);
17080  ae_vector_set_length(&state->hasbndu, n, _state);
17081  ae_vector_set_length(&state->xstart, n, _state);
17082  ae_vector_set_length(&state->gc, n, _state);
17083  ae_vector_set_length(&state->xn, n, _state);
17084  ae_vector_set_length(&state->gn, n, _state);
17085  ae_vector_set_length(&state->xp, n, _state);
17086  ae_vector_set_length(&state->gp, n, _state);
17087  ae_vector_set_length(&state->d, n, _state);
17088  ae_vector_set_length(&state->s, n, _state);
17089  ae_vector_set_length(&state->x, n, _state);
17090  ae_vector_set_length(&state->g, n, _state);
17091  ae_vector_set_length(&state->work, n, _state);
17092  for(i=0; i<=n-1; i++)
17093  {
17094  state->bndl.ptr.p_double[i] = _state->v_neginf;
17095  state->hasbndl.ptr.p_bool[i] = ae_false;
17096  state->bndu.ptr.p_double[i] = _state->v_posinf;
17097  state->hasbndu.ptr.p_bool[i] = ae_false;
17098  state->s.ptr.p_double[i] = 1.0;
17099  }
17100  minbleicsetlc(state, &c, &ct, 0, _state);
17101  minbleicsetcond(state, 0.0, 0.0, 0.0, 0, _state);
17102  minbleicsetxrep(state, ae_false, _state);
17103  minbleicsetdrep(state, ae_false, _state);
17104  minbleicsetstpmax(state, 0.0, _state);
17105  minbleicsetprecdefault(state, _state);
17106  minbleicrestartfrom(state, x, _state);
17107  ae_frame_leave(_state);
17108 }
17109 
17110 
17111 /*************************************************************************
17112 This subroutine updates estimate of the good step length given:
17113 1) previous estimate
17114 2) new length of the good step
17115 
17116 It makes sure that estimate does not change too rapidly - ratio of new and
17117 old estimates will be at least 0.01, at most 100.0
17118 
17119 In case previous estimate of good step is zero (no estimate), new estimate
17120 is used unconditionally.
17121 
17122  -- ALGLIB --
17123  Copyright 16.01.2013 by Bochkanov Sergey
17124 *************************************************************************/
17125 static void minbleic_updateestimateofgoodstep(double* estimate,
17126  double newstep,
17127  ae_state *_state)
17128 {
17129 
17130 
17131  if( ae_fp_eq(*estimate,0) )
17132  {
17133  *estimate = newstep;
17134  return;
17135  }
17136  if( ae_fp_less(newstep,*estimate*0.01) )
17137  {
17138  *estimate = *estimate*0.01;
17139  return;
17140  }
17141  if( ae_fp_greater(newstep,*estimate*100) )
17142  {
17143  *estimate = *estimate*100;
17144  return;
17145  }
17146  *estimate = newstep;
17147 }
17148 
17149 
17150 ae_bool _minbleicstate_init(void* _p, ae_state *_state, ae_bool make_automatic)
17151 {
17152  minbleicstate *p = (minbleicstate*)_p;
17153  ae_touch_ptr((void*)p);
17154  if( !_sactiveset_init(&p->sas, _state, make_automatic) )
17155  return ae_false;
17156  if( !ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic) )
17157  return ae_false;
17158  if( !ae_vector_init(&p->diagh, 0, DT_REAL, _state, make_automatic) )
17159  return ae_false;
17160  if( !ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic) )
17161  return ae_false;
17162  if( !ae_vector_init(&p->g, 0, DT_REAL, _state, make_automatic) )
17163  return ae_false;
17164  if( !_rcommstate_init(&p->rstate, _state, make_automatic) )
17165  return ae_false;
17166  if( !ae_vector_init(&p->gc, 0, DT_REAL, _state, make_automatic) )
17167  return ae_false;
17168  if( !ae_vector_init(&p->xn, 0, DT_REAL, _state, make_automatic) )
17169  return ae_false;
17170  if( !ae_vector_init(&p->gn, 0, DT_REAL, _state, make_automatic) )
17171  return ae_false;
17172  if( !ae_vector_init(&p->xp, 0, DT_REAL, _state, make_automatic) )
17173  return ae_false;
17174  if( !ae_vector_init(&p->gp, 0, DT_REAL, _state, make_automatic) )
17175  return ae_false;
17176  if( !ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic) )
17177  return ae_false;
17178  if( !ae_matrix_init(&p->cleic, 0, 0, DT_REAL, _state, make_automatic) )
17179  return ae_false;
17180  if( !ae_vector_init(&p->hasbndl, 0, DT_BOOL, _state, make_automatic) )
17181  return ae_false;
17182  if( !ae_vector_init(&p->hasbndu, 0, DT_BOOL, _state, make_automatic) )
17183  return ae_false;
17184  if( !ae_vector_init(&p->bndl, 0, DT_REAL, _state, make_automatic) )
17185  return ae_false;
17186  if( !ae_vector_init(&p->bndu, 0, DT_REAL, _state, make_automatic) )
17187  return ae_false;
17188  if( !ae_vector_init(&p->xstart, 0, DT_REAL, _state, make_automatic) )
17189  return ae_false;
17190  if( !_snnlssolver_init(&p->solver, _state, make_automatic) )
17191  return ae_false;
17192  if( !ae_vector_init(&p->tmpprec, 0, DT_REAL, _state, make_automatic) )
17193  return ae_false;
17194  if( !ae_vector_init(&p->work, 0, DT_REAL, _state, make_automatic) )
17195  return ae_false;
17196  if( !_linminstate_init(&p->lstate, _state, make_automatic) )
17197  return ae_false;
17198  if( !ae_vector_init(&p->rho, 0, DT_REAL, _state, make_automatic) )
17199  return ae_false;
17200  if( !ae_matrix_init(&p->yk, 0, 0, DT_REAL, _state, make_automatic) )
17201  return ae_false;
17202  if( !ae_matrix_init(&p->sk, 0, 0, DT_REAL, _state, make_automatic) )
17203  return ae_false;
17204  if( !ae_vector_init(&p->theta, 0, DT_REAL, _state, make_automatic) )
17205  return ae_false;
17206  return ae_true;
17207 }
17208 
17209 
17210 ae_bool _minbleicstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
17211 {
17212  minbleicstate *dst = (minbleicstate*)_dst;
17213  minbleicstate *src = (minbleicstate*)_src;
17214  dst->nmain = src->nmain;
17215  dst->nslack = src->nslack;
17216  dst->epsg = src->epsg;
17217  dst->epsf = src->epsf;
17218  dst->epsx = src->epsx;
17219  dst->maxits = src->maxits;
17220  dst->xrep = src->xrep;
17221  dst->drep = src->drep;
17222  dst->stpmax = src->stpmax;
17223  dst->diffstep = src->diffstep;
17224  if( !_sactiveset_init_copy(&dst->sas, &src->sas, _state, make_automatic) )
17225  return ae_false;
17226  if( !ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic) )
17227  return ae_false;
17228  dst->prectype = src->prectype;
17229  if( !ae_vector_init_copy(&dst->diagh, &src->diagh, _state, make_automatic) )
17230  return ae_false;
17231  if( !ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic) )
17232  return ae_false;
17233  dst->f = src->f;
17234  if( !ae_vector_init_copy(&dst->g, &src->g, _state, make_automatic) )
17235  return ae_false;
17236  dst->needf = src->needf;
17237  dst->needfg = src->needfg;
17238  dst->xupdated = src->xupdated;
17239  dst->lsstart = src->lsstart;
17240  dst->lbfgssearch = src->lbfgssearch;
17241  dst->boundedstep = src->boundedstep;
17242  dst->teststep = src->teststep;
17243  if( !_rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic) )
17244  return ae_false;
17245  if( !ae_vector_init_copy(&dst->gc, &src->gc, _state, make_automatic) )
17246  return ae_false;
17247  if( !ae_vector_init_copy(&dst->xn, &src->xn, _state, make_automatic) )
17248  return ae_false;
17249  if( !ae_vector_init_copy(&dst->gn, &src->gn, _state, make_automatic) )
17250  return ae_false;
17251  if( !ae_vector_init_copy(&dst->xp, &src->xp, _state, make_automatic) )
17252  return ae_false;
17253  if( !ae_vector_init_copy(&dst->gp, &src->gp, _state, make_automatic) )
17254  return ae_false;
17255  dst->fc = src->fc;
17256  dst->fn = src->fn;
17257  dst->fp = src->fp;
17258  if( !ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic) )
17259  return ae_false;
17260  if( !ae_matrix_init_copy(&dst->cleic, &src->cleic, _state, make_automatic) )
17261  return ae_false;
17262  dst->nec = src->nec;
17263  dst->nic = src->nic;
17264  dst->lastgoodstep = src->lastgoodstep;
17265  dst->lastscaledgoodstep = src->lastscaledgoodstep;
17266  dst->maxscaledgrad = src->maxscaledgrad;
17267  if( !ae_vector_init_copy(&dst->hasbndl, &src->hasbndl, _state, make_automatic) )
17268  return ae_false;
17269  if( !ae_vector_init_copy(&dst->hasbndu, &src->hasbndu, _state, make_automatic) )
17270  return ae_false;
17271  if( !ae_vector_init_copy(&dst->bndl, &src->bndl, _state, make_automatic) )
17272  return ae_false;
17273  if( !ae_vector_init_copy(&dst->bndu, &src->bndu, _state, make_automatic) )
17274  return ae_false;
17275  dst->repinneriterationscount = src->repinneriterationscount;
17276  dst->repouteriterationscount = src->repouteriterationscount;
17277  dst->repnfev = src->repnfev;
17278  dst->repvaridx = src->repvaridx;
17279  dst->repterminationtype = src->repterminationtype;
17280  dst->repdebugeqerr = src->repdebugeqerr;
17281  dst->repdebugfs = src->repdebugfs;
17282  dst->repdebugff = src->repdebugff;
17283  dst->repdebugdx = src->repdebugdx;
17284  dst->repdebugfeasqpits = src->repdebugfeasqpits;
17285  dst->repdebugfeasgpaits = src->repdebugfeasgpaits;
17286  if( !ae_vector_init_copy(&dst->xstart, &src->xstart, _state, make_automatic) )
17287  return ae_false;
17288  if( !_snnlssolver_init_copy(&dst->solver, &src->solver, _state, make_automatic) )
17289  return ae_false;
17290  dst->fbase = src->fbase;
17291  dst->fm2 = src->fm2;
17292  dst->fm1 = src->fm1;
17293  dst->fp1 = src->fp1;
17294  dst->fp2 = src->fp2;
17295  dst->xm1 = src->xm1;
17296  dst->xp1 = src->xp1;
17297  dst->gm1 = src->gm1;
17298  dst->gp1 = src->gp1;
17299  dst->cidx = src->cidx;
17300  dst->cval = src->cval;
17301  if( !ae_vector_init_copy(&dst->tmpprec, &src->tmpprec, _state, make_automatic) )
17302  return ae_false;
17303  dst->nfev = src->nfev;
17304  dst->mcstage = src->mcstage;
17305  dst->stp = src->stp;
17306  dst->curstpmax = src->curstpmax;
17307  dst->activationstep = src->activationstep;
17308  if( !ae_vector_init_copy(&dst->work, &src->work, _state, make_automatic) )
17309  return ae_false;
17310  if( !_linminstate_init_copy(&dst->lstate, &src->lstate, _state, make_automatic) )
17311  return ae_false;
17312  dst->trimthreshold = src->trimthreshold;
17313  dst->nonmonotoniccnt = src->nonmonotoniccnt;
17314  dst->k = src->k;
17315  dst->q = src->q;
17316  dst->p = src->p;
17317  if( !ae_vector_init_copy(&dst->rho, &src->rho, _state, make_automatic) )
17318  return ae_false;
17319  if( !ae_matrix_init_copy(&dst->yk, &src->yk, _state, make_automatic) )
17320  return ae_false;
17321  if( !ae_matrix_init_copy(&dst->sk, &src->sk, _state, make_automatic) )
17322  return ae_false;
17323  if( !ae_vector_init_copy(&dst->theta, &src->theta, _state, make_automatic) )
17324  return ae_false;
17325  return ae_true;
17326 }
17327 
17328 
17329 void _minbleicstate_clear(void* _p)
17330 {
17331  minbleicstate *p = (minbleicstate*)_p;
17332  ae_touch_ptr((void*)p);
17333  _sactiveset_clear(&p->sas);
17334  ae_vector_clear(&p->s);
17335  ae_vector_clear(&p->diagh);
17336  ae_vector_clear(&p->x);
17337  ae_vector_clear(&p->g);
17338  _rcommstate_clear(&p->rstate);
17339  ae_vector_clear(&p->gc);
17340  ae_vector_clear(&p->xn);
17341  ae_vector_clear(&p->gn);
17342  ae_vector_clear(&p->xp);
17343  ae_vector_clear(&p->gp);
17344  ae_vector_clear(&p->d);
17345  ae_matrix_clear(&p->cleic);
17346  ae_vector_clear(&p->hasbndl);
17347  ae_vector_clear(&p->hasbndu);
17348  ae_vector_clear(&p->bndl);
17349  ae_vector_clear(&p->bndu);
17350  ae_vector_clear(&p->xstart);
17351  _snnlssolver_clear(&p->solver);
17352  ae_vector_clear(&p->tmpprec);
17353  ae_vector_clear(&p->work);
17354  _linminstate_clear(&p->lstate);
17355  ae_vector_clear(&p->rho);
17356  ae_matrix_clear(&p->yk);
17357  ae_matrix_clear(&p->sk);
17358  ae_vector_clear(&p->theta);
17359 }
17360 
17361 
17362 void _minbleicstate_destroy(void* _p)
17363 {
17364  minbleicstate *p = (minbleicstate*)_p;
17365  ae_touch_ptr((void*)p);
17366  _sactiveset_destroy(&p->sas);
17367  ae_vector_destroy(&p->s);
17368  ae_vector_destroy(&p->diagh);
17369  ae_vector_destroy(&p->x);
17370  ae_vector_destroy(&p->g);
17371  _rcommstate_destroy(&p->rstate);
17372  ae_vector_destroy(&p->gc);
17373  ae_vector_destroy(&p->xn);
17374  ae_vector_destroy(&p->gn);
17375  ae_vector_destroy(&p->xp);
17376  ae_vector_destroy(&p->gp);
17377  ae_vector_destroy(&p->d);
17378  ae_matrix_destroy(&p->cleic);
17379  ae_vector_destroy(&p->hasbndl);
17380  ae_vector_destroy(&p->hasbndu);
17381  ae_vector_destroy(&p->bndl);
17382  ae_vector_destroy(&p->bndu);
17383  ae_vector_destroy(&p->xstart);
17384  _snnlssolver_destroy(&p->solver);
17385  ae_vector_destroy(&p->tmpprec);
17386  ae_vector_destroy(&p->work);
17387  _linminstate_destroy(&p->lstate);
17388  ae_vector_destroy(&p->rho);
17389  ae_matrix_destroy(&p->yk);
17390  ae_matrix_destroy(&p->sk);
17391  ae_vector_destroy(&p->theta);
17392 }
17393 
17394 
17395 ae_bool _minbleicreport_init(void* _p, ae_state *_state, ae_bool make_automatic)
17396 {
17397  minbleicreport *p = (minbleicreport*)_p;
17398  ae_touch_ptr((void*)p);
17399  return ae_true;
17400 }
17401 
17402 
17403 ae_bool _minbleicreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
17404 {
17405  minbleicreport *dst = (minbleicreport*)_dst;
17406  minbleicreport *src = (minbleicreport*)_src;
17407  dst->iterationscount = src->iterationscount;
17408  dst->nfev = src->nfev;
17409  dst->varidx = src->varidx;
17410  dst->terminationtype = src->terminationtype;
17411  dst->debugeqerr = src->debugeqerr;
17412  dst->debugfs = src->debugfs;
17413  dst->debugff = src->debugff;
17414  dst->debugdx = src->debugdx;
17415  dst->debugfeasqpits = src->debugfeasqpits;
17416  dst->debugfeasgpaits = src->debugfeasgpaits;
17417  dst->inneriterationscount = src->inneriterationscount;
17418  dst->outeriterationscount = src->outeriterationscount;
17419  return ae_true;
17420 }
17421 
17422 
17423 void _minbleicreport_clear(void* _p)
17424 {
17425  minbleicreport *p = (minbleicreport*)_p;
17426  ae_touch_ptr((void*)p);
17427 }
17428 
17429 
17430 void _minbleicreport_destroy(void* _p)
17431 {
17432  minbleicreport *p = (minbleicreport*)_p;
17433  ae_touch_ptr((void*)p);
17434 }
17435 
17436 
17437 
17438 
17439 /*************************************************************************
17440  LIMITED MEMORY BFGS METHOD FOR LARGE SCALE OPTIMIZATION
17441 
17442 DESCRIPTION:
17443 The subroutine minimizes function F(x) of N arguments by using a quasi-
17444 Newton method (LBFGS scheme) which is optimized to use a minimum amount
17445 of memory.
17446 The subroutine generates the approximation of an inverse Hessian matrix by
17447 using information about the last M steps of the algorithm (instead of N).
17448 It lessens a required amount of memory from a value of order N^2 to a
17449 value of order 2*N*M.
17450 
17451 
17452 REQUIREMENTS:
17453 Algorithm will request following information during its operation:
17454 * function value F and its gradient G (simultaneously) at given point X
17455 
17456 
17457 USAGE:
17458 1. User initializes algorithm state with MinLBFGSCreate() call
17459 2. User tunes solver parameters with MinLBFGSSetCond() MinLBFGSSetStpMax()
17460  and other functions
17461 3. User calls MinLBFGSOptimize() function which takes algorithm state and
17462  pointer (delegate, etc.) to callback function which calculates F/G.
17463 4. User calls MinLBFGSResults() to get solution
17464 5. Optionally user may call MinLBFGSRestartFrom() to solve another problem
17465  with same N/M but another starting point and/or another function.
17466  MinLBFGSRestartFrom() allows to reuse already initialized structure.
17467 
17468 
17469 INPUT PARAMETERS:
17470  N - problem dimension. N>0
17471  M - number of corrections in the BFGS scheme of Hessian
17472  approximation update. Recommended value: 3<=M<=7. The smaller
17473  value causes worse convergence, the bigger will not cause a
17474  considerably better convergence, but will cause a fall in the
17475  performance. M<=N.
17476  X - initial solution approximation, array[0..N-1].
17477 
17478 
17479 OUTPUT PARAMETERS:
17480  State - structure which stores algorithm state
17481 
17482 
17483 NOTES:
17484 1. you may tune stopping conditions with MinLBFGSSetCond() function
17485 2. if target function contains exp() or other fast growing functions, and
17486  optimization algorithm makes too large steps which leads to overflow,
17487  use MinLBFGSSetStpMax() function to bound algorithm's steps. However,
17488  L-BFGS rarely needs such a tuning.
17489 
17490 
17491  -- ALGLIB --
17492  Copyright 02.04.2010 by Bochkanov Sergey
17493 *************************************************************************/
17494 void minlbfgscreate(ae_int_t n,
17495  ae_int_t m,
17496  /* Real */ ae_vector* x,
17497  minlbfgsstate* state,
17498  ae_state *_state)
17499 {
17500 
17501  _minlbfgsstate_clear(state);
17502 
17503  ae_assert(n>=1, "MinLBFGSCreate: N<1!", _state);
17504  ae_assert(m>=1, "MinLBFGSCreate: M<1", _state);
17505  ae_assert(m<=n, "MinLBFGSCreate: M>N", _state);
17506  ae_assert(x->cnt>=n, "MinLBFGSCreate: Length(X)<N!", _state);
17507  ae_assert(isfinitevector(x, n, _state), "MinLBFGSCreate: X contains infinite or NaN values!", _state);
17508  minlbfgscreatex(n, m, x, 0, 0.0, state, _state);
17509 }
17510 
17511 
17512 /*************************************************************************
17513 The subroutine is finite difference variant of MinLBFGSCreate(). It uses
17514 finite differences in order to differentiate target function.
17515 
17516 Description below contains information which is specific to this function
17517 only. We recommend to read comments on MinLBFGSCreate() in order to get
17518 more information about creation of LBFGS optimizer.
17519 
17520 INPUT PARAMETERS:
17521  N - problem dimension, N>0:
17522  * if given, only leading N elements of X are used
17523  * if not given, automatically determined from size of X
17524  M - number of corrections in the BFGS scheme of Hessian
17525  approximation update. Recommended value: 3<=M<=7. The smaller
17526  value causes worse convergence, the bigger will not cause a
17527  considerably better convergence, but will cause a fall in the
17528  performance. M<=N.
17529  X - starting point, array[0..N-1].
17530  DiffStep- differentiation step, >0
17531 
17532 OUTPUT PARAMETERS:
17533  State - structure which stores algorithm state
17534 
17535 NOTES:
17536 1. algorithm uses 4-point central formula for differentiation.
17537 2. differentiation step along I-th axis is equal to DiffStep*S[I] where
17538  S[] is scaling vector which can be set by MinLBFGSSetScale() call.
17539 3. we recommend you to use moderate values of differentiation step. Too
17540  large step will result in too large truncation errors, while too small
17541  step will result in too large numerical errors. 1.0E-6 can be good
17542  value to start with.
17543 4. Numerical differentiation is very inefficient - one gradient
17544  calculation needs 4*N function evaluations. This function will work for
17545  any N - either small (1...10), moderate (10...100) or large (100...).
17546  However, performance penalty will be too severe for any N's except for
17547  small ones.
17548  We should also say that code which relies on numerical differentiation
17549  is less robust and precise. LBFGS needs exact gradient values.
17550  Imprecise gradient may slow down convergence, especially on highly
17551  nonlinear problems.
17552  Thus we recommend to use this function for fast prototyping on small-
17553  dimensional problems only, and to implement analytical gradient as soon
17554  as possible.
17555 
17556  -- ALGLIB --
17557  Copyright 16.05.2011 by Bochkanov Sergey
17558 *************************************************************************/
17559 void minlbfgscreatef(ae_int_t n,
17560  ae_int_t m,
17561  /* Real */ ae_vector* x,
17562  double diffstep,
17563  minlbfgsstate* state,
17564  ae_state *_state)
17565 {
17566 
17567  _minlbfgsstate_clear(state);
17568 
17569  ae_assert(n>=1, "MinLBFGSCreateF: N too small!", _state);
17570  ae_assert(m>=1, "MinLBFGSCreateF: M<1", _state);
17571  ae_assert(m<=n, "MinLBFGSCreateF: M>N", _state);
17572  ae_assert(x->cnt>=n, "MinLBFGSCreateF: Length(X)<N!", _state);
17573  ae_assert(isfinitevector(x, n, _state), "MinLBFGSCreateF: X contains infinite or NaN values!", _state);
17574  ae_assert(ae_isfinite(diffstep, _state), "MinLBFGSCreateF: DiffStep is infinite or NaN!", _state);
17575  ae_assert(ae_fp_greater(diffstep,0), "MinLBFGSCreateF: DiffStep is non-positive!", _state);
17576  minlbfgscreatex(n, m, x, 0, diffstep, state, _state);
17577 }
17578 
17579 
17580 /*************************************************************************
17581 This function sets stopping conditions for L-BFGS optimization algorithm.
17582 
17583 INPUT PARAMETERS:
17584  State - structure which stores algorithm state
17585  EpsG - >=0
17586  The subroutine finishes its work if the condition
17587  |v|<EpsG is satisfied, where:
17588  * |.| means Euclidian norm
17589  * v - scaled gradient vector, v[i]=g[i]*s[i]
17590  * g - gradient
17591  * s - scaling coefficients set by MinLBFGSSetScale()
17592  EpsF - >=0
17593  The subroutine finishes its work if on k+1-th iteration
17594  the condition |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1}
17595  is satisfied.
17596  EpsX - >=0
17597  The subroutine finishes its work if on k+1-th iteration
17598  the condition |v|<=EpsX is fulfilled, where:
17599  * |.| means Euclidian norm
17600  * v - scaled step vector, v[i]=dx[i]/s[i]
17601  * dx - ste pvector, dx=X(k+1)-X(k)
17602  * s - scaling coefficients set by MinLBFGSSetScale()
17603  MaxIts - maximum number of iterations. If MaxIts=0, the number of
17604  iterations is unlimited.
17605 
17606 Passing EpsG=0, EpsF=0, EpsX=0 and MaxIts=0 (simultaneously) will lead to
17607 automatic stopping criterion selection (small EpsX).
17608 
17609  -- ALGLIB --
17610  Copyright 02.04.2010 by Bochkanov Sergey
17611 *************************************************************************/
17612 void minlbfgssetcond(minlbfgsstate* state,
17613  double epsg,
17614  double epsf,
17615  double epsx,
17616  ae_int_t maxits,
17617  ae_state *_state)
17618 {
17619 
17620 
17621  ae_assert(ae_isfinite(epsg, _state), "MinLBFGSSetCond: EpsG is not finite number!", _state);
17622  ae_assert(ae_fp_greater_eq(epsg,0), "MinLBFGSSetCond: negative EpsG!", _state);
17623  ae_assert(ae_isfinite(epsf, _state), "MinLBFGSSetCond: EpsF is not finite number!", _state);
17624  ae_assert(ae_fp_greater_eq(epsf,0), "MinLBFGSSetCond: negative EpsF!", _state);
17625  ae_assert(ae_isfinite(epsx, _state), "MinLBFGSSetCond: EpsX is not finite number!", _state);
17626  ae_assert(ae_fp_greater_eq(epsx,0), "MinLBFGSSetCond: negative EpsX!", _state);
17627  ae_assert(maxits>=0, "MinLBFGSSetCond: negative MaxIts!", _state);
17628  if( ((ae_fp_eq(epsg,0)&&ae_fp_eq(epsf,0))&&ae_fp_eq(epsx,0))&&maxits==0 )
17629  {
17630  epsx = 1.0E-6;
17631  }
17632  state->epsg = epsg;
17633  state->epsf = epsf;
17634  state->epsx = epsx;
17635  state->maxits = maxits;
17636 }
17637 
17638 
17639 /*************************************************************************
17640 This function turns on/off reporting.
17641 
17642 INPUT PARAMETERS:
17643  State - structure which stores algorithm state
17644  NeedXRep- whether iteration reports are needed or not
17645 
17646 If NeedXRep is True, algorithm will call rep() callback function if it is
17647 provided to MinLBFGSOptimize().
17648 
17649 
17650  -- ALGLIB --
17651  Copyright 02.04.2010 by Bochkanov Sergey
17652 *************************************************************************/
17653 void minlbfgssetxrep(minlbfgsstate* state,
17654  ae_bool needxrep,
17655  ae_state *_state)
17656 {
17657 
17658 
17659  state->xrep = needxrep;
17660 }
17661 
17662 
17663 /*************************************************************************
17664 This function sets maximum step length
17665 
17666 INPUT PARAMETERS:
17667  State - structure which stores algorithm state
17668  StpMax - maximum step length, >=0. Set StpMax to 0.0 (default), if
17669  you don't want to limit step length.
17670 
17671 Use this subroutine when you optimize target function which contains exp()
17672 or other fast growing functions, and optimization algorithm makes too
17673 large steps which leads to overflow. This function allows us to reject
17674 steps that are too large (and therefore expose us to the possible
17675 overflow) without actually calculating function value at the x+stp*d.
17676 
17677  -- ALGLIB --
17678  Copyright 02.04.2010 by Bochkanov Sergey
17679 *************************************************************************/
17680 void minlbfgssetstpmax(minlbfgsstate* state,
17681  double stpmax,
17682  ae_state *_state)
17683 {
17684 
17685 
17686  ae_assert(ae_isfinite(stpmax, _state), "MinLBFGSSetStpMax: StpMax is not finite!", _state);
17687  ae_assert(ae_fp_greater_eq(stpmax,0), "MinLBFGSSetStpMax: StpMax<0!", _state);
17688  state->stpmax = stpmax;
17689 }
17690 
17691 
17692 /*************************************************************************
17693 This function sets scaling coefficients for LBFGS optimizer.
17694 
17695 ALGLIB optimizers use scaling matrices to test stopping conditions (step
17696 size and gradient are scaled before comparison with tolerances). Scale of
17697 the I-th variable is a translation invariant measure of:
17698 a) "how large" the variable is
17699 b) how large the step should be to make significant changes in the function
17700 
17701 Scaling is also used by finite difference variant of the optimizer - step
17702 along I-th axis is equal to DiffStep*S[I].
17703 
17704 In most optimizers (and in the LBFGS too) scaling is NOT a form of
17705 preconditioning. It just affects stopping conditions. You should set
17706 preconditioner by separate call to one of the MinLBFGSSetPrec...()
17707 functions.
17708 
17709 There is special preconditioning mode, however, which uses scaling
17710 coefficients to form diagonal preconditioning matrix. You can turn this
17711 mode on, if you want. But you should understand that scaling is not the
17712 same thing as preconditioning - these are two different, although related
17713 forms of tuning solver.
17714 
17715 INPUT PARAMETERS:
17716  State - structure stores algorithm state
17717  S - array[N], non-zero scaling coefficients
17718  S[i] may be negative, sign doesn't matter.
17719 
17720  -- ALGLIB --
17721  Copyright 14.01.2011 by Bochkanov Sergey
17722 *************************************************************************/
17723 void minlbfgssetscale(minlbfgsstate* state,
17724  /* Real */ ae_vector* s,
17725  ae_state *_state)
17726 {
17727  ae_int_t i;
17728 
17729 
17730  ae_assert(s->cnt>=state->n, "MinLBFGSSetScale: Length(S)<N", _state);
17731  for(i=0; i<=state->n-1; i++)
17732  {
17733  ae_assert(ae_isfinite(s->ptr.p_double[i], _state), "MinLBFGSSetScale: S contains infinite or NAN elements", _state);
17734  ae_assert(ae_fp_neq(s->ptr.p_double[i],0), "MinLBFGSSetScale: S contains zero elements", _state);
17735  state->s.ptr.p_double[i] = ae_fabs(s->ptr.p_double[i], _state);
17736  }
17737 }
17738 
17739 
17740 /*************************************************************************
17741 Extended subroutine for internal use only.
17742 
17743 Accepts additional parameters:
17744 
17745  Flags - additional settings:
17746  * Flags = 0 means no additional settings
17747  * Flags = 1 "do not allocate memory". used when solving
17748  a many subsequent tasks with same N/M values.
17749  First call MUST be without this flag bit set,
17750  subsequent calls of MinLBFGS with same
17751  MinLBFGSState structure can set Flags to 1.
17752  DiffStep - numerical differentiation step
17753 
17754  -- ALGLIB --
17755  Copyright 02.04.2010 by Bochkanov Sergey
17756 *************************************************************************/
17757 void minlbfgscreatex(ae_int_t n,
17758  ae_int_t m,
17759  /* Real */ ae_vector* x,
17760  ae_int_t flags,
17761  double diffstep,
17762  minlbfgsstate* state,
17763  ae_state *_state)
17764 {
17765  ae_bool allocatemem;
17766  ae_int_t i;
17767 
17768 
17769  ae_assert(n>=1, "MinLBFGS: N too small!", _state);
17770  ae_assert(m>=1, "MinLBFGS: M too small!", _state);
17771  ae_assert(m<=n, "MinLBFGS: M too large!", _state);
17772 
17773  /*
17774  * Initialize
17775  */
17776  state->teststep = 0;
17777  state->diffstep = diffstep;
17778  state->n = n;
17779  state->m = m;
17780  allocatemem = flags%2==0;
17781  flags = flags/2;
17782  if( allocatemem )
17783  {
17784  ae_vector_set_length(&state->rho, m, _state);
17785  ae_vector_set_length(&state->theta, m, _state);
17786  ae_matrix_set_length(&state->yk, m, n, _state);
17787  ae_matrix_set_length(&state->sk, m, n, _state);
17788  ae_vector_set_length(&state->d, n, _state);
17789  ae_vector_set_length(&state->x, n, _state);
17790  ae_vector_set_length(&state->s, n, _state);
17791  ae_vector_set_length(&state->g, n, _state);
17792  ae_vector_set_length(&state->work, n, _state);
17793  }
17794  minlbfgssetcond(state, 0, 0, 0, 0, _state);
17795  minlbfgssetxrep(state, ae_false, _state);
17796  minlbfgssetstpmax(state, 0, _state);
17797  minlbfgsrestartfrom(state, x, _state);
17798  for(i=0; i<=n-1; i++)
17799  {
17800  state->s.ptr.p_double[i] = 1.0;
17801  }
17802  state->prectype = 0;
17803 }
17804 
17805 
17806 /*************************************************************************
17807 Modification of the preconditioner: default preconditioner (simple
17808 scaling, same for all elements of X) is used.
17809 
17810 INPUT PARAMETERS:
17811  State - structure which stores algorithm state
17812 
17813 NOTE: you can change preconditioner "on the fly", during algorithm
17814 iterations.
17815 
17816  -- ALGLIB --
17817  Copyright 13.10.2010 by Bochkanov Sergey
17818 *************************************************************************/
17819 void minlbfgssetprecdefault(minlbfgsstate* state, ae_state *_state)
17820 {
17821 
17822 
17823  state->prectype = 0;
17824 }
17825 
17826 
17827 /*************************************************************************
17828 Modification of the preconditioner: Cholesky factorization of approximate
17829 Hessian is used.
17830 
17831 INPUT PARAMETERS:
17832  State - structure which stores algorithm state
17833  P - triangular preconditioner, Cholesky factorization of
17834  the approximate Hessian. array[0..N-1,0..N-1],
17835  (if larger, only leading N elements are used).
17836  IsUpper - whether upper or lower triangle of P is given
17837  (other triangle is not referenced)
17838 
17839 After call to this function preconditioner is changed to P (P is copied
17840 into the internal buffer).
17841 
17842 NOTE: you can change preconditioner "on the fly", during algorithm
17843 iterations.
17844 
17845 NOTE 2: P should be nonsingular. Exception will be thrown otherwise.
17846 
17847  -- ALGLIB --
17848  Copyright 13.10.2010 by Bochkanov Sergey
17849 *************************************************************************/
17850 void minlbfgssetpreccholesky(minlbfgsstate* state,
17851  /* Real */ ae_matrix* p,
17852  ae_bool isupper,
17853  ae_state *_state)
17854 {
17855  ae_int_t i;
17856  double mx;
17857 
17858 
17859  ae_assert(isfinitertrmatrix(p, state->n, isupper, _state), "MinLBFGSSetPrecCholesky: P contains infinite or NAN values!", _state);
17860  mx = 0;
17861  for(i=0; i<=state->n-1; i++)
17862  {
17863  mx = ae_maxreal(mx, ae_fabs(p->ptr.pp_double[i][i], _state), _state);
17864  }
17865  ae_assert(ae_fp_greater(mx,0), "MinLBFGSSetPrecCholesky: P is strictly singular!", _state);
17866  if( state->denseh.rows<state->n||state->denseh.cols<state->n )
17867  {
17868  ae_matrix_set_length(&state->denseh, state->n, state->n, _state);
17869  }
17870  state->prectype = 1;
17871  if( isupper )
17872  {
17873  rmatrixcopy(state->n, state->n, p, 0, 0, &state->denseh, 0, 0, _state);
17874  }
17875  else
17876  {
17877  rmatrixtranspose(state->n, state->n, p, 0, 0, &state->denseh, 0, 0, _state);
17878  }
17879 }
17880 
17881 
17882 /*************************************************************************
17883 Modification of the preconditioner: diagonal of approximate Hessian is
17884 used.
17885 
17886 INPUT PARAMETERS:
17887  State - structure which stores algorithm state
17888  D - diagonal of the approximate Hessian, array[0..N-1],
17889  (if larger, only leading N elements are used).
17890 
17891 NOTE: you can change preconditioner "on the fly", during algorithm
17892 iterations.
17893 
17894 NOTE 2: D[i] should be positive. Exception will be thrown otherwise.
17895 
17896 NOTE 3: you should pass diagonal of approximate Hessian - NOT ITS INVERSE.
17897 
17898  -- ALGLIB --
17899  Copyright 13.10.2010 by Bochkanov Sergey
17900 *************************************************************************/
17901 void minlbfgssetprecdiag(minlbfgsstate* state,
17902  /* Real */ ae_vector* d,
17903  ae_state *_state)
17904 {
17905  ae_int_t i;
17906 
17907 
17908  ae_assert(d->cnt>=state->n, "MinLBFGSSetPrecDiag: D is too short", _state);
17909  for(i=0; i<=state->n-1; i++)
17910  {
17911  ae_assert(ae_isfinite(d->ptr.p_double[i], _state), "MinLBFGSSetPrecDiag: D contains infinite or NAN elements", _state);
17912  ae_assert(ae_fp_greater(d->ptr.p_double[i],0), "MinLBFGSSetPrecDiag: D contains non-positive elements", _state);
17913  }
17914  rvectorsetlengthatleast(&state->diagh, state->n, _state);
17915  state->prectype = 2;
17916  for(i=0; i<=state->n-1; i++)
17917  {
17918  state->diagh.ptr.p_double[i] = d->ptr.p_double[i];
17919  }
17920 }
17921 
17922 
17923 /*************************************************************************
17924 Modification of the preconditioner: scale-based diagonal preconditioning.
17925 
17926 This preconditioning mode can be useful when you don't have approximate
17927 diagonal of Hessian, but you know that your variables are badly scaled
17928 (for example, one variable is in [1,10], and another in [1000,100000]),
17929 and most part of the ill-conditioning comes from different scales of vars.
17930 
17931 In this case simple scale-based preconditioner, with H[i] = 1/(s[i]^2),
17932 can greatly improve convergence.
17933 
17934 IMPRTANT: you should set scale of your variables with MinLBFGSSetScale()
17935 call (before or after MinLBFGSSetPrecScale() call). Without knowledge of
17936 the scale of your variables scale-based preconditioner will be just unit
17937 matrix.
17938 
17939 INPUT PARAMETERS:
17940  State - structure which stores algorithm state
17941 
17942  -- ALGLIB --
17943  Copyright 13.10.2010 by Bochkanov Sergey
17944 *************************************************************************/
17945 void minlbfgssetprecscale(minlbfgsstate* state, ae_state *_state)
17946 {
17947 
17948 
17949  state->prectype = 3;
17950 }
17951 
17952 
17953 /*************************************************************************
17954 NOTES:
17955 
17956 1. This function has two different implementations: one which uses exact
17957  (analytical) user-supplied gradient, and one which uses function value
17958  only and numerically differentiates function in order to obtain
17959  gradient.
17960 
17961  Depending on the specific function used to create optimizer object
17962  (either MinLBFGSCreate() for analytical gradient or MinLBFGSCreateF()
17963  for numerical differentiation) you should choose appropriate variant of
17964  MinLBFGSOptimize() - one which accepts function AND gradient or one
17965  which accepts function ONLY.
17966 
17967  Be careful to choose variant of MinLBFGSOptimize() which corresponds to
17968  your optimization scheme! Table below lists different combinations of
17969  callback (function/gradient) passed to MinLBFGSOptimize() and specific
17970  function used to create optimizer.
17971 
17972 
17973  | USER PASSED TO MinLBFGSOptimize()
17974  CREATED WITH | function only | function and gradient
17975  ------------------------------------------------------------
17976  MinLBFGSCreateF() | work FAIL
17977  MinLBFGSCreate() | FAIL work
17978 
17979  Here "FAIL" denotes inappropriate combinations of optimizer creation
17980  function and MinLBFGSOptimize() version. Attemps to use such
17981  combination (for example, to create optimizer with MinLBFGSCreateF() and
17982  to pass gradient information to MinCGOptimize()) will lead to exception
17983  being thrown. Either you did not pass gradient when it WAS needed or
17984  you passed gradient when it was NOT needed.
17985 
17986  -- ALGLIB --
17987  Copyright 20.03.2009 by Bochkanov Sergey
17988 *************************************************************************/
17989 ae_bool minlbfgsiteration(minlbfgsstate* state, ae_state *_state)
17990 {
17991  ae_int_t n;
17992  ae_int_t m;
17993  ae_int_t i;
17994  ae_int_t j;
17995  ae_int_t ic;
17996  ae_int_t mcinfo;
17997  double v;
17998  double vv;
17999  ae_bool result;
18000 
18001 
18002 
18003  /*
18004  * Reverse communication preparations
18005  * I know it looks ugly, but it works the same way
18006  * anywhere from C++ to Python.
18007  *
18008  * This code initializes locals by:
18009  * * random values determined during code
18010  * generation - on first subroutine call
18011  * * values from previous call - on subsequent calls
18012  */
18013  if( state->rstate.stage>=0 )
18014  {
18015  n = state->rstate.ia.ptr.p_int[0];
18016  m = state->rstate.ia.ptr.p_int[1];
18017  i = state->rstate.ia.ptr.p_int[2];
18018  j = state->rstate.ia.ptr.p_int[3];
18019  ic = state->rstate.ia.ptr.p_int[4];
18020  mcinfo = state->rstate.ia.ptr.p_int[5];
18021  v = state->rstate.ra.ptr.p_double[0];
18022  vv = state->rstate.ra.ptr.p_double[1];
18023  }
18024  else
18025  {
18026  n = -983;
18027  m = -989;
18028  i = -834;
18029  j = 900;
18030  ic = -287;
18031  mcinfo = 364;
18032  v = 214;
18033  vv = -338;
18034  }
18035  if( state->rstate.stage==0 )
18036  {
18037  goto lbl_0;
18038  }
18039  if( state->rstate.stage==1 )
18040  {
18041  goto lbl_1;
18042  }
18043  if( state->rstate.stage==2 )
18044  {
18045  goto lbl_2;
18046  }
18047  if( state->rstate.stage==3 )
18048  {
18049  goto lbl_3;
18050  }
18051  if( state->rstate.stage==4 )
18052  {
18053  goto lbl_4;
18054  }
18055  if( state->rstate.stage==5 )
18056  {
18057  goto lbl_5;
18058  }
18059  if( state->rstate.stage==6 )
18060  {
18061  goto lbl_6;
18062  }
18063  if( state->rstate.stage==7 )
18064  {
18065  goto lbl_7;
18066  }
18067  if( state->rstate.stage==8 )
18068  {
18069  goto lbl_8;
18070  }
18071  if( state->rstate.stage==9 )
18072  {
18073  goto lbl_9;
18074  }
18075  if( state->rstate.stage==10 )
18076  {
18077  goto lbl_10;
18078  }
18079  if( state->rstate.stage==11 )
18080  {
18081  goto lbl_11;
18082  }
18083  if( state->rstate.stage==12 )
18084  {
18085  goto lbl_12;
18086  }
18087  if( state->rstate.stage==13 )
18088  {
18089  goto lbl_13;
18090  }
18091  if( state->rstate.stage==14 )
18092  {
18093  goto lbl_14;
18094  }
18095  if( state->rstate.stage==15 )
18096  {
18097  goto lbl_15;
18098  }
18099  if( state->rstate.stage==16 )
18100  {
18101  goto lbl_16;
18102  }
18103 
18104  /*
18105  * Routine body
18106  */
18107 
18108  /*
18109  * Unload frequently used variables from State structure
18110  * (just for typing convenience)
18111  */
18112  n = state->n;
18113  m = state->m;
18114  state->repterminationtype = 0;
18115  state->repiterationscount = 0;
18116  state->repvaridx = -1;
18117  state->repnfev = 0;
18118 
18119  /*
18120  * Check, that transferred derivative value is right
18121  */
18122  minlbfgs_clearrequestfields(state, _state);
18123  if( !(ae_fp_eq(state->diffstep,0)&&ae_fp_greater(state->teststep,0)) )
18124  {
18125  goto lbl_17;
18126  }
18127  state->needfg = ae_true;
18128  i = 0;
18129 lbl_19:
18130  if( i>n-1 )
18131  {
18132  goto lbl_21;
18133  }
18134  v = state->x.ptr.p_double[i];
18135  state->x.ptr.p_double[i] = v-state->teststep*state->s.ptr.p_double[i];
18136  state->rstate.stage = 0;
18137  goto lbl_rcomm;
18138 lbl_0:
18139  state->fm1 = state->f;
18140  state->fp1 = state->g.ptr.p_double[i];
18141  state->x.ptr.p_double[i] = v+state->teststep*state->s.ptr.p_double[i];
18142  state->rstate.stage = 1;
18143  goto lbl_rcomm;
18144 lbl_1:
18145  state->fm2 = state->f;
18146  state->fp2 = state->g.ptr.p_double[i];
18147  state->x.ptr.p_double[i] = v;
18148  state->rstate.stage = 2;
18149  goto lbl_rcomm;
18150 lbl_2:
18151 
18152  /*
18153  * 2*State.TestStep - scale parameter
18154  * width of segment [Xi-TestStep;Xi+TestStep]
18155  */
18156  if( !derivativecheck(state->fm1, state->fp1, state->fm2, state->fp2, state->f, state->g.ptr.p_double[i], 2*state->teststep, _state) )
18157  {
18158  state->repvaridx = i;
18159  state->repterminationtype = -7;
18160  result = ae_false;
18161  return result;
18162  }
18163  i = i+1;
18164  goto lbl_19;
18165 lbl_21:
18166  state->needfg = ae_false;
18167 lbl_17:
18168 
18169  /*
18170  * Calculate F/G at the initial point
18171  */
18172  minlbfgs_clearrequestfields(state, _state);
18173  if( ae_fp_neq(state->diffstep,0) )
18174  {
18175  goto lbl_22;
18176  }
18177  state->needfg = ae_true;
18178  state->rstate.stage = 3;
18179  goto lbl_rcomm;
18180 lbl_3:
18181  state->needfg = ae_false;
18182  goto lbl_23;
18183 lbl_22:
18184  state->needf = ae_true;
18185  state->rstate.stage = 4;
18186  goto lbl_rcomm;
18187 lbl_4:
18188  state->fbase = state->f;
18189  i = 0;
18190 lbl_24:
18191  if( i>n-1 )
18192  {
18193  goto lbl_26;
18194  }
18195  v = state->x.ptr.p_double[i];
18196  state->x.ptr.p_double[i] = v-state->diffstep*state->s.ptr.p_double[i];
18197  state->rstate.stage = 5;
18198  goto lbl_rcomm;
18199 lbl_5:
18200  state->fm2 = state->f;
18201  state->x.ptr.p_double[i] = v-0.5*state->diffstep*state->s.ptr.p_double[i];
18202  state->rstate.stage = 6;
18203  goto lbl_rcomm;
18204 lbl_6:
18205  state->fm1 = state->f;
18206  state->x.ptr.p_double[i] = v+0.5*state->diffstep*state->s.ptr.p_double[i];
18207  state->rstate.stage = 7;
18208  goto lbl_rcomm;
18209 lbl_7:
18210  state->fp1 = state->f;
18211  state->x.ptr.p_double[i] = v+state->diffstep*state->s.ptr.p_double[i];
18212  state->rstate.stage = 8;
18213  goto lbl_rcomm;
18214 lbl_8:
18215  state->fp2 = state->f;
18216  state->x.ptr.p_double[i] = v;
18217  state->g.ptr.p_double[i] = (8*(state->fp1-state->fm1)-(state->fp2-state->fm2))/(6*state->diffstep*state->s.ptr.p_double[i]);
18218  i = i+1;
18219  goto lbl_24;
18220 lbl_26:
18221  state->f = state->fbase;
18222  state->needf = ae_false;
18223 lbl_23:
18224  trimprepare(state->f, &state->trimthreshold, _state);
18225  if( !state->xrep )
18226  {
18227  goto lbl_27;
18228  }
18229  minlbfgs_clearrequestfields(state, _state);
18230  state->xupdated = ae_true;
18231  state->rstate.stage = 9;
18232  goto lbl_rcomm;
18233 lbl_9:
18234  state->xupdated = ae_false;
18235 lbl_27:
18236  state->repnfev = 1;
18237  state->fold = state->f;
18238  v = 0;
18239  for(i=0; i<=n-1; i++)
18240  {
18241  v = v+ae_sqr(state->g.ptr.p_double[i]*state->s.ptr.p_double[i], _state);
18242  }
18243  if( ae_fp_less_eq(ae_sqrt(v, _state),state->epsg) )
18244  {
18245  state->repterminationtype = 4;
18246  result = ae_false;
18247  return result;
18248  }
18249 
18250  /*
18251  * Choose initial step and direction.
18252  * Apply preconditioner, if we have something other than default.
18253  */
18254  ae_v_moveneg(&state->d.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1));
18255  if( state->prectype==0 )
18256  {
18257 
18258  /*
18259  * Default preconditioner is used, but we can't use it before iterations will start
18260  */
18261  v = ae_v_dotproduct(&state->g.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1));
18262  v = ae_sqrt(v, _state);
18263  if( ae_fp_eq(state->stpmax,0) )
18264  {
18265  state->stp = ae_minreal(1.0/v, 1, _state);
18266  }
18267  else
18268  {
18269  state->stp = ae_minreal(1.0/v, state->stpmax, _state);
18270  }
18271  }
18272  if( state->prectype==1 )
18273  {
18274 
18275  /*
18276  * Cholesky preconditioner is used
18277  */
18278  fblscholeskysolve(&state->denseh, 1.0, n, ae_true, &state->d, &state->autobuf, _state);
18279  state->stp = 1;
18280  }
18281  if( state->prectype==2 )
18282  {
18283 
18284  /*
18285  * diagonal approximation is used
18286  */
18287  for(i=0; i<=n-1; i++)
18288  {
18289  state->d.ptr.p_double[i] = state->d.ptr.p_double[i]/state->diagh.ptr.p_double[i];
18290  }
18291  state->stp = 1;
18292  }
18293  if( state->prectype==3 )
18294  {
18295 
18296  /*
18297  * scale-based preconditioner is used
18298  */
18299  for(i=0; i<=n-1; i++)
18300  {
18301  state->d.ptr.p_double[i] = state->d.ptr.p_double[i]*state->s.ptr.p_double[i]*state->s.ptr.p_double[i];
18302  }
18303  state->stp = 1;
18304  }
18305 
18306  /*
18307  * Main cycle
18308  */
18309  state->k = 0;
18310 lbl_29:
18311  if( ae_false )
18312  {
18313  goto lbl_30;
18314  }
18315 
18316  /*
18317  * Main cycle: prepare to 1-D line search
18318  */
18319  state->p = state->k%m;
18320  state->q = ae_minint(state->k, m-1, _state);
18321 
18322  /*
18323  * Store X[k], G[k]
18324  */
18325  ae_v_moveneg(&state->sk.ptr.pp_double[state->p][0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,n-1));
18326  ae_v_moveneg(&state->yk.ptr.pp_double[state->p][0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1));
18327 
18328  /*
18329  * Minimize F(x+alpha*d)
18330  * Calculate S[k], Y[k]
18331  */
18332  state->mcstage = 0;
18333  if( state->k!=0 )
18334  {
18335  state->stp = 1.0;
18336  }
18337  linminnormalized(&state->d, &state->stp, n, _state);
18338  mcsrch(n, &state->x, &state->f, &state->g, &state->d, &state->stp, state->stpmax, minlbfgs_gtol, &mcinfo, &state->nfev, &state->work, &state->lstate, &state->mcstage, _state);
18339 lbl_31:
18340  if( state->mcstage==0 )
18341  {
18342  goto lbl_32;
18343  }
18344  minlbfgs_clearrequestfields(state, _state);
18345  if( ae_fp_neq(state->diffstep,0) )
18346  {
18347  goto lbl_33;
18348  }
18349  state->needfg = ae_true;
18350  state->rstate.stage = 10;
18351  goto lbl_rcomm;
18352 lbl_10:
18353  state->needfg = ae_false;
18354  goto lbl_34;
18355 lbl_33:
18356  state->needf = ae_true;
18357  state->rstate.stage = 11;
18358  goto lbl_rcomm;
18359 lbl_11:
18360  state->fbase = state->f;
18361  i = 0;
18362 lbl_35:
18363  if( i>n-1 )
18364  {
18365  goto lbl_37;
18366  }
18367  v = state->x.ptr.p_double[i];
18368  state->x.ptr.p_double[i] = v-state->diffstep*state->s.ptr.p_double[i];
18369  state->rstate.stage = 12;
18370  goto lbl_rcomm;
18371 lbl_12:
18372  state->fm2 = state->f;
18373  state->x.ptr.p_double[i] = v-0.5*state->diffstep*state->s.ptr.p_double[i];
18374  state->rstate.stage = 13;
18375  goto lbl_rcomm;
18376 lbl_13:
18377  state->fm1 = state->f;
18378  state->x.ptr.p_double[i] = v+0.5*state->diffstep*state->s.ptr.p_double[i];
18379  state->rstate.stage = 14;
18380  goto lbl_rcomm;
18381 lbl_14:
18382  state->fp1 = state->f;
18383  state->x.ptr.p_double[i] = v+state->diffstep*state->s.ptr.p_double[i];
18384  state->rstate.stage = 15;
18385  goto lbl_rcomm;
18386 lbl_15:
18387  state->fp2 = state->f;
18388  state->x.ptr.p_double[i] = v;
18389  state->g.ptr.p_double[i] = (8*(state->fp1-state->fm1)-(state->fp2-state->fm2))/(6*state->diffstep*state->s.ptr.p_double[i]);
18390  i = i+1;
18391  goto lbl_35;
18392 lbl_37:
18393  state->f = state->fbase;
18394  state->needf = ae_false;
18395 lbl_34:
18396  trimfunction(&state->f, &state->g, n, state->trimthreshold, _state);
18397  mcsrch(n, &state->x, &state->f, &state->g, &state->d, &state->stp, state->stpmax, minlbfgs_gtol, &mcinfo, &state->nfev, &state->work, &state->lstate, &state->mcstage, _state);
18398  goto lbl_31;
18399 lbl_32:
18400  if( !state->xrep )
18401  {
18402  goto lbl_38;
18403  }
18404 
18405  /*
18406  * report
18407  */
18408  minlbfgs_clearrequestfields(state, _state);
18409  state->xupdated = ae_true;
18410  state->rstate.stage = 16;
18411  goto lbl_rcomm;
18412 lbl_16:
18413  state->xupdated = ae_false;
18414 lbl_38:
18415  state->repnfev = state->repnfev+state->nfev;
18416  state->repiterationscount = state->repiterationscount+1;
18417  ae_v_add(&state->sk.ptr.pp_double[state->p][0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,n-1));
18418  ae_v_add(&state->yk.ptr.pp_double[state->p][0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1));
18419 
18420  /*
18421  * Stopping conditions
18422  */
18423  if( state->repiterationscount>=state->maxits&&state->maxits>0 )
18424  {
18425 
18426  /*
18427  * Too many iterations
18428  */
18429  state->repterminationtype = 5;
18430  result = ae_false;
18431  return result;
18432  }
18433  v = 0;
18434  for(i=0; i<=n-1; i++)
18435  {
18436  v = v+ae_sqr(state->g.ptr.p_double[i]*state->s.ptr.p_double[i], _state);
18437  }
18438  if( ae_fp_less_eq(ae_sqrt(v, _state),state->epsg) )
18439  {
18440 
18441  /*
18442  * Gradient is small enough
18443  */
18444  state->repterminationtype = 4;
18445  result = ae_false;
18446  return result;
18447  }
18448  if( ae_fp_less_eq(state->fold-state->f,state->epsf*ae_maxreal(ae_fabs(state->fold, _state), ae_maxreal(ae_fabs(state->f, _state), 1.0, _state), _state)) )
18449  {
18450 
18451  /*
18452  * F(k+1)-F(k) is small enough
18453  */
18454  state->repterminationtype = 1;
18455  result = ae_false;
18456  return result;
18457  }
18458  v = 0;
18459  for(i=0; i<=n-1; i++)
18460  {
18461  v = v+ae_sqr(state->sk.ptr.pp_double[state->p][i]/state->s.ptr.p_double[i], _state);
18462  }
18463  if( ae_fp_less_eq(ae_sqrt(v, _state),state->epsx) )
18464  {
18465 
18466  /*
18467  * X(k+1)-X(k) is small enough
18468  */
18469  state->repterminationtype = 2;
18470  result = ae_false;
18471  return result;
18472  }
18473 
18474  /*
18475  * If Wolfe conditions are satisfied, we can update
18476  * limited memory model.
18477  *
18478  * However, if conditions are not satisfied (NFEV limit is met,
18479  * function is too wild, ...), we'll skip L-BFGS update
18480  */
18481  if( mcinfo!=1 )
18482  {
18483 
18484  /*
18485  * Skip update.
18486  *
18487  * In such cases we'll initialize search direction by
18488  * antigradient vector, because it leads to more
18489  * transparent code with less number of special cases
18490  */
18491  state->fold = state->f;
18492  ae_v_moveneg(&state->d.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1));
18493  }
18494  else
18495  {
18496 
18497  /*
18498  * Calculate Rho[k], GammaK
18499  */
18500  v = ae_v_dotproduct(&state->yk.ptr.pp_double[state->p][0], 1, &state->sk.ptr.pp_double[state->p][0], 1, ae_v_len(0,n-1));
18501  vv = ae_v_dotproduct(&state->yk.ptr.pp_double[state->p][0], 1, &state->yk.ptr.pp_double[state->p][0], 1, ae_v_len(0,n-1));
18502  if( ae_fp_eq(v,0)||ae_fp_eq(vv,0) )
18503  {
18504 
18505  /*
18506  * Rounding errors make further iterations impossible.
18507  */
18508  state->repterminationtype = -2;
18509  result = ae_false;
18510  return result;
18511  }
18512  state->rho.ptr.p_double[state->p] = 1/v;
18513  state->gammak = v/vv;
18514 
18515  /*
18516  * Calculate d(k+1) = -H(k+1)*g(k+1)
18517  *
18518  * for I:=K downto K-Q do
18519  * V = s(i)^T * work(iteration:I)
18520  * theta(i) = V
18521  * work(iteration:I+1) = work(iteration:I) - V*Rho(i)*y(i)
18522  * work(last iteration) = H0*work(last iteration) - preconditioner
18523  * for I:=K-Q to K do
18524  * V = y(i)^T*work(iteration:I)
18525  * work(iteration:I+1) = work(iteration:I) +(-V+theta(i))*Rho(i)*s(i)
18526  *
18527  * NOW WORK CONTAINS d(k+1)
18528  */
18529  ae_v_move(&state->work.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1));
18530  for(i=state->k; i>=state->k-state->q; i--)
18531  {
18532  ic = i%m;
18533  v = ae_v_dotproduct(&state->sk.ptr.pp_double[ic][0], 1, &state->work.ptr.p_double[0], 1, ae_v_len(0,n-1));
18534  state->theta.ptr.p_double[ic] = v;
18535  vv = v*state->rho.ptr.p_double[ic];
18536  ae_v_subd(&state->work.ptr.p_double[0], 1, &state->yk.ptr.pp_double[ic][0], 1, ae_v_len(0,n-1), vv);
18537  }
18538  if( state->prectype==0 )
18539  {
18540 
18541  /*
18542  * Simple preconditioner is used
18543  */
18544  v = state->gammak;
18545  ae_v_muld(&state->work.ptr.p_double[0], 1, ae_v_len(0,n-1), v);
18546  }
18547  if( state->prectype==1 )
18548  {
18549 
18550  /*
18551  * Cholesky preconditioner is used
18552  */
18553  fblscholeskysolve(&state->denseh, 1, n, ae_true, &state->work, &state->autobuf, _state);
18554  }
18555  if( state->prectype==2 )
18556  {
18557 
18558  /*
18559  * diagonal approximation is used
18560  */
18561  for(i=0; i<=n-1; i++)
18562  {
18563  state->work.ptr.p_double[i] = state->work.ptr.p_double[i]/state->diagh.ptr.p_double[i];
18564  }
18565  }
18566  if( state->prectype==3 )
18567  {
18568 
18569  /*
18570  * scale-based preconditioner is used
18571  */
18572  for(i=0; i<=n-1; i++)
18573  {
18574  state->work.ptr.p_double[i] = state->work.ptr.p_double[i]*state->s.ptr.p_double[i]*state->s.ptr.p_double[i];
18575  }
18576  }
18577  for(i=state->k-state->q; i<=state->k; i++)
18578  {
18579  ic = i%m;
18580  v = ae_v_dotproduct(&state->yk.ptr.pp_double[ic][0], 1, &state->work.ptr.p_double[0], 1, ae_v_len(0,n-1));
18581  vv = state->rho.ptr.p_double[ic]*(-v+state->theta.ptr.p_double[ic]);
18582  ae_v_addd(&state->work.ptr.p_double[0], 1, &state->sk.ptr.pp_double[ic][0], 1, ae_v_len(0,n-1), vv);
18583  }
18584  ae_v_moveneg(&state->d.ptr.p_double[0], 1, &state->work.ptr.p_double[0], 1, ae_v_len(0,n-1));
18585 
18586  /*
18587  * Next step
18588  */
18589  state->fold = state->f;
18590  state->k = state->k+1;
18591  }
18592  goto lbl_29;
18593 lbl_30:
18594  result = ae_false;
18595  return result;
18596 
18597  /*
18598  * Saving state
18599  */
18600 lbl_rcomm:
18601  result = ae_true;
18602  state->rstate.ia.ptr.p_int[0] = n;
18603  state->rstate.ia.ptr.p_int[1] = m;
18604  state->rstate.ia.ptr.p_int[2] = i;
18605  state->rstate.ia.ptr.p_int[3] = j;
18606  state->rstate.ia.ptr.p_int[4] = ic;
18607  state->rstate.ia.ptr.p_int[5] = mcinfo;
18608  state->rstate.ra.ptr.p_double[0] = v;
18609  state->rstate.ra.ptr.p_double[1] = vv;
18610  return result;
18611 }
18612 
18613 
18614 /*************************************************************************
18615 L-BFGS algorithm results
18616 
18617 INPUT PARAMETERS:
18618  State - algorithm state
18619 
18620 OUTPUT PARAMETERS:
18621  X - array[0..N-1], solution
18622  Rep - optimization report:
18623  * Rep.TerminationType completion code:
18624  * -7 gradient verification failed.
18625  See MinLBFGSSetGradientCheck() for more information.
18626  * -2 rounding errors prevent further improvement.
18627  X contains best point found.
18628  * -1 incorrect parameters were specified
18629  * 1 relative function improvement is no more than
18630  EpsF.
18631  * 2 relative step is no more than EpsX.
18632  * 4 gradient norm is no more than EpsG
18633  * 5 MaxIts steps was taken
18634  * 7 stopping conditions are too stringent,
18635  further improvement is impossible
18636  * Rep.IterationsCount contains iterations count
18637  * NFEV contains number of function calculations
18638 
18639  -- ALGLIB --
18640  Copyright 02.04.2010 by Bochkanov Sergey
18641 *************************************************************************/
18642 void minlbfgsresults(minlbfgsstate* state,
18643  /* Real */ ae_vector* x,
18644  minlbfgsreport* rep,
18645  ae_state *_state)
18646 {
18647 
18648  ae_vector_clear(x);
18649  _minlbfgsreport_clear(rep);
18650 
18651  minlbfgsresultsbuf(state, x, rep, _state);
18652 }
18653 
18654 
18655 /*************************************************************************
18656 L-BFGS algorithm results
18657 
18658 Buffered implementation of MinLBFGSResults which uses pre-allocated buffer
18659 to store X[]. If buffer size is too small, it resizes buffer. It is
18660 intended to be used in the inner cycles of performance critical algorithms
18661 where array reallocation penalty is too large to be ignored.
18662 
18663  -- ALGLIB --
18664  Copyright 20.08.2010 by Bochkanov Sergey
18665 *************************************************************************/
18666 void minlbfgsresultsbuf(minlbfgsstate* state,
18667  /* Real */ ae_vector* x,
18668  minlbfgsreport* rep,
18669  ae_state *_state)
18670 {
18671 
18672 
18673  if( x->cnt<state->n )
18674  {
18675  ae_vector_set_length(x, state->n, _state);
18676  }
18677  ae_v_move(&x->ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,state->n-1));
18678  rep->iterationscount = state->repiterationscount;
18679  rep->nfev = state->repnfev;
18680  rep->varidx = state->repvaridx;
18681  rep->terminationtype = state->repterminationtype;
18682 }
18683 
18684 
18685 /*************************************************************************
18686 This subroutine restarts LBFGS algorithm from new point. All optimization
18687 parameters are left unchanged.
18688 
18689 This function allows to solve multiple optimization problems (which
18690 must have same number of dimensions) without object reallocation penalty.
18691 
18692 INPUT PARAMETERS:
18693  State - structure used to store algorithm state
18694  X - new starting point.
18695 
18696  -- ALGLIB --
18697  Copyright 30.07.2010 by Bochkanov Sergey
18698 *************************************************************************/
18699 void minlbfgsrestartfrom(minlbfgsstate* state,
18700  /* Real */ ae_vector* x,
18701  ae_state *_state)
18702 {
18703 
18704 
18705  ae_assert(x->cnt>=state->n, "MinLBFGSRestartFrom: Length(X)<N!", _state);
18706  ae_assert(isfinitevector(x, state->n, _state), "MinLBFGSRestartFrom: X contains infinite or NaN values!", _state);
18707  ae_v_move(&state->x.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,state->n-1));
18708  ae_vector_set_length(&state->rstate.ia, 5+1, _state);
18709  ae_vector_set_length(&state->rstate.ra, 1+1, _state);
18710  state->rstate.stage = -1;
18711  minlbfgs_clearrequestfields(state, _state);
18712 }
18713 
18714 
18715 /*************************************************************************
18716 This subroutine turns on verification of the user-supplied analytic
18717 gradient:
18718 * user calls this subroutine before optimization begins
18719 * MinLBFGSOptimize() is called
18720 * prior to actual optimization, for each component of parameters being
18721  optimized X[i] algorithm performs following steps:
18722  * two trial steps are made to X[i]-TestStep*S[i] and X[i]+TestStep*S[i],
18723  where X[i] is i-th component of the initial point and S[i] is a scale
18724  of i-th parameter
18725  * if needed, steps are bounded with respect to constraints on X[]
18726  * F(X) is evaluated at these trial points
18727  * we perform one more evaluation in the middle point of the interval
18728  * we build cubic model using function values and derivatives at trial
18729  points and we compare its prediction with actual value in the middle
18730  point
18731  * in case difference between prediction and actual value is higher than
18732  some predetermined threshold, algorithm stops with completion code -7;
18733  Rep.VarIdx is set to index of the parameter with incorrect derivative.
18734 * after verification is over, algorithm proceeds to the actual optimization.
18735 
18736 NOTE 1: verification needs N (parameters count) gradient evaluations. It
18737  is very costly and you should use it only for low dimensional
18738  problems, when you want to be sure that you've correctly
18739  calculated analytic derivatives. You should not use it in the
18740  production code (unless you want to check derivatives provided by
18741  some third party).
18742 
18743 NOTE 2: you should carefully choose TestStep. Value which is too large
18744  (so large that function behaviour is significantly non-cubic) will
18745  lead to false alarms. You may use different step for different
18746  parameters by means of setting scale with MinLBFGSSetScale().
18747 
18748 NOTE 3: this function may lead to false positives. In case it reports that
18749  I-th derivative was calculated incorrectly, you may decrease test
18750  step and try one more time - maybe your function changes too
18751  sharply and your step is too large for such rapidly chanding
18752  function.
18753 
18754 INPUT PARAMETERS:
18755  State - structure used to store algorithm state
18756  TestStep - verification step:
18757  * TestStep=0 turns verification off
18758  * TestStep>0 activates verification
18759 
18760  -- ALGLIB --
18761  Copyright 24.05.2012 by Bochkanov Sergey
18762 *************************************************************************/
18763 void minlbfgssetgradientcheck(minlbfgsstate* state,
18764  double teststep,
18765  ae_state *_state)
18766 {
18767 
18768 
18769  ae_assert(ae_isfinite(teststep, _state), "MinLBFGSSetGradientCheck: TestStep contains NaN or Infinite", _state);
18770  ae_assert(ae_fp_greater_eq(teststep,0), "MinLBFGSSetGradientCheck: invalid argument TestStep(TestStep<0)", _state);
18771  state->teststep = teststep;
18772 }
18773 
18774 
18775 /*************************************************************************
18776 Clears request fileds (to be sure that we don't forgot to clear something)
18777 *************************************************************************/
18778 static void minlbfgs_clearrequestfields(minlbfgsstate* state,
18779  ae_state *_state)
18780 {
18781 
18782 
18783  state->needf = ae_false;
18784  state->needfg = ae_false;
18785  state->xupdated = ae_false;
18786 }
18787 
18788 
18789 ae_bool _minlbfgsstate_init(void* _p, ae_state *_state, ae_bool make_automatic)
18790 {
18791  minlbfgsstate *p = (minlbfgsstate*)_p;
18792  ae_touch_ptr((void*)p);
18793  if( !ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic) )
18794  return ae_false;
18795  if( !ae_vector_init(&p->rho, 0, DT_REAL, _state, make_automatic) )
18796  return ae_false;
18797  if( !ae_matrix_init(&p->yk, 0, 0, DT_REAL, _state, make_automatic) )
18798  return ae_false;
18799  if( !ae_matrix_init(&p->sk, 0, 0, DT_REAL, _state, make_automatic) )
18800  return ae_false;
18801  if( !ae_vector_init(&p->theta, 0, DT_REAL, _state, make_automatic) )
18802  return ae_false;
18803  if( !ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic) )
18804  return ae_false;
18805  if( !ae_vector_init(&p->work, 0, DT_REAL, _state, make_automatic) )
18806  return ae_false;
18807  if( !ae_matrix_init(&p->denseh, 0, 0, DT_REAL, _state, make_automatic) )
18808  return ae_false;
18809  if( !ae_vector_init(&p->diagh, 0, DT_REAL, _state, make_automatic) )
18810  return ae_false;
18811  if( !ae_vector_init(&p->autobuf, 0, DT_REAL, _state, make_automatic) )
18812  return ae_false;
18813  if( !ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic) )
18814  return ae_false;
18815  if( !ae_vector_init(&p->g, 0, DT_REAL, _state, make_automatic) )
18816  return ae_false;
18817  if( !_rcommstate_init(&p->rstate, _state, make_automatic) )
18818  return ae_false;
18819  if( !_linminstate_init(&p->lstate, _state, make_automatic) )
18820  return ae_false;
18821  return ae_true;
18822 }
18823 
18824 
18825 ae_bool _minlbfgsstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
18826 {
18827  minlbfgsstate *dst = (minlbfgsstate*)_dst;
18828  minlbfgsstate *src = (minlbfgsstate*)_src;
18829  dst->n = src->n;
18830  dst->m = src->m;
18831  dst->epsg = src->epsg;
18832  dst->epsf = src->epsf;
18833  dst->epsx = src->epsx;
18834  dst->maxits = src->maxits;
18835  dst->xrep = src->xrep;
18836  dst->stpmax = src->stpmax;
18837  if( !ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic) )
18838  return ae_false;
18839  dst->diffstep = src->diffstep;
18840  dst->nfev = src->nfev;
18841  dst->mcstage = src->mcstage;
18842  dst->k = src->k;
18843  dst->q = src->q;
18844  dst->p = src->p;
18845  if( !ae_vector_init_copy(&dst->rho, &src->rho, _state, make_automatic) )
18846  return ae_false;
18847  if( !ae_matrix_init_copy(&dst->yk, &src->yk, _state, make_automatic) )
18848  return ae_false;
18849  if( !ae_matrix_init_copy(&dst->sk, &src->sk, _state, make_automatic) )
18850  return ae_false;
18851  if( !ae_vector_init_copy(&dst->theta, &src->theta, _state, make_automatic) )
18852  return ae_false;
18853  if( !ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic) )
18854  return ae_false;
18855  dst->stp = src->stp;
18856  if( !ae_vector_init_copy(&dst->work, &src->work, _state, make_automatic) )
18857  return ae_false;
18858  dst->fold = src->fold;
18859  dst->trimthreshold = src->trimthreshold;
18860  dst->prectype = src->prectype;
18861  dst->gammak = src->gammak;
18862  if( !ae_matrix_init_copy(&dst->denseh, &src->denseh, _state, make_automatic) )
18863  return ae_false;
18864  if( !ae_vector_init_copy(&dst->diagh, &src->diagh, _state, make_automatic) )
18865  return ae_false;
18866  dst->fbase = src->fbase;
18867  dst->fm2 = src->fm2;
18868  dst->fm1 = src->fm1;
18869  dst->fp1 = src->fp1;
18870  dst->fp2 = src->fp2;
18871  if( !ae_vector_init_copy(&dst->autobuf, &src->autobuf, _state, make_automatic) )
18872  return ae_false;
18873  if( !ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic) )
18874  return ae_false;
18875  dst->f = src->f;
18876  if( !ae_vector_init_copy(&dst->g, &src->g, _state, make_automatic) )
18877  return ae_false;
18878  dst->needf = src->needf;
18879  dst->needfg = src->needfg;
18880  dst->xupdated = src->xupdated;
18881  dst->teststep = src->teststep;
18882  if( !_rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic) )
18883  return ae_false;
18884  dst->repiterationscount = src->repiterationscount;
18885  dst->repnfev = src->repnfev;
18886  dst->repvaridx = src->repvaridx;
18887  dst->repterminationtype = src->repterminationtype;
18888  if( !_linminstate_init_copy(&dst->lstate, &src->lstate, _state, make_automatic) )
18889  return ae_false;
18890  return ae_true;
18891 }
18892 
18893 
18894 void _minlbfgsstate_clear(void* _p)
18895 {
18896  minlbfgsstate *p = (minlbfgsstate*)_p;
18897  ae_touch_ptr((void*)p);
18898  ae_vector_clear(&p->s);
18899  ae_vector_clear(&p->rho);
18900  ae_matrix_clear(&p->yk);
18901  ae_matrix_clear(&p->sk);
18902  ae_vector_clear(&p->theta);
18903  ae_vector_clear(&p->d);
18904  ae_vector_clear(&p->work);
18905  ae_matrix_clear(&p->denseh);
18906  ae_vector_clear(&p->diagh);
18907  ae_vector_clear(&p->autobuf);
18908  ae_vector_clear(&p->x);
18909  ae_vector_clear(&p->g);
18910  _rcommstate_clear(&p->rstate);
18911  _linminstate_clear(&p->lstate);
18912 }
18913 
18914 
18915 void _minlbfgsstate_destroy(void* _p)
18916 {
18917  minlbfgsstate *p = (minlbfgsstate*)_p;
18918  ae_touch_ptr((void*)p);
18919  ae_vector_destroy(&p->s);
18920  ae_vector_destroy(&p->rho);
18921  ae_matrix_destroy(&p->yk);
18922  ae_matrix_destroy(&p->sk);
18923  ae_vector_destroy(&p->theta);
18924  ae_vector_destroy(&p->d);
18925  ae_vector_destroy(&p->work);
18926  ae_matrix_destroy(&p->denseh);
18927  ae_vector_destroy(&p->diagh);
18928  ae_vector_destroy(&p->autobuf);
18929  ae_vector_destroy(&p->x);
18930  ae_vector_destroy(&p->g);
18931  _rcommstate_destroy(&p->rstate);
18932  _linminstate_destroy(&p->lstate);
18933 }
18934 
18935 
18936 ae_bool _minlbfgsreport_init(void* _p, ae_state *_state, ae_bool make_automatic)
18937 {
18938  minlbfgsreport *p = (minlbfgsreport*)_p;
18939  ae_touch_ptr((void*)p);
18940  return ae_true;
18941 }
18942 
18943 
18944 ae_bool _minlbfgsreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
18945 {
18946  minlbfgsreport *dst = (minlbfgsreport*)_dst;
18947  minlbfgsreport *src = (minlbfgsreport*)_src;
18948  dst->iterationscount = src->iterationscount;
18949  dst->nfev = src->nfev;
18950  dst->varidx = src->varidx;
18951  dst->terminationtype = src->terminationtype;
18952  return ae_true;
18953 }
18954 
18955 
18956 void _minlbfgsreport_clear(void* _p)
18957 {
18958  minlbfgsreport *p = (minlbfgsreport*)_p;
18959  ae_touch_ptr((void*)p);
18960 }
18961 
18962 
18963 void _minlbfgsreport_destroy(void* _p)
18964 {
18965  minlbfgsreport *p = (minlbfgsreport*)_p;
18966  ae_touch_ptr((void*)p);
18967 }
18968 
18969 
18970 
18971 
18972 /*************************************************************************
18973  CONSTRAINED QUADRATIC PROGRAMMING
18974 
18975 The subroutine creates QP optimizer. After initial creation, it contains
18976 default optimization problem with zero quadratic and linear terms and no
18977 constraints. You should set quadratic/linear terms with calls to functions
18978 provided by MinQP subpackage.
18979 
18980 INPUT PARAMETERS:
18981  N - problem size
18982 
18983 OUTPUT PARAMETERS:
18984  State - optimizer with zero quadratic/linear terms
18985  and no constraints
18986 
18987  -- ALGLIB --
18988  Copyright 11.01.2011 by Bochkanov Sergey
18989 *************************************************************************/
18990 void minqpcreate(ae_int_t n, minqpstate* state, ae_state *_state)
18991 {
18992  ae_int_t i;
18993 
18994  _minqpstate_clear(state);
18995 
18996  ae_assert(n>=1, "MinQPCreate: N<1", _state);
18997 
18998  /*
18999  * initialize QP solver
19000  */
19001  state->n = n;
19002  state->nec = 0;
19003  state->nic = 0;
19004  state->repterminationtype = 0;
19005  state->anorm = 1;
19006  state->akind = 0;
19007  cqminit(n, &state->a, _state);
19008  sasinit(n, &state->sas, _state);
19009  ae_vector_set_length(&state->b, n, _state);
19010  ae_vector_set_length(&state->bndl, n, _state);
19011  ae_vector_set_length(&state->bndu, n, _state);
19012  ae_vector_set_length(&state->workbndl, n, _state);
19013  ae_vector_set_length(&state->workbndu, n, _state);
19014  ae_vector_set_length(&state->havebndl, n, _state);
19015  ae_vector_set_length(&state->havebndu, n, _state);
19016  ae_vector_set_length(&state->s, n, _state);
19017  ae_vector_set_length(&state->startx, n, _state);
19018  ae_vector_set_length(&state->xorigin, n, _state);
19019  ae_vector_set_length(&state->xs, n, _state);
19020  ae_vector_set_length(&state->xn, n, _state);
19021  ae_vector_set_length(&state->gc, n, _state);
19022  ae_vector_set_length(&state->pg, n, _state);
19023  for(i=0; i<=n-1; i++)
19024  {
19025  state->bndl.ptr.p_double[i] = _state->v_neginf;
19026  state->bndu.ptr.p_double[i] = _state->v_posinf;
19027  state->havebndl.ptr.p_bool[i] = ae_false;
19028  state->havebndu.ptr.p_bool[i] = ae_false;
19029  state->b.ptr.p_double[i] = 0.0;
19030  state->startx.ptr.p_double[i] = 0.0;
19031  state->xorigin.ptr.p_double[i] = 0.0;
19032  state->s.ptr.p_double[i] = 1.0;
19033  }
19034  state->havex = ae_false;
19035  minqpsetalgocholesky(state, _state);
19036  normestimatorcreate(n, n, 5, 5, &state->estimator, _state);
19037  minbleiccreate(n, &state->startx, &state->solver, _state);
19038 }
19039 
19040 
19041 /*************************************************************************
19042 This function sets linear term for QP solver.
19043 
19044 By default, linear term is zero.
19045 
19046 INPUT PARAMETERS:
19047  State - structure which stores algorithm state
19048  B - linear term, array[N].
19049 
19050  -- ALGLIB --
19051  Copyright 11.01.2011 by Bochkanov Sergey
19052 *************************************************************************/
19053 void minqpsetlinearterm(minqpstate* state,
19054  /* Real */ ae_vector* b,
19055  ae_state *_state)
19056 {
19057  ae_int_t n;
19058 
19059 
19060  n = state->n;
19061  ae_assert(b->cnt>=n, "MinQPSetLinearTerm: Length(B)<N", _state);
19062  ae_assert(isfinitevector(b, n, _state), "MinQPSetLinearTerm: B contains infinite or NaN elements", _state);
19063  minqpsetlineartermfast(state, b, _state);
19064 }
19065 
19066 
19067 /*************************************************************************
19068 This function sets dense quadratic term for QP solver. By default,
19069 quadratic term is zero.
19070 
19071 SUPPORT BY ALGLIB QP ALGORITHMS:
19072 
19073 Dense quadratic term can be handled by any of the QP algorithms supported
19074 by ALGLIB QP Solver.
19075 
19076 IMPORTANT:
19077 
19078 This solver minimizes following function:
19079  f(x) = 0.5*x'*A*x + b'*x.
19080 Note that quadratic term has 0.5 before it. So if you want to minimize
19081  f(x) = x^2 + x
19082 you should rewrite your problem as follows:
19083  f(x) = 0.5*(2*x^2) + x
19084 and your matrix A will be equal to [[2.0]], not to [[1.0]]
19085 
19086 INPUT PARAMETERS:
19087  State - structure which stores algorithm state
19088  A - matrix, array[N,N]
19089  IsUpper - (optional) storage type:
19090  * if True, symmetric matrix A is given by its upper
19091  triangle, and the lower triangle isn’t used
19092  * if False, symmetric matrix A is given by its lower
19093  triangle, and the upper triangle isn’t used
19094  * if not given, both lower and upper triangles must be
19095  filled.
19096 
19097  -- ALGLIB --
19098  Copyright 11.01.2011 by Bochkanov Sergey
19099 *************************************************************************/
19100 void minqpsetquadraticterm(minqpstate* state,
19101  /* Real */ ae_matrix* a,
19102  ae_bool isupper,
19103  ae_state *_state)
19104 {
19105  ae_int_t n;
19106 
19107 
19108  n = state->n;
19109  ae_assert(a->rows>=n, "MinQPSetQuadraticTerm: Rows(A)<N", _state);
19110  ae_assert(a->cols>=n, "MinQPSetQuadraticTerm: Cols(A)<N", _state);
19111  ae_assert(isfinitertrmatrix(a, n, isupper, _state), "MinQPSetQuadraticTerm: A contains infinite or NaN elements", _state);
19112  minqpsetquadratictermfast(state, a, isupper, 0.0, _state);
19113 }
19114 
19115 
19116 /*************************************************************************
19117 This function sets sparse quadratic term for QP solver. By default,
19118 quadratic term is zero.
19119 
19120 SUPPORT BY ALGLIB QP ALGORITHMS:
19121 
19122 Sparse quadratic term is supported only by BLEIC-based QP algorithm (one
19123 which is activated by MinQPSetAlgoBLEIC function). Cholesky-based QP algo
19124 won't be able to deal with sparse quadratic term and will terminate
19125 abnormally.
19126 
19127 IF YOU CALLED THIS FUNCTION, YOU MUST SWITCH TO BLEIC-BASED QP ALGORITHM
19128 BEFORE CALLING MINQPOPTIMIZE() FUNCTION.
19129 
19130 IMPORTANT:
19131 
19132 This solver minimizes following function:
19133  f(x) = 0.5*x'*A*x + b'*x.
19134 Note that quadratic term has 0.5 before it. So if you want to minimize
19135  f(x) = x^2 + x
19136 you should rewrite your problem as follows:
19137  f(x) = 0.5*(2*x^2) + x
19138 and your matrix A will be equal to [[2.0]], not to [[1.0]]
19139 
19140 INPUT PARAMETERS:
19141  State - structure which stores algorithm state
19142  A - matrix, array[N,N]
19143  IsUpper - (optional) storage type:
19144  * if True, symmetric matrix A is given by its upper
19145  triangle, and the lower triangle isn’t used
19146  * if False, symmetric matrix A is given by its lower
19147  triangle, and the upper triangle isn’t used
19148  * if not given, both lower and upper triangles must be
19149  filled.
19150 
19151  -- ALGLIB --
19152  Copyright 11.01.2011 by Bochkanov Sergey
19153 *************************************************************************/
19154 void minqpsetquadratictermsparse(minqpstate* state,
19155  sparsematrix* a,
19156  ae_bool isupper,
19157  ae_state *_state)
19158 {
19159  ae_int_t n;
19160 
19161 
19162  n = state->n;
19163  ae_assert(sparsegetnrows(a, _state)>=n, "MinQPSetQuadraticTermSparse: Rows(A)<N", _state);
19164  ae_assert(sparsegetncols(a, _state)>=n, "MinQPSetQuadraticTermSparse: Cols(A)<N", _state);
19165  sparsecopytocrs(a, &state->sparsea, _state);
19166  state->sparseaupper = isupper;
19167  state->akind = 1;
19168 }
19169 
19170 
19171 /*************************************************************************
19172 This function sets starting point for QP solver. It is useful to have
19173 good initial approximation to the solution, because it will increase
19174 speed of convergence and identification of active constraints.
19175 
19176 INPUT PARAMETERS:
19177  State - structure which stores algorithm state
19178  X - starting point, array[N].
19179 
19180  -- ALGLIB --
19181  Copyright 11.01.2011 by Bochkanov Sergey
19182 *************************************************************************/
19183 void minqpsetstartingpoint(minqpstate* state,
19184  /* Real */ ae_vector* x,
19185  ae_state *_state)
19186 {
19187  ae_int_t n;
19188 
19189 
19190  n = state->n;
19191  ae_assert(x->cnt>=n, "MinQPSetStartingPoint: Length(B)<N", _state);
19192  ae_assert(isfinitevector(x, n, _state), "MinQPSetStartingPoint: X contains infinite or NaN elements", _state);
19193  minqpsetstartingpointfast(state, x, _state);
19194 }
19195 
19196 
19197 /*************************************************************************
19198 This function sets origin for QP solver. By default, following QP program
19199 is solved:
19200 
19201  min(0.5*x'*A*x+b'*x)
19202 
19203 This function allows to solve different problem:
19204 
19205  min(0.5*(x-x_origin)'*A*(x-x_origin)+b'*(x-x_origin))
19206 
19207 INPUT PARAMETERS:
19208  State - structure which stores algorithm state
19209  XOrigin - origin, array[N].
19210 
19211  -- ALGLIB --
19212  Copyright 11.01.2011 by Bochkanov Sergey
19213 *************************************************************************/
19214 void minqpsetorigin(minqpstate* state,
19215  /* Real */ ae_vector* xorigin,
19216  ae_state *_state)
19217 {
19218  ae_int_t n;
19219 
19220 
19221  n = state->n;
19222  ae_assert(xorigin->cnt>=n, "MinQPSetOrigin: Length(B)<N", _state);
19223  ae_assert(isfinitevector(xorigin, n, _state), "MinQPSetOrigin: B contains infinite or NaN elements", _state);
19224  minqpsetoriginfast(state, xorigin, _state);
19225 }
19226 
19227 
19228 /*************************************************************************
19229 This function sets scaling coefficients.
19230 
19231 ALGLIB optimizers use scaling matrices to test stopping conditions (step
19232 size and gradient are scaled before comparison with tolerances). Scale of
19233 the I-th variable is a translation invariant measure of:
19234 a) "how large" the variable is
19235 b) how large the step should be to make significant changes in the function
19236 
19237 BLEIC-based QP solver uses scale for two purposes:
19238 * to evaluate stopping conditions
19239 * for preconditioning of the underlying BLEIC solver
19240 
19241 INPUT PARAMETERS:
19242  State - structure stores algorithm state
19243  S - array[N], non-zero scaling coefficients
19244  S[i] may be negative, sign doesn't matter.
19245 
19246  -- ALGLIB --
19247  Copyright 14.01.2011 by Bochkanov Sergey
19248 *************************************************************************/
19249 void minqpsetscale(minqpstate* state,
19250  /* Real */ ae_vector* s,
19251  ae_state *_state)
19252 {
19253  ae_int_t i;
19254 
19255 
19256  ae_assert(s->cnt>=state->n, "MinQPSetScale: Length(S)<N", _state);
19257  for(i=0; i<=state->n-1; i++)
19258  {
19259  ae_assert(ae_isfinite(s->ptr.p_double[i], _state), "MinQPSetScale: S contains infinite or NAN elements", _state);
19260  ae_assert(ae_fp_neq(s->ptr.p_double[i],0), "MinQPSetScale: S contains zero elements", _state);
19261  state->s.ptr.p_double[i] = ae_fabs(s->ptr.p_double[i], _state);
19262  }
19263 }
19264 
19265 
19266 /*************************************************************************
19267 This function tells solver to use Cholesky-based algorithm. This algorithm
19268 is active by default.
19269 
19270 DESCRIPTION:
19271 
19272 Cholesky-based algorithm can be used only for problems which:
19273 * have dense quadratic term, set by MinQPSetQuadraticTerm(), sparse or
19274  structured problems are not supported.
19275 * are strictly convex, i.e. quadratic term is symmetric positive definite,
19276  indefinite or semidefinite problems are not supported by this algorithm.
19277 
19278 If anything of what listed above is violated, you may use BLEIC-based QP
19279 algorithm which can be activated by MinQPSetAlgoBLEIC().
19280 
19281 BENEFITS AND DRAWBACKS:
19282 
19283 This algorithm gives best precision amongst all QP solvers provided by
19284 ALGLIB (Newton iterations have much higher precision than any other
19285 optimization algorithm). This solver also gracefully handles problems with
19286 very large amount of constraints.
19287 
19288 Performance of the algorithm is good because internally it uses Level 3
19289 Dense BLAS for its performance-critical parts.
19290 
19291 
19292 From the other side, algorithm has O(N^3) complexity for unconstrained
19293 problems and up to orders of magnitude slower on constrained problems
19294 (these additional iterations are needed to identify active constraints).
19295 So, its running time depends on number of constraints active at solution.
19296 
19297 Furthermore, this algorithm can not solve problems with sparse matrices or
19298 problems with semidefinite/indefinite matrices of any kind (dense/sparse).
19299 
19300 INPUT PARAMETERS:
19301  State - structure which stores algorithm state
19302 
19303  -- ALGLIB --
19304  Copyright 11.01.2011 by Bochkanov Sergey
19305 *************************************************************************/
19306 void minqpsetalgocholesky(minqpstate* state, ae_state *_state)
19307 {
19308 
19309 
19310  state->algokind = 1;
19311 }
19312 
19313 
19314 /*************************************************************************
19315 This function tells solver to use BLEIC-based algorithm and sets stopping
19316 criteria for the algorithm.
19317 
19318 DESCRIPTION:
19319 
19320 BLEIC-based QP algorithm can be used for any kind of QP problems:
19321 * problems with both dense and sparse quadratic terms
19322 * problems with positive definite, semidefinite, indefinite terms
19323 
19324 BLEIC-based algorithm can solve even indefinite problems - as long as they
19325 are bounded from below on the feasible set. Of course, global minimum is
19326 found only for positive definite and semidefinite problems. As for
19327 indefinite ones - only local minimum is found.
19328 
19329 BENEFITS AND DRAWBACKS:
19330 
19331 This algorithm can be used to solve both convex and indefinite QP problems
19332 and it can utilize sparsity of the quadratic term (algorithm calculates
19333 matrix-vector products, which can be performed efficiently in case of
19334 sparse matrix).
19335 
19336 Algorithm has iteration cost, which (assuming fixed amount of non-boundary
19337 linear constraints) linearly depends on problem size. Boundary constraints
19338 does not significantly change iteration cost.
19339 
19340 Thus, it outperforms Cholesky-based QP algorithm (CQP) on high-dimensional
19341 sparse problems with moderate amount of constraints.
19342 
19343 
19344 From the other side, unlike CQP solver, this algorithm does NOT make use
19345 of Level 3 Dense BLAS. Thus, its performance on dense problems is inferior
19346 to that of CQP solver.
19347 
19348 Its precision is also inferior to that of CQP. CQP performs Newton steps
19349 which are know to achieve very good precision. In many cases Newton step
19350 leads us exactly to the solution. BLEIC-QP performs LBFGS steps, which are
19351 good at detecting neighborhood of the solution, buy need many iterations
19352 to find solution with 6 digits of precision.
19353 
19354 INPUT PARAMETERS:
19355  State - structure which stores algorithm state
19356  EpsG - >=0
19357  The subroutine finishes its work if the condition
19358  |v|<EpsG is satisfied, where:
19359  * |.| means Euclidian norm
19360  * v - scaled constrained gradient vector, v[i]=g[i]*s[i]
19361  * g - gradient
19362  * s - scaling coefficients set by MinQPSetScale()
19363  EpsF - >=0
19364  The subroutine finishes its work if exploratory steepest
19365  descent step on k+1-th iteration satisfies following
19366  condition: |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1}
19367  EpsX - >=0
19368  The subroutine finishes its work if exploratory steepest
19369  descent step on k+1-th iteration satisfies following
19370  condition:
19371  * |.| means Euclidian norm
19372  * v - scaled step vector, v[i]=dx[i]/s[i]
19373  * dx - step vector, dx=X(k+1)-X(k)
19374  * s - scaling coefficients set by MinQPSetScale()
19375  MaxIts - maximum number of iterations. If MaxIts=0, the number of
19376  iterations is unlimited.
19377 
19378 Passing EpsG=0, EpsF=0 and EpsX=0 and MaxIts=0 (simultaneously) will lead
19379 to automatic stopping criterion selection (presently it is small step
19380 length, but it may change in the future versions of ALGLIB).
19381 
19382 IT IS VERY IMPORTANT THAT YOU CALL MinQPSetScale() WHEN YOU USE THIS ALGO!
19383 
19384  -- ALGLIB --
19385  Copyright 11.01.2011 by Bochkanov Sergey
19386 *************************************************************************/
19387 void minqpsetalgobleic(minqpstate* state,
19388  double epsg,
19389  double epsf,
19390  double epsx,
19391  ae_int_t maxits,
19392  ae_state *_state)
19393 {
19394 
19395 
19396  ae_assert(ae_isfinite(epsg, _state), "MinQPSetAlgoBLEIC: EpsG is not finite number", _state);
19397  ae_assert(ae_fp_greater_eq(epsg,0), "MinQPSetAlgoBLEIC: negative EpsG", _state);
19398  ae_assert(ae_isfinite(epsf, _state), "MinQPSetAlgoBLEIC: EpsF is not finite number", _state);
19399  ae_assert(ae_fp_greater_eq(epsf,0), "MinQPSetAlgoBLEIC: negative EpsF", _state);
19400  ae_assert(ae_isfinite(epsx, _state), "MinQPSetAlgoBLEIC: EpsX is not finite number", _state);
19401  ae_assert(ae_fp_greater_eq(epsx,0), "MinQPSetAlgoBLEIC: negative EpsX", _state);
19402  ae_assert(maxits>=0, "MinQPSetAlgoBLEIC: negative MaxIts!", _state);
19403  state->algokind = 2;
19404  if( ((ae_fp_eq(epsg,0)&&ae_fp_eq(epsf,0))&&ae_fp_eq(epsx,0))&&maxits==0 )
19405  {
19406  epsx = 1.0E-6;
19407  }
19408  state->bleicepsg = epsg;
19409  state->bleicepsf = epsf;
19410  state->bleicepsx = epsx;
19411  state->bleicmaxits = maxits;
19412 }
19413 
19414 
19415 /*************************************************************************
19416 This function sets boundary constraints for QP solver
19417 
19418 Boundary constraints are inactive by default (after initial creation).
19419 After being set, they are preserved until explicitly turned off with
19420 another SetBC() call.
19421 
19422 INPUT PARAMETERS:
19423  State - structure stores algorithm state
19424  BndL - lower bounds, array[N].
19425  If some (all) variables are unbounded, you may specify
19426  very small number or -INF (latter is recommended because
19427  it will allow solver to use better algorithm).
19428  BndU - upper bounds, array[N].
19429  If some (all) variables are unbounded, you may specify
19430  very large number or +INF (latter is recommended because
19431  it will allow solver to use better algorithm).
19432 
19433 NOTE: it is possible to specify BndL[i]=BndU[i]. In this case I-th
19434 variable will be "frozen" at X[i]=BndL[i]=BndU[i].
19435 
19436  -- ALGLIB --
19437  Copyright 11.01.2011 by Bochkanov Sergey
19438 *************************************************************************/
19439 void minqpsetbc(minqpstate* state,
19440  /* Real */ ae_vector* bndl,
19441  /* Real */ ae_vector* bndu,
19442  ae_state *_state)
19443 {
19444  ae_int_t i;
19445  ae_int_t n;
19446 
19447 
19448  n = state->n;
19449  ae_assert(bndl->cnt>=n, "MinQPSetBC: Length(BndL)<N", _state);
19450  ae_assert(bndu->cnt>=n, "MinQPSetBC: Length(BndU)<N", _state);
19451  for(i=0; i<=n-1; i++)
19452  {
19453  ae_assert(ae_isfinite(bndl->ptr.p_double[i], _state)||ae_isneginf(bndl->ptr.p_double[i], _state), "MinQPSetBC: BndL contains NAN or +INF", _state);
19454  ae_assert(ae_isfinite(bndu->ptr.p_double[i], _state)||ae_isposinf(bndu->ptr.p_double[i], _state), "MinQPSetBC: BndU contains NAN or -INF", _state);
19455  state->bndl.ptr.p_double[i] = bndl->ptr.p_double[i];
19456  state->havebndl.ptr.p_bool[i] = ae_isfinite(bndl->ptr.p_double[i], _state);
19457  state->bndu.ptr.p_double[i] = bndu->ptr.p_double[i];
19458  state->havebndu.ptr.p_bool[i] = ae_isfinite(bndu->ptr.p_double[i], _state);
19459  }
19460 }
19461 
19462 
19463 /*************************************************************************
19464 This function sets linear constraints for QP optimizer.
19465 
19466 Linear constraints are inactive by default (after initial creation).
19467 
19468 INPUT PARAMETERS:
19469  State - structure previously allocated with MinQPCreate call.
19470  C - linear constraints, array[K,N+1].
19471  Each row of C represents one constraint, either equality
19472  or inequality (see below):
19473  * first N elements correspond to coefficients,
19474  * last element corresponds to the right part.
19475  All elements of C (including right part) must be finite.
19476  CT - type of constraints, array[K]:
19477  * if CT[i]>0, then I-th constraint is C[i,*]*x >= C[i,n+1]
19478  * if CT[i]=0, then I-th constraint is C[i,*]*x = C[i,n+1]
19479  * if CT[i]<0, then I-th constraint is C[i,*]*x <= C[i,n+1]
19480  K - number of equality/inequality constraints, K>=0:
19481  * if given, only leading K elements of C/CT are used
19482  * if not given, automatically determined from sizes of C/CT
19483 
19484 NOTE 1: linear (non-bound) constraints are satisfied only approximately -
19485  there always exists some minor violation (about 10^-10...10^-13)
19486  due to numerical errors.
19487 
19488  -- ALGLIB --
19489  Copyright 19.06.2012 by Bochkanov Sergey
19490 *************************************************************************/
19491 void minqpsetlc(minqpstate* state,
19492  /* Real */ ae_matrix* c,
19493  /* Integer */ ae_vector* ct,
19494  ae_int_t k,
19495  ae_state *_state)
19496 {
19497  ae_int_t n;
19498  ae_int_t i;
19499  ae_int_t j;
19500  double v;
19501 
19502 
19503  n = state->n;
19504 
19505  /*
19506  * First, check for errors in the inputs
19507  */
19508  ae_assert(k>=0, "MinQPSetLC: K<0", _state);
19509  ae_assert(c->cols>=n+1||k==0, "MinQPSetLC: Cols(C)<N+1", _state);
19510  ae_assert(c->rows>=k, "MinQPSetLC: Rows(C)<K", _state);
19511  ae_assert(ct->cnt>=k, "MinQPSetLC: Length(CT)<K", _state);
19512  ae_assert(apservisfinitematrix(c, k, n+1, _state), "MinQPSetLC: C contains infinite or NaN values!", _state);
19513 
19514  /*
19515  * Handle zero K
19516  */
19517  if( k==0 )
19518  {
19519  state->nec = 0;
19520  state->nic = 0;
19521  return;
19522  }
19523 
19524  /*
19525  * Equality constraints are stored first, in the upper
19526  * NEC rows of State.CLEIC matrix. Inequality constraints
19527  * are stored in the next NIC rows.
19528  *
19529  * NOTE: we convert inequality constraints to the form
19530  * A*x<=b before copying them.
19531  */
19532  rmatrixsetlengthatleast(&state->cleic, k, n+1, _state);
19533  state->nec = 0;
19534  state->nic = 0;
19535  for(i=0; i<=k-1; i++)
19536  {
19537  if( ct->ptr.p_int[i]==0 )
19538  {
19539  ae_v_move(&state->cleic.ptr.pp_double[state->nec][0], 1, &c->ptr.pp_double[i][0], 1, ae_v_len(0,n));
19540  state->nec = state->nec+1;
19541  }
19542  }
19543  for(i=0; i<=k-1; i++)
19544  {
19545  if( ct->ptr.p_int[i]!=0 )
19546  {
19547  if( ct->ptr.p_int[i]>0 )
19548  {
19549  ae_v_moveneg(&state->cleic.ptr.pp_double[state->nec+state->nic][0], 1, &c->ptr.pp_double[i][0], 1, ae_v_len(0,n));
19550  }
19551  else
19552  {
19553  ae_v_move(&state->cleic.ptr.pp_double[state->nec+state->nic][0], 1, &c->ptr.pp_double[i][0], 1, ae_v_len(0,n));
19554  }
19555  state->nic = state->nic+1;
19556  }
19557  }
19558 
19559  /*
19560  * Normalize rows of State.CLEIC: each row must have unit norm.
19561  * Norm is calculated using first N elements (i.e. right part is
19562  * not counted when we calculate norm).
19563  */
19564  for(i=0; i<=k-1; i++)
19565  {
19566  v = 0;
19567  for(j=0; j<=n-1; j++)
19568  {
19569  v = v+ae_sqr(state->cleic.ptr.pp_double[i][j], _state);
19570  }
19571  if( ae_fp_eq(v,0) )
19572  {
19573  continue;
19574  }
19575  v = 1/ae_sqrt(v, _state);
19576  ae_v_muld(&state->cleic.ptr.pp_double[i][0], 1, ae_v_len(0,n), v);
19577  }
19578 }
19579 
19580 
19581 /*************************************************************************
19582 This function solves quadratic programming problem.
19583 You should call it after setting solver options with MinQPSet...() calls.
19584 
19585 INPUT PARAMETERS:
19586  State - algorithm state
19587 
19588 You should use MinQPResults() function to access results after calls
19589 to this function.
19590 
19591  -- ALGLIB --
19592  Copyright 11.01.2011 by Bochkanov Sergey.
19593  Special thanks to Elvira Illarionova for important suggestions on
19594  the linearly constrained QP algorithm.
19595 *************************************************************************/
19596 void minqpoptimize(minqpstate* state, ae_state *_state)
19597 {
19598  ae_int_t n;
19599  ae_int_t i;
19600  ae_int_t nbc;
19601  double v0;
19602  double v1;
19603  double v;
19604  double d2;
19605  double d1;
19606  double d0;
19607  double noisetolerance;
19608  double fprev;
19609  double fcand;
19610  double fcur;
19611  ae_int_t nextaction;
19612  ae_int_t actstatus;
19613  double noiselevel;
19614  ae_int_t badnewtonits;
19615  double maxscaledgrad;
19616 
19617 
19618  noisetolerance = 10;
19619  n = state->n;
19620  state->repterminationtype = -5;
19621  state->repinneriterationscount = 0;
19622  state->repouteriterationscount = 0;
19623  state->repncholesky = 0;
19624  state->repnmv = 0;
19625  state->debugphase1flops = 0;
19626  state->debugphase2flops = 0;
19627  state->debugphase3flops = 0;
19628  rvectorsetlengthatleast(&state->rctmpg, n, _state);
19629 
19630  /*
19631  * check correctness of constraints
19632  */
19633  for(i=0; i<=n-1; i++)
19634  {
19635  if( state->havebndl.ptr.p_bool[i]&&state->havebndu.ptr.p_bool[i] )
19636  {
19637  if( ae_fp_greater(state->bndl.ptr.p_double[i],state->bndu.ptr.p_double[i]) )
19638  {
19639  state->repterminationtype = -3;
19640  return;
19641  }
19642  }
19643  }
19644 
19645  /*
19646  * count number of bound and linear constraints
19647  */
19648  nbc = 0;
19649  for(i=0; i<=n-1; i++)
19650  {
19651  if( state->havebndl.ptr.p_bool[i] )
19652  {
19653  nbc = nbc+1;
19654  }
19655  if( state->havebndu.ptr.p_bool[i] )
19656  {
19657  nbc = nbc+1;
19658  }
19659  }
19660 
19661  /*
19662  * Initial point:
19663  * * if we have starting point in StartX, we just have to bound it
19664  * * if we do not have StartX, deduce initial point from boundary constraints
19665  */
19666  if( state->havex )
19667  {
19668  for(i=0; i<=n-1; i++)
19669  {
19670  state->xs.ptr.p_double[i] = state->startx.ptr.p_double[i];
19671  if( state->havebndl.ptr.p_bool[i]&&ae_fp_less(state->xs.ptr.p_double[i],state->bndl.ptr.p_double[i]) )
19672  {
19673  state->xs.ptr.p_double[i] = state->bndl.ptr.p_double[i];
19674  }
19675  if( state->havebndu.ptr.p_bool[i]&&ae_fp_greater(state->xs.ptr.p_double[i],state->bndu.ptr.p_double[i]) )
19676  {
19677  state->xs.ptr.p_double[i] = state->bndu.ptr.p_double[i];
19678  }
19679  }
19680  }
19681  else
19682  {
19683  for(i=0; i<=n-1; i++)
19684  {
19685  if( state->havebndl.ptr.p_bool[i]&&state->havebndu.ptr.p_bool[i] )
19686  {
19687  state->xs.ptr.p_double[i] = 0.5*(state->bndl.ptr.p_double[i]+state->bndu.ptr.p_double[i]);
19688  continue;
19689  }
19690  if( state->havebndl.ptr.p_bool[i] )
19691  {
19692  state->xs.ptr.p_double[i] = state->bndl.ptr.p_double[i];
19693  continue;
19694  }
19695  if( state->havebndu.ptr.p_bool[i] )
19696  {
19697  state->xs.ptr.p_double[i] = state->bndu.ptr.p_double[i];
19698  continue;
19699  }
19700  state->xs.ptr.p_double[i] = 0;
19701  }
19702  }
19703 
19704  /*
19705  * Cholesky solver.
19706  */
19707  if( state->algokind==1 )
19708  {
19709 
19710  /*
19711  * Check matrix type.
19712  * Cholesky solver supports only dense matrices.
19713  */
19714  if( state->akind!=0 )
19715  {
19716  state->repterminationtype = -5;
19717  return;
19718  }
19719 
19720  /*
19721  * Our formulation of quadratic problem includes origin point,
19722  * i.e. we have F(x-x_origin) which is minimized subject to
19723  * constraints on x, instead of having simply F(x).
19724  *
19725  * Here we make transition from non-zero origin to zero one.
19726  * In order to make such transition we have to:
19727  * 1. subtract x_origin from x_start
19728  * 2. modify constraints
19729  * 3. solve problem
19730  * 4. add x_origin to solution
19731  *
19732  * There is alternate solution - to modify quadratic function
19733  * by expansion of multipliers containing (x-x_origin), but
19734  * we prefer to modify constraints, because it is a) more precise
19735  * and b) easier to to.
19736  *
19737  * Parts (1)-(2) are done here. After this block is over,
19738  * we have:
19739  * * XS, which stores shifted XStart (if we don't have XStart,
19740  * value of XS will be ignored later)
19741  * * WorkBndL, WorkBndU, which store modified boundary constraints.
19742  */
19743  for(i=0; i<=n-1; i++)
19744  {
19745  if( state->havebndl.ptr.p_bool[i] )
19746  {
19747  state->workbndl.ptr.p_double[i] = state->bndl.ptr.p_double[i]-state->xorigin.ptr.p_double[i];
19748  }
19749  else
19750  {
19751  state->workbndl.ptr.p_double[i] = _state->v_neginf;
19752  }
19753  if( state->havebndu.ptr.p_bool[i] )
19754  {
19755  state->workbndu.ptr.p_double[i] = state->bndu.ptr.p_double[i]-state->xorigin.ptr.p_double[i];
19756  }
19757  else
19758  {
19759  state->workbndu.ptr.p_double[i] = _state->v_posinf;
19760  }
19761  }
19762  rmatrixsetlengthatleast(&state->workcleic, state->nec+state->nic, n+1, _state);
19763  for(i=0; i<=state->nec+state->nic-1; i++)
19764  {
19765  v = ae_v_dotproduct(&state->cleic.ptr.pp_double[i][0], 1, &state->xorigin.ptr.p_double[0], 1, ae_v_len(0,n-1));
19766  ae_v_move(&state->workcleic.ptr.pp_double[i][0], 1, &state->cleic.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
19767  state->workcleic.ptr.pp_double[i][n] = state->cleic.ptr.pp_double[i][n]-v;
19768  }
19769 
19770  /*
19771  * Starting point XS
19772  */
19773  if( state->havex )
19774  {
19775 
19776  /*
19777  * We have starting point in StartX, so we just have to shift and bound it
19778  */
19779  for(i=0; i<=n-1; i++)
19780  {
19781  state->xs.ptr.p_double[i] = state->startx.ptr.p_double[i]-state->xorigin.ptr.p_double[i];
19782  if( state->havebndl.ptr.p_bool[i] )
19783  {
19784  if( ae_fp_less(state->xs.ptr.p_double[i],state->workbndl.ptr.p_double[i]) )
19785  {
19786  state->xs.ptr.p_double[i] = state->workbndl.ptr.p_double[i];
19787  }
19788  }
19789  if( state->havebndu.ptr.p_bool[i] )
19790  {
19791  if( ae_fp_greater(state->xs.ptr.p_double[i],state->workbndu.ptr.p_double[i]) )
19792  {
19793  state->xs.ptr.p_double[i] = state->workbndu.ptr.p_double[i];
19794  }
19795  }
19796  }
19797  }
19798  else
19799  {
19800 
19801  /*
19802  * We don't have starting point, so we deduce it from
19803  * constraints (if they are present).
19804  *
19805  * NOTE: XS contains some meaningless values from previous block
19806  * which are ignored by code below.
19807  */
19808  for(i=0; i<=n-1; i++)
19809  {
19810  if( state->havebndl.ptr.p_bool[i]&&state->havebndu.ptr.p_bool[i] )
19811  {
19812  state->xs.ptr.p_double[i] = 0.5*(state->workbndl.ptr.p_double[i]+state->workbndu.ptr.p_double[i]);
19813  if( ae_fp_less(state->xs.ptr.p_double[i],state->workbndl.ptr.p_double[i]) )
19814  {
19815  state->xs.ptr.p_double[i] = state->workbndl.ptr.p_double[i];
19816  }
19817  if( ae_fp_greater(state->xs.ptr.p_double[i],state->workbndu.ptr.p_double[i]) )
19818  {
19819  state->xs.ptr.p_double[i] = state->workbndu.ptr.p_double[i];
19820  }
19821  continue;
19822  }
19823  if( state->havebndl.ptr.p_bool[i] )
19824  {
19825  state->xs.ptr.p_double[i] = state->workbndl.ptr.p_double[i];
19826  continue;
19827  }
19828  if( state->havebndu.ptr.p_bool[i] )
19829  {
19830  state->xs.ptr.p_double[i] = state->workbndu.ptr.p_double[i];
19831  continue;
19832  }
19833  state->xs.ptr.p_double[i] = 0;
19834  }
19835  }
19836 
19837  /*
19838  * Handle special case - no constraints
19839  */
19840  if( nbc==0&&state->nec+state->nic==0 )
19841  {
19842 
19843  /*
19844  * "Simple" unconstrained Cholesky
19845  */
19846  bvectorsetlengthatleast(&state->tmpb, n, _state);
19847  for(i=0; i<=n-1; i++)
19848  {
19849  state->tmpb.ptr.p_bool[i] = ae_false;
19850  }
19851  state->repncholesky = state->repncholesky+1;
19852  cqmsetb(&state->a, &state->b, _state);
19853  cqmsetactiveset(&state->a, &state->xs, &state->tmpb, _state);
19854  if( !cqmconstrainedoptimum(&state->a, &state->xn, _state) )
19855  {
19856  state->repterminationtype = -5;
19857  return;
19858  }
19859  ae_v_move(&state->xs.ptr.p_double[0], 1, &state->xn.ptr.p_double[0], 1, ae_v_len(0,n-1));
19860  ae_v_add(&state->xs.ptr.p_double[0], 1, &state->xorigin.ptr.p_double[0], 1, ae_v_len(0,n-1));
19861  state->repinneriterationscount = 1;
19862  state->repouteriterationscount = 1;
19863  state->repterminationtype = 4;
19864  return;
19865  }
19866 
19867  /*
19868  * Prepare "active set" structure
19869  */
19870  sassetbc(&state->sas, &state->workbndl, &state->workbndu, _state);
19871  sassetlcx(&state->sas, &state->workcleic, state->nec, state->nic, _state);
19872  sassetscale(&state->sas, &state->s, _state);
19873  if( !sasstartoptimization(&state->sas, &state->xs, _state) )
19874  {
19875  state->repterminationtype = -3;
19876  return;
19877  }
19878 
19879  /*
19880  * Main cycle of CQP algorithm
19881  */
19882  state->repterminationtype = 4;
19883  badnewtonits = 0;
19884  maxscaledgrad = 0.0;
19885  for(;;)
19886  {
19887 
19888  /*
19889  * Update iterations count
19890  */
19891  inc(&state->repouteriterationscount, _state);
19892  inc(&state->repinneriterationscount, _state);
19893 
19894  /*
19895  * Phase 1.
19896  *
19897  * Determine active set.
19898  * Update MaxScaledGrad.
19899  */
19900  cqmadx(&state->a, &state->sas.xc, &state->rctmpg, _state);
19901  ae_v_add(&state->rctmpg.ptr.p_double[0], 1, &state->b.ptr.p_double[0], 1, ae_v_len(0,n-1));
19902  sasreactivateconstraints(&state->sas, &state->rctmpg, _state);
19903  v = 0.0;
19904  for(i=0; i<=n-1; i++)
19905  {
19906  v = v+ae_sqr(state->rctmpg.ptr.p_double[i]*state->s.ptr.p_double[i], _state);
19907  }
19908  maxscaledgrad = ae_maxreal(maxscaledgrad, ae_sqrt(v, _state), _state);
19909 
19910  /*
19911  * Phase 2: perform penalized steepest descent step.
19912  *
19913  * NextAction control variable is set on exit from this loop:
19914  * * NextAction>0 in case we have to proceed to Phase 3 (Newton step)
19915  * * NextAction<0 in case we have to proceed to Phase 1 (recalculate active set)
19916  * * NextAction=0 in case we found solution (step along projected gradient is small enough)
19917  */
19918  for(;;)
19919  {
19920 
19921  /*
19922  * Calculate constrained descent direction, store to PG.
19923  * Successful termination if PG is zero.
19924  */
19925  cqmadx(&state->a, &state->sas.xc, &state->gc, _state);
19926  ae_v_add(&state->gc.ptr.p_double[0], 1, &state->b.ptr.p_double[0], 1, ae_v_len(0,n-1));
19927  sasconstraineddescent(&state->sas, &state->gc, &state->pg, _state);
19928  state->debugphase2flops = state->debugphase2flops+4*(state->nec+state->nic)*n;
19929  v0 = ae_v_dotproduct(&state->pg.ptr.p_double[0], 1, &state->pg.ptr.p_double[0], 1, ae_v_len(0,n-1));
19930  if( ae_fp_eq(v0,0) )
19931  {
19932 
19933  /*
19934  * Constrained derivative is zero.
19935  * Solution found.
19936  */
19937  nextaction = 0;
19938  break;
19939  }
19940 
19941  /*
19942  * Build quadratic model of F along descent direction:
19943  * F(xc+alpha*pg) = D2*alpha^2 + D1*alpha + D0
19944  * Store noise level in the XC (noise level is used to classify
19945  * step as singificant or insignificant).
19946  *
19947  * In case function curvature is negative or product of descent
19948  * direction and gradient is non-negative, iterations are terminated.
19949  *
19950  * NOTE: D0 is not actually used, but we prefer to maintain it.
19951  */
19952  fprev = minqp_minqpmodelvalue(&state->a, &state->b, &state->sas.xc, n, &state->tmp0, _state);
19953  fprev = fprev+minqp_penaltyfactor*maxscaledgrad*sasactivelcpenalty1(&state->sas, &state->sas.xc, _state);
19954  cqmevalx(&state->a, &state->sas.xc, &v, &noiselevel, _state);
19955  v0 = cqmxtadx2(&state->a, &state->pg, _state);
19956  state->debugphase2flops = state->debugphase2flops+3*2*n*n;
19957  d2 = v0;
19958  v1 = ae_v_dotproduct(&state->pg.ptr.p_double[0], 1, &state->gc.ptr.p_double[0], 1, ae_v_len(0,n-1));
19959  d1 = v1;
19960  d0 = fprev;
19961  if( ae_fp_less_eq(d2,0) )
19962  {
19963 
19964  /*
19965  * Second derivative is non-positive, function is non-convex.
19966  */
19967  state->repterminationtype = -5;
19968  nextaction = 0;
19969  break;
19970  }
19971  if( ae_fp_greater_eq(d1,0) )
19972  {
19973 
19974  /*
19975  * Second derivative is positive, first derivative is non-negative.
19976  * Solution found.
19977  */
19978  nextaction = 0;
19979  break;
19980  }
19981 
19982  /*
19983  * Modify quadratic model - add penalty for violation of the active
19984  * constraints.
19985  *
19986  * Boundary constraints are always satisfied exactly, so we do not
19987  * add penalty term for them. General equality constraint of the
19988  * form a'*(xc+alpha*d)=b adds penalty term:
19989  * P(alpha) = (a'*(xc+alpha*d)-b)^2
19990  * = (alpha*(a'*d) + (a'*xc-b))^2
19991  * = alpha^2*(a'*d)^2 + alpha*2*(a'*d)*(a'*xc-b) + (a'*xc-b)^2
19992  * Each penalty term is multiplied by 100*Anorm before adding it to
19993  * the 1-dimensional quadratic model.
19994  *
19995  * Penalization of the quadratic model improves behavior of the
19996  * algorithm in the presence of the multiple degenerate constraints.
19997  * In particular, it prevents algorithm from making large steps in
19998  * directions which violate equality constraints.
19999  */
20000  for(i=0; i<=state->nec+state->nic-1; i++)
20001  {
20002  if( state->sas.activeset.ptr.p_int[n+i]>0 )
20003  {
20004  v0 = ae_v_dotproduct(&state->workcleic.ptr.pp_double[i][0], 1, &state->pg.ptr.p_double[0], 1, ae_v_len(0,n-1));
20005  v1 = ae_v_dotproduct(&state->workcleic.ptr.pp_double[i][0], 1, &state->sas.xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
20006  v1 = v1-state->workcleic.ptr.pp_double[i][n];
20007  v = 100*state->anorm;
20008  d2 = d2+v*ae_sqr(v0, _state);
20009  d1 = d1+v*2*v0*v1;
20010  d0 = d0+v*ae_sqr(v1, _state);
20011  }
20012  }
20013  state->debugphase2flops = state->debugphase2flops+2*2*(state->nec+state->nic)*n;
20014 
20015  /*
20016  * Try unbounded step.
20017  * In case function change is dominated by noise or function actually increased
20018  * instead of decreasing, we terminate iterations.
20019  */
20020  v = -d1/(2*d2);
20021  ae_v_move(&state->xn.ptr.p_double[0], 1, &state->sas.xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
20022  ae_v_addd(&state->xn.ptr.p_double[0], 1, &state->pg.ptr.p_double[0], 1, ae_v_len(0,n-1), v);
20023  fcand = minqp_minqpmodelvalue(&state->a, &state->b, &state->xn, n, &state->tmp0, _state);
20024  fcand = fcand+minqp_penaltyfactor*maxscaledgrad*sasactivelcpenalty1(&state->sas, &state->xn, _state);
20025  state->debugphase2flops = state->debugphase2flops+2*n*n;
20026  if( ae_fp_greater_eq(fcand,fprev-noiselevel*noisetolerance) )
20027  {
20028  nextaction = 0;
20029  break;
20030  }
20031 
20032  /*
20033  * Save active set
20034  * Perform bounded step with (possible) activation
20035  */
20036  actstatus = minqp_minqpboundedstepandactivation(state, &state->xn, &state->tmp0, _state);
20037  fcur = minqp_minqpmodelvalue(&state->a, &state->b, &state->sas.xc, n, &state->tmp0, _state);
20038  state->debugphase2flops = state->debugphase2flops+2*n*n;
20039 
20040  /*
20041  * Depending on results, decide what to do:
20042  * 1. In case step was performed without activation of constraints,
20043  * we proceed to Newton method
20044  * 2. In case there was activated at least one constraint with ActiveSet[I]<0,
20045  * we proceed to Phase 1 and re-evaluate active set.
20046  * 3. Otherwise (activation of the constraints with ActiveSet[I]=0)
20047  * we try Phase 2 one more time.
20048  */
20049  if( actstatus<0 )
20050  {
20051 
20052  /*
20053  * Step without activation, proceed to Newton
20054  */
20055  nextaction = 1;
20056  break;
20057  }
20058  if( actstatus==0 )
20059  {
20060 
20061  /*
20062  * No new constraints added during last activation - only
20063  * ones which were at the boundary (ActiveSet[I]=0), but
20064  * inactive due to numerical noise.
20065  *
20066  * Now, these constraints are added to the active set, and
20067  * we try to perform steepest descent (Phase 2) one more time.
20068  */
20069  continue;
20070  }
20071  else
20072  {
20073 
20074  /*
20075  * Last step activated at least one significantly new
20076  * constraint (ActiveSet[I]<0), we have to re-evaluate
20077  * active set (Phase 1).
20078  */
20079  nextaction = -1;
20080  break;
20081  }
20082  }
20083  if( nextaction<0 )
20084  {
20085  continue;
20086  }
20087  if( nextaction==0 )
20088  {
20089  break;
20090  }
20091 
20092  /*
20093  * Phase 3: fast equality-constrained solver
20094  *
20095  * NOTE: this solver uses Augmented Lagrangian algorithm to solve
20096  * equality-constrained subproblems. This algorithm may
20097  * perform steps which increase function values instead of
20098  * decreasing it (in hard cases, like overconstrained problems).
20099  *
20100  * Such non-monononic steps may create a loop, when Augmented
20101  * Lagrangian algorithm performs uphill step, and steepest
20102  * descent algorithm (Phase 2) performs downhill step in the
20103  * opposite direction.
20104  *
20105  * In order to prevent iterations to continue forever we
20106  * count iterations when AL algorithm increased function
20107  * value instead of decreasing it. When number of such "bad"
20108  * iterations will increase beyong MaxBadNewtonIts, we will
20109  * terminate algorithm.
20110  */
20111  fprev = minqp_minqpmodelvalue(&state->a, &state->b, &state->sas.xc, n, &state->tmp0, _state);
20112  for(;;)
20113  {
20114 
20115  /*
20116  * Calculate optimum subject to presently active constraints
20117  */
20118  state->repncholesky = state->repncholesky+1;
20119  state->debugphase3flops = state->debugphase3flops+ae_pow(n, 3, _state)/3;
20120  if( !minqp_minqpconstrainedoptimum(state, &state->a, state->anorm, &state->b, &state->xn, &state->tmp0, &state->tmpb, &state->tmp1, _state) )
20121  {
20122  state->repterminationtype = -5;
20123  sasstopoptimization(&state->sas, _state);
20124  return;
20125  }
20126 
20127  /*
20128  * Add constraints.
20129  * If no constraints was added, accept candidate point XN and move to next phase.
20130  */
20131  if( minqp_minqpboundedstepandactivation(state, &state->xn, &state->tmp0, _state)<0 )
20132  {
20133  break;
20134  }
20135  }
20136  fcur = minqp_minqpmodelvalue(&state->a, &state->b, &state->sas.xc, n, &state->tmp0, _state);
20137  if( ae_fp_greater_eq(fcur,fprev) )
20138  {
20139  badnewtonits = badnewtonits+1;
20140  }
20141  if( badnewtonits>=minqp_maxbadnewtonits )
20142  {
20143 
20144  /*
20145  * Algorithm found solution, but keeps iterating because Newton
20146  * algorithm performs uphill steps (noise in the Augmented Lagrangian
20147  * algorithm). We terminate algorithm; it is considered normal
20148  * termination.
20149  */
20150  break;
20151  }
20152  }
20153  sasstopoptimization(&state->sas, _state);
20154 
20155  /*
20156  * Post-process: add XOrigin to XC
20157  */
20158  for(i=0; i<=n-1; i++)
20159  {
20160  if( state->havebndl.ptr.p_bool[i]&&ae_fp_eq(state->sas.xc.ptr.p_double[i],state->workbndl.ptr.p_double[i]) )
20161  {
20162  state->xs.ptr.p_double[i] = state->bndl.ptr.p_double[i];
20163  continue;
20164  }
20165  if( state->havebndu.ptr.p_bool[i]&&ae_fp_eq(state->sas.xc.ptr.p_double[i],state->workbndu.ptr.p_double[i]) )
20166  {
20167  state->xs.ptr.p_double[i] = state->bndu.ptr.p_double[i];
20168  continue;
20169  }
20170  state->xs.ptr.p_double[i] = boundval(state->sas.xc.ptr.p_double[i]+state->xorigin.ptr.p_double[i], state->bndl.ptr.p_double[i], state->bndu.ptr.p_double[i], _state);
20171  }
20172  return;
20173  }
20174 
20175  /*
20176  * BLEIC solver
20177  */
20178  if( state->algokind==2 )
20179  {
20180  ae_assert(state->akind==0||state->akind==1, "MinQPOptimize: unexpected AKind", _state);
20181  ivectorsetlengthatleast(&state->tmpi, state->nec+state->nic, _state);
20182  rvectorsetlengthatleast(&state->tmp0, n, _state);
20183  rvectorsetlengthatleast(&state->tmp1, n, _state);
20184  for(i=0; i<=state->nec-1; i++)
20185  {
20186  state->tmpi.ptr.p_int[i] = 0;
20187  }
20188  for(i=0; i<=state->nic-1; i++)
20189  {
20190  state->tmpi.ptr.p_int[state->nec+i] = -1;
20191  }
20192  minbleicsetlc(&state->solver, &state->cleic, &state->tmpi, state->nec+state->nic, _state);
20193  minbleicsetbc(&state->solver, &state->bndl, &state->bndu, _state);
20194  minbleicsetdrep(&state->solver, ae_true, _state);
20195  minbleicsetcond(&state->solver, ae_minrealnumber, 0.0, 0.0, state->bleicmaxits, _state);
20196  minbleicsetscale(&state->solver, &state->s, _state);
20197  minbleicsetprecscale(&state->solver, _state);
20198  minbleicrestartfrom(&state->solver, &state->xs, _state);
20199  state->repterminationtype = 0;
20200  while(minbleiciteration(&state->solver, _state))
20201  {
20202 
20203  /*
20204  * Line search started
20205  */
20206  if( state->solver.lsstart )
20207  {
20208 
20209  /*
20210  * Iteration counters:
20211  * * inner iterations count is increased on every line search
20212  * * outer iterations count is increased only at steepest descent line search
20213  */
20214  inc(&state->repinneriterationscount, _state);
20215  if( !state->solver.lbfgssearch )
20216  {
20217  inc(&state->repouteriterationscount, _state);
20218  }
20219 
20220  /*
20221  * Build quadratic model of F along descent direction:
20222  * F(x+alpha*d) = D2*alpha^2 + D1*alpha + D0
20223  */
20224  d0 = state->solver.f;
20225  d1 = ae_v_dotproduct(&state->solver.d.ptr.p_double[0], 1, &state->solver.g.ptr.p_double[0], 1, ae_v_len(0,n-1));
20226  d2 = 0;
20227  if( state->akind==0 )
20228  {
20229  d2 = cqmxtadx2(&state->a, &state->solver.d, _state);
20230  }
20231  if( state->akind==1 )
20232  {
20233  sparsesmv(&state->sparsea, state->sparseaupper, &state->solver.d, &state->tmp0, _state);
20234  d2 = 0.0;
20235  for(i=0; i<=n-1; i++)
20236  {
20237  d2 = d2+state->solver.d.ptr.p_double[i]*state->tmp0.ptr.p_double[i];
20238  }
20239  d2 = 0.5*d2;
20240  }
20241 
20242  /*
20243  * Suggest new step
20244  */
20245  if( ae_fp_less(d1,0)&&ae_fp_greater(d2,0) )
20246  {
20247  state->solver.stp = safeminposrv(-d1, 2*d2, state->solver.curstpmax, _state);
20248  }
20249 
20250  /*
20251  * This line search may be started from steepest descent
20252  * stage (stage 2) or from L-BFGS stage (stage 3) of the
20253  * BLEIC algorithm. Depending on stage type, different
20254  * checks are performed.
20255  *
20256  * Say, L-BFGS stage is an equality-constrained refinement
20257  * stage of BLEIC. This stage refines current iterate
20258  * under "frozen" equality constraints. We can terminate
20259  * iterations at this stage only when we encounter
20260  * unconstrained direction of negative curvature. In all
20261  * other cases (say, when constrained gradient is zero)
20262  * we should not terminate algorithm because everything may
20263  * change after de-activating presently active constraints.
20264  *
20265  * At steepest descent stage of BLEIC we can terminate algorithm
20266  * because it found minimum (steepest descent step is zero
20267  * or too short). We also perform check for direction of
20268  * negative curvature.
20269  */
20270  if( (ae_fp_less(d2,0)||(ae_fp_eq(d2,0)&&ae_fp_less(d1,0)))&&!state->solver.boundedstep )
20271  {
20272 
20273  /*
20274  * Function is unbounded from below:
20275  * * function will decrease along D, i.e. either:
20276  * * D2<0
20277  * * D2=0 and D1<0
20278  * * step is unconstrained
20279  *
20280  * If these conditions are true, we abnormally terminate QP
20281  * algorithm with return code -4 (we can do so at any stage
20282  * of BLEIC - whether it is L-BFGS or steepest descent one).
20283  */
20284  state->repterminationtype = -4;
20285  for(i=0; i<=n-1; i++)
20286  {
20287  state->xs.ptr.p_double[i] = state->solver.x.ptr.p_double[i];
20288  }
20289  break;
20290  }
20291  if( !state->solver.lbfgssearch&&ae_fp_greater_eq(d2,0) )
20292  {
20293 
20294  /*
20295  * Tests for "normal" convergence.
20296  *
20297  * These tests are performed only at "steepest descent" stage
20298  * of the BLEIC algorithm, and only when function is non-concave
20299  * (D2>=0) along direction D.
20300  *
20301  * NOTE: we do not test iteration count (MaxIts) here, because
20302  * this stopping condition is tested by BLEIC itself.
20303  */
20304  if( ae_fp_greater_eq(d1,0) )
20305  {
20306 
20307  /*
20308  * "Emergency" stopping condition: D is non-descent direction.
20309  * Sometimes it is possible because of numerical noise in the
20310  * target function.
20311  */
20312  state->repterminationtype = 4;
20313  for(i=0; i<=n-1; i++)
20314  {
20315  state->xs.ptr.p_double[i] = state->solver.x.ptr.p_double[i];
20316  }
20317  break;
20318  }
20319  if( ae_fp_greater(d2,0) )
20320  {
20321 
20322  /*
20323  * Stopping condition #4 - gradient norm is small:
20324  *
20325  * 1. rescale State.Solver.D and State.Solver.G according to
20326  * current scaling, store results to Tmp0 and Tmp1.
20327  * 2. Normalize Tmp0 (scaled direction vector).
20328  * 3. compute directional derivative (in scaled variables),
20329  * which is equal to DOTPRODUCT(Tmp0,Tmp1).
20330  */
20331  v = 0;
20332  for(i=0; i<=n-1; i++)
20333  {
20334  state->tmp0.ptr.p_double[i] = state->solver.d.ptr.p_double[i]/state->s.ptr.p_double[i];
20335  state->tmp1.ptr.p_double[i] = state->solver.g.ptr.p_double[i]*state->s.ptr.p_double[i];
20336  v = v+ae_sqr(state->tmp0.ptr.p_double[i], _state);
20337  }
20338  ae_assert(ae_fp_greater(v,0), "MinQPOptimize: inernal errror (scaled direction is zero)", _state);
20339  v = 1/ae_sqrt(v, _state);
20340  ae_v_muld(&state->tmp0.ptr.p_double[0], 1, ae_v_len(0,n-1), v);
20341  v = ae_v_dotproduct(&state->tmp0.ptr.p_double[0], 1, &state->tmp1.ptr.p_double[0], 1, ae_v_len(0,n-1));
20342  if( ae_fp_less_eq(ae_fabs(v, _state),state->bleicepsg) )
20343  {
20344  state->repterminationtype = 4;
20345  for(i=0; i<=n-1; i++)
20346  {
20347  state->xs.ptr.p_double[i] = state->solver.x.ptr.p_double[i];
20348  }
20349  break;
20350  }
20351 
20352  /*
20353  * Stopping condition #1 - relative function improvement is small:
20354  *
20355  * 1. calculate steepest descent step: V = -D1/(2*D2)
20356  * 2. calculate function change: V1= D2*V^2 + D1*V
20357  * 3. stop if function change is small enough
20358  */
20359  v = -d1/(2*d2);
20360  v1 = d2*v*v+d1*v;
20361  if( ae_fp_less_eq(ae_fabs(v1, _state),state->bleicepsf*ae_maxreal(d0, 1.0, _state)) )
20362  {
20363  state->repterminationtype = 1;
20364  for(i=0; i<=n-1; i++)
20365  {
20366  state->xs.ptr.p_double[i] = state->solver.x.ptr.p_double[i];
20367  }
20368  break;
20369  }
20370 
20371  /*
20372  * Stopping condition #2 - scaled step is small:
20373  *
20374  * 1. calculate step multiplier V0 (step itself is D*V0)
20375  * 2. calculate scaled step length V
20376  * 3. stop if step is small enough
20377  */
20378  v0 = -d1/(2*d2);
20379  v = 0;
20380  for(i=0; i<=n-1; i++)
20381  {
20382  v = v+ae_sqr(v0*state->solver.d.ptr.p_double[i]/state->s.ptr.p_double[i], _state);
20383  }
20384  if( ae_fp_less_eq(ae_sqrt(v, _state),state->bleicepsx) )
20385  {
20386  state->repterminationtype = 2;
20387  for(i=0; i<=n-1; i++)
20388  {
20389  state->xs.ptr.p_double[i] = state->solver.x.ptr.p_double[i];
20390  }
20391  break;
20392  }
20393  }
20394  }
20395  }
20396 
20397  /*
20398  * Gradient evaluation
20399  */
20400  if( state->solver.needfg )
20401  {
20402  for(i=0; i<=n-1; i++)
20403  {
20404  state->tmp0.ptr.p_double[i] = state->solver.x.ptr.p_double[i]-state->xorigin.ptr.p_double[i];
20405  }
20406  if( state->akind==0 )
20407  {
20408  cqmadx(&state->a, &state->tmp0, &state->tmp1, _state);
20409  }
20410  if( state->akind==1 )
20411  {
20412  sparsesmv(&state->sparsea, state->sparseaupper, &state->tmp0, &state->tmp1, _state);
20413  }
20414  v0 = ae_v_dotproduct(&state->tmp0.ptr.p_double[0], 1, &state->tmp1.ptr.p_double[0], 1, ae_v_len(0,n-1));
20415  v1 = ae_v_dotproduct(&state->tmp0.ptr.p_double[0], 1, &state->b.ptr.p_double[0], 1, ae_v_len(0,n-1));
20416  state->solver.f = 0.5*v0+v1;
20417  ae_v_move(&state->solver.g.ptr.p_double[0], 1, &state->tmp1.ptr.p_double[0], 1, ae_v_len(0,n-1));
20418  ae_v_add(&state->solver.g.ptr.p_double[0], 1, &state->b.ptr.p_double[0], 1, ae_v_len(0,n-1));
20419  }
20420  }
20421  if( state->repterminationtype==0 )
20422  {
20423 
20424  /*
20425  * BLEIC optimizer was terminated by one of its inner stopping
20426  * conditions. Usually it is iteration counter (if such
20427  * stopping condition was specified by user).
20428  */
20429  minbleicresults(&state->solver, &state->xs, &state->solverrep, _state);
20430  state->repterminationtype = state->solverrep.terminationtype;
20431  }
20432  else
20433  {
20434 
20435  /*
20436  * BLEIC optimizer was terminated in "emergency" mode by QP
20437  * solver.
20438  *
20439  * NOTE: such termination is "emergency" only when viewed from
20440  * BLEIC's position. QP solver sees such termination as
20441  * routine one, triggered by QP's stopping criteria.
20442  */
20443  minbleicemergencytermination(&state->solver, _state);
20444  }
20445  return;
20446  }
20447 }
20448 
20449 
20450 /*************************************************************************
20451 QP solver results
20452 
20453 INPUT PARAMETERS:
20454  State - algorithm state
20455 
20456 OUTPUT PARAMETERS:
20457  X - array[0..N-1], solution.
20458  This array is allocated and initialized only when
20459  Rep.TerminationType parameter is positive (success).
20460  Rep - optimization report. You should check Rep.TerminationType,
20461  which contains completion code, and you may check another
20462  fields which contain another information about algorithm
20463  functioning.
20464 
20465  Failure codes returned by algorithm are:
20466  * -5 inappropriate solver was used:
20467  * Cholesky solver for (semi)indefinite problems
20468  * Cholesky solver for problems with sparse matrix
20469  * -4 BLEIC-QP algorithm found unconstrained direction
20470  of negative curvature (function is unbounded from
20471  below even under constraints), no meaningful
20472  minimum can be found.
20473  * -3 inconsistent constraints (or maybe feasible point
20474  is too hard to find). If you are sure that
20475  constraints are feasible, try to restart optimizer
20476  with better initial approximation.
20477 
20478  Completion codes specific for Cholesky algorithm:
20479  * 4 successful completion
20480 
20481  Completion codes specific for BLEIC-based algorithm:
20482  * 1 relative function improvement is no more than EpsF.
20483  * 2 scaled step is no more than EpsX.
20484  * 4 scaled gradient norm is no more than EpsG.
20485  * 5 MaxIts steps was taken
20486 
20487  -- ALGLIB --
20488  Copyright 11.01.2011 by Bochkanov Sergey
20489 *************************************************************************/
20490 void minqpresults(minqpstate* state,
20491  /* Real */ ae_vector* x,
20492  minqpreport* rep,
20493  ae_state *_state)
20494 {
20495 
20496  ae_vector_clear(x);
20497  _minqpreport_clear(rep);
20498 
20499  minqpresultsbuf(state, x, rep, _state);
20500 }
20501 
20502 
20503 /*************************************************************************
20504 QP results
20505 
20506 Buffered implementation of MinQPResults() which uses pre-allocated buffer
20507 to store X[]. If buffer size is too small, it resizes buffer. It is
20508 intended to be used in the inner cycles of performance critical algorithms
20509 where array reallocation penalty is too large to be ignored.
20510 
20511  -- ALGLIB --
20512  Copyright 11.01.2011 by Bochkanov Sergey
20513 *************************************************************************/
20514 void minqpresultsbuf(minqpstate* state,
20515  /* Real */ ae_vector* x,
20516  minqpreport* rep,
20517  ae_state *_state)
20518 {
20519 
20520 
20521  if( x->cnt<state->n )
20522  {
20523  ae_vector_set_length(x, state->n, _state);
20524  }
20525  ae_v_move(&x->ptr.p_double[0], 1, &state->xs.ptr.p_double[0], 1, ae_v_len(0,state->n-1));
20526  rep->inneriterationscount = state->repinneriterationscount;
20527  rep->outeriterationscount = state->repouteriterationscount;
20528  rep->nmv = state->repnmv;
20529  rep->ncholesky = state->repncholesky;
20530  rep->terminationtype = state->repterminationtype;
20531 }
20532 
20533 
20534 /*************************************************************************
20535 Fast version of MinQPSetLinearTerm(), which doesn't check its arguments.
20536 For internal use only.
20537 
20538  -- ALGLIB --
20539  Copyright 11.01.2011 by Bochkanov Sergey
20540 *************************************************************************/
20541 void minqpsetlineartermfast(minqpstate* state,
20542  /* Real */ ae_vector* b,
20543  ae_state *_state)
20544 {
20545 
20546 
20547  ae_v_move(&state->b.ptr.p_double[0], 1, &b->ptr.p_double[0], 1, ae_v_len(0,state->n-1));
20548 }
20549 
20550 
20551 /*************************************************************************
20552 Fast version of MinQPSetQuadraticTerm(), which doesn't check its arguments.
20553 
20554 It accepts additional parameter - shift S, which allows to "shift" matrix
20555 A by adding s*I to A. S must be positive (although it is not checked).
20556 
20557 For internal use only.
20558 
20559  -- ALGLIB --
20560  Copyright 11.01.2011 by Bochkanov Sergey
20561 *************************************************************************/
20562 void minqpsetquadratictermfast(minqpstate* state,
20563  /* Real */ ae_matrix* a,
20564  ae_bool isupper,
20565  double s,
20566  ae_state *_state)
20567 {
20568  ae_int_t i;
20569  ae_int_t j;
20570  ae_int_t n;
20571 
20572 
20573  n = state->n;
20574  state->akind = 0;
20575  cqmseta(&state->a, a, isupper, 1.0, _state);
20576  if( ae_fp_greater(s,0) )
20577  {
20578  rvectorsetlengthatleast(&state->tmp0, n, _state);
20579  for(i=0; i<=n-1; i++)
20580  {
20581  state->tmp0.ptr.p_double[i] = a->ptr.pp_double[i][i]+s;
20582  }
20583  cqmrewritedensediagonal(&state->a, &state->tmp0, _state);
20584  }
20585 
20586  /*
20587  * Estimate norm of A
20588  * (it will be used later in the quadratic penalty function)
20589  */
20590  state->anorm = 0;
20591  for(i=0; i<=n-1; i++)
20592  {
20593  if( isupper )
20594  {
20595  for(j=i; j<=n-1; j++)
20596  {
20597  state->anorm = ae_maxreal(state->anorm, ae_fabs(a->ptr.pp_double[i][j], _state), _state);
20598  }
20599  }
20600  else
20601  {
20602  for(j=0; j<=i; j++)
20603  {
20604  state->anorm = ae_maxreal(state->anorm, ae_fabs(a->ptr.pp_double[i][j], _state), _state);
20605  }
20606  }
20607  }
20608  state->anorm = state->anorm*n;
20609 }
20610 
20611 
20612 /*************************************************************************
20613 Internal function which allows to rewrite diagonal of quadratic term.
20614 For internal use only.
20615 
20616 This function can be used only when you have dense A and already made
20617 MinQPSetQuadraticTerm(Fast) call.
20618 
20619  -- ALGLIB --
20620  Copyright 16.01.2011 by Bochkanov Sergey
20621 *************************************************************************/
20622 void minqprewritediagonal(minqpstate* state,
20623  /* Real */ ae_vector* s,
20624  ae_state *_state)
20625 {
20626 
20627 
20628  cqmrewritedensediagonal(&state->a, s, _state);
20629 }
20630 
20631 
20632 /*************************************************************************
20633 Fast version of MinQPSetStartingPoint(), which doesn't check its arguments.
20634 For internal use only.
20635 
20636  -- ALGLIB --
20637  Copyright 11.01.2011 by Bochkanov Sergey
20638 *************************************************************************/
20639 void minqpsetstartingpointfast(minqpstate* state,
20640  /* Real */ ae_vector* x,
20641  ae_state *_state)
20642 {
20643  ae_int_t n;
20644 
20645 
20646  n = state->n;
20647  ae_v_move(&state->startx.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1));
20648  state->havex = ae_true;
20649 }
20650 
20651 
20652 /*************************************************************************
20653 Fast version of MinQPSetOrigin(), which doesn't check its arguments.
20654 For internal use only.
20655 
20656  -- ALGLIB --
20657  Copyright 11.01.2011 by Bochkanov Sergey
20658 *************************************************************************/
20659 void minqpsetoriginfast(minqpstate* state,
20660  /* Real */ ae_vector* xorigin,
20661  ae_state *_state)
20662 {
20663  ae_int_t n;
20664 
20665 
20666  n = state->n;
20667  ae_v_move(&state->xorigin.ptr.p_double[0], 1, &xorigin->ptr.p_double[0], 1, ae_v_len(0,n-1));
20668 }
20669 
20670 
20671 /*************************************************************************
20672 Having feasible current point XC and possibly infeasible candidate point
20673 XN, this function performs longest step from XC to XN which retains
20674 feasibility. In case XN is found to be infeasible, at least one constraint
20675 is activated.
20676 
20677 For example, if we have:
20678  XC=0.5
20679  XN=1.2
20680  x>=0, x<=1
20681 then this function will move us to X=1.0 and activate constraint "x<=1".
20682 
20683 INPUT PARAMETERS:
20684  State - MinQP state.
20685  XC - current point, must be feasible with respect to
20686  all constraints
20687  XN - candidate point, can be infeasible with respect to some
20688  constraints. Must be located in the subspace of current
20689  active set, i.e. it is feasible with respect to already
20690  active constraints.
20691  Buf - temporary buffer, automatically resized if needed
20692 
20693 OUTPUT PARAMETERS:
20694  State - this function changes following fields of State:
20695  * State.ActiveSet
20696  * State.ActiveC - active linear constraints
20697  XC - new position
20698 
20699 RESULT:
20700  >0, in case at least one inactive non-candidate constraint was activated
20701  =0, in case only "candidate" constraints were activated
20702  <0, in case no constraints were activated by the step
20703 
20704 
20705  -- ALGLIB --
20706  Copyright 29.02.2012 by Bochkanov Sergey
20707 *************************************************************************/
20708 static ae_int_t minqp_minqpboundedstepandactivation(minqpstate* state,
20709  /* Real */ ae_vector* xn,
20710  /* Real */ ae_vector* buf,
20711  ae_state *_state)
20712 {
20713  ae_int_t n;
20714  double stpmax;
20715  ae_int_t cidx;
20716  double cval;
20717  ae_bool needact;
20718  double v;
20719  ae_int_t result;
20720 
20721 
20722  n = state->n;
20723  rvectorsetlengthatleast(buf, n, _state);
20724  ae_v_move(&buf->ptr.p_double[0], 1, &xn->ptr.p_double[0], 1, ae_v_len(0,n-1));
20725  ae_v_sub(&buf->ptr.p_double[0], 1, &state->sas.xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
20726  sasexploredirection(&state->sas, buf, &stpmax, &cidx, &cval, _state);
20727  needact = ae_fp_less_eq(stpmax,1);
20728  v = ae_minreal(stpmax, 1.0, _state);
20729  ae_v_muld(&buf->ptr.p_double[0], 1, ae_v_len(0,n-1), v);
20730  ae_v_add(&buf->ptr.p_double[0], 1, &state->sas.xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
20731  result = sasmoveto(&state->sas, buf, needact, cidx, cval, _state);
20732  return result;
20733 }
20734 
20735 
20736 /*************************************************************************
20737 Model value: f = 0.5*x'*A*x + b'*x
20738 
20739 INPUT PARAMETERS:
20740  A - convex quadratic model; only main quadratic term is used,
20741  other parts of the model (D/Q/linear term) are ignored.
20742  This function does not modify model state.
20743  B - right part
20744  XC - evaluation point
20745  Tmp - temporary buffer, automatically resized if needed
20746 
20747  -- ALGLIB --
20748  Copyright 20.06.2012 by Bochkanov Sergey
20749 *************************************************************************/
20750 static double minqp_minqpmodelvalue(convexquadraticmodel* a,
20751  /* Real */ ae_vector* b,
20752  /* Real */ ae_vector* xc,
20753  ae_int_t n,
20754  /* Real */ ae_vector* tmp,
20755  ae_state *_state)
20756 {
20757  double v0;
20758  double v1;
20759  double result;
20760 
20761 
20762  rvectorsetlengthatleast(tmp, n, _state);
20763  cqmadx(a, xc, tmp, _state);
20764  v0 = ae_v_dotproduct(&xc->ptr.p_double[0], 1, &tmp->ptr.p_double[0], 1, ae_v_len(0,n-1));
20765  v1 = ae_v_dotproduct(&xc->ptr.p_double[0], 1, &b->ptr.p_double[0], 1, ae_v_len(0,n-1));
20766  result = 0.5*v0+v1;
20767  return result;
20768 }
20769 
20770 
20771 /*************************************************************************
20772 Optimum of A subject to:
20773 a) active boundary constraints (given by ActiveSet[] and corresponding
20774  elements of XC)
20775 b) active linear constraints (given by C, R, LagrangeC)
20776 
20777 INPUT PARAMETERS:
20778  A - main quadratic term of the model;
20779  although structure may store linear and rank-K terms,
20780  these terms are ignored and rewritten by this function.
20781  ANorm - estimate of ||A|| (2-norm is used)
20782  B - array[N], linear term of the model
20783  XN - possibly preallocated buffer
20784  Tmp - temporary buffer (automatically resized)
20785  Tmp1 - temporary buffer (automatically resized)
20786 
20787 OUTPUT PARAMETERS:
20788  A - modified quadratic model (this function changes rank-K
20789  term and linear term of the model)
20790  LagrangeC- current estimate of the Lagrange coefficients
20791  XN - solution
20792 
20793 RESULT:
20794  True on success, False on failure (non-SPD model)
20795 
20796  -- ALGLIB --
20797  Copyright 20.06.2012 by Bochkanov Sergey
20798 *************************************************************************/
20799 static ae_bool minqp_minqpconstrainedoptimum(minqpstate* state,
20800  convexquadraticmodel* a,
20801  double anorm,
20802  /* Real */ ae_vector* b,
20803  /* Real */ ae_vector* xn,
20804  /* Real */ ae_vector* tmp,
20805  /* Boolean */ ae_vector* tmpb,
20806  /* Real */ ae_vector* lagrangec,
20807  ae_state *_state)
20808 {
20809  ae_int_t itidx;
20810  ae_int_t i;
20811  double v;
20812  double feaserrold;
20813  double feaserrnew;
20814  double theta;
20815  ae_int_t n;
20816  ae_bool result;
20817 
20818 
20819  n = state->n;
20820 
20821  /*
20822  * Rebuild basis accroding to current active set.
20823  * We call SASRebuildBasis() to make sure that fields of SAS
20824  * store up to date values.
20825  */
20826  sasrebuildbasis(&state->sas, _state);
20827 
20828  /*
20829  * Allocate temporaries.
20830  */
20831  rvectorsetlengthatleast(tmp, ae_maxint(n, state->sas.basissize, _state), _state);
20832  bvectorsetlengthatleast(tmpb, n, _state);
20833  rvectorsetlengthatleast(lagrangec, state->sas.basissize, _state);
20834 
20835  /*
20836  * Prepare model
20837  */
20838  for(i=0; i<=state->sas.basissize-1; i++)
20839  {
20840  tmp->ptr.p_double[i] = state->sas.pbasis.ptr.pp_double[i][n];
20841  }
20842  theta = 100.0*anorm;
20843  for(i=0; i<=n-1; i++)
20844  {
20845  if( state->sas.activeset.ptr.p_int[i]>0 )
20846  {
20847  tmpb->ptr.p_bool[i] = ae_true;
20848  }
20849  else
20850  {
20851  tmpb->ptr.p_bool[i] = ae_false;
20852  }
20853  }
20854  cqmsetactiveset(a, &state->sas.xc, tmpb, _state);
20855  cqmsetq(a, &state->sas.pbasis, tmp, state->sas.basissize, theta, _state);
20856 
20857  /*
20858  * Iterate until optimal values of Lagrange multipliers are found
20859  */
20860  for(i=0; i<=state->sas.basissize-1; i++)
20861  {
20862  lagrangec->ptr.p_double[i] = 0;
20863  }
20864  feaserrnew = ae_maxrealnumber;
20865  result = ae_true;
20866  for(itidx=1; itidx<=minqp_maxlagrangeits; itidx++)
20867  {
20868 
20869  /*
20870  * Generate right part B using linear term and current
20871  * estimate of the Lagrange multipliers.
20872  */
20873  ae_v_move(&tmp->ptr.p_double[0], 1, &b->ptr.p_double[0], 1, ae_v_len(0,n-1));
20874  for(i=0; i<=state->sas.basissize-1; i++)
20875  {
20876  v = lagrangec->ptr.p_double[i];
20877  ae_v_subd(&tmp->ptr.p_double[0], 1, &state->sas.pbasis.ptr.pp_double[i][0], 1, ae_v_len(0,n-1), v);
20878  }
20879  cqmsetb(a, tmp, _state);
20880 
20881  /*
20882  * Solve
20883  */
20884  result = cqmconstrainedoptimum(a, xn, _state);
20885  if( !result )
20886  {
20887  return result;
20888  }
20889 
20890  /*
20891  * Compare feasibility errors.
20892  * Terminate if error decreased too slowly.
20893  */
20894  feaserrold = feaserrnew;
20895  feaserrnew = 0;
20896  for(i=0; i<=state->sas.basissize-1; i++)
20897  {
20898  v = ae_v_dotproduct(&state->sas.pbasis.ptr.pp_double[i][0], 1, &xn->ptr.p_double[0], 1, ae_v_len(0,n-1));
20899  feaserrnew = feaserrnew+ae_sqr(v-state->sas.pbasis.ptr.pp_double[i][n], _state);
20900  }
20901  feaserrnew = ae_sqrt(feaserrnew, _state);
20902  if( ae_fp_greater_eq(feaserrnew,0.2*feaserrold) )
20903  {
20904  break;
20905  }
20906 
20907  /*
20908  * Update Lagrange multipliers
20909  */
20910  for(i=0; i<=state->sas.basissize-1; i++)
20911  {
20912  v = ae_v_dotproduct(&state->sas.pbasis.ptr.pp_double[i][0], 1, &xn->ptr.p_double[0], 1, ae_v_len(0,n-1));
20913  lagrangec->ptr.p_double[i] = lagrangec->ptr.p_double[i]-theta*(v-state->sas.pbasis.ptr.pp_double[i][n]);
20914  }
20915  }
20916  return result;
20917 }
20918 
20919 
20920 ae_bool _minqpstate_init(void* _p, ae_state *_state, ae_bool make_automatic)
20921 {
20922  minqpstate *p = (minqpstate*)_p;
20923  ae_touch_ptr((void*)p);
20924  if( !_convexquadraticmodel_init(&p->a, _state, make_automatic) )
20925  return ae_false;
20926  if( !_sparsematrix_init(&p->sparsea, _state, make_automatic) )
20927  return ae_false;
20928  if( !ae_vector_init(&p->b, 0, DT_REAL, _state, make_automatic) )
20929  return ae_false;
20930  if( !ae_vector_init(&p->bndl, 0, DT_REAL, _state, make_automatic) )
20931  return ae_false;
20932  if( !ae_vector_init(&p->bndu, 0, DT_REAL, _state, make_automatic) )
20933  return ae_false;
20934  if( !ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic) )
20935  return ae_false;
20936  if( !ae_vector_init(&p->havebndl, 0, DT_BOOL, _state, make_automatic) )
20937  return ae_false;
20938  if( !ae_vector_init(&p->havebndu, 0, DT_BOOL, _state, make_automatic) )
20939  return ae_false;
20940  if( !ae_vector_init(&p->xorigin, 0, DT_REAL, _state, make_automatic) )
20941  return ae_false;
20942  if( !ae_vector_init(&p->startx, 0, DT_REAL, _state, make_automatic) )
20943  return ae_false;
20944  if( !ae_matrix_init(&p->cleic, 0, 0, DT_REAL, _state, make_automatic) )
20945  return ae_false;
20946  if( !_sactiveset_init(&p->sas, _state, make_automatic) )
20947  return ae_false;
20948  if( !ae_vector_init(&p->gc, 0, DT_REAL, _state, make_automatic) )
20949  return ae_false;
20950  if( !ae_vector_init(&p->xn, 0, DT_REAL, _state, make_automatic) )
20951  return ae_false;
20952  if( !ae_vector_init(&p->pg, 0, DT_REAL, _state, make_automatic) )
20953  return ae_false;
20954  if( !ae_vector_init(&p->workbndl, 0, DT_REAL, _state, make_automatic) )
20955  return ae_false;
20956  if( !ae_vector_init(&p->workbndu, 0, DT_REAL, _state, make_automatic) )
20957  return ae_false;
20958  if( !ae_matrix_init(&p->workcleic, 0, 0, DT_REAL, _state, make_automatic) )
20959  return ae_false;
20960  if( !ae_vector_init(&p->xs, 0, DT_REAL, _state, make_automatic) )
20961  return ae_false;
20962  if( !ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic) )
20963  return ae_false;
20964  if( !ae_vector_init(&p->tmp1, 0, DT_REAL, _state, make_automatic) )
20965  return ae_false;
20966  if( !ae_vector_init(&p->tmpb, 0, DT_BOOL, _state, make_automatic) )
20967  return ae_false;
20968  if( !ae_vector_init(&p->rctmpg, 0, DT_REAL, _state, make_automatic) )
20969  return ae_false;
20970  if( !ae_vector_init(&p->tmpi, 0, DT_INT, _state, make_automatic) )
20971  return ae_false;
20972  if( !_normestimatorstate_init(&p->estimator, _state, make_automatic) )
20973  return ae_false;
20974  if( !_minbleicstate_init(&p->solver, _state, make_automatic) )
20975  return ae_false;
20976  if( !_minbleicreport_init(&p->solverrep, _state, make_automatic) )
20977  return ae_false;
20978  return ae_true;
20979 }
20980 
20981 
20982 ae_bool _minqpstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
20983 {
20984  minqpstate *dst = (minqpstate*)_dst;
20985  minqpstate *src = (minqpstate*)_src;
20986  dst->n = src->n;
20987  dst->algokind = src->algokind;
20988  dst->akind = src->akind;
20989  if( !_convexquadraticmodel_init_copy(&dst->a, &src->a, _state, make_automatic) )
20990  return ae_false;
20991  if( !_sparsematrix_init_copy(&dst->sparsea, &src->sparsea, _state, make_automatic) )
20992  return ae_false;
20993  dst->sparseaupper = src->sparseaupper;
20994  dst->anorm = src->anorm;
20995  if( !ae_vector_init_copy(&dst->b, &src->b, _state, make_automatic) )
20996  return ae_false;
20997  if( !ae_vector_init_copy(&dst->bndl, &src->bndl, _state, make_automatic) )
20998  return ae_false;
20999  if( !ae_vector_init_copy(&dst->bndu, &src->bndu, _state, make_automatic) )
21000  return ae_false;
21001  if( !ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic) )
21002  return ae_false;
21003  if( !ae_vector_init_copy(&dst->havebndl, &src->havebndl, _state, make_automatic) )
21004  return ae_false;
21005  if( !ae_vector_init_copy(&dst->havebndu, &src->havebndu, _state, make_automatic) )
21006  return ae_false;
21007  if( !ae_vector_init_copy(&dst->xorigin, &src->xorigin, _state, make_automatic) )
21008  return ae_false;
21009  if( !ae_vector_init_copy(&dst->startx, &src->startx, _state, make_automatic) )
21010  return ae_false;
21011  dst->havex = src->havex;
21012  if( !ae_matrix_init_copy(&dst->cleic, &src->cleic, _state, make_automatic) )
21013  return ae_false;
21014  dst->nec = src->nec;
21015  dst->nic = src->nic;
21016  dst->bleicepsg = src->bleicepsg;
21017  dst->bleicepsf = src->bleicepsf;
21018  dst->bleicepsx = src->bleicepsx;
21019  dst->bleicmaxits = src->bleicmaxits;
21020  if( !_sactiveset_init_copy(&dst->sas, &src->sas, _state, make_automatic) )
21021  return ae_false;
21022  if( !ae_vector_init_copy(&dst->gc, &src->gc, _state, make_automatic) )
21023  return ae_false;
21024  if( !ae_vector_init_copy(&dst->xn, &src->xn, _state, make_automatic) )
21025  return ae_false;
21026  if( !ae_vector_init_copy(&dst->pg, &src->pg, _state, make_automatic) )
21027  return ae_false;
21028  if( !ae_vector_init_copy(&dst->workbndl, &src->workbndl, _state, make_automatic) )
21029  return ae_false;
21030  if( !ae_vector_init_copy(&dst->workbndu, &src->workbndu, _state, make_automatic) )
21031  return ae_false;
21032  if( !ae_matrix_init_copy(&dst->workcleic, &src->workcleic, _state, make_automatic) )
21033  return ae_false;
21034  if( !ae_vector_init_copy(&dst->xs, &src->xs, _state, make_automatic) )
21035  return ae_false;
21036  dst->repinneriterationscount = src->repinneriterationscount;
21037  dst->repouteriterationscount = src->repouteriterationscount;
21038  dst->repncholesky = src->repncholesky;
21039  dst->repnmv = src->repnmv;
21040  dst->repterminationtype = src->repterminationtype;
21041  dst->debugphase1flops = src->debugphase1flops;
21042  dst->debugphase2flops = src->debugphase2flops;
21043  dst->debugphase3flops = src->debugphase3flops;
21044  if( !ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic) )
21045  return ae_false;
21046  if( !ae_vector_init_copy(&dst->tmp1, &src->tmp1, _state, make_automatic) )
21047  return ae_false;
21048  if( !ae_vector_init_copy(&dst->tmpb, &src->tmpb, _state, make_automatic) )
21049  return ae_false;
21050  if( !ae_vector_init_copy(&dst->rctmpg, &src->rctmpg, _state, make_automatic) )
21051  return ae_false;
21052  if( !ae_vector_init_copy(&dst->tmpi, &src->tmpi, _state, make_automatic) )
21053  return ae_false;
21054  if( !_normestimatorstate_init_copy(&dst->estimator, &src->estimator, _state, make_automatic) )
21055  return ae_false;
21056  if( !_minbleicstate_init_copy(&dst->solver, &src->solver, _state, make_automatic) )
21057  return ae_false;
21058  if( !_minbleicreport_init_copy(&dst->solverrep, &src->solverrep, _state, make_automatic) )
21059  return ae_false;
21060  return ae_true;
21061 }
21062 
21063 
21064 void _minqpstate_clear(void* _p)
21065 {
21066  minqpstate *p = (minqpstate*)_p;
21067  ae_touch_ptr((void*)p);
21068  _convexquadraticmodel_clear(&p->a);
21069  _sparsematrix_clear(&p->sparsea);
21070  ae_vector_clear(&p->b);
21071  ae_vector_clear(&p->bndl);
21072  ae_vector_clear(&p->bndu);
21073  ae_vector_clear(&p->s);
21074  ae_vector_clear(&p->havebndl);
21075  ae_vector_clear(&p->havebndu);
21076  ae_vector_clear(&p->xorigin);
21077  ae_vector_clear(&p->startx);
21078  ae_matrix_clear(&p->cleic);
21079  _sactiveset_clear(&p->sas);
21080  ae_vector_clear(&p->gc);
21081  ae_vector_clear(&p->xn);
21082  ae_vector_clear(&p->pg);
21083  ae_vector_clear(&p->workbndl);
21084  ae_vector_clear(&p->workbndu);
21085  ae_matrix_clear(&p->workcleic);
21086  ae_vector_clear(&p->xs);
21087  ae_vector_clear(&p->tmp0);
21088  ae_vector_clear(&p->tmp1);
21089  ae_vector_clear(&p->tmpb);
21090  ae_vector_clear(&p->rctmpg);
21091  ae_vector_clear(&p->tmpi);
21092  _normestimatorstate_clear(&p->estimator);
21093  _minbleicstate_clear(&p->solver);
21094  _minbleicreport_clear(&p->solverrep);
21095 }
21096 
21097 
21098 void _minqpstate_destroy(void* _p)
21099 {
21100  minqpstate *p = (minqpstate*)_p;
21101  ae_touch_ptr((void*)p);
21102  _convexquadraticmodel_destroy(&p->a);
21103  _sparsematrix_destroy(&p->sparsea);
21104  ae_vector_destroy(&p->b);
21105  ae_vector_destroy(&p->bndl);
21106  ae_vector_destroy(&p->bndu);
21107  ae_vector_destroy(&p->s);
21108  ae_vector_destroy(&p->havebndl);
21109  ae_vector_destroy(&p->havebndu);
21110  ae_vector_destroy(&p->xorigin);
21111  ae_vector_destroy(&p->startx);
21112  ae_matrix_destroy(&p->cleic);
21113  _sactiveset_destroy(&p->sas);
21114  ae_vector_destroy(&p->gc);
21115  ae_vector_destroy(&p->xn);
21116  ae_vector_destroy(&p->pg);
21117  ae_vector_destroy(&p->workbndl);
21118  ae_vector_destroy(&p->workbndu);
21119  ae_matrix_destroy(&p->workcleic);
21120  ae_vector_destroy(&p->xs);
21121  ae_vector_destroy(&p->tmp0);
21122  ae_vector_destroy(&p->tmp1);
21123  ae_vector_destroy(&p->tmpb);
21124  ae_vector_destroy(&p->rctmpg);
21125  ae_vector_destroy(&p->tmpi);
21126  _normestimatorstate_destroy(&p->estimator);
21127  _minbleicstate_destroy(&p->solver);
21128  _minbleicreport_destroy(&p->solverrep);
21129 }
21130 
21131 
21132 ae_bool _minqpreport_init(void* _p, ae_state *_state, ae_bool make_automatic)
21133 {
21134  minqpreport *p = (minqpreport*)_p;
21135  ae_touch_ptr((void*)p);
21136  return ae_true;
21137 }
21138 
21139 
21140 ae_bool _minqpreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
21141 {
21142  minqpreport *dst = (minqpreport*)_dst;
21143  minqpreport *src = (minqpreport*)_src;
21144  dst->inneriterationscount = src->inneriterationscount;
21145  dst->outeriterationscount = src->outeriterationscount;
21146  dst->nmv = src->nmv;
21147  dst->ncholesky = src->ncholesky;
21148  dst->terminationtype = src->terminationtype;
21149  return ae_true;
21150 }
21151 
21152 
21153 void _minqpreport_clear(void* _p)
21154 {
21155  minqpreport *p = (minqpreport*)_p;
21156  ae_touch_ptr((void*)p);
21157 }
21158 
21159 
21160 void _minqpreport_destroy(void* _p)
21161 {
21162  minqpreport *p = (minqpreport*)_p;
21163  ae_touch_ptr((void*)p);
21164 }
21165 
21166 
21167 
21168 
21169 /*************************************************************************
21170  IMPROVED LEVENBERG-MARQUARDT METHOD FOR
21171  NON-LINEAR LEAST SQUARES OPTIMIZATION
21172 
21173 DESCRIPTION:
21174 This function is used to find minimum of function which is represented as
21175 sum of squares:
21176  F(x) = f[0]^2(x[0],...,x[n-1]) + ... + f[m-1]^2(x[0],...,x[n-1])
21177 using value of function vector f[] and Jacobian of f[].
21178 
21179 
21180 REQUIREMENTS:
21181 This algorithm will request following information during its operation:
21182 
21183 * function vector f[] at given point X
21184 * function vector f[] and Jacobian of f[] (simultaneously) at given point
21185 
21186 There are several overloaded versions of MinLMOptimize() function which
21187 correspond to different LM-like optimization algorithms provided by this
21188 unit. You should choose version which accepts fvec() and jac() callbacks.
21189 First one is used to calculate f[] at given point, second one calculates
21190 f[] and Jacobian df[i]/dx[j].
21191 
21192 You can try to initialize MinLMState structure with VJ function and then
21193 use incorrect version of MinLMOptimize() (for example, version which
21194 works with general form function and does not provide Jacobian), but it
21195 will lead to exception being thrown after first attempt to calculate
21196 Jacobian.
21197 
21198 
21199 USAGE:
21200 1. User initializes algorithm state with MinLMCreateVJ() call
21201 2. User tunes solver parameters with MinLMSetCond(), MinLMSetStpMax() and
21202  other functions
21203 3. User calls MinLMOptimize() function which takes algorithm state and
21204  callback functions.
21205 4. User calls MinLMResults() to get solution
21206 5. Optionally, user may call MinLMRestartFrom() to solve another problem
21207  with same N/M but another starting point and/or another function.
21208  MinLMRestartFrom() allows to reuse already initialized structure.
21209 
21210 
21211 INPUT PARAMETERS:
21212  N - dimension, N>1
21213  * if given, only leading N elements of X are used
21214  * if not given, automatically determined from size of X
21215  M - number of functions f[i]
21216  X - initial solution, array[0..N-1]
21217 
21218 OUTPUT PARAMETERS:
21219  State - structure which stores algorithm state
21220 
21221 NOTES:
21222 1. you may tune stopping conditions with MinLMSetCond() function
21223 2. if target function contains exp() or other fast growing functions, and
21224  optimization algorithm makes too large steps which leads to overflow,
21225  use MinLMSetStpMax() function to bound algorithm's steps.
21226 
21227  -- ALGLIB --
21228  Copyright 30.03.2009 by Bochkanov Sergey
21229 *************************************************************************/
21230 void minlmcreatevj(ae_int_t n,
21231  ae_int_t m,
21232  /* Real */ ae_vector* x,
21233  minlmstate* state,
21234  ae_state *_state)
21235 {
21236 
21237  _minlmstate_clear(state);
21238 
21239  ae_assert(n>=1, "MinLMCreateVJ: N<1!", _state);
21240  ae_assert(m>=1, "MinLMCreateVJ: M<1!", _state);
21241  ae_assert(x->cnt>=n, "MinLMCreateVJ: Length(X)<N!", _state);
21242  ae_assert(isfinitevector(x, n, _state), "MinLMCreateVJ: X contains infinite or NaN values!", _state);
21243 
21244  /*
21245  * initialize, check parameters
21246  */
21247  state->teststep = 0;
21248  state->n = n;
21249  state->m = m;
21250  state->algomode = 1;
21251  state->hasf = ae_false;
21252  state->hasfi = ae_true;
21253  state->hasg = ae_false;
21254 
21255  /*
21256  * second stage of initialization
21257  */
21258  minlm_lmprepare(n, m, ae_false, state, _state);
21259  minlmsetacctype(state, 0, _state);
21260  minlmsetcond(state, 0, 0, 0, 0, _state);
21261  minlmsetxrep(state, ae_false, _state);
21262  minlmsetstpmax(state, 0, _state);
21263  minlmrestartfrom(state, x, _state);
21264 }
21265 
21266 
21267 /*************************************************************************
21268  IMPROVED LEVENBERG-MARQUARDT METHOD FOR
21269  NON-LINEAR LEAST SQUARES OPTIMIZATION
21270 
21271 DESCRIPTION:
21272 This function is used to find minimum of function which is represented as
21273 sum of squares:
21274  F(x) = f[0]^2(x[0],...,x[n-1]) + ... + f[m-1]^2(x[0],...,x[n-1])
21275 using value of function vector f[] only. Finite differences are used to
21276 calculate Jacobian.
21277 
21278 
21279 REQUIREMENTS:
21280 This algorithm will request following information during its operation:
21281 * function vector f[] at given point X
21282 
21283 There are several overloaded versions of MinLMOptimize() function which
21284 correspond to different LM-like optimization algorithms provided by this
21285 unit. You should choose version which accepts fvec() callback.
21286 
21287 You can try to initialize MinLMState structure with VJ function and then
21288 use incorrect version of MinLMOptimize() (for example, version which
21289 works with general form function and does not accept function vector), but
21290 it will lead to exception being thrown after first attempt to calculate
21291 Jacobian.
21292 
21293 
21294 USAGE:
21295 1. User initializes algorithm state with MinLMCreateV() call
21296 2. User tunes solver parameters with MinLMSetCond(), MinLMSetStpMax() and
21297  other functions
21298 3. User calls MinLMOptimize() function which takes algorithm state and
21299  callback functions.
21300 4. User calls MinLMResults() to get solution
21301 5. Optionally, user may call MinLMRestartFrom() to solve another problem
21302  with same N/M but another starting point and/or another function.
21303  MinLMRestartFrom() allows to reuse already initialized structure.
21304 
21305 
21306 INPUT PARAMETERS:
21307  N - dimension, N>1
21308  * if given, only leading N elements of X are used
21309  * if not given, automatically determined from size of X
21310  M - number of functions f[i]
21311  X - initial solution, array[0..N-1]
21312  DiffStep- differentiation step, >0
21313 
21314 OUTPUT PARAMETERS:
21315  State - structure which stores algorithm state
21316 
21317 See also MinLMIteration, MinLMResults.
21318 
21319 NOTES:
21320 1. you may tune stopping conditions with MinLMSetCond() function
21321 2. if target function contains exp() or other fast growing functions, and
21322  optimization algorithm makes too large steps which leads to overflow,
21323  use MinLMSetStpMax() function to bound algorithm's steps.
21324 
21325  -- ALGLIB --
21326  Copyright 30.03.2009 by Bochkanov Sergey
21327 *************************************************************************/
21328 void minlmcreatev(ae_int_t n,
21329  ae_int_t m,
21330  /* Real */ ae_vector* x,
21331  double diffstep,
21332  minlmstate* state,
21333  ae_state *_state)
21334 {
21335 
21336  _minlmstate_clear(state);
21337 
21338  ae_assert(ae_isfinite(diffstep, _state), "MinLMCreateV: DiffStep is not finite!", _state);
21339  ae_assert(ae_fp_greater(diffstep,0), "MinLMCreateV: DiffStep<=0!", _state);
21340  ae_assert(n>=1, "MinLMCreateV: N<1!", _state);
21341  ae_assert(m>=1, "MinLMCreateV: M<1!", _state);
21342  ae_assert(x->cnt>=n, "MinLMCreateV: Length(X)<N!", _state);
21343  ae_assert(isfinitevector(x, n, _state), "MinLMCreateV: X contains infinite or NaN values!", _state);
21344 
21345  /*
21346  * Initialize
21347  */
21348  state->teststep = 0;
21349  state->n = n;
21350  state->m = m;
21351  state->algomode = 0;
21352  state->hasf = ae_false;
21353  state->hasfi = ae_true;
21354  state->hasg = ae_false;
21355  state->diffstep = diffstep;
21356 
21357  /*
21358  * Second stage of initialization
21359  */
21360  minlm_lmprepare(n, m, ae_false, state, _state);
21361  minlmsetacctype(state, 1, _state);
21362  minlmsetcond(state, 0, 0, 0, 0, _state);
21363  minlmsetxrep(state, ae_false, _state);
21364  minlmsetstpmax(state, 0, _state);
21365  minlmrestartfrom(state, x, _state);
21366 }
21367 
21368 
21369 /*************************************************************************
21370  LEVENBERG-MARQUARDT-LIKE METHOD FOR NON-LINEAR OPTIMIZATION
21371 
21372 DESCRIPTION:
21373 This function is used to find minimum of general form (not "sum-of-
21374 -squares") function
21375  F = F(x[0], ..., x[n-1])
21376 using its gradient and Hessian. Levenberg-Marquardt modification with
21377 L-BFGS pre-optimization and internal pre-conditioned L-BFGS optimization
21378 after each Levenberg-Marquardt step is used.
21379 
21380 
21381 REQUIREMENTS:
21382 This algorithm will request following information during its operation:
21383 
21384 * function value F at given point X
21385 * F and gradient G (simultaneously) at given point X
21386 * F, G and Hessian H (simultaneously) at given point X
21387 
21388 There are several overloaded versions of MinLMOptimize() function which
21389 correspond to different LM-like optimization algorithms provided by this
21390 unit. You should choose version which accepts func(), grad() and hess()
21391 function pointers. First pointer is used to calculate F at given point,
21392 second one calculates F(x) and grad F(x), third one calculates F(x),
21393 grad F(x), hess F(x).
21394 
21395 You can try to initialize MinLMState structure with FGH-function and then
21396 use incorrect version of MinLMOptimize() (for example, version which does
21397 not provide Hessian matrix), but it will lead to exception being thrown
21398 after first attempt to calculate Hessian.
21399 
21400 
21401 USAGE:
21402 1. User initializes algorithm state with MinLMCreateFGH() call
21403 2. User tunes solver parameters with MinLMSetCond(), MinLMSetStpMax() and
21404  other functions
21405 3. User calls MinLMOptimize() function which takes algorithm state and
21406  pointers (delegates, etc.) to callback functions.
21407 4. User calls MinLMResults() to get solution
21408 5. Optionally, user may call MinLMRestartFrom() to solve another problem
21409  with same N but another starting point and/or another function.
21410  MinLMRestartFrom() allows to reuse already initialized structure.
21411 
21412 
21413 INPUT PARAMETERS:
21414  N - dimension, N>1
21415  * if given, only leading N elements of X are used
21416  * if not given, automatically determined from size of X
21417  X - initial solution, array[0..N-1]
21418 
21419 OUTPUT PARAMETERS:
21420  State - structure which stores algorithm state
21421 
21422 NOTES:
21423 1. you may tune stopping conditions with MinLMSetCond() function
21424 2. if target function contains exp() or other fast growing functions, and
21425  optimization algorithm makes too large steps which leads to overflow,
21426  use MinLMSetStpMax() function to bound algorithm's steps.
21427 
21428  -- ALGLIB --
21429  Copyright 30.03.2009 by Bochkanov Sergey
21430 *************************************************************************/
21431 void minlmcreatefgh(ae_int_t n,
21432  /* Real */ ae_vector* x,
21433  minlmstate* state,
21434  ae_state *_state)
21435 {
21436 
21437  _minlmstate_clear(state);
21438 
21439  ae_assert(n>=1, "MinLMCreateFGH: N<1!", _state);
21440  ae_assert(x->cnt>=n, "MinLMCreateFGH: Length(X)<N!", _state);
21441  ae_assert(isfinitevector(x, n, _state), "MinLMCreateFGH: X contains infinite or NaN values!", _state);
21442 
21443  /*
21444  * initialize
21445  */
21446  state->teststep = 0;
21447  state->n = n;
21448  state->m = 0;
21449  state->algomode = 2;
21450  state->hasf = ae_true;
21451  state->hasfi = ae_false;
21452  state->hasg = ae_true;
21453 
21454  /*
21455  * init2
21456  */
21457  minlm_lmprepare(n, 0, ae_true, state, _state);
21458  minlmsetacctype(state, 2, _state);
21459  minlmsetcond(state, 0, 0, 0, 0, _state);
21460  minlmsetxrep(state, ae_false, _state);
21461  minlmsetstpmax(state, 0, _state);
21462  minlmrestartfrom(state, x, _state);
21463 }
21464 
21465 
21466 /*************************************************************************
21467 This function sets stopping conditions for Levenberg-Marquardt optimization
21468 algorithm.
21469 
21470 INPUT PARAMETERS:
21471  State - structure which stores algorithm state
21472  EpsG - >=0
21473  The subroutine finishes its work if the condition
21474  |v|<EpsG is satisfied, where:
21475  * |.| means Euclidian norm
21476  * v - scaled gradient vector, v[i]=g[i]*s[i]
21477  * g - gradient
21478  * s - scaling coefficients set by MinLMSetScale()
21479  EpsF - >=0
21480  The subroutine finishes its work if on k+1-th iteration
21481  the condition |F(k+1)-F(k)|<=EpsF*max{|F(k)|,|F(k+1)|,1}
21482  is satisfied.
21483  EpsX - >=0
21484  The subroutine finishes its work if on k+1-th iteration
21485  the condition |v|<=EpsX is fulfilled, where:
21486  * |.| means Euclidian norm
21487  * v - scaled step vector, v[i]=dx[i]/s[i]
21488  * dx - ste pvector, dx=X(k+1)-X(k)
21489  * s - scaling coefficients set by MinLMSetScale()
21490  MaxIts - maximum number of iterations. If MaxIts=0, the number of
21491  iterations is unlimited. Only Levenberg-Marquardt
21492  iterations are counted (L-BFGS/CG iterations are NOT
21493  counted because their cost is very low compared to that of
21494  LM).
21495 
21496 Passing EpsG=0, EpsF=0, EpsX=0 and MaxIts=0 (simultaneously) will lead to
21497 automatic stopping criterion selection (small EpsX).
21498 
21499  -- ALGLIB --
21500  Copyright 02.04.2010 by Bochkanov Sergey
21501 *************************************************************************/
21502 void minlmsetcond(minlmstate* state,
21503  double epsg,
21504  double epsf,
21505  double epsx,
21506  ae_int_t maxits,
21507  ae_state *_state)
21508 {
21509 
21510 
21511  ae_assert(ae_isfinite(epsg, _state), "MinLMSetCond: EpsG is not finite number!", _state);
21512  ae_assert(ae_fp_greater_eq(epsg,0), "MinLMSetCond: negative EpsG!", _state);
21513  ae_assert(ae_isfinite(epsf, _state), "MinLMSetCond: EpsF is not finite number!", _state);
21514  ae_assert(ae_fp_greater_eq(epsf,0), "MinLMSetCond: negative EpsF!", _state);
21515  ae_assert(ae_isfinite(epsx, _state), "MinLMSetCond: EpsX is not finite number!", _state);
21516  ae_assert(ae_fp_greater_eq(epsx,0), "MinLMSetCond: negative EpsX!", _state);
21517  ae_assert(maxits>=0, "MinLMSetCond: negative MaxIts!", _state);
21518  if( ((ae_fp_eq(epsg,0)&&ae_fp_eq(epsf,0))&&ae_fp_eq(epsx,0))&&maxits==0 )
21519  {
21520  epsx = 1.0E-6;
21521  }
21522  state->epsg = epsg;
21523  state->epsf = epsf;
21524  state->epsx = epsx;
21525  state->maxits = maxits;
21526 }
21527 
21528 
21529 /*************************************************************************
21530 This function turns on/off reporting.
21531 
21532 INPUT PARAMETERS:
21533  State - structure which stores algorithm state
21534  NeedXRep- whether iteration reports are needed or not
21535 
21536 If NeedXRep is True, algorithm will call rep() callback function if it is
21537 provided to MinLMOptimize(). Both Levenberg-Marquardt and internal L-BFGS
21538 iterations are reported.
21539 
21540  -- ALGLIB --
21541  Copyright 02.04.2010 by Bochkanov Sergey
21542 *************************************************************************/
21543 void minlmsetxrep(minlmstate* state, ae_bool needxrep, ae_state *_state)
21544 {
21545 
21546 
21547  state->xrep = needxrep;
21548 }
21549 
21550 
21551 /*************************************************************************
21552 This function sets maximum step length
21553 
21554 INPUT PARAMETERS:
21555  State - structure which stores algorithm state
21556  StpMax - maximum step length, >=0. Set StpMax to 0.0, if you don't
21557  want to limit step length.
21558 
21559 Use this subroutine when you optimize target function which contains exp()
21560 or other fast growing functions, and optimization algorithm makes too
21561 large steps which leads to overflow. This function allows us to reject
21562 steps that are too large (and therefore expose us to the possible
21563 overflow) without actually calculating function value at the x+stp*d.
21564 
21565 NOTE: non-zero StpMax leads to moderate performance degradation because
21566 intermediate step of preconditioned L-BFGS optimization is incompatible
21567 with limits on step size.
21568 
21569  -- ALGLIB --
21570  Copyright 02.04.2010 by Bochkanov Sergey
21571 *************************************************************************/
21572 void minlmsetstpmax(minlmstate* state, double stpmax, ae_state *_state)
21573 {
21574 
21575 
21576  ae_assert(ae_isfinite(stpmax, _state), "MinLMSetStpMax: StpMax is not finite!", _state);
21577  ae_assert(ae_fp_greater_eq(stpmax,0), "MinLMSetStpMax: StpMax<0!", _state);
21578  state->stpmax = stpmax;
21579 }
21580 
21581 
21582 /*************************************************************************
21583 This function sets scaling coefficients for LM optimizer.
21584 
21585 ALGLIB optimizers use scaling matrices to test stopping conditions (step
21586 size and gradient are scaled before comparison with tolerances). Scale of
21587 the I-th variable is a translation invariant measure of:
21588 a) "how large" the variable is
21589 b) how large the step should be to make significant changes in the function
21590 
21591 Generally, scale is NOT considered to be a form of preconditioner. But LM
21592 optimizer is unique in that it uses scaling matrix both in the stopping
21593 condition tests and as Marquardt damping factor.
21594 
21595 Proper scaling is very important for the algorithm performance. It is less
21596 important for the quality of results, but still has some influence (it is
21597 easier to converge when variables are properly scaled, so premature
21598 stopping is possible when very badly scalled variables are combined with
21599 relaxed stopping conditions).
21600 
21601 INPUT PARAMETERS:
21602  State - structure stores algorithm state
21603  S - array[N], non-zero scaling coefficients
21604  S[i] may be negative, sign doesn't matter.
21605 
21606  -- ALGLIB --
21607  Copyright 14.01.2011 by Bochkanov Sergey
21608 *************************************************************************/
21609 void minlmsetscale(minlmstate* state,
21610  /* Real */ ae_vector* s,
21611  ae_state *_state)
21612 {
21613  ae_int_t i;
21614 
21615 
21616  ae_assert(s->cnt>=state->n, "MinLMSetScale: Length(S)<N", _state);
21617  for(i=0; i<=state->n-1; i++)
21618  {
21619  ae_assert(ae_isfinite(s->ptr.p_double[i], _state), "MinLMSetScale: S contains infinite or NAN elements", _state);
21620  ae_assert(ae_fp_neq(s->ptr.p_double[i],0), "MinLMSetScale: S contains zero elements", _state);
21621  state->s.ptr.p_double[i] = ae_fabs(s->ptr.p_double[i], _state);
21622  }
21623 }
21624 
21625 
21626 /*************************************************************************
21627 This function sets boundary constraints for LM optimizer
21628 
21629 Boundary constraints are inactive by default (after initial creation).
21630 They are preserved until explicitly turned off with another SetBC() call.
21631 
21632 INPUT PARAMETERS:
21633  State - structure stores algorithm state
21634  BndL - lower bounds, array[N].
21635  If some (all) variables are unbounded, you may specify
21636  very small number or -INF (latter is recommended because
21637  it will allow solver to use better algorithm).
21638  BndU - upper bounds, array[N].
21639  If some (all) variables are unbounded, you may specify
21640  very large number or +INF (latter is recommended because
21641  it will allow solver to use better algorithm).
21642 
21643 NOTE 1: it is possible to specify BndL[i]=BndU[i]. In this case I-th
21644 variable will be "frozen" at X[i]=BndL[i]=BndU[i].
21645 
21646 NOTE 2: this solver has following useful properties:
21647 * bound constraints are always satisfied exactly
21648 * function is evaluated only INSIDE area specified by bound constraints
21649  or at its boundary
21650 
21651  -- ALGLIB --
21652  Copyright 14.01.2011 by Bochkanov Sergey
21653 *************************************************************************/
21654 void minlmsetbc(minlmstate* state,
21655  /* Real */ ae_vector* bndl,
21656  /* Real */ ae_vector* bndu,
21657  ae_state *_state)
21658 {
21659  ae_int_t i;
21660  ae_int_t n;
21661 
21662 
21663  n = state->n;
21664  ae_assert(bndl->cnt>=n, "MinLMSetBC: Length(BndL)<N", _state);
21665  ae_assert(bndu->cnt>=n, "MinLMSetBC: Length(BndU)<N", _state);
21666  for(i=0; i<=n-1; i++)
21667  {
21668  ae_assert(ae_isfinite(bndl->ptr.p_double[i], _state)||ae_isneginf(bndl->ptr.p_double[i], _state), "MinLMSetBC: BndL contains NAN or +INF", _state);
21669  ae_assert(ae_isfinite(bndu->ptr.p_double[i], _state)||ae_isposinf(bndu->ptr.p_double[i], _state), "MinLMSetBC: BndU contains NAN or -INF", _state);
21670  state->bndl.ptr.p_double[i] = bndl->ptr.p_double[i];
21671  state->havebndl.ptr.p_bool[i] = ae_isfinite(bndl->ptr.p_double[i], _state);
21672  state->bndu.ptr.p_double[i] = bndu->ptr.p_double[i];
21673  state->havebndu.ptr.p_bool[i] = ae_isfinite(bndu->ptr.p_double[i], _state);
21674  }
21675 }
21676 
21677 
21678 /*************************************************************************
21679 This function is used to change acceleration settings
21680 
21681 You can choose between three acceleration strategies:
21682 * AccType=0, no acceleration.
21683 * AccType=1, secant updates are used to update quadratic model after each
21684  iteration. After fixed number of iterations (or after model breakdown)
21685  we recalculate quadratic model using analytic Jacobian or finite
21686  differences. Number of secant-based iterations depends on optimization
21687  settings: about 3 iterations - when we have analytic Jacobian, up to 2*N
21688  iterations - when we use finite differences to calculate Jacobian.
21689 
21690 AccType=1 is recommended when Jacobian calculation cost is prohibitive
21691 high (several Mx1 function vector calculations followed by several NxN
21692 Cholesky factorizations are faster than calculation of one M*N Jacobian).
21693 It should also be used when we have no Jacobian, because finite difference
21694 approximation takes too much time to compute.
21695 
21696 Table below list optimization protocols (XYZ protocol corresponds to
21697 MinLMCreateXYZ) and acceleration types they support (and use by default).
21698 
21699 ACCELERATION TYPES SUPPORTED BY OPTIMIZATION PROTOCOLS:
21700 
21701 protocol 0 1 comment
21702 V + +
21703 VJ + +
21704 FGH +
21705 
21706 DAFAULT VALUES:
21707 
21708 protocol 0 1 comment
21709 V x without acceleration it is so slooooooooow
21710 VJ x
21711 FGH x
21712 
21713 NOTE: this function should be called before optimization. Attempt to call
21714 it during algorithm iterations may result in unexpected behavior.
21715 
21716 NOTE: attempt to call this function with unsupported protocol/acceleration
21717 combination will result in exception being thrown.
21718 
21719  -- ALGLIB --
21720  Copyright 14.10.2010 by Bochkanov Sergey
21721 *************************************************************************/
21722 void minlmsetacctype(minlmstate* state,
21723  ae_int_t acctype,
21724  ae_state *_state)
21725 {
21726 
21727 
21728  ae_assert((acctype==0||acctype==1)||acctype==2, "MinLMSetAccType: incorrect AccType!", _state);
21729  if( acctype==2 )
21730  {
21731  acctype = 0;
21732  }
21733  if( acctype==0 )
21734  {
21735  state->maxmodelage = 0;
21736  state->makeadditers = ae_false;
21737  return;
21738  }
21739  if( acctype==1 )
21740  {
21741  ae_assert(state->hasfi, "MinLMSetAccType: AccType=1 is incompatible with current protocol!", _state);
21742  if( state->algomode==0 )
21743  {
21744  state->maxmodelage = 2*state->n;
21745  }
21746  else
21747  {
21748  state->maxmodelage = minlm_smallmodelage;
21749  }
21750  state->makeadditers = ae_false;
21751  return;
21752  }
21753 }
21754 
21755 
21756 /*************************************************************************
21757 NOTES:
21758 
21759 1. Depending on function used to create state structure, this algorithm
21760  may accept Jacobian and/or Hessian and/or gradient. According to the
21761  said above, there ase several versions of this function, which accept
21762  different sets of callbacks.
21763 
21764  This flexibility opens way to subtle errors - you may create state with
21765  MinLMCreateFGH() (optimization using Hessian), but call function which
21766  does not accept Hessian. So when algorithm will request Hessian, there
21767  will be no callback to call. In this case exception will be thrown.
21768 
21769  Be careful to avoid such errors because there is no way to find them at
21770  compile time - you can see them at runtime only.
21771 
21772  -- ALGLIB --
21773  Copyright 10.03.2009 by Bochkanov Sergey
21774 *************************************************************************/
21775 ae_bool minlmiteration(minlmstate* state, ae_state *_state)
21776 {
21777  ae_int_t n;
21778  ae_int_t m;
21779  ae_bool bflag;
21780  ae_int_t iflag;
21781  double v;
21782  double s;
21783  double t;
21784  ae_int_t i;
21785  ae_int_t k;
21786  ae_bool result;
21787 
21788 
21789 
21790  /*
21791  * Reverse communication preparations
21792  * I know it looks ugly, but it works the same way
21793  * anywhere from C++ to Python.
21794  *
21795  * This code initializes locals by:
21796  * * random values determined during code
21797  * generation - on first subroutine call
21798  * * values from previous call - on subsequent calls
21799  */
21800  if( state->rstate.stage>=0 )
21801  {
21802  n = state->rstate.ia.ptr.p_int[0];
21803  m = state->rstate.ia.ptr.p_int[1];
21804  iflag = state->rstate.ia.ptr.p_int[2];
21805  i = state->rstate.ia.ptr.p_int[3];
21806  k = state->rstate.ia.ptr.p_int[4];
21807  bflag = state->rstate.ba.ptr.p_bool[0];
21808  v = state->rstate.ra.ptr.p_double[0];
21809  s = state->rstate.ra.ptr.p_double[1];
21810  t = state->rstate.ra.ptr.p_double[2];
21811  }
21812  else
21813  {
21814  n = -983;
21815  m = -989;
21816  iflag = -834;
21817  i = 900;
21818  k = -287;
21819  bflag = ae_false;
21820  v = 214;
21821  s = -338;
21822  t = -686;
21823  }
21824  if( state->rstate.stage==0 )
21825  {
21826  goto lbl_0;
21827  }
21828  if( state->rstate.stage==1 )
21829  {
21830  goto lbl_1;
21831  }
21832  if( state->rstate.stage==2 )
21833  {
21834  goto lbl_2;
21835  }
21836  if( state->rstate.stage==3 )
21837  {
21838  goto lbl_3;
21839  }
21840  if( state->rstate.stage==4 )
21841  {
21842  goto lbl_4;
21843  }
21844  if( state->rstate.stage==5 )
21845  {
21846  goto lbl_5;
21847  }
21848  if( state->rstate.stage==6 )
21849  {
21850  goto lbl_6;
21851  }
21852  if( state->rstate.stage==7 )
21853  {
21854  goto lbl_7;
21855  }
21856  if( state->rstate.stage==8 )
21857  {
21858  goto lbl_8;
21859  }
21860  if( state->rstate.stage==9 )
21861  {
21862  goto lbl_9;
21863  }
21864  if( state->rstate.stage==10 )
21865  {
21866  goto lbl_10;
21867  }
21868  if( state->rstate.stage==11 )
21869  {
21870  goto lbl_11;
21871  }
21872  if( state->rstate.stage==12 )
21873  {
21874  goto lbl_12;
21875  }
21876  if( state->rstate.stage==13 )
21877  {
21878  goto lbl_13;
21879  }
21880  if( state->rstate.stage==14 )
21881  {
21882  goto lbl_14;
21883  }
21884  if( state->rstate.stage==15 )
21885  {
21886  goto lbl_15;
21887  }
21888  if( state->rstate.stage==16 )
21889  {
21890  goto lbl_16;
21891  }
21892  if( state->rstate.stage==17 )
21893  {
21894  goto lbl_17;
21895  }
21896  if( state->rstate.stage==18 )
21897  {
21898  goto lbl_18;
21899  }
21900 
21901  /*
21902  * Routine body
21903  */
21904 
21905  /*
21906  * prepare
21907  */
21908  n = state->n;
21909  m = state->m;
21910  state->repiterationscount = 0;
21911  state->repterminationtype = 0;
21912  state->repfuncidx = -1;
21913  state->repvaridx = -1;
21914  state->repnfunc = 0;
21915  state->repnjac = 0;
21916  state->repngrad = 0;
21917  state->repnhess = 0;
21918  state->repncholesky = 0;
21919 
21920  /*
21921  * check consistency of constraints,
21922  * enforce feasibility of the solution
21923  * set constraints
21924  */
21925  if( !enforceboundaryconstraints(&state->xbase, &state->bndl, &state->havebndl, &state->bndu, &state->havebndu, n, 0, _state) )
21926  {
21927  state->repterminationtype = -3;
21928  result = ae_false;
21929  return result;
21930  }
21931  minqpsetbc(&state->qpstate, &state->bndl, &state->bndu, _state);
21932 
21933  /*
21934  * Check, that transferred derivative value is right
21935  */
21936  minlm_clearrequestfields(state, _state);
21937  if( !(state->algomode==1&&ae_fp_greater(state->teststep,0)) )
21938  {
21939  goto lbl_19;
21940  }
21941  ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
21942  state->needfij = ae_true;
21943  i = 0;
21944 lbl_21:
21945  if( i>n-1 )
21946  {
21947  goto lbl_23;
21948  }
21949  ae_assert((state->havebndl.ptr.p_bool[i]&&ae_fp_less_eq(state->bndl.ptr.p_double[i],state->x.ptr.p_double[i]))||!state->havebndl.ptr.p_bool[i], "MinLM: internal error(State.X is out of bounds)", _state);
21950  ae_assert((state->havebndu.ptr.p_bool[i]&&ae_fp_less_eq(state->x.ptr.p_double[i],state->bndu.ptr.p_double[i]))||!state->havebndu.ptr.p_bool[i], "MinLMIteration: internal error(State.X is out of bounds)", _state);
21951  v = state->x.ptr.p_double[i];
21952  state->x.ptr.p_double[i] = v-state->teststep*state->s.ptr.p_double[i];
21953  if( state->havebndl.ptr.p_bool[i] )
21954  {
21955  state->x.ptr.p_double[i] = ae_maxreal(state->x.ptr.p_double[i], state->bndl.ptr.p_double[i], _state);
21956  }
21957  state->xm1 = state->x.ptr.p_double[i];
21958  state->rstate.stage = 0;
21959  goto lbl_rcomm;
21960 lbl_0:
21961  ae_v_move(&state->fm1.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,m-1));
21962  ae_v_move(&state->gm1.ptr.p_double[0], 1, &state->j.ptr.pp_double[0][i], state->j.stride, ae_v_len(0,m-1));
21963  state->x.ptr.p_double[i] = v+state->teststep*state->s.ptr.p_double[i];
21964  if( state->havebndu.ptr.p_bool[i] )
21965  {
21966  state->x.ptr.p_double[i] = ae_minreal(state->x.ptr.p_double[i], state->bndu.ptr.p_double[i], _state);
21967  }
21968  state->xp1 = state->x.ptr.p_double[i];
21969  state->rstate.stage = 1;
21970  goto lbl_rcomm;
21971 lbl_1:
21972  ae_v_move(&state->fp1.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,m-1));
21973  ae_v_move(&state->gp1.ptr.p_double[0], 1, &state->j.ptr.pp_double[0][i], state->j.stride, ae_v_len(0,m-1));
21974  state->x.ptr.p_double[i] = (state->xm1+state->xp1)/2;
21975  if( state->havebndl.ptr.p_bool[i] )
21976  {
21977  state->x.ptr.p_double[i] = ae_maxreal(state->x.ptr.p_double[i], state->bndl.ptr.p_double[i], _state);
21978  }
21979  if( state->havebndu.ptr.p_bool[i] )
21980  {
21981  state->x.ptr.p_double[i] = ae_minreal(state->x.ptr.p_double[i], state->bndu.ptr.p_double[i], _state);
21982  }
21983  state->rstate.stage = 2;
21984  goto lbl_rcomm;
21985 lbl_2:
21986  ae_v_move(&state->fc1.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,m-1));
21987  ae_v_move(&state->gc1.ptr.p_double[0], 1, &state->j.ptr.pp_double[0][i], state->j.stride, ae_v_len(0,m-1));
21988  state->x.ptr.p_double[i] = v;
21989  for(k=0; k<=m-1; k++)
21990  {
21991  if( !derivativecheck(state->fm1.ptr.p_double[k], state->gm1.ptr.p_double[k], state->fp1.ptr.p_double[k], state->gp1.ptr.p_double[k], state->fc1.ptr.p_double[k], state->gc1.ptr.p_double[k], state->xp1-state->xm1, _state) )
21992  {
21993  state->repfuncidx = k;
21994  state->repvaridx = i;
21995  state->repterminationtype = -7;
21996  result = ae_false;
21997  return result;
21998  }
21999  }
22000  i = i+1;
22001  goto lbl_21;
22002 lbl_23:
22003  state->needfij = ae_false;
22004 lbl_19:
22005 
22006  /*
22007  * Initial report of current point
22008  *
22009  * Note 1: we rewrite State.X twice because
22010  * user may accidentally change it after first call.
22011  *
22012  * Note 2: we set NeedF or NeedFI depending on what
22013  * information about function we have.
22014  */
22015  if( !state->xrep )
22016  {
22017  goto lbl_24;
22018  }
22019  ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
22020  minlm_clearrequestfields(state, _state);
22021  if( !state->hasf )
22022  {
22023  goto lbl_26;
22024  }
22025  state->needf = ae_true;
22026  state->rstate.stage = 3;
22027  goto lbl_rcomm;
22028 lbl_3:
22029  state->needf = ae_false;
22030  goto lbl_27;
22031 lbl_26:
22032  ae_assert(state->hasfi, "MinLM: internal error 2!", _state);
22033  state->needfi = ae_true;
22034  state->rstate.stage = 4;
22035  goto lbl_rcomm;
22036 lbl_4:
22037  state->needfi = ae_false;
22038  v = ae_v_dotproduct(&state->fi.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,m-1));
22039  state->f = v;
22040 lbl_27:
22041  state->repnfunc = state->repnfunc+1;
22042  ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
22043  minlm_clearrequestfields(state, _state);
22044  state->xupdated = ae_true;
22045  state->rstate.stage = 5;
22046  goto lbl_rcomm;
22047 lbl_5:
22048  state->xupdated = ae_false;
22049 lbl_24:
22050 
22051  /*
22052  * Prepare control variables
22053  */
22054  state->nu = 1;
22055  state->lambdav = -ae_maxrealnumber;
22056  state->modelage = state->maxmodelage+1;
22057  state->deltaxready = ae_false;
22058  state->deltafready = ae_false;
22059 
22060  /*
22061  * Main cycle.
22062  *
22063  * We move through it until either:
22064  * * one of the stopping conditions is met
22065  * * we decide that stopping conditions are too stringent
22066  * and break from cycle
22067  *
22068  */
22069 lbl_28:
22070  if( ae_false )
22071  {
22072  goto lbl_29;
22073  }
22074 
22075  /*
22076  * First, we have to prepare quadratic model for our function.
22077  * We use BFlag to ensure that model is prepared;
22078  * if it is false at the end of this block, something went wrong.
22079  *
22080  * We may either calculate brand new model or update old one.
22081  *
22082  * Before this block we have:
22083  * * State.XBase - current position.
22084  * * State.DeltaX - if DeltaXReady is True
22085  * * State.DeltaF - if DeltaFReady is True
22086  *
22087  * After this block is over, we will have:
22088  * * State.XBase - base point (unchanged)
22089  * * State.FBase - F(XBase)
22090  * * State.GBase - linear term
22091  * * State.QuadraticModel - quadratic term
22092  * * State.LambdaV - current estimate for lambda
22093  *
22094  * We also clear DeltaXReady/DeltaFReady flags
22095  * after initialization is done.
22096  */
22097  bflag = ae_false;
22098  if( !(state->algomode==0||state->algomode==1) )
22099  {
22100  goto lbl_30;
22101  }
22102 
22103  /*
22104  * Calculate f[] and Jacobian
22105  */
22106  if( !(state->modelage>state->maxmodelage||!(state->deltaxready&&state->deltafready)) )
22107  {
22108  goto lbl_32;
22109  }
22110 
22111  /*
22112  * Refresh model (using either finite differences or analytic Jacobian)
22113  */
22114  if( state->algomode!=0 )
22115  {
22116  goto lbl_34;
22117  }
22118 
22119  /*
22120  * Optimization using F values only.
22121  * Use finite differences to estimate Jacobian.
22122  */
22123  ae_assert(state->hasfi, "MinLMIteration: internal error when estimating Jacobian (no f[])", _state);
22124  k = 0;
22125 lbl_36:
22126  if( k>n-1 )
22127  {
22128  goto lbl_38;
22129  }
22130 
22131  /*
22132  * We guard X[k] from leaving [BndL,BndU].
22133  * In case BndL=BndU, we assume that derivative in this direction is zero.
22134  */
22135  ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
22136  state->x.ptr.p_double[k] = state->x.ptr.p_double[k]-state->s.ptr.p_double[k]*state->diffstep;
22137  if( state->havebndl.ptr.p_bool[k] )
22138  {
22139  state->x.ptr.p_double[k] = ae_maxreal(state->x.ptr.p_double[k], state->bndl.ptr.p_double[k], _state);
22140  }
22141  if( state->havebndu.ptr.p_bool[k] )
22142  {
22143  state->x.ptr.p_double[k] = ae_minreal(state->x.ptr.p_double[k], state->bndu.ptr.p_double[k], _state);
22144  }
22145  state->xm1 = state->x.ptr.p_double[k];
22146  minlm_clearrequestfields(state, _state);
22147  state->needfi = ae_true;
22148  state->rstate.stage = 6;
22149  goto lbl_rcomm;
22150 lbl_6:
22151  state->repnfunc = state->repnfunc+1;
22152  ae_v_move(&state->fm1.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,m-1));
22153  ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
22154  state->x.ptr.p_double[k] = state->x.ptr.p_double[k]+state->s.ptr.p_double[k]*state->diffstep;
22155  if( state->havebndl.ptr.p_bool[k] )
22156  {
22157  state->x.ptr.p_double[k] = ae_maxreal(state->x.ptr.p_double[k], state->bndl.ptr.p_double[k], _state);
22158  }
22159  if( state->havebndu.ptr.p_bool[k] )
22160  {
22161  state->x.ptr.p_double[k] = ae_minreal(state->x.ptr.p_double[k], state->bndu.ptr.p_double[k], _state);
22162  }
22163  state->xp1 = state->x.ptr.p_double[k];
22164  minlm_clearrequestfields(state, _state);
22165  state->needfi = ae_true;
22166  state->rstate.stage = 7;
22167  goto lbl_rcomm;
22168 lbl_7:
22169  state->repnfunc = state->repnfunc+1;
22170  ae_v_move(&state->fp1.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,m-1));
22171  v = state->xp1-state->xm1;
22172  if( ae_fp_neq(v,0) )
22173  {
22174  v = 1/v;
22175  ae_v_moved(&state->j.ptr.pp_double[0][k], state->j.stride, &state->fp1.ptr.p_double[0], 1, ae_v_len(0,m-1), v);
22176  ae_v_subd(&state->j.ptr.pp_double[0][k], state->j.stride, &state->fm1.ptr.p_double[0], 1, ae_v_len(0,m-1), v);
22177  }
22178  else
22179  {
22180  for(i=0; i<=m-1; i++)
22181  {
22182  state->j.ptr.pp_double[i][k] = 0;
22183  }
22184  }
22185  k = k+1;
22186  goto lbl_36;
22187 lbl_38:
22188 
22189  /*
22190  * Calculate F(XBase)
22191  */
22192  ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
22193  minlm_clearrequestfields(state, _state);
22194  state->needfi = ae_true;
22195  state->rstate.stage = 8;
22196  goto lbl_rcomm;
22197 lbl_8:
22198  state->needfi = ae_false;
22199  state->repnfunc = state->repnfunc+1;
22200  state->repnjac = state->repnjac+1;
22201 
22202  /*
22203  * New model
22204  */
22205  state->modelage = 0;
22206  goto lbl_35;
22207 lbl_34:
22208 
22209  /*
22210  * Obtain f[] and Jacobian
22211  */
22212  ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
22213  minlm_clearrequestfields(state, _state);
22214  state->needfij = ae_true;
22215  state->rstate.stage = 9;
22216  goto lbl_rcomm;
22217 lbl_9:
22218  state->needfij = ae_false;
22219  state->repnfunc = state->repnfunc+1;
22220  state->repnjac = state->repnjac+1;
22221 
22222  /*
22223  * New model
22224  */
22225  state->modelage = 0;
22226 lbl_35:
22227  goto lbl_33;
22228 lbl_32:
22229 
22230  /*
22231  * State.J contains Jacobian or its current approximation;
22232  * refresh it using secant updates:
22233  *
22234  * f(x0+dx) = f(x0) + J*dx,
22235  * J_new = J_old + u*h'
22236  * h = x_new-x_old
22237  * u = (f_new - f_old - J_old*h)/(h'h)
22238  *
22239  * We can explicitly generate h and u, but it is
22240  * preferential to do in-place calculations. Only
22241  * I-th row of J_old is needed to calculate u[I],
22242  * so we can update J row by row in one pass.
22243  *
22244  * NOTE: we expect that State.XBase contains new point,
22245  * State.FBase contains old point, State.DeltaX and
22246  * State.DeltaY contain updates from last step.
22247  */
22248  ae_assert(state->deltaxready&&state->deltafready, "MinLMIteration: uninitialized DeltaX/DeltaF", _state);
22249  t = ae_v_dotproduct(&state->deltax.ptr.p_double[0], 1, &state->deltax.ptr.p_double[0], 1, ae_v_len(0,n-1));
22250  ae_assert(ae_fp_neq(t,0), "MinLM: internal error (T=0)", _state);
22251  for(i=0; i<=m-1; i++)
22252  {
22253  v = ae_v_dotproduct(&state->j.ptr.pp_double[i][0], 1, &state->deltax.ptr.p_double[0], 1, ae_v_len(0,n-1));
22254  v = (state->deltaf.ptr.p_double[i]-v)/t;
22255  ae_v_addd(&state->j.ptr.pp_double[i][0], 1, &state->deltax.ptr.p_double[0], 1, ae_v_len(0,n-1), v);
22256  }
22257  ae_v_move(&state->fi.ptr.p_double[0], 1, &state->fibase.ptr.p_double[0], 1, ae_v_len(0,m-1));
22258  ae_v_add(&state->fi.ptr.p_double[0], 1, &state->deltaf.ptr.p_double[0], 1, ae_v_len(0,m-1));
22259 
22260  /*
22261  * Increase model age
22262  */
22263  state->modelage = state->modelage+1;
22264 lbl_33:
22265 
22266  /*
22267  * Generate quadratic model:
22268  * f(xbase+dx) =
22269  * = (f0 + J*dx)'(f0 + J*dx)
22270  * = f0^2 + dx'J'f0 + f0*J*dx + dx'J'J*dx
22271  * = f0^2 + 2*f0*J*dx + dx'J'J*dx
22272  *
22273  * Note that we calculate 2*(J'J) instead of J'J because
22274  * our quadratic model is based on Tailor decomposition,
22275  * i.e. it has 0.5 before quadratic term.
22276  */
22277  rmatrixgemm(n, n, m, 2.0, &state->j, 0, 0, 1, &state->j, 0, 0, 0, 0.0, &state->quadraticmodel, 0, 0, _state);
22278  rmatrixmv(n, m, &state->j, 0, 0, 1, &state->fi, 0, &state->gbase, 0, _state);
22279  ae_v_muld(&state->gbase.ptr.p_double[0], 1, ae_v_len(0,n-1), 2);
22280  v = ae_v_dotproduct(&state->fi.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,m-1));
22281  state->fbase = v;
22282  ae_v_move(&state->fibase.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,m-1));
22283 
22284  /*
22285  * set control variables
22286  */
22287  bflag = ae_true;
22288 lbl_30:
22289  if( state->algomode!=2 )
22290  {
22291  goto lbl_39;
22292  }
22293  ae_assert(!state->hasfi, "MinLMIteration: internal error (HasFI is True in Hessian-based mode)", _state);
22294 
22295  /*
22296  * Obtain F, G, H
22297  */
22298  ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
22299  minlm_clearrequestfields(state, _state);
22300  state->needfgh = ae_true;
22301  state->rstate.stage = 10;
22302  goto lbl_rcomm;
22303 lbl_10:
22304  state->needfgh = ae_false;
22305  state->repnfunc = state->repnfunc+1;
22306  state->repngrad = state->repngrad+1;
22307  state->repnhess = state->repnhess+1;
22308  rmatrixcopy(n, n, &state->h, 0, 0, &state->quadraticmodel, 0, 0, _state);
22309  ae_v_move(&state->gbase.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1));
22310  state->fbase = state->f;
22311 
22312  /*
22313  * set control variables
22314  */
22315  bflag = ae_true;
22316  state->modelage = 0;
22317 lbl_39:
22318  ae_assert(bflag, "MinLM: internal integrity check failed!", _state);
22319  state->deltaxready = ae_false;
22320  state->deltafready = ae_false;
22321 
22322  /*
22323  * If Lambda is not initialized, initialize it using quadratic model
22324  */
22325  if( ae_fp_less(state->lambdav,0) )
22326  {
22327  state->lambdav = 0;
22328  for(i=0; i<=n-1; i++)
22329  {
22330  state->lambdav = ae_maxreal(state->lambdav, ae_fabs(state->quadraticmodel.ptr.pp_double[i][i], _state)*ae_sqr(state->s.ptr.p_double[i], _state), _state);
22331  }
22332  state->lambdav = 0.001*state->lambdav;
22333  if( ae_fp_eq(state->lambdav,0) )
22334  {
22335  state->lambdav = 1;
22336  }
22337  }
22338 
22339  /*
22340  * Test stopping conditions for function gradient
22341  */
22342  if( ae_fp_greater(minlm_boundedscaledantigradnorm(state, &state->xbase, &state->gbase, _state),state->epsg) )
22343  {
22344  goto lbl_41;
22345  }
22346  if( state->modelage!=0 )
22347  {
22348  goto lbl_43;
22349  }
22350 
22351  /*
22352  * Model is fresh, we can rely on it and terminate algorithm
22353  */
22354  state->repterminationtype = 4;
22355  if( !state->xrep )
22356  {
22357  goto lbl_45;
22358  }
22359  ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
22360  state->f = state->fbase;
22361  minlm_clearrequestfields(state, _state);
22362  state->xupdated = ae_true;
22363  state->rstate.stage = 11;
22364  goto lbl_rcomm;
22365 lbl_11:
22366  state->xupdated = ae_false;
22367 lbl_45:
22368  result = ae_false;
22369  return result;
22370  goto lbl_44;
22371 lbl_43:
22372 
22373  /*
22374  * Model is not fresh, we should refresh it and test
22375  * conditions once more
22376  */
22377  state->modelage = state->maxmodelage+1;
22378  goto lbl_28;
22379 lbl_44:
22380 lbl_41:
22381 
22382  /*
22383  * Find value of Levenberg-Marquardt damping parameter which:
22384  * * leads to positive definite damped model
22385  * * within bounds specified by StpMax
22386  * * generates step which decreases function value
22387  *
22388  * After this block IFlag is set to:
22389  * * -3, if constraints are infeasible
22390  * * -2, if model update is needed (either Lambda growth is too large
22391  * or step is too short, but we can't rely on model and stop iterations)
22392  * * -1, if model is fresh, Lambda have grown too large, termination is needed
22393  * * 0, if everything is OK, continue iterations
22394  *
22395  * State.Nu can have any value on enter, but after exit it is set to 1.0
22396  */
22397  iflag = -99;
22398 lbl_47:
22399  if( ae_false )
22400  {
22401  goto lbl_48;
22402  }
22403 
22404  /*
22405  * Do we need model update?
22406  */
22407  if( state->modelage>0&&ae_fp_greater_eq(state->nu,minlm_suspiciousnu) )
22408  {
22409  iflag = -2;
22410  goto lbl_48;
22411  }
22412 
22413  /*
22414  * Setup quadratic solver and solve quadratic programming problem.
22415  * After problem is solved we'll try to bound step by StpMax
22416  * (Lambda will be increased if step size is too large).
22417  *
22418  * We use BFlag variable to indicate that we have to increase Lambda.
22419  * If it is False, we will try to increase Lambda and move to new iteration.
22420  */
22421  bflag = ae_true;
22422  minqpsetstartingpointfast(&state->qpstate, &state->xbase, _state);
22423  minqpsetoriginfast(&state->qpstate, &state->xbase, _state);
22424  minqpsetlineartermfast(&state->qpstate, &state->gbase, _state);
22425  minqpsetquadratictermfast(&state->qpstate, &state->quadraticmodel, ae_true, 0.0, _state);
22426  for(i=0; i<=n-1; i++)
22427  {
22428  state->tmp0.ptr.p_double[i] = state->quadraticmodel.ptr.pp_double[i][i]+state->lambdav/ae_sqr(state->s.ptr.p_double[i], _state);
22429  }
22430  minqprewritediagonal(&state->qpstate, &state->tmp0, _state);
22431  minqpoptimize(&state->qpstate, _state);
22432  minqpresultsbuf(&state->qpstate, &state->xdir, &state->qprep, _state);
22433  if( state->qprep.terminationtype>0 )
22434  {
22435 
22436  /*
22437  * successful solution of QP problem
22438  */
22439  ae_v_sub(&state->xdir.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
22440  v = ae_v_dotproduct(&state->xdir.ptr.p_double[0], 1, &state->xdir.ptr.p_double[0], 1, ae_v_len(0,n-1));
22441  if( ae_isfinite(v, _state) )
22442  {
22443  v = ae_sqrt(v, _state);
22444  if( ae_fp_greater(state->stpmax,0)&&ae_fp_greater(v,state->stpmax) )
22445  {
22446  bflag = ae_false;
22447  }
22448  }
22449  else
22450  {
22451  bflag = ae_false;
22452  }
22453  }
22454  else
22455  {
22456 
22457  /*
22458  * Either problem is non-convex (increase LambdaV) or constraints are inconsistent
22459  */
22460  ae_assert(state->qprep.terminationtype==-3||state->qprep.terminationtype==-5, "MinLM: unexpected completion code from QP solver", _state);
22461  if( state->qprep.terminationtype==-3 )
22462  {
22463  iflag = -3;
22464  goto lbl_48;
22465  }
22466  bflag = ae_false;
22467  }
22468  if( !bflag )
22469  {
22470 
22471  /*
22472  * Solution failed:
22473  * try to increase lambda to make matrix positive definite and continue.
22474  */
22475  if( !minlm_increaselambda(&state->lambdav, &state->nu, _state) )
22476  {
22477  iflag = -1;
22478  goto lbl_48;
22479  }
22480  goto lbl_47;
22481  }
22482 
22483  /*
22484  * Step in State.XDir and it is bounded by StpMax.
22485  *
22486  * We should check stopping conditions on step size here.
22487  * DeltaX, which is used for secant updates, is initialized here.
22488  *
22489  * This code is a bit tricky because sometimes XDir<>0, but
22490  * it is so small that XDir+XBase==XBase (in finite precision
22491  * arithmetics). So we set DeltaX to XBase, then
22492  * add XDir, and then subtract XBase to get exact value of
22493  * DeltaX.
22494  *
22495  * Step length is estimated using DeltaX.
22496  *
22497  * NOTE: stopping conditions are tested
22498  * for fresh models only (ModelAge=0)
22499  */
22500  ae_v_move(&state->deltax.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
22501  ae_v_add(&state->deltax.ptr.p_double[0], 1, &state->xdir.ptr.p_double[0], 1, ae_v_len(0,n-1));
22502  ae_v_sub(&state->deltax.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
22503  state->deltaxready = ae_true;
22504  v = 0.0;
22505  for(i=0; i<=n-1; i++)
22506  {
22507  v = v+ae_sqr(state->deltax.ptr.p_double[i]/state->s.ptr.p_double[i], _state);
22508  }
22509  v = ae_sqrt(v, _state);
22510  if( ae_fp_greater(v,state->epsx) )
22511  {
22512  goto lbl_49;
22513  }
22514  if( state->modelage!=0 )
22515  {
22516  goto lbl_51;
22517  }
22518 
22519  /*
22520  * Step is too short, model is fresh and we can rely on it.
22521  * Terminating.
22522  */
22523  state->repterminationtype = 2;
22524  if( !state->xrep )
22525  {
22526  goto lbl_53;
22527  }
22528  ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
22529  state->f = state->fbase;
22530  minlm_clearrequestfields(state, _state);
22531  state->xupdated = ae_true;
22532  state->rstate.stage = 12;
22533  goto lbl_rcomm;
22534 lbl_12:
22535  state->xupdated = ae_false;
22536 lbl_53:
22537  result = ae_false;
22538  return result;
22539  goto lbl_52;
22540 lbl_51:
22541 
22542  /*
22543  * Step is suspiciously short, but model is not fresh
22544  * and we can't rely on it.
22545  */
22546  iflag = -2;
22547  goto lbl_48;
22548 lbl_52:
22549 lbl_49:
22550 
22551  /*
22552  * Let's evaluate new step:
22553  * a) if we have Fi vector, we evaluate it using rcomm, and
22554  * then we manually calculate State.F as sum of squares of Fi[]
22555  * b) if we have F value, we just evaluate it through rcomm interface
22556  *
22557  * We prefer (a) because we may need Fi vector for additional
22558  * iterations
22559  */
22560  ae_assert(state->hasfi||state->hasf, "MinLM: internal error 2!", _state);
22561  ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
22562  ae_v_add(&state->x.ptr.p_double[0], 1, &state->xdir.ptr.p_double[0], 1, ae_v_len(0,n-1));
22563  minlm_clearrequestfields(state, _state);
22564  if( !state->hasfi )
22565  {
22566  goto lbl_55;
22567  }
22568  state->needfi = ae_true;
22569  state->rstate.stage = 13;
22570  goto lbl_rcomm;
22571 lbl_13:
22572  state->needfi = ae_false;
22573  v = ae_v_dotproduct(&state->fi.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,m-1));
22574  state->f = v;
22575  ae_v_move(&state->deltaf.ptr.p_double[0], 1, &state->fi.ptr.p_double[0], 1, ae_v_len(0,m-1));
22576  ae_v_sub(&state->deltaf.ptr.p_double[0], 1, &state->fibase.ptr.p_double[0], 1, ae_v_len(0,m-1));
22577  state->deltafready = ae_true;
22578  goto lbl_56;
22579 lbl_55:
22580  state->needf = ae_true;
22581  state->rstate.stage = 14;
22582  goto lbl_rcomm;
22583 lbl_14:
22584  state->needf = ae_false;
22585 lbl_56:
22586  state->repnfunc = state->repnfunc+1;
22587  if( ae_fp_greater_eq(state->f,state->fbase) )
22588  {
22589 
22590  /*
22591  * Increase lambda and continue
22592  */
22593  if( !minlm_increaselambda(&state->lambdav, &state->nu, _state) )
22594  {
22595  iflag = -1;
22596  goto lbl_48;
22597  }
22598  goto lbl_47;
22599  }
22600 
22601  /*
22602  * We've found our step!
22603  */
22604  iflag = 0;
22605  goto lbl_48;
22606  goto lbl_47;
22607 lbl_48:
22608  state->nu = 1;
22609  ae_assert(iflag>=-3&&iflag<=0, "MinLM: internal integrity check failed!", _state);
22610  if( iflag==-3 )
22611  {
22612  state->repterminationtype = -3;
22613  result = ae_false;
22614  return result;
22615  }
22616  if( iflag==-2 )
22617  {
22618  state->modelage = state->maxmodelage+1;
22619  goto lbl_28;
22620  }
22621  if( iflag==-1 )
22622  {
22623  goto lbl_29;
22624  }
22625 
22626  /*
22627  * Levenberg-Marquardt step is ready.
22628  * Compare predicted vs. actual decrease and decide what to do with lambda.
22629  *
22630  * NOTE: we expect that State.DeltaX contains direction of step,
22631  * State.F contains function value at new point.
22632  */
22633  ae_assert(state->deltaxready, "MinLM: deltaX is not ready", _state);
22634  t = 0;
22635  for(i=0; i<=n-1; i++)
22636  {
22637  v = ae_v_dotproduct(&state->quadraticmodel.ptr.pp_double[i][0], 1, &state->deltax.ptr.p_double[0], 1, ae_v_len(0,n-1));
22638  t = t+state->deltax.ptr.p_double[i]*state->gbase.ptr.p_double[i]+0.5*state->deltax.ptr.p_double[i]*v;
22639  }
22640  state->predicteddecrease = -t;
22641  state->actualdecrease = -(state->f-state->fbase);
22642  if( ae_fp_less_eq(state->predicteddecrease,0) )
22643  {
22644  goto lbl_29;
22645  }
22646  v = state->actualdecrease/state->predicteddecrease;
22647  if( ae_fp_greater_eq(v,0.1) )
22648  {
22649  goto lbl_57;
22650  }
22651  if( minlm_increaselambda(&state->lambdav, &state->nu, _state) )
22652  {
22653  goto lbl_59;
22654  }
22655 
22656  /*
22657  * Lambda is too large, we have to break iterations.
22658  */
22659  state->repterminationtype = 7;
22660  if( !state->xrep )
22661  {
22662  goto lbl_61;
22663  }
22664  ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
22665  state->f = state->fbase;
22666  minlm_clearrequestfields(state, _state);
22667  state->xupdated = ae_true;
22668  state->rstate.stage = 15;
22669  goto lbl_rcomm;
22670 lbl_15:
22671  state->xupdated = ae_false;
22672 lbl_61:
22673  result = ae_false;
22674  return result;
22675 lbl_59:
22676 lbl_57:
22677  if( ae_fp_greater(v,0.5) )
22678  {
22679  minlm_decreaselambda(&state->lambdav, &state->nu, _state);
22680  }
22681 
22682  /*
22683  * Accept step, report it and
22684  * test stopping conditions on iterations count and function decrease.
22685  *
22686  * NOTE: we expect that State.DeltaX contains direction of step,
22687  * State.F contains function value at new point.
22688  *
22689  * NOTE2: we should update XBase ONLY. In the beginning of the next
22690  * iteration we expect that State.FIBase is NOT updated and
22691  * contains old value of a function vector.
22692  */
22693  ae_v_add(&state->xbase.ptr.p_double[0], 1, &state->deltax.ptr.p_double[0], 1, ae_v_len(0,n-1));
22694  if( !state->xrep )
22695  {
22696  goto lbl_63;
22697  }
22698  ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
22699  minlm_clearrequestfields(state, _state);
22700  state->xupdated = ae_true;
22701  state->rstate.stage = 16;
22702  goto lbl_rcomm;
22703 lbl_16:
22704  state->xupdated = ae_false;
22705 lbl_63:
22706  state->repiterationscount = state->repiterationscount+1;
22707  if( state->repiterationscount>=state->maxits&&state->maxits>0 )
22708  {
22709  state->repterminationtype = 5;
22710  }
22711  if( state->modelage==0 )
22712  {
22713  if( ae_fp_less_eq(ae_fabs(state->f-state->fbase, _state),state->epsf*ae_maxreal(1, ae_maxreal(ae_fabs(state->f, _state), ae_fabs(state->fbase, _state), _state), _state)) )
22714  {
22715  state->repterminationtype = 1;
22716  }
22717  }
22718  if( state->repterminationtype<=0 )
22719  {
22720  goto lbl_65;
22721  }
22722  if( !state->xrep )
22723  {
22724  goto lbl_67;
22725  }
22726 
22727  /*
22728  * Report: XBase contains new point, F contains function value at new point
22729  */
22730  ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
22731  minlm_clearrequestfields(state, _state);
22732  state->xupdated = ae_true;
22733  state->rstate.stage = 17;
22734  goto lbl_rcomm;
22735 lbl_17:
22736  state->xupdated = ae_false;
22737 lbl_67:
22738  result = ae_false;
22739  return result;
22740 lbl_65:
22741  state->modelage = state->modelage+1;
22742  goto lbl_28;
22743 lbl_29:
22744 
22745  /*
22746  * Lambda is too large, we have to break iterations.
22747  */
22748  state->repterminationtype = 7;
22749  if( !state->xrep )
22750  {
22751  goto lbl_69;
22752  }
22753  ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
22754  state->f = state->fbase;
22755  minlm_clearrequestfields(state, _state);
22756  state->xupdated = ae_true;
22757  state->rstate.stage = 18;
22758  goto lbl_rcomm;
22759 lbl_18:
22760  state->xupdated = ae_false;
22761 lbl_69:
22762  result = ae_false;
22763  return result;
22764 
22765  /*
22766  * Saving state
22767  */
22768 lbl_rcomm:
22769  result = ae_true;
22770  state->rstate.ia.ptr.p_int[0] = n;
22771  state->rstate.ia.ptr.p_int[1] = m;
22772  state->rstate.ia.ptr.p_int[2] = iflag;
22773  state->rstate.ia.ptr.p_int[3] = i;
22774  state->rstate.ia.ptr.p_int[4] = k;
22775  state->rstate.ba.ptr.p_bool[0] = bflag;
22776  state->rstate.ra.ptr.p_double[0] = v;
22777  state->rstate.ra.ptr.p_double[1] = s;
22778  state->rstate.ra.ptr.p_double[2] = t;
22779  return result;
22780 }
22781 
22782 
22783 /*************************************************************************
22784 Levenberg-Marquardt algorithm results
22785 
22786 INPUT PARAMETERS:
22787  State - algorithm state
22788 
22789 OUTPUT PARAMETERS:
22790  X - array[0..N-1], solution
22791  Rep - optimization report;
22792  see comments for this structure for more info.
22793 
22794  -- ALGLIB --
22795  Copyright 10.03.2009 by Bochkanov Sergey
22796 *************************************************************************/
22797 void minlmresults(minlmstate* state,
22798  /* Real */ ae_vector* x,
22799  minlmreport* rep,
22800  ae_state *_state)
22801 {
22802 
22803  ae_vector_clear(x);
22804  _minlmreport_clear(rep);
22805 
22806  minlmresultsbuf(state, x, rep, _state);
22807 }
22808 
22809 
22810 /*************************************************************************
22811 Levenberg-Marquardt algorithm results
22812 
22813 Buffered implementation of MinLMResults(), which uses pre-allocated buffer
22814 to store X[]. If buffer size is too small, it resizes buffer. It is
22815 intended to be used in the inner cycles of performance critical algorithms
22816 where array reallocation penalty is too large to be ignored.
22817 
22818  -- ALGLIB --
22819  Copyright 10.03.2009 by Bochkanov Sergey
22820 *************************************************************************/
22821 void minlmresultsbuf(minlmstate* state,
22822  /* Real */ ae_vector* x,
22823  minlmreport* rep,
22824  ae_state *_state)
22825 {
22826 
22827 
22828  if( x->cnt<state->n )
22829  {
22830  ae_vector_set_length(x, state->n, _state);
22831  }
22832  ae_v_move(&x->ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,state->n-1));
22833  rep->iterationscount = state->repiterationscount;
22834  rep->terminationtype = state->repterminationtype;
22835  rep->funcidx = state->repfuncidx;
22836  rep->varidx = state->repvaridx;
22837  rep->nfunc = state->repnfunc;
22838  rep->njac = state->repnjac;
22839  rep->ngrad = state->repngrad;
22840  rep->nhess = state->repnhess;
22841  rep->ncholesky = state->repncholesky;
22842 }
22843 
22844 
22845 /*************************************************************************
22846 This subroutine restarts LM algorithm from new point. All optimization
22847 parameters are left unchanged.
22848 
22849 This function allows to solve multiple optimization problems (which
22850 must have same number of dimensions) without object reallocation penalty.
22851 
22852 INPUT PARAMETERS:
22853  State - structure used for reverse communication previously
22854  allocated with MinLMCreateXXX call.
22855  X - new starting point.
22856 
22857  -- ALGLIB --
22858  Copyright 30.07.2010 by Bochkanov Sergey
22859 *************************************************************************/
22860 void minlmrestartfrom(minlmstate* state,
22861  /* Real */ ae_vector* x,
22862  ae_state *_state)
22863 {
22864 
22865 
22866  ae_assert(x->cnt>=state->n, "MinLMRestartFrom: Length(X)<N!", _state);
22867  ae_assert(isfinitevector(x, state->n, _state), "MinLMRestartFrom: X contains infinite or NaN values!", _state);
22868  ae_v_move(&state->xbase.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,state->n-1));
22869  ae_vector_set_length(&state->rstate.ia, 4+1, _state);
22870  ae_vector_set_length(&state->rstate.ba, 0+1, _state);
22871  ae_vector_set_length(&state->rstate.ra, 2+1, _state);
22872  state->rstate.stage = -1;
22873  minlm_clearrequestfields(state, _state);
22874 }
22875 
22876 
22877 /*************************************************************************
22878 This is obsolete function.
22879 
22880 Since ALGLIB 3.3 it is equivalent to MinLMCreateVJ().
22881 
22882  -- ALGLIB --
22883  Copyright 30.03.2009 by Bochkanov Sergey
22884 *************************************************************************/
22885 void minlmcreatevgj(ae_int_t n,
22886  ae_int_t m,
22887  /* Real */ ae_vector* x,
22888  minlmstate* state,
22889  ae_state *_state)
22890 {
22891 
22892  _minlmstate_clear(state);
22893 
22894  minlmcreatevj(n, m, x, state, _state);
22895 }
22896 
22897 
22898 /*************************************************************************
22899 This is obsolete function.
22900 
22901 Since ALGLIB 3.3 it is equivalent to MinLMCreateFJ().
22902 
22903  -- ALGLIB --
22904  Copyright 30.03.2009 by Bochkanov Sergey
22905 *************************************************************************/
22906 void minlmcreatefgj(ae_int_t n,
22907  ae_int_t m,
22908  /* Real */ ae_vector* x,
22909  minlmstate* state,
22910  ae_state *_state)
22911 {
22912 
22913  _minlmstate_clear(state);
22914 
22915  minlmcreatefj(n, m, x, state, _state);
22916 }
22917 
22918 
22919 /*************************************************************************
22920 This function is considered obsolete since ALGLIB 3.1.0 and is present for
22921 backward compatibility only. We recommend to use MinLMCreateVJ, which
22922 provides similar, but more consistent and feature-rich interface.
22923 
22924  -- ALGLIB --
22925  Copyright 30.03.2009 by Bochkanov Sergey
22926 *************************************************************************/
22927 void minlmcreatefj(ae_int_t n,
22928  ae_int_t m,
22929  /* Real */ ae_vector* x,
22930  minlmstate* state,
22931  ae_state *_state)
22932 {
22933 
22934  _minlmstate_clear(state);
22935 
22936  ae_assert(n>=1, "MinLMCreateFJ: N<1!", _state);
22937  ae_assert(m>=1, "MinLMCreateFJ: M<1!", _state);
22938  ae_assert(x->cnt>=n, "MinLMCreateFJ: Length(X)<N!", _state);
22939  ae_assert(isfinitevector(x, n, _state), "MinLMCreateFJ: X contains infinite or NaN values!", _state);
22940 
22941  /*
22942  * initialize
22943  */
22944  state->teststep = 0;
22945  state->n = n;
22946  state->m = m;
22947  state->algomode = 1;
22948  state->hasf = ae_true;
22949  state->hasfi = ae_false;
22950  state->hasg = ae_false;
22951 
22952  /*
22953  * init 2
22954  */
22955  minlm_lmprepare(n, m, ae_true, state, _state);
22956  minlmsetacctype(state, 0, _state);
22957  minlmsetcond(state, 0, 0, 0, 0, _state);
22958  minlmsetxrep(state, ae_false, _state);
22959  minlmsetstpmax(state, 0, _state);
22960  minlmrestartfrom(state, x, _state);
22961 }
22962 
22963 
22964 /*************************************************************************
22965 This subroutine turns on verification of the user-supplied analytic
22966 gradient:
22967 * user calls this subroutine before optimization begins
22968 * MinLMOptimize() is called
22969 * prior to actual optimization, for each function Fi and each component
22970  of parameters being optimized X[j] algorithm performs following steps:
22971  * two trial steps are made to X[j]-TestStep*S[j] and X[j]+TestStep*S[j],
22972  where X[j] is j-th parameter and S[j] is a scale of j-th parameter
22973  * if needed, steps are bounded with respect to constraints on X[]
22974  * Fi(X) is evaluated at these trial points
22975  * we perform one more evaluation in the middle point of the interval
22976  * we build cubic model using function values and derivatives at trial
22977  points and we compare its prediction with actual value in the middle
22978  point
22979  * in case difference between prediction and actual value is higher than
22980  some predetermined threshold, algorithm stops with completion code -7;
22981  Rep.VarIdx is set to index of the parameter with incorrect derivative,
22982  Rep.FuncIdx is set to index of the function.
22983 * after verification is over, algorithm proceeds to the actual optimization.
22984 
22985 NOTE 1: verification needs N (parameters count) Jacobian evaluations. It
22986  is very costly and you should use it only for low dimensional
22987  problems, when you want to be sure that you've correctly
22988  calculated analytic derivatives. You should not use it in the
22989  production code (unless you want to check derivatives provided
22990  by some third party).
22991 
22992 NOTE 2: you should carefully choose TestStep. Value which is too large
22993  (so large that function behaviour is significantly non-cubic) will
22994  lead to false alarms. You may use different step for different
22995  parameters by means of setting scale with MinLMSetScale().
22996 
22997 NOTE 3: this function may lead to false positives. In case it reports that
22998  I-th derivative was calculated incorrectly, you may decrease test
22999  step and try one more time - maybe your function changes too
23000  sharply and your step is too large for such rapidly chanding
23001  function.
23002 
23003 INPUT PARAMETERS:
23004  State - structure used to store algorithm state
23005  TestStep - verification step:
23006  * TestStep=0 turns verification off
23007  * TestStep>0 activates verification
23008 
23009  -- ALGLIB --
23010  Copyright 15.06.2012 by Bochkanov Sergey
23011 *************************************************************************/
23012 void minlmsetgradientcheck(minlmstate* state,
23013  double teststep,
23014  ae_state *_state)
23015 {
23016 
23017 
23018  ae_assert(ae_isfinite(teststep, _state), "MinLMSetGradientCheck: TestStep contains NaN or Infinite", _state);
23019  ae_assert(ae_fp_greater_eq(teststep,0), "MinLMSetGradientCheck: invalid argument TestStep(TestStep<0)", _state);
23020  state->teststep = teststep;
23021 }
23022 
23023 
23024 /*************************************************************************
23025 Prepare internal structures (except for RComm).
23026 
23027 Note: M must be zero for FGH mode, non-zero for V/VJ/FJ/FGJ mode.
23028 *************************************************************************/
23029 static void minlm_lmprepare(ae_int_t n,
23030  ae_int_t m,
23031  ae_bool havegrad,
23032  minlmstate* state,
23033  ae_state *_state)
23034 {
23035  ae_int_t i;
23036 
23037 
23038  if( n<=0||m<0 )
23039  {
23040  return;
23041  }
23042  if( havegrad )
23043  {
23044  ae_vector_set_length(&state->g, n, _state);
23045  }
23046  if( m!=0 )
23047  {
23048  ae_matrix_set_length(&state->j, m, n, _state);
23049  ae_vector_set_length(&state->fi, m, _state);
23050  ae_vector_set_length(&state->fibase, m, _state);
23051  ae_vector_set_length(&state->deltaf, m, _state);
23052  ae_vector_set_length(&state->fm1, m, _state);
23053  ae_vector_set_length(&state->fp1, m, _state);
23054  ae_vector_set_length(&state->fc1, m, _state);
23055  ae_vector_set_length(&state->gm1, m, _state);
23056  ae_vector_set_length(&state->gp1, m, _state);
23057  ae_vector_set_length(&state->gc1, m, _state);
23058  }
23059  else
23060  {
23061  ae_matrix_set_length(&state->h, n, n, _state);
23062  }
23063  ae_vector_set_length(&state->x, n, _state);
23064  ae_vector_set_length(&state->deltax, n, _state);
23065  ae_matrix_set_length(&state->quadraticmodel, n, n, _state);
23066  ae_vector_set_length(&state->xbase, n, _state);
23067  ae_vector_set_length(&state->gbase, n, _state);
23068  ae_vector_set_length(&state->xdir, n, _state);
23069  ae_vector_set_length(&state->tmp0, n, _state);
23070 
23071  /*
23072  * prepare internal L-BFGS
23073  */
23074  for(i=0; i<=n-1; i++)
23075  {
23076  state->x.ptr.p_double[i] = 0;
23077  }
23078  minlbfgscreate(n, ae_minint(minlm_additers, n, _state), &state->x, &state->internalstate, _state);
23079  minlbfgssetcond(&state->internalstate, 0.0, 0.0, 0.0, ae_minint(minlm_additers, n, _state), _state);
23080 
23081  /*
23082  * Prepare internal QP solver
23083  */
23084  minqpcreate(n, &state->qpstate, _state);
23085  minqpsetalgocholesky(&state->qpstate, _state);
23086 
23087  /*
23088  * Prepare boundary constraints
23089  */
23090  ae_vector_set_length(&state->bndl, n, _state);
23091  ae_vector_set_length(&state->bndu, n, _state);
23092  ae_vector_set_length(&state->havebndl, n, _state);
23093  ae_vector_set_length(&state->havebndu, n, _state);
23094  for(i=0; i<=n-1; i++)
23095  {
23096  state->bndl.ptr.p_double[i] = _state->v_neginf;
23097  state->havebndl.ptr.p_bool[i] = ae_false;
23098  state->bndu.ptr.p_double[i] = _state->v_posinf;
23099  state->havebndu.ptr.p_bool[i] = ae_false;
23100  }
23101 
23102  /*
23103  * Prepare scaling matrix
23104  */
23105  ae_vector_set_length(&state->s, n, _state);
23106  for(i=0; i<=n-1; i++)
23107  {
23108  state->s.ptr.p_double[i] = 1.0;
23109  }
23110 }
23111 
23112 
23113 /*************************************************************************
23114 Clears request fileds (to be sure that we don't forgot to clear something)
23115 *************************************************************************/
23116 static void minlm_clearrequestfields(minlmstate* state, ae_state *_state)
23117 {
23118 
23119 
23120  state->needf = ae_false;
23121  state->needfg = ae_false;
23122  state->needfgh = ae_false;
23123  state->needfij = ae_false;
23124  state->needfi = ae_false;
23125  state->xupdated = ae_false;
23126 }
23127 
23128 
23129 /*************************************************************************
23130 Increases lambda, returns False when there is a danger of overflow
23131 *************************************************************************/
23132 static ae_bool minlm_increaselambda(double* lambdav,
23133  double* nu,
23134  ae_state *_state)
23135 {
23136  double lnlambda;
23137  double lnnu;
23138  double lnlambdaup;
23139  double lnmax;
23140  ae_bool result;
23141 
23142 
23143  result = ae_false;
23144  lnlambda = ae_log(*lambdav, _state);
23145  lnlambdaup = ae_log(minlm_lambdaup, _state);
23146  lnnu = ae_log(*nu, _state);
23147  lnmax = ae_log(ae_maxrealnumber, _state);
23148  if( ae_fp_greater(lnlambda+lnlambdaup+lnnu,0.25*lnmax) )
23149  {
23150  return result;
23151  }
23152  if( ae_fp_greater(lnnu+ae_log(2, _state),lnmax) )
23153  {
23154  return result;
23155  }
23156  *lambdav = *lambdav*minlm_lambdaup*(*nu);
23157  *nu = *nu*2;
23158  result = ae_true;
23159  return result;
23160 }
23161 
23162 
23163 /*************************************************************************
23164 Decreases lambda, but leaves it unchanged when there is danger of underflow.
23165 *************************************************************************/
23166 static void minlm_decreaselambda(double* lambdav,
23167  double* nu,
23168  ae_state *_state)
23169 {
23170 
23171 
23172  *nu = 1;
23173  if( ae_fp_less(ae_log(*lambdav, _state)+ae_log(minlm_lambdadown, _state),ae_log(ae_minrealnumber, _state)) )
23174  {
23175  *lambdav = ae_minrealnumber;
23176  }
23177  else
23178  {
23179  *lambdav = *lambdav*minlm_lambdadown;
23180  }
23181 }
23182 
23183 
23184 /*************************************************************************
23185 Returns norm of bounded scaled anti-gradient.
23186 
23187 Bounded antigradient is a vector obtained from anti-gradient by zeroing
23188 components which point outwards:
23189  result = norm(v)
23190  v[i]=0 if ((-g[i]<0)and(x[i]=bndl[i])) or
23191  ((-g[i]>0)and(x[i]=bndu[i]))
23192  v[i]=-g[i]*s[i] otherwise, where s[i] is a scale for I-th variable
23193 
23194 This function may be used to check a stopping criterion.
23195 
23196  -- ALGLIB --
23197  Copyright 14.01.2011 by Bochkanov Sergey
23198 *************************************************************************/
23199 static double minlm_boundedscaledantigradnorm(minlmstate* state,
23200  /* Real */ ae_vector* x,
23201  /* Real */ ae_vector* g,
23202  ae_state *_state)
23203 {
23204  ae_int_t n;
23205  ae_int_t i;
23206  double v;
23207  double result;
23208 
23209 
23210  result = 0;
23211  n = state->n;
23212  for(i=0; i<=n-1; i++)
23213  {
23214  v = -g->ptr.p_double[i]*state->s.ptr.p_double[i];
23215  if( state->havebndl.ptr.p_bool[i] )
23216  {
23217  if( ae_fp_less_eq(x->ptr.p_double[i],state->bndl.ptr.p_double[i])&&ae_fp_less(-g->ptr.p_double[i],0) )
23218  {
23219  v = 0;
23220  }
23221  }
23222  if( state->havebndu.ptr.p_bool[i] )
23223  {
23224  if( ae_fp_greater_eq(x->ptr.p_double[i],state->bndu.ptr.p_double[i])&&ae_fp_greater(-g->ptr.p_double[i],0) )
23225  {
23226  v = 0;
23227  }
23228  }
23229  result = result+ae_sqr(v, _state);
23230  }
23231  result = ae_sqrt(result, _state);
23232  return result;
23233 }
23234 
23235 
23236 ae_bool _minlmstate_init(void* _p, ae_state *_state, ae_bool make_automatic)
23237 {
23238  minlmstate *p = (minlmstate*)_p;
23239  ae_touch_ptr((void*)p);
23240  if( !ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic) )
23241  return ae_false;
23242  if( !ae_vector_init(&p->fi, 0, DT_REAL, _state, make_automatic) )
23243  return ae_false;
23244  if( !ae_matrix_init(&p->j, 0, 0, DT_REAL, _state, make_automatic) )
23245  return ae_false;
23246  if( !ae_matrix_init(&p->h, 0, 0, DT_REAL, _state, make_automatic) )
23247  return ae_false;
23248  if( !ae_vector_init(&p->g, 0, DT_REAL, _state, make_automatic) )
23249  return ae_false;
23250  if( !ae_vector_init(&p->xbase, 0, DT_REAL, _state, make_automatic) )
23251  return ae_false;
23252  if( !ae_vector_init(&p->fibase, 0, DT_REAL, _state, make_automatic) )
23253  return ae_false;
23254  if( !ae_vector_init(&p->gbase, 0, DT_REAL, _state, make_automatic) )
23255  return ae_false;
23256  if( !ae_matrix_init(&p->quadraticmodel, 0, 0, DT_REAL, _state, make_automatic) )
23257  return ae_false;
23258  if( !ae_vector_init(&p->bndl, 0, DT_REAL, _state, make_automatic) )
23259  return ae_false;
23260  if( !ae_vector_init(&p->bndu, 0, DT_REAL, _state, make_automatic) )
23261  return ae_false;
23262  if( !ae_vector_init(&p->havebndl, 0, DT_BOOL, _state, make_automatic) )
23263  return ae_false;
23264  if( !ae_vector_init(&p->havebndu, 0, DT_BOOL, _state, make_automatic) )
23265  return ae_false;
23266  if( !ae_vector_init(&p->s, 0, DT_REAL, _state, make_automatic) )
23267  return ae_false;
23268  if( !ae_vector_init(&p->xdir, 0, DT_REAL, _state, make_automatic) )
23269  return ae_false;
23270  if( !ae_vector_init(&p->deltax, 0, DT_REAL, _state, make_automatic) )
23271  return ae_false;
23272  if( !ae_vector_init(&p->deltaf, 0, DT_REAL, _state, make_automatic) )
23273  return ae_false;
23274  if( !_rcommstate_init(&p->rstate, _state, make_automatic) )
23275  return ae_false;
23276  if( !ae_vector_init(&p->choleskybuf, 0, DT_REAL, _state, make_automatic) )
23277  return ae_false;
23278  if( !ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic) )
23279  return ae_false;
23280  if( !ae_vector_init(&p->fm1, 0, DT_REAL, _state, make_automatic) )
23281  return ae_false;
23282  if( !ae_vector_init(&p->fp1, 0, DT_REAL, _state, make_automatic) )
23283  return ae_false;
23284  if( !ae_vector_init(&p->fc1, 0, DT_REAL, _state, make_automatic) )
23285  return ae_false;
23286  if( !ae_vector_init(&p->gm1, 0, DT_REAL, _state, make_automatic) )
23287  return ae_false;
23288  if( !ae_vector_init(&p->gp1, 0, DT_REAL, _state, make_automatic) )
23289  return ae_false;
23290  if( !ae_vector_init(&p->gc1, 0, DT_REAL, _state, make_automatic) )
23291  return ae_false;
23292  if( !_minlbfgsstate_init(&p->internalstate, _state, make_automatic) )
23293  return ae_false;
23294  if( !_minlbfgsreport_init(&p->internalrep, _state, make_automatic) )
23295  return ae_false;
23296  if( !_minqpstate_init(&p->qpstate, _state, make_automatic) )
23297  return ae_false;
23298  if( !_minqpreport_init(&p->qprep, _state, make_automatic) )
23299  return ae_false;
23300  return ae_true;
23301 }
23302 
23303 
23304 ae_bool _minlmstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
23305 {
23306  minlmstate *dst = (minlmstate*)_dst;
23307  minlmstate *src = (minlmstate*)_src;
23308  dst->n = src->n;
23309  dst->m = src->m;
23310  dst->diffstep = src->diffstep;
23311  dst->epsg = src->epsg;
23312  dst->epsf = src->epsf;
23313  dst->epsx = src->epsx;
23314  dst->maxits = src->maxits;
23315  dst->xrep = src->xrep;
23316  dst->stpmax = src->stpmax;
23317  dst->maxmodelage = src->maxmodelage;
23318  dst->makeadditers = src->makeadditers;
23319  if( !ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic) )
23320  return ae_false;
23321  dst->f = src->f;
23322  if( !ae_vector_init_copy(&dst->fi, &src->fi, _state, make_automatic) )
23323  return ae_false;
23324  if( !ae_matrix_init_copy(&dst->j, &src->j, _state, make_automatic) )
23325  return ae_false;
23326  if( !ae_matrix_init_copy(&dst->h, &src->h, _state, make_automatic) )
23327  return ae_false;
23328  if( !ae_vector_init_copy(&dst->g, &src->g, _state, make_automatic) )
23329  return ae_false;
23330  dst->needf = src->needf;
23331  dst->needfg = src->needfg;
23332  dst->needfgh = src->needfgh;
23333  dst->needfij = src->needfij;
23334  dst->needfi = src->needfi;
23335  dst->xupdated = src->xupdated;
23336  dst->algomode = src->algomode;
23337  dst->hasf = src->hasf;
23338  dst->hasfi = src->hasfi;
23339  dst->hasg = src->hasg;
23340  if( !ae_vector_init_copy(&dst->xbase, &src->xbase, _state, make_automatic) )
23341  return ae_false;
23342  dst->fbase = src->fbase;
23343  if( !ae_vector_init_copy(&dst->fibase, &src->fibase, _state, make_automatic) )
23344  return ae_false;
23345  if( !ae_vector_init_copy(&dst->gbase, &src->gbase, _state, make_automatic) )
23346  return ae_false;
23347  if( !ae_matrix_init_copy(&dst->quadraticmodel, &src->quadraticmodel, _state, make_automatic) )
23348  return ae_false;
23349  if( !ae_vector_init_copy(&dst->bndl, &src->bndl, _state, make_automatic) )
23350  return ae_false;
23351  if( !ae_vector_init_copy(&dst->bndu, &src->bndu, _state, make_automatic) )
23352  return ae_false;
23353  if( !ae_vector_init_copy(&dst->havebndl, &src->havebndl, _state, make_automatic) )
23354  return ae_false;
23355  if( !ae_vector_init_copy(&dst->havebndu, &src->havebndu, _state, make_automatic) )
23356  return ae_false;
23357  if( !ae_vector_init_copy(&dst->s, &src->s, _state, make_automatic) )
23358  return ae_false;
23359  dst->lambdav = src->lambdav;
23360  dst->nu = src->nu;
23361  dst->modelage = src->modelage;
23362  if( !ae_vector_init_copy(&dst->xdir, &src->xdir, _state, make_automatic) )
23363  return ae_false;
23364  if( !ae_vector_init_copy(&dst->deltax, &src->deltax, _state, make_automatic) )
23365  return ae_false;
23366  if( !ae_vector_init_copy(&dst->deltaf, &src->deltaf, _state, make_automatic) )
23367  return ae_false;
23368  dst->deltaxready = src->deltaxready;
23369  dst->deltafready = src->deltafready;
23370  dst->teststep = src->teststep;
23371  dst->repiterationscount = src->repiterationscount;
23372  dst->repterminationtype = src->repterminationtype;
23373  dst->repfuncidx = src->repfuncidx;
23374  dst->repvaridx = src->repvaridx;
23375  dst->repnfunc = src->repnfunc;
23376  dst->repnjac = src->repnjac;
23377  dst->repngrad = src->repngrad;
23378  dst->repnhess = src->repnhess;
23379  dst->repncholesky = src->repncholesky;
23380  if( !_rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic) )
23381  return ae_false;
23382  if( !ae_vector_init_copy(&dst->choleskybuf, &src->choleskybuf, _state, make_automatic) )
23383  return ae_false;
23384  if( !ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic) )
23385  return ae_false;
23386  dst->actualdecrease = src->actualdecrease;
23387  dst->predicteddecrease = src->predicteddecrease;
23388  dst->xm1 = src->xm1;
23389  dst->xp1 = src->xp1;
23390  if( !ae_vector_init_copy(&dst->fm1, &src->fm1, _state, make_automatic) )
23391  return ae_false;
23392  if( !ae_vector_init_copy(&dst->fp1, &src->fp1, _state, make_automatic) )
23393  return ae_false;
23394  if( !ae_vector_init_copy(&dst->fc1, &src->fc1, _state, make_automatic) )
23395  return ae_false;
23396  if( !ae_vector_init_copy(&dst->gm1, &src->gm1, _state, make_automatic) )
23397  return ae_false;
23398  if( !ae_vector_init_copy(&dst->gp1, &src->gp1, _state, make_automatic) )
23399  return ae_false;
23400  if( !ae_vector_init_copy(&dst->gc1, &src->gc1, _state, make_automatic) )
23401  return ae_false;
23402  if( !_minlbfgsstate_init_copy(&dst->internalstate, &src->internalstate, _state, make_automatic) )
23403  return ae_false;
23404  if( !_minlbfgsreport_init_copy(&dst->internalrep, &src->internalrep, _state, make_automatic) )
23405  return ae_false;
23406  if( !_minqpstate_init_copy(&dst->qpstate, &src->qpstate, _state, make_automatic) )
23407  return ae_false;
23408  if( !_minqpreport_init_copy(&dst->qprep, &src->qprep, _state, make_automatic) )
23409  return ae_false;
23410  return ae_true;
23411 }
23412 
23413 
23414 void _minlmstate_clear(void* _p)
23415 {
23416  minlmstate *p = (minlmstate*)_p;
23417  ae_touch_ptr((void*)p);
23418  ae_vector_clear(&p->x);
23419  ae_vector_clear(&p->fi);
23420  ae_matrix_clear(&p->j);
23421  ae_matrix_clear(&p->h);
23422  ae_vector_clear(&p->g);
23423  ae_vector_clear(&p->xbase);
23424  ae_vector_clear(&p->fibase);
23425  ae_vector_clear(&p->gbase);
23426  ae_matrix_clear(&p->quadraticmodel);
23427  ae_vector_clear(&p->bndl);
23428  ae_vector_clear(&p->bndu);
23429  ae_vector_clear(&p->havebndl);
23430  ae_vector_clear(&p->havebndu);
23431  ae_vector_clear(&p->s);
23432  ae_vector_clear(&p->xdir);
23433  ae_vector_clear(&p->deltax);
23434  ae_vector_clear(&p->deltaf);
23435  _rcommstate_clear(&p->rstate);
23436  ae_vector_clear(&p->choleskybuf);
23437  ae_vector_clear(&p->tmp0);
23438  ae_vector_clear(&p->fm1);
23439  ae_vector_clear(&p->fp1);
23440  ae_vector_clear(&p->fc1);
23441  ae_vector_clear(&p->gm1);
23442  ae_vector_clear(&p->gp1);
23443  ae_vector_clear(&p->gc1);
23444  _minlbfgsstate_clear(&p->internalstate);
23445  _minlbfgsreport_clear(&p->internalrep);
23446  _minqpstate_clear(&p->qpstate);
23447  _minqpreport_clear(&p->qprep);
23448 }
23449 
23450 
23451 void _minlmstate_destroy(void* _p)
23452 {
23453  minlmstate *p = (minlmstate*)_p;
23454  ae_touch_ptr((void*)p);
23455  ae_vector_destroy(&p->x);
23456  ae_vector_destroy(&p->fi);
23457  ae_matrix_destroy(&p->j);
23458  ae_matrix_destroy(&p->h);
23459  ae_vector_destroy(&p->g);
23460  ae_vector_destroy(&p->xbase);
23461  ae_vector_destroy(&p->fibase);
23462  ae_vector_destroy(&p->gbase);
23463  ae_matrix_destroy(&p->quadraticmodel);
23464  ae_vector_destroy(&p->bndl);
23465  ae_vector_destroy(&p->bndu);
23466  ae_vector_destroy(&p->havebndl);
23467  ae_vector_destroy(&p->havebndu);
23468  ae_vector_destroy(&p->s);
23469  ae_vector_destroy(&p->xdir);
23470  ae_vector_destroy(&p->deltax);
23471  ae_vector_destroy(&p->deltaf);
23472  _rcommstate_destroy(&p->rstate);
23473  ae_vector_destroy(&p->choleskybuf);
23474  ae_vector_destroy(&p->tmp0);
23475  ae_vector_destroy(&p->fm1);
23476  ae_vector_destroy(&p->fp1);
23477  ae_vector_destroy(&p->fc1);
23478  ae_vector_destroy(&p->gm1);
23479  ae_vector_destroy(&p->gp1);
23480  ae_vector_destroy(&p->gc1);
23481  _minlbfgsstate_destroy(&p->internalstate);
23482  _minlbfgsreport_destroy(&p->internalrep);
23483  _minqpstate_destroy(&p->qpstate);
23484  _minqpreport_destroy(&p->qprep);
23485 }
23486 
23487 
23488 ae_bool _minlmreport_init(void* _p, ae_state *_state, ae_bool make_automatic)
23489 {
23490  minlmreport *p = (minlmreport*)_p;
23491  ae_touch_ptr((void*)p);
23492  return ae_true;
23493 }
23494 
23495 
23496 ae_bool _minlmreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
23497 {
23498  minlmreport *dst = (minlmreport*)_dst;
23499  minlmreport *src = (minlmreport*)_src;
23500  dst->iterationscount = src->iterationscount;
23501  dst->terminationtype = src->terminationtype;
23502  dst->funcidx = src->funcidx;
23503  dst->varidx = src->varidx;
23504  dst->nfunc = src->nfunc;
23505  dst->njac = src->njac;
23506  dst->ngrad = src->ngrad;
23507  dst->nhess = src->nhess;
23508  dst->ncholesky = src->ncholesky;
23509  return ae_true;
23510 }
23511 
23512 
23513 void _minlmreport_clear(void* _p)
23514 {
23515  minlmreport *p = (minlmreport*)_p;
23516  ae_touch_ptr((void*)p);
23517 }
23518 
23519 
23520 void _minlmreport_destroy(void* _p)
23521 {
23522  minlmreport *p = (minlmreport*)_p;
23523  ae_touch_ptr((void*)p);
23524 }
23525 
23526 
23527 
23528 
23529 /*************************************************************************
23530 Obsolete function, use MinLBFGSSetPrecDefault() instead.
23531 
23532  -- ALGLIB --
23533  Copyright 13.10.2010 by Bochkanov Sergey
23534 *************************************************************************/
23535 void minlbfgssetdefaultpreconditioner(minlbfgsstate* state,
23536  ae_state *_state)
23537 {
23538 
23539 
23540  minlbfgssetprecdefault(state, _state);
23541 }
23542 
23543 
23544 /*************************************************************************
23545 Obsolete function, use MinLBFGSSetCholeskyPreconditioner() instead.
23546 
23547  -- ALGLIB --
23548  Copyright 13.10.2010 by Bochkanov Sergey
23549 *************************************************************************/
23550 void minlbfgssetcholeskypreconditioner(minlbfgsstate* state,
23551  /* Real */ ae_matrix* p,
23552  ae_bool isupper,
23553  ae_state *_state)
23554 {
23555 
23556 
23557  minlbfgssetpreccholesky(state, p, isupper, _state);
23558 }
23559 
23560 
23561 /*************************************************************************
23562 This is obsolete function which was used by previous version of the BLEIC
23563 optimizer. It does nothing in the current version of BLEIC.
23564 
23565  -- ALGLIB --
23566  Copyright 28.11.2010 by Bochkanov Sergey
23567 *************************************************************************/
23568 void minbleicsetbarrierwidth(minbleicstate* state,
23569  double mu,
23570  ae_state *_state)
23571 {
23572 
23573 
23574 }
23575 
23576 
23577 /*************************************************************************
23578 This is obsolete function which was used by previous version of the BLEIC
23579 optimizer. It does nothing in the current version of BLEIC.
23580 
23581  -- ALGLIB --
23582  Copyright 28.11.2010 by Bochkanov Sergey
23583 *************************************************************************/
23584 void minbleicsetbarrierdecay(minbleicstate* state,
23585  double mudecay,
23586  ae_state *_state)
23587 {
23588 
23589 
23590 }
23591 
23592 
23593 /*************************************************************************
23594 Obsolete optimization algorithm.
23595 Was replaced by MinBLEIC subpackage.
23596 
23597  -- ALGLIB --
23598  Copyright 25.03.2010 by Bochkanov Sergey
23599 *************************************************************************/
23600 void minasacreate(ae_int_t n,
23601  /* Real */ ae_vector* x,
23602  /* Real */ ae_vector* bndl,
23603  /* Real */ ae_vector* bndu,
23604  minasastate* state,
23605  ae_state *_state)
23606 {
23607  ae_int_t i;
23608 
23609  _minasastate_clear(state);
23610 
23611  ae_assert(n>=1, "MinASA: N too small!", _state);
23612  ae_assert(x->cnt>=n, "MinCGCreate: Length(X)<N!", _state);
23613  ae_assert(isfinitevector(x, n, _state), "MinCGCreate: X contains infinite or NaN values!", _state);
23614  ae_assert(bndl->cnt>=n, "MinCGCreate: Length(BndL)<N!", _state);
23615  ae_assert(isfinitevector(bndl, n, _state), "MinCGCreate: BndL contains infinite or NaN values!", _state);
23616  ae_assert(bndu->cnt>=n, "MinCGCreate: Length(BndU)<N!", _state);
23617  ae_assert(isfinitevector(bndu, n, _state), "MinCGCreate: BndU contains infinite or NaN values!", _state);
23618  for(i=0; i<=n-1; i++)
23619  {
23620  ae_assert(ae_fp_less_eq(bndl->ptr.p_double[i],bndu->ptr.p_double[i]), "MinASA: inconsistent bounds!", _state);
23621  ae_assert(ae_fp_less_eq(bndl->ptr.p_double[i],x->ptr.p_double[i]), "MinASA: infeasible X!", _state);
23622  ae_assert(ae_fp_less_eq(x->ptr.p_double[i],bndu->ptr.p_double[i]), "MinASA: infeasible X!", _state);
23623  }
23624 
23625  /*
23626  * Initialize
23627  */
23628  state->n = n;
23629  minasasetcond(state, 0, 0, 0, 0, _state);
23630  minasasetxrep(state, ae_false, _state);
23631  minasasetstpmax(state, 0, _state);
23632  minasasetalgorithm(state, -1, _state);
23633  ae_vector_set_length(&state->bndl, n, _state);
23634  ae_vector_set_length(&state->bndu, n, _state);
23635  ae_vector_set_length(&state->ak, n, _state);
23636  ae_vector_set_length(&state->xk, n, _state);
23637  ae_vector_set_length(&state->dk, n, _state);
23638  ae_vector_set_length(&state->an, n, _state);
23639  ae_vector_set_length(&state->xn, n, _state);
23640  ae_vector_set_length(&state->dn, n, _state);
23641  ae_vector_set_length(&state->x, n, _state);
23642  ae_vector_set_length(&state->d, n, _state);
23643  ae_vector_set_length(&state->g, n, _state);
23644  ae_vector_set_length(&state->gc, n, _state);
23645  ae_vector_set_length(&state->work, n, _state);
23646  ae_vector_set_length(&state->yk, n, _state);
23647  minasarestartfrom(state, x, bndl, bndu, _state);
23648 }
23649 
23650 
23651 /*************************************************************************
23652 Obsolete optimization algorithm.
23653 Was replaced by MinBLEIC subpackage.
23654 
23655  -- ALGLIB --
23656  Copyright 02.04.2010 by Bochkanov Sergey
23657 *************************************************************************/
23658 void minasasetcond(minasastate* state,
23659  double epsg,
23660  double epsf,
23661  double epsx,
23662  ae_int_t maxits,
23663  ae_state *_state)
23664 {
23665 
23666 
23667  ae_assert(ae_isfinite(epsg, _state), "MinASASetCond: EpsG is not finite number!", _state);
23668  ae_assert(ae_fp_greater_eq(epsg,0), "MinASASetCond: negative EpsG!", _state);
23669  ae_assert(ae_isfinite(epsf, _state), "MinASASetCond: EpsF is not finite number!", _state);
23670  ae_assert(ae_fp_greater_eq(epsf,0), "MinASASetCond: negative EpsF!", _state);
23671  ae_assert(ae_isfinite(epsx, _state), "MinASASetCond: EpsX is not finite number!", _state);
23672  ae_assert(ae_fp_greater_eq(epsx,0), "MinASASetCond: negative EpsX!", _state);
23673  ae_assert(maxits>=0, "MinASASetCond: negative MaxIts!", _state);
23674  if( ((ae_fp_eq(epsg,0)&&ae_fp_eq(epsf,0))&&ae_fp_eq(epsx,0))&&maxits==0 )
23675  {
23676  epsx = 1.0E-6;
23677  }
23678  state->epsg = epsg;
23679  state->epsf = epsf;
23680  state->epsx = epsx;
23681  state->maxits = maxits;
23682 }
23683 
23684 
23685 /*************************************************************************
23686 Obsolete optimization algorithm.
23687 Was replaced by MinBLEIC subpackage.
23688 
23689  -- ALGLIB --
23690  Copyright 02.04.2010 by Bochkanov Sergey
23691 *************************************************************************/
23692 void minasasetxrep(minasastate* state, ae_bool needxrep, ae_state *_state)
23693 {
23694 
23695 
23696  state->xrep = needxrep;
23697 }
23698 
23699 
23700 /*************************************************************************
23701 Obsolete optimization algorithm.
23702 Was replaced by MinBLEIC subpackage.
23703 
23704  -- ALGLIB --
23705  Copyright 02.04.2010 by Bochkanov Sergey
23706 *************************************************************************/
23707 void minasasetalgorithm(minasastate* state,
23708  ae_int_t algotype,
23709  ae_state *_state)
23710 {
23711 
23712 
23713  ae_assert(algotype>=-1&&algotype<=1, "MinASASetAlgorithm: incorrect AlgoType!", _state);
23714  if( algotype==-1 )
23715  {
23716  algotype = 1;
23717  }
23718  state->cgtype = algotype;
23719 }
23720 
23721 
23722 /*************************************************************************
23723 Obsolete optimization algorithm.
23724 Was replaced by MinBLEIC subpackage.
23725 
23726  -- ALGLIB --
23727  Copyright 02.04.2010 by Bochkanov Sergey
23728 *************************************************************************/
23729 void minasasetstpmax(minasastate* state, double stpmax, ae_state *_state)
23730 {
23731 
23732 
23733  ae_assert(ae_isfinite(stpmax, _state), "MinASASetStpMax: StpMax is not finite!", _state);
23734  ae_assert(ae_fp_greater_eq(stpmax,0), "MinASASetStpMax: StpMax<0!", _state);
23735  state->stpmax = stpmax;
23736 }
23737 
23738 
23739 /*************************************************************************
23740 
23741  -- ALGLIB --
23742  Copyright 20.03.2009 by Bochkanov Sergey
23743 *************************************************************************/
23744 ae_bool minasaiteration(minasastate* state, ae_state *_state)
23745 {
23746  ae_int_t n;
23747  ae_int_t i;
23748  double betak;
23749  double v;
23750  double vv;
23751  ae_int_t mcinfo;
23752  ae_bool b;
23753  ae_bool stepfound;
23754  ae_int_t diffcnt;
23755  ae_bool result;
23756 
23757 
23758 
23759  /*
23760  * Reverse communication preparations
23761  * I know it looks ugly, but it works the same way
23762  * anywhere from C++ to Python.
23763  *
23764  * This code initializes locals by:
23765  * * random values determined during code
23766  * generation - on first subroutine call
23767  * * values from previous call - on subsequent calls
23768  */
23769  if( state->rstate.stage>=0 )
23770  {
23771  n = state->rstate.ia.ptr.p_int[0];
23772  i = state->rstate.ia.ptr.p_int[1];
23773  mcinfo = state->rstate.ia.ptr.p_int[2];
23774  diffcnt = state->rstate.ia.ptr.p_int[3];
23775  b = state->rstate.ba.ptr.p_bool[0];
23776  stepfound = state->rstate.ba.ptr.p_bool[1];
23777  betak = state->rstate.ra.ptr.p_double[0];
23778  v = state->rstate.ra.ptr.p_double[1];
23779  vv = state->rstate.ra.ptr.p_double[2];
23780  }
23781  else
23782  {
23783  n = -983;
23784  i = -989;
23785  mcinfo = -834;
23786  diffcnt = 900;
23787  b = ae_true;
23788  stepfound = ae_false;
23789  betak = 214;
23790  v = -338;
23791  vv = -686;
23792  }
23793  if( state->rstate.stage==0 )
23794  {
23795  goto lbl_0;
23796  }
23797  if( state->rstate.stage==1 )
23798  {
23799  goto lbl_1;
23800  }
23801  if( state->rstate.stage==2 )
23802  {
23803  goto lbl_2;
23804  }
23805  if( state->rstate.stage==3 )
23806  {
23807  goto lbl_3;
23808  }
23809  if( state->rstate.stage==4 )
23810  {
23811  goto lbl_4;
23812  }
23813  if( state->rstate.stage==5 )
23814  {
23815  goto lbl_5;
23816  }
23817  if( state->rstate.stage==6 )
23818  {
23819  goto lbl_6;
23820  }
23821  if( state->rstate.stage==7 )
23822  {
23823  goto lbl_7;
23824  }
23825  if( state->rstate.stage==8 )
23826  {
23827  goto lbl_8;
23828  }
23829  if( state->rstate.stage==9 )
23830  {
23831  goto lbl_9;
23832  }
23833  if( state->rstate.stage==10 )
23834  {
23835  goto lbl_10;
23836  }
23837  if( state->rstate.stage==11 )
23838  {
23839  goto lbl_11;
23840  }
23841  if( state->rstate.stage==12 )
23842  {
23843  goto lbl_12;
23844  }
23845  if( state->rstate.stage==13 )
23846  {
23847  goto lbl_13;
23848  }
23849  if( state->rstate.stage==14 )
23850  {
23851  goto lbl_14;
23852  }
23853 
23854  /*
23855  * Routine body
23856  */
23857 
23858  /*
23859  * Prepare
23860  */
23861  n = state->n;
23862  state->repterminationtype = 0;
23863  state->repiterationscount = 0;
23864  state->repnfev = 0;
23865  state->debugrestartscount = 0;
23866  state->cgtype = 1;
23867  ae_v_move(&state->xk.ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,n-1));
23868  for(i=0; i<=n-1; i++)
23869  {
23870  if( ae_fp_eq(state->xk.ptr.p_double[i],state->bndl.ptr.p_double[i])||ae_fp_eq(state->xk.ptr.p_double[i],state->bndu.ptr.p_double[i]) )
23871  {
23872  state->ak.ptr.p_double[i] = 0;
23873  }
23874  else
23875  {
23876  state->ak.ptr.p_double[i] = 1;
23877  }
23878  }
23879  state->mu = 0.1;
23880  state->curalgo = 0;
23881 
23882  /*
23883  * Calculate F/G, initialize algorithm
23884  */
23885  mincomp_clearrequestfields(state, _state);
23886  state->needfg = ae_true;
23887  state->rstate.stage = 0;
23888  goto lbl_rcomm;
23889 lbl_0:
23890  state->needfg = ae_false;
23891  if( !state->xrep )
23892  {
23893  goto lbl_15;
23894  }
23895 
23896  /*
23897  * progress report
23898  */
23899  mincomp_clearrequestfields(state, _state);
23900  state->xupdated = ae_true;
23901  state->rstate.stage = 1;
23902  goto lbl_rcomm;
23903 lbl_1:
23904  state->xupdated = ae_false;
23905 lbl_15:
23906  if( ae_fp_less_eq(mincomp_asaboundedantigradnorm(state, _state),state->epsg) )
23907  {
23908  state->repterminationtype = 4;
23909  result = ae_false;
23910  return result;
23911  }
23912  state->repnfev = state->repnfev+1;
23913 
23914  /*
23915  * Main cycle
23916  *
23917  * At the beginning of new iteration:
23918  * * CurAlgo stores current algorithm selector
23919  * * State.XK, State.F and State.G store current X/F/G
23920  * * State.AK stores current set of active constraints
23921  */
23922 lbl_17:
23923  if( ae_false )
23924  {
23925  goto lbl_18;
23926  }
23927 
23928  /*
23929  * GPA algorithm
23930  */
23931  if( state->curalgo!=0 )
23932  {
23933  goto lbl_19;
23934  }
23935  state->k = 0;
23936  state->acount = 0;
23937 lbl_21:
23938  if( ae_false )
23939  {
23940  goto lbl_22;
23941  }
23942 
23943  /*
23944  * Determine Dk = proj(xk - gk)-xk
23945  */
23946  for(i=0; i<=n-1; i++)
23947  {
23948  state->d.ptr.p_double[i] = boundval(state->xk.ptr.p_double[i]-state->g.ptr.p_double[i], state->bndl.ptr.p_double[i], state->bndu.ptr.p_double[i], _state)-state->xk.ptr.p_double[i];
23949  }
23950 
23951  /*
23952  * Armijo line search.
23953  * * exact search with alpha=1 is tried first,
23954  * 'exact' means that we evaluate f() EXACTLY at
23955  * bound(x-g,bndl,bndu), without intermediate floating
23956  * point operations.
23957  * * alpha<1 are tried if explicit search wasn't successful
23958  * Result is placed into XN.
23959  *
23960  * Two types of search are needed because we can't
23961  * just use second type with alpha=1 because in finite
23962  * precision arithmetics (x1-x0)+x0 may differ from x1.
23963  * So while x1 is correctly bounded (it lie EXACTLY on
23964  * boundary, if it is active), (x1-x0)+x0 may be
23965  * not bounded.
23966  */
23967  v = ae_v_dotproduct(&state->d.ptr.p_double[0], 1, &state->g.ptr.p_double[0], 1, ae_v_len(0,n-1));
23968  state->dginit = v;
23969  state->finit = state->f;
23970  if( !(ae_fp_less_eq(mincomp_asad1norm(state, _state),state->stpmax)||ae_fp_eq(state->stpmax,0)) )
23971  {
23972  goto lbl_23;
23973  }
23974 
23975  /*
23976  * Try alpha=1 step first
23977  */
23978  for(i=0; i<=n-1; i++)
23979  {
23980  state->x.ptr.p_double[i] = boundval(state->xk.ptr.p_double[i]-state->g.ptr.p_double[i], state->bndl.ptr.p_double[i], state->bndu.ptr.p_double[i], _state);
23981  }
23982  mincomp_clearrequestfields(state, _state);
23983  state->needfg = ae_true;
23984  state->rstate.stage = 2;
23985  goto lbl_rcomm;
23986 lbl_2:
23987  state->needfg = ae_false;
23988  state->repnfev = state->repnfev+1;
23989  stepfound = ae_fp_less_eq(state->f,state->finit+mincomp_gpaftol*state->dginit);
23990  goto lbl_24;
23991 lbl_23:
23992  stepfound = ae_false;
23993 lbl_24:
23994  if( !stepfound )
23995  {
23996  goto lbl_25;
23997  }
23998 
23999  /*
24000  * we are at the boundary(ies)
24001  */
24002  ae_v_move(&state->xn.ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,n-1));
24003  state->stp = 1;
24004  goto lbl_26;
24005 lbl_25:
24006 
24007  /*
24008  * alpha=1 is too large, try smaller values
24009  */
24010  state->stp = 1;
24011  linminnormalized(&state->d, &state->stp, n, _state);
24012  state->dginit = state->dginit/state->stp;
24013  state->stp = mincomp_gpadecay*state->stp;
24014  if( ae_fp_greater(state->stpmax,0) )
24015  {
24016  state->stp = ae_minreal(state->stp, state->stpmax, _state);
24017  }
24018 lbl_27:
24019  if( ae_false )
24020  {
24021  goto lbl_28;
24022  }
24023  v = state->stp;
24024  ae_v_move(&state->x.ptr.p_double[0], 1, &state->xk.ptr.p_double[0], 1, ae_v_len(0,n-1));
24025  ae_v_addd(&state->x.ptr.p_double[0], 1, &state->d.ptr.p_double[0], 1, ae_v_len(0,n-1), v);
24026  mincomp_clearrequestfields(state, _state);
24027  state->needfg = ae_true;
24028  state->rstate.stage = 3;
24029  goto lbl_rcomm;
24030 lbl_3:
24031  state->needfg = ae_false;
24032  state->repnfev = state->repnfev+1;
24033  if( ae_fp_less_eq(state->stp,mincomp_stpmin) )
24034  {
24035  goto lbl_28;
24036  }
24037  if( ae_fp_less_eq(state->f,state->finit+state->stp*mincomp_gpaftol*state->dginit) )
24038  {
24039  goto lbl_28;
24040  }
24041  state->stp = state->stp*mincomp_gpadecay;
24042  goto lbl_27;
24043 lbl_28:
24044  ae_v_move(&state->xn.ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,n-1));
24045 lbl_26:
24046  state->repiterationscount = state->repiterationscount+1;
24047  if( !state->xrep )
24048  {
24049  goto lbl_29;
24050  }
24051 
24052  /*
24053  * progress report
24054  */
24055  mincomp_clearrequestfields(state, _state);
24056  state->xupdated = ae_true;
24057  state->rstate.stage = 4;
24058  goto lbl_rcomm;
24059 lbl_4:
24060  state->xupdated = ae_false;
24061 lbl_29:
24062 
24063  /*
24064  * Calculate new set of active constraints.
24065  * Reset counter if active set was changed.
24066  * Prepare for the new iteration
24067  */
24068  for(i=0; i<=n-1; i++)
24069  {
24070  if( ae_fp_eq(state->xn.ptr.p_double[i],state->bndl.ptr.p_double[i])||ae_fp_eq(state->xn.ptr.p_double[i],state->bndu.ptr.p_double[i]) )
24071  {
24072  state->an.ptr.p_double[i] = 0;
24073  }
24074  else
24075  {
24076  state->an.ptr.p_double[i] = 1;
24077  }
24078  }
24079  for(i=0; i<=n-1; i++)
24080  {
24081  if( ae_fp_neq(state->ak.ptr.p_double[i],state->an.ptr.p_double[i]) )
24082  {
24083  state->acount = -1;
24084  break;
24085  }
24086  }
24087  state->acount = state->acount+1;
24088  ae_v_move(&state->xk.ptr.p_double[0], 1, &state->xn.ptr.p_double[0], 1, ae_v_len(0,n-1));
24089  ae_v_move(&state->ak.ptr.p_double[0], 1, &state->an.ptr.p_double[0], 1, ae_v_len(0,n-1));
24090 
24091  /*
24092  * Stopping conditions
24093  */
24094  if( !(state->repiterationscount>=state->maxits&&state->maxits>0) )
24095  {
24096  goto lbl_31;
24097  }
24098 
24099  /*
24100  * Too many iterations
24101  */
24102  state->repterminationtype = 5;
24103  if( !state->xrep )
24104  {
24105  goto lbl_33;
24106  }
24107  mincomp_clearrequestfields(state, _state);
24108  state->xupdated = ae_true;
24109  state->rstate.stage = 5;
24110  goto lbl_rcomm;
24111 lbl_5:
24112  state->xupdated = ae_false;
24113 lbl_33:
24114  result = ae_false;
24115  return result;
24116 lbl_31:
24117  if( ae_fp_greater(mincomp_asaboundedantigradnorm(state, _state),state->epsg) )
24118  {
24119  goto lbl_35;
24120  }
24121 
24122  /*
24123  * Gradient is small enough
24124  */
24125  state->repterminationtype = 4;
24126  if( !state->xrep )
24127  {
24128  goto lbl_37;
24129  }
24130  mincomp_clearrequestfields(state, _state);
24131  state->xupdated = ae_true;
24132  state->rstate.stage = 6;
24133  goto lbl_rcomm;
24134 lbl_6:
24135  state->xupdated = ae_false;
24136 lbl_37:
24137  result = ae_false;
24138  return result;
24139 lbl_35:
24140  v = ae_v_dotproduct(&state->d.ptr.p_double[0], 1, &state->d.ptr.p_double[0], 1, ae_v_len(0,n-1));
24141  if( ae_fp_greater(ae_sqrt(v, _state)*state->stp,state->epsx) )
24142  {
24143  goto lbl_39;
24144  }
24145 
24146  /*
24147  * Step size is too small, no further improvement is
24148  * possible
24149  */
24150  state->repterminationtype = 2;
24151  if( !state->xrep )
24152  {
24153  goto lbl_41;
24154  }
24155  mincomp_clearrequestfields(state, _state);
24156  state->xupdated = ae_true;
24157  state->rstate.stage = 7;
24158  goto lbl_rcomm;
24159 lbl_7:
24160  state->xupdated = ae_false;
24161 lbl_41:
24162  result = ae_false;
24163  return result;
24164 lbl_39:
24165  if( ae_fp_greater(state->finit-state->f,state->epsf*ae_maxreal(ae_fabs(state->finit, _state), ae_maxreal(ae_fabs(state->f, _state), 1.0, _state), _state)) )
24166  {
24167  goto lbl_43;
24168  }
24169 
24170  /*
24171  * F(k+1)-F(k) is small enough
24172  */
24173  state->repterminationtype = 1;
24174  if( !state->xrep )
24175  {
24176  goto lbl_45;
24177  }
24178  mincomp_clearrequestfields(state, _state);
24179  state->xupdated = ae_true;
24180  state->rstate.stage = 8;
24181  goto lbl_rcomm;
24182 lbl_8:
24183  state->xupdated = ae_false;
24184 lbl_45:
24185  result = ae_false;
24186  return result;
24187 lbl_43:
24188 
24189  /*
24190  * Decide - should we switch algorithm or not
24191  */
24192  if( mincomp_asauisempty(state, _state) )
24193  {
24194  if( ae_fp_greater_eq(mincomp_asaginorm(state, _state),state->mu*mincomp_asad1norm(state, _state)) )
24195  {
24196  state->curalgo = 1;
24197  goto lbl_22;
24198  }
24199  else
24200  {
24201  state->mu = state->mu*mincomp_asarho;
24202  }
24203  }
24204  else
24205  {
24206  if( state->acount==mincomp_n1 )
24207  {
24208  if( ae_fp_greater_eq(mincomp_asaginorm(state, _state),state->mu*mincomp_asad1norm(state, _state)) )
24209  {
24210  state->curalgo = 1;
24211  goto lbl_22;
24212  }
24213  }
24214  }
24215 
24216  /*
24217  * Next iteration
24218  */
24219  state->k = state->k+1;
24220  goto lbl_21;
24221 lbl_22:
24222 lbl_19:
24223 
24224  /*
24225  * CG algorithm
24226  */
24227  if( state->curalgo!=1 )
24228  {
24229  goto lbl_47;
24230  }
24231 
24232  /*
24233  * first, check that there are non-active constraints.
24234  * move to GPA algorithm, if all constraints are active
24235  */
24236  b = ae_true;
24237  for(i=0; i<=n-1; i++)
24238  {
24239  if( ae_fp_neq(state->ak.ptr.p_double[i],0) )
24240  {
24241  b = ae_false;
24242  break;
24243  }
24244  }
24245  if( b )
24246  {
24247  state->curalgo = 0;
24248  goto lbl_17;
24249  }
24250 
24251  /*
24252  * CG iterations
24253  */
24254  state->fold = state->f;
24255  ae_v_move(&state->xk.ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,n-1));
24256  for(i=0; i<=n-1; i++)
24257  {
24258  state->dk.ptr.p_double[i] = -state->g.ptr.p_double[i]*state->ak.ptr.p_double[i];
24259  state->gc.ptr.p_double[i] = state->g.ptr.p_double[i]*state->ak.ptr.p_double[i];
24260  }
24261 lbl_49:
24262  if( ae_false )
24263  {
24264  goto lbl_50;
24265  }
24266 
24267  /*
24268  * Store G[k] for later calculation of Y[k]
24269  */
24270  for(i=0; i<=n-1; i++)
24271  {
24272  state->yk.ptr.p_double[i] = -state->gc.ptr.p_double[i];
24273  }
24274 
24275  /*
24276  * Make a CG step in direction given by DK[]:
24277  * * calculate step. Step projection into feasible set
24278  * is used. It has several benefits: a) step may be
24279  * found with usual line search, b) multiple constraints
24280  * may be activated with one step, c) activated constraints
24281  * are detected in a natural way - just compare x[i] with
24282  * bounds
24283  * * update active set, set B to True, if there
24284  * were changes in the set.
24285  */
24286  ae_v_move(&state->d.ptr.p_double[0], 1, &state->dk.ptr.p_double[0], 1, ae_v_len(0,n-1));
24287  ae_v_move(&state->xn.ptr.p_double[0], 1, &state->xk.ptr.p_double[0], 1, ae_v_len(0,n-1));
24288  state->mcstage = 0;
24289  state->stp = 1;
24290  linminnormalized(&state->d, &state->stp, n, _state);
24291  if( ae_fp_neq(state->laststep,0) )
24292  {
24293  state->stp = state->laststep;
24294  }
24295  mcsrch(n, &state->xn, &state->f, &state->gc, &state->d, &state->stp, state->stpmax, mincomp_gtol, &mcinfo, &state->nfev, &state->work, &state->lstate, &state->mcstage, _state);
24296 lbl_51:
24297  if( state->mcstage==0 )
24298  {
24299  goto lbl_52;
24300  }
24301 
24302  /*
24303  * preprocess data: bound State.XN so it belongs to the
24304  * feasible set and store it in the State.X
24305  */
24306  for(i=0; i<=n-1; i++)
24307  {
24308  state->x.ptr.p_double[i] = boundval(state->xn.ptr.p_double[i], state->bndl.ptr.p_double[i], state->bndu.ptr.p_double[i], _state);
24309  }
24310 
24311  /*
24312  * RComm
24313  */
24314  mincomp_clearrequestfields(state, _state);
24315  state->needfg = ae_true;
24316  state->rstate.stage = 9;
24317  goto lbl_rcomm;
24318 lbl_9:
24319  state->needfg = ae_false;
24320 
24321  /*
24322  * postprocess data: zero components of G corresponding to
24323  * the active constraints
24324  */
24325  for(i=0; i<=n-1; i++)
24326  {
24327  if( ae_fp_eq(state->x.ptr.p_double[i],state->bndl.ptr.p_double[i])||ae_fp_eq(state->x.ptr.p_double[i],state->bndu.ptr.p_double[i]) )
24328  {
24329  state->gc.ptr.p_double[i] = 0;
24330  }
24331  else
24332  {
24333  state->gc.ptr.p_double[i] = state->g.ptr.p_double[i];
24334  }
24335  }
24336  mcsrch(n, &state->xn, &state->f, &state->gc, &state->d, &state->stp, state->stpmax, mincomp_gtol, &mcinfo, &state->nfev, &state->work, &state->lstate, &state->mcstage, _state);
24337  goto lbl_51;
24338 lbl_52:
24339  diffcnt = 0;
24340  for(i=0; i<=n-1; i++)
24341  {
24342 
24343  /*
24344  * XN contains unprojected result, project it,
24345  * save copy to X (will be used for progress reporting)
24346  */
24347  state->xn.ptr.p_double[i] = boundval(state->xn.ptr.p_double[i], state->bndl.ptr.p_double[i], state->bndu.ptr.p_double[i], _state);
24348 
24349  /*
24350  * update active set
24351  */
24352  if( ae_fp_eq(state->xn.ptr.p_double[i],state->bndl.ptr.p_double[i])||ae_fp_eq(state->xn.ptr.p_double[i],state->bndu.ptr.p_double[i]) )
24353  {
24354  state->an.ptr.p_double[i] = 0;
24355  }
24356  else
24357  {
24358  state->an.ptr.p_double[i] = 1;
24359  }
24360  if( ae_fp_neq(state->an.ptr.p_double[i],state->ak.ptr.p_double[i]) )
24361  {
24362  diffcnt = diffcnt+1;
24363  }
24364  state->ak.ptr.p_double[i] = state->an.ptr.p_double[i];
24365  }
24366  ae_v_move(&state->xk.ptr.p_double[0], 1, &state->xn.ptr.p_double[0], 1, ae_v_len(0,n-1));
24367  state->repnfev = state->repnfev+state->nfev;
24368  state->repiterationscount = state->repiterationscount+1;
24369  if( !state->xrep )
24370  {
24371  goto lbl_53;
24372  }
24373 
24374  /*
24375  * progress report
24376  */
24377  mincomp_clearrequestfields(state, _state);
24378  state->xupdated = ae_true;
24379  state->rstate.stage = 10;
24380  goto lbl_rcomm;
24381 lbl_10:
24382  state->xupdated = ae_false;
24383 lbl_53:
24384 
24385  /*
24386  * Update info about step length
24387  */
24388  v = ae_v_dotproduct(&state->d.ptr.p_double[0], 1, &state->d.ptr.p_double[0], 1, ae_v_len(0,n-1));
24389  state->laststep = ae_sqrt(v, _state)*state->stp;
24390 
24391  /*
24392  * Check stopping conditions.
24393  */
24394  if( ae_fp_greater(mincomp_asaboundedantigradnorm(state, _state),state->epsg) )
24395  {
24396  goto lbl_55;
24397  }
24398 
24399  /*
24400  * Gradient is small enough
24401  */
24402  state->repterminationtype = 4;
24403  if( !state->xrep )
24404  {
24405  goto lbl_57;
24406  }
24407  mincomp_clearrequestfields(state, _state);
24408  state->xupdated = ae_true;
24409  state->rstate.stage = 11;
24410  goto lbl_rcomm;
24411 lbl_11:
24412  state->xupdated = ae_false;
24413 lbl_57:
24414  result = ae_false;
24415  return result;
24416 lbl_55:
24417  if( !(state->repiterationscount>=state->maxits&&state->maxits>0) )
24418  {
24419  goto lbl_59;
24420  }
24421 
24422  /*
24423  * Too many iterations
24424  */
24425  state->repterminationtype = 5;
24426  if( !state->xrep )
24427  {
24428  goto lbl_61;
24429  }
24430  mincomp_clearrequestfields(state, _state);
24431  state->xupdated = ae_true;
24432  state->rstate.stage = 12;
24433  goto lbl_rcomm;
24434 lbl_12:
24435  state->xupdated = ae_false;
24436 lbl_61:
24437  result = ae_false;
24438  return result;
24439 lbl_59:
24440  if( !(ae_fp_greater_eq(mincomp_asaginorm(state, _state),state->mu*mincomp_asad1norm(state, _state))&&diffcnt==0) )
24441  {
24442  goto lbl_63;
24443  }
24444 
24445  /*
24446  * These conditions (EpsF/EpsX) are explicitly or implicitly
24447  * related to the current step size and influenced
24448  * by changes in the active constraints.
24449  *
24450  * For these reasons they are checked only when we don't
24451  * want to 'unstick' at the end of the iteration and there
24452  * were no changes in the active set.
24453  *
24454  * NOTE: consition |G|>=Mu*|D1| must be exactly opposite
24455  * to the condition used to switch back to GPA. At least
24456  * one inequality must be strict, otherwise infinite cycle
24457  * may occur when |G|=Mu*|D1| (we DON'T test stopping
24458  * conditions and we DON'T switch to GPA, so we cycle
24459  * indefinitely).
24460  */
24461  if( ae_fp_greater(state->fold-state->f,state->epsf*ae_maxreal(ae_fabs(state->fold, _state), ae_maxreal(ae_fabs(state->f, _state), 1.0, _state), _state)) )
24462  {
24463  goto lbl_65;
24464  }
24465 
24466  /*
24467  * F(k+1)-F(k) is small enough
24468  */
24469  state->repterminationtype = 1;
24470  if( !state->xrep )
24471  {
24472  goto lbl_67;
24473  }
24474  mincomp_clearrequestfields(state, _state);
24475  state->xupdated = ae_true;
24476  state->rstate.stage = 13;
24477  goto lbl_rcomm;
24478 lbl_13:
24479  state->xupdated = ae_false;
24480 lbl_67:
24481  result = ae_false;
24482  return result;
24483 lbl_65:
24484  if( ae_fp_greater(state->laststep,state->epsx) )
24485  {
24486  goto lbl_69;
24487  }
24488 
24489  /*
24490  * X(k+1)-X(k) is small enough
24491  */
24492  state->repterminationtype = 2;
24493  if( !state->xrep )
24494  {
24495  goto lbl_71;
24496  }
24497  mincomp_clearrequestfields(state, _state);
24498  state->xupdated = ae_true;
24499  state->rstate.stage = 14;
24500  goto lbl_rcomm;
24501 lbl_14:
24502  state->xupdated = ae_false;
24503 lbl_71:
24504  result = ae_false;
24505  return result;
24506 lbl_69:
24507 lbl_63:
24508 
24509  /*
24510  * Check conditions for switching
24511  */
24512  if( ae_fp_less(mincomp_asaginorm(state, _state),state->mu*mincomp_asad1norm(state, _state)) )
24513  {
24514  state->curalgo = 0;
24515  goto lbl_50;
24516  }
24517  if( diffcnt>0 )
24518  {
24519  if( mincomp_asauisempty(state, _state)||diffcnt>=mincomp_n2 )
24520  {
24521  state->curalgo = 1;
24522  }
24523  else
24524  {
24525  state->curalgo = 0;
24526  }
24527  goto lbl_50;
24528  }
24529 
24530  /*
24531  * Calculate D(k+1)
24532  *
24533  * Line search may result in:
24534  * * maximum feasible step being taken (already processed)
24535  * * point satisfying Wolfe conditions
24536  * * some kind of error (CG is restarted by assigning 0.0 to Beta)
24537  */
24538  if( mcinfo==1 )
24539  {
24540 
24541  /*
24542  * Standard Wolfe conditions are satisfied:
24543  * * calculate Y[K] and BetaK
24544  */
24545  ae_v_add(&state->yk.ptr.p_double[0], 1, &state->gc.ptr.p_double[0], 1, ae_v_len(0,n-1));
24546  vv = ae_v_dotproduct(&state->yk.ptr.p_double[0], 1, &state->dk.ptr.p_double[0], 1, ae_v_len(0,n-1));
24547  v = ae_v_dotproduct(&state->gc.ptr.p_double[0], 1, &state->gc.ptr.p_double[0], 1, ae_v_len(0,n-1));
24548  state->betady = v/vv;
24549  v = ae_v_dotproduct(&state->gc.ptr.p_double[0], 1, &state->yk.ptr.p_double[0], 1, ae_v_len(0,n-1));
24550  state->betahs = v/vv;
24551  if( state->cgtype==0 )
24552  {
24553  betak = state->betady;
24554  }
24555  if( state->cgtype==1 )
24556  {
24557  betak = ae_maxreal(0, ae_minreal(state->betady, state->betahs, _state), _state);
24558  }
24559  }
24560  else
24561  {
24562 
24563  /*
24564  * Something is wrong (may be function is too wild or too flat).
24565  *
24566  * We'll set BetaK=0, which will restart CG algorithm.
24567  * We can stop later (during normal checks) if stopping conditions are met.
24568  */
24569  betak = 0;
24570  state->debugrestartscount = state->debugrestartscount+1;
24571  }
24572  ae_v_moveneg(&state->dn.ptr.p_double[0], 1, &state->gc.ptr.p_double[0], 1, ae_v_len(0,n-1));
24573  ae_v_addd(&state->dn.ptr.p_double[0], 1, &state->dk.ptr.p_double[0], 1, ae_v_len(0,n-1), betak);
24574  ae_v_move(&state->dk.ptr.p_double[0], 1, &state->dn.ptr.p_double[0], 1, ae_v_len(0,n-1));
24575 
24576  /*
24577  * update other information
24578  */
24579  state->fold = state->f;
24580  state->k = state->k+1;
24581  goto lbl_49;
24582 lbl_50:
24583 lbl_47:
24584  goto lbl_17;
24585 lbl_18:
24586  result = ae_false;
24587  return result;
24588 
24589  /*
24590  * Saving state
24591  */
24592 lbl_rcomm:
24593  result = ae_true;
24594  state->rstate.ia.ptr.p_int[0] = n;
24595  state->rstate.ia.ptr.p_int[1] = i;
24596  state->rstate.ia.ptr.p_int[2] = mcinfo;
24597  state->rstate.ia.ptr.p_int[3] = diffcnt;
24598  state->rstate.ba.ptr.p_bool[0] = b;
24599  state->rstate.ba.ptr.p_bool[1] = stepfound;
24600  state->rstate.ra.ptr.p_double[0] = betak;
24601  state->rstate.ra.ptr.p_double[1] = v;
24602  state->rstate.ra.ptr.p_double[2] = vv;
24603  return result;
24604 }
24605 
24606 
24607 /*************************************************************************
24608 Obsolete optimization algorithm.
24609 Was replaced by MinBLEIC subpackage.
24610 
24611  -- ALGLIB --
24612  Copyright 20.03.2009 by Bochkanov Sergey
24613 *************************************************************************/
24614 void minasaresults(minasastate* state,
24615  /* Real */ ae_vector* x,
24616  minasareport* rep,
24617  ae_state *_state)
24618 {
24619 
24620  ae_vector_clear(x);
24621  _minasareport_clear(rep);
24622 
24623  minasaresultsbuf(state, x, rep, _state);
24624 }
24625 
24626 
24627 /*************************************************************************
24628 Obsolete optimization algorithm.
24629 Was replaced by MinBLEIC subpackage.
24630 
24631  -- ALGLIB --
24632  Copyright 20.03.2009 by Bochkanov Sergey
24633 *************************************************************************/
24634 void minasaresultsbuf(minasastate* state,
24635  /* Real */ ae_vector* x,
24636  minasareport* rep,
24637  ae_state *_state)
24638 {
24639  ae_int_t i;
24640 
24641 
24642  if( x->cnt<state->n )
24643  {
24644  ae_vector_set_length(x, state->n, _state);
24645  }
24646  ae_v_move(&x->ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,state->n-1));
24647  rep->iterationscount = state->repiterationscount;
24648  rep->nfev = state->repnfev;
24649  rep->terminationtype = state->repterminationtype;
24650  rep->activeconstraints = 0;
24651  for(i=0; i<=state->n-1; i++)
24652  {
24653  if( ae_fp_eq(state->ak.ptr.p_double[i],0) )
24654  {
24655  rep->activeconstraints = rep->activeconstraints+1;
24656  }
24657  }
24658 }
24659 
24660 
24661 /*************************************************************************
24662 Obsolete optimization algorithm.
24663 Was replaced by MinBLEIC subpackage.
24664 
24665  -- ALGLIB --
24666  Copyright 30.07.2010 by Bochkanov Sergey
24667 *************************************************************************/
24668 void minasarestartfrom(minasastate* state,
24669  /* Real */ ae_vector* x,
24670  /* Real */ ae_vector* bndl,
24671  /* Real */ ae_vector* bndu,
24672  ae_state *_state)
24673 {
24674 
24675 
24676  ae_assert(x->cnt>=state->n, "MinASARestartFrom: Length(X)<N!", _state);
24677  ae_assert(isfinitevector(x, state->n, _state), "MinASARestartFrom: X contains infinite or NaN values!", _state);
24678  ae_assert(bndl->cnt>=state->n, "MinASARestartFrom: Length(BndL)<N!", _state);
24679  ae_assert(isfinitevector(bndl, state->n, _state), "MinASARestartFrom: BndL contains infinite or NaN values!", _state);
24680  ae_assert(bndu->cnt>=state->n, "MinASARestartFrom: Length(BndU)<N!", _state);
24681  ae_assert(isfinitevector(bndu, state->n, _state), "MinASARestartFrom: BndU contains infinite or NaN values!", _state);
24682  ae_v_move(&state->x.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,state->n-1));
24683  ae_v_move(&state->bndl.ptr.p_double[0], 1, &bndl->ptr.p_double[0], 1, ae_v_len(0,state->n-1));
24684  ae_v_move(&state->bndu.ptr.p_double[0], 1, &bndu->ptr.p_double[0], 1, ae_v_len(0,state->n-1));
24685  state->laststep = 0;
24686  ae_vector_set_length(&state->rstate.ia, 3+1, _state);
24687  ae_vector_set_length(&state->rstate.ba, 1+1, _state);
24688  ae_vector_set_length(&state->rstate.ra, 2+1, _state);
24689  state->rstate.stage = -1;
24690  mincomp_clearrequestfields(state, _state);
24691 }
24692 
24693 
24694 /*************************************************************************
24695 Returns norm of bounded anti-gradient.
24696 
24697 Bounded antigradient is a vector obtained from anti-gradient by zeroing
24698 components which point outwards:
24699  result = norm(v)
24700  v[i]=0 if ((-g[i]<0)and(x[i]=bndl[i])) or
24701  ((-g[i]>0)and(x[i]=bndu[i]))
24702  v[i]=-g[i] otherwise
24703 
24704 This function may be used to check a stopping criterion.
24705 
24706  -- ALGLIB --
24707  Copyright 20.03.2009 by Bochkanov Sergey
24708 *************************************************************************/
24709 static double mincomp_asaboundedantigradnorm(minasastate* state,
24710  ae_state *_state)
24711 {
24712  ae_int_t i;
24713  double v;
24714  double result;
24715 
24716 
24717  result = 0;
24718  for(i=0; i<=state->n-1; i++)
24719  {
24720  v = -state->g.ptr.p_double[i];
24721  if( ae_fp_eq(state->x.ptr.p_double[i],state->bndl.ptr.p_double[i])&&ae_fp_less(-state->g.ptr.p_double[i],0) )
24722  {
24723  v = 0;
24724  }
24725  if( ae_fp_eq(state->x.ptr.p_double[i],state->bndu.ptr.p_double[i])&&ae_fp_greater(-state->g.ptr.p_double[i],0) )
24726  {
24727  v = 0;
24728  }
24729  result = result+ae_sqr(v, _state);
24730  }
24731  result = ae_sqrt(result, _state);
24732  return result;
24733 }
24734 
24735 
24736 /*************************************************************************
24737 Returns norm of GI(x).
24738 
24739 GI(x) is a gradient vector whose components associated with active
24740 constraints are zeroed. It differs from bounded anti-gradient because
24741 components of GI(x) are zeroed independently of sign(g[i]), and
24742 anti-gradient's components are zeroed with respect to both constraint and
24743 sign.
24744 
24745  -- ALGLIB --
24746  Copyright 20.03.2009 by Bochkanov Sergey
24747 *************************************************************************/
24748 static double mincomp_asaginorm(minasastate* state, ae_state *_state)
24749 {
24750  ae_int_t i;
24751  double result;
24752 
24753 
24754  result = 0;
24755  for(i=0; i<=state->n-1; i++)
24756  {
24757  if( ae_fp_neq(state->x.ptr.p_double[i],state->bndl.ptr.p_double[i])&&ae_fp_neq(state->x.ptr.p_double[i],state->bndu.ptr.p_double[i]) )
24758  {
24759  result = result+ae_sqr(state->g.ptr.p_double[i], _state);
24760  }
24761  }
24762  result = ae_sqrt(result, _state);
24763  return result;
24764 }
24765 
24766 
24767 /*************************************************************************
24768 Returns norm(D1(State.X))
24769 
24770 For a meaning of D1 see 'NEW ACTIVE SET ALGORITHM FOR BOX CONSTRAINED
24771 OPTIMIZATION' by WILLIAM W. HAGER AND HONGCHAO ZHANG.
24772 
24773  -- ALGLIB --
24774  Copyright 20.03.2009 by Bochkanov Sergey
24775 *************************************************************************/
24776 static double mincomp_asad1norm(minasastate* state, ae_state *_state)
24777 {
24778  ae_int_t i;
24779  double result;
24780 
24781 
24782  result = 0;
24783  for(i=0; i<=state->n-1; i++)
24784  {
24785  result = result+ae_sqr(boundval(state->x.ptr.p_double[i]-state->g.ptr.p_double[i], state->bndl.ptr.p_double[i], state->bndu.ptr.p_double[i], _state)-state->x.ptr.p_double[i], _state);
24786  }
24787  result = ae_sqrt(result, _state);
24788  return result;
24789 }
24790 
24791 
24792 /*************************************************************************
24793 Returns True, if U set is empty.
24794 
24795 * State.X is used as point,
24796 * State.G - as gradient,
24797 * D is calculated within function (because State.D may have different
24798  meaning depending on current optimization algorithm)
24799 
24800 For a meaning of U see 'NEW ACTIVE SET ALGORITHM FOR BOX CONSTRAINED
24801 OPTIMIZATION' by WILLIAM W. HAGER AND HONGCHAO ZHANG.
24802 
24803  -- ALGLIB --
24804  Copyright 20.03.2009 by Bochkanov Sergey
24805 *************************************************************************/
24806 static ae_bool mincomp_asauisempty(minasastate* state, ae_state *_state)
24807 {
24808  ae_int_t i;
24809  double d;
24810  double d2;
24811  double d32;
24812  ae_bool result;
24813 
24814 
24815  d = mincomp_asad1norm(state, _state);
24816  d2 = ae_sqrt(d, _state);
24817  d32 = d*d2;
24818  result = ae_true;
24819  for(i=0; i<=state->n-1; i++)
24820  {
24821  if( ae_fp_greater_eq(ae_fabs(state->g.ptr.p_double[i], _state),d2)&&ae_fp_greater_eq(ae_minreal(state->x.ptr.p_double[i]-state->bndl.ptr.p_double[i], state->bndu.ptr.p_double[i]-state->x.ptr.p_double[i], _state),d32) )
24822  {
24823  result = ae_false;
24824  return result;
24825  }
24826  }
24827  return result;
24828 }
24829 
24830 
24831 /*************************************************************************
24832 Clears request fileds (to be sure that we don't forgot to clear something)
24833 *************************************************************************/
24834 static void mincomp_clearrequestfields(minasastate* state,
24835  ae_state *_state)
24836 {
24837 
24838 
24839  state->needfg = ae_false;
24840  state->xupdated = ae_false;
24841 }
24842 
24843 
24844 ae_bool _minasastate_init(void* _p, ae_state *_state, ae_bool make_automatic)
24845 {
24846  minasastate *p = (minasastate*)_p;
24847  ae_touch_ptr((void*)p);
24848  if( !ae_vector_init(&p->bndl, 0, DT_REAL, _state, make_automatic) )
24849  return ae_false;
24850  if( !ae_vector_init(&p->bndu, 0, DT_REAL, _state, make_automatic) )
24851  return ae_false;
24852  if( !ae_vector_init(&p->ak, 0, DT_REAL, _state, make_automatic) )
24853  return ae_false;
24854  if( !ae_vector_init(&p->xk, 0, DT_REAL, _state, make_automatic) )
24855  return ae_false;
24856  if( !ae_vector_init(&p->dk, 0, DT_REAL, _state, make_automatic) )
24857  return ae_false;
24858  if( !ae_vector_init(&p->an, 0, DT_REAL, _state, make_automatic) )
24859  return ae_false;
24860  if( !ae_vector_init(&p->xn, 0, DT_REAL, _state, make_automatic) )
24861  return ae_false;
24862  if( !ae_vector_init(&p->dn, 0, DT_REAL, _state, make_automatic) )
24863  return ae_false;
24864  if( !ae_vector_init(&p->d, 0, DT_REAL, _state, make_automatic) )
24865  return ae_false;
24866  if( !ae_vector_init(&p->work, 0, DT_REAL, _state, make_automatic) )
24867  return ae_false;
24868  if( !ae_vector_init(&p->yk, 0, DT_REAL, _state, make_automatic) )
24869  return ae_false;
24870  if( !ae_vector_init(&p->gc, 0, DT_REAL, _state, make_automatic) )
24871  return ae_false;
24872  if( !ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic) )
24873  return ae_false;
24874  if( !ae_vector_init(&p->g, 0, DT_REAL, _state, make_automatic) )
24875  return ae_false;
24876  if( !_rcommstate_init(&p->rstate, _state, make_automatic) )
24877  return ae_false;
24878  if( !_linminstate_init(&p->lstate, _state, make_automatic) )
24879  return ae_false;
24880  return ae_true;
24881 }
24882 
24883 
24884 ae_bool _minasastate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
24885 {
24886  minasastate *dst = (minasastate*)_dst;
24887  minasastate *src = (minasastate*)_src;
24888  dst->n = src->n;
24889  dst->epsg = src->epsg;
24890  dst->epsf = src->epsf;
24891  dst->epsx = src->epsx;
24892  dst->maxits = src->maxits;
24893  dst->xrep = src->xrep;
24894  dst->stpmax = src->stpmax;
24895  dst->cgtype = src->cgtype;
24896  dst->k = src->k;
24897  dst->nfev = src->nfev;
24898  dst->mcstage = src->mcstage;
24899  if( !ae_vector_init_copy(&dst->bndl, &src->bndl, _state, make_automatic) )
24900  return ae_false;
24901  if( !ae_vector_init_copy(&dst->bndu, &src->bndu, _state, make_automatic) )
24902  return ae_false;
24903  dst->curalgo = src->curalgo;
24904  dst->acount = src->acount;
24905  dst->mu = src->mu;
24906  dst->finit = src->finit;
24907  dst->dginit = src->dginit;
24908  if( !ae_vector_init_copy(&dst->ak, &src->ak, _state, make_automatic) )
24909  return ae_false;
24910  if( !ae_vector_init_copy(&dst->xk, &src->xk, _state, make_automatic) )
24911  return ae_false;
24912  if( !ae_vector_init_copy(&dst->dk, &src->dk, _state, make_automatic) )
24913  return ae_false;
24914  if( !ae_vector_init_copy(&dst->an, &src->an, _state, make_automatic) )
24915  return ae_false;
24916  if( !ae_vector_init_copy(&dst->xn, &src->xn, _state, make_automatic) )
24917  return ae_false;
24918  if( !ae_vector_init_copy(&dst->dn, &src->dn, _state, make_automatic) )
24919  return ae_false;
24920  if( !ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic) )
24921  return ae_false;
24922  dst->fold = src->fold;
24923  dst->stp = src->stp;
24924  if( !ae_vector_init_copy(&dst->work, &src->work, _state, make_automatic) )
24925  return ae_false;
24926  if( !ae_vector_init_copy(&dst->yk, &src->yk, _state, make_automatic) )
24927  return ae_false;
24928  if( !ae_vector_init_copy(&dst->gc, &src->gc, _state, make_automatic) )
24929  return ae_false;
24930  dst->laststep = src->laststep;
24931  if( !ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic) )
24932  return ae_false;
24933  dst->f = src->f;
24934  if( !ae_vector_init_copy(&dst->g, &src->g, _state, make_automatic) )
24935  return ae_false;
24936  dst->needfg = src->needfg;
24937  dst->xupdated = src->xupdated;
24938  if( !_rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic) )
24939  return ae_false;
24940  dst->repiterationscount = src->repiterationscount;
24941  dst->repnfev = src->repnfev;
24942  dst->repterminationtype = src->repterminationtype;
24943  dst->debugrestartscount = src->debugrestartscount;
24944  if( !_linminstate_init_copy(&dst->lstate, &src->lstate, _state, make_automatic) )
24945  return ae_false;
24946  dst->betahs = src->betahs;
24947  dst->betady = src->betady;
24948  return ae_true;
24949 }
24950 
24951 
24952 void _minasastate_clear(void* _p)
24953 {
24954  minasastate *p = (minasastate*)_p;
24955  ae_touch_ptr((void*)p);
24956  ae_vector_clear(&p->bndl);
24957  ae_vector_clear(&p->bndu);
24958  ae_vector_clear(&p->ak);
24959  ae_vector_clear(&p->xk);
24960  ae_vector_clear(&p->dk);
24961  ae_vector_clear(&p->an);
24962  ae_vector_clear(&p->xn);
24963  ae_vector_clear(&p->dn);
24964  ae_vector_clear(&p->d);
24965  ae_vector_clear(&p->work);
24966  ae_vector_clear(&p->yk);
24967  ae_vector_clear(&p->gc);
24968  ae_vector_clear(&p->x);
24969  ae_vector_clear(&p->g);
24970  _rcommstate_clear(&p->rstate);
24971  _linminstate_clear(&p->lstate);
24972 }
24973 
24974 
24975 void _minasastate_destroy(void* _p)
24976 {
24977  minasastate *p = (minasastate*)_p;
24978  ae_touch_ptr((void*)p);
24979  ae_vector_destroy(&p->bndl);
24980  ae_vector_destroy(&p->bndu);
24981  ae_vector_destroy(&p->ak);
24982  ae_vector_destroy(&p->xk);
24983  ae_vector_destroy(&p->dk);
24984  ae_vector_destroy(&p->an);
24985  ae_vector_destroy(&p->xn);
24986  ae_vector_destroy(&p->dn);
24987  ae_vector_destroy(&p->d);
24988  ae_vector_destroy(&p->work);
24989  ae_vector_destroy(&p->yk);
24990  ae_vector_destroy(&p->gc);
24991  ae_vector_destroy(&p->x);
24992  ae_vector_destroy(&p->g);
24993  _rcommstate_destroy(&p->rstate);
24994  _linminstate_destroy(&p->lstate);
24995 }
24996 
24997 
24998 ae_bool _minasareport_init(void* _p, ae_state *_state, ae_bool make_automatic)
24999 {
25000  minasareport *p = (minasareport*)_p;
25001  ae_touch_ptr((void*)p);
25002  return ae_true;
25003 }
25004 
25005 
25006 ae_bool _minasareport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
25007 {
25008  minasareport *dst = (minasareport*)_dst;
25009  minasareport *src = (minasareport*)_src;
25010  dst->iterationscount = src->iterationscount;
25011  dst->nfev = src->nfev;
25012  dst->terminationtype = src->terminationtype;
25013  dst->activeconstraints = src->activeconstraints;
25014  return ae_true;
25015 }
25016 
25017 
25018 void _minasareport_clear(void* _p)
25019 {
25020  minasareport *p = (minasareport*)_p;
25021  ae_touch_ptr((void*)p);
25022 }
25023 
25024 
25025 void _minasareport_destroy(void* _p)
25026 {
25027  minasareport *p = (minasareport*)_p;
25028  ae_touch_ptr((void*)p);
25029 }
25030 
25031 
25032 
25033 }
25034 
void minlmcreatevj(const ae_int_t n, const ae_int_t m, const real_1d_array &x, minlmstate &state)
void _minqpstate_clear(void *_p)
minbleicreport & operator=(const minbleicreport &rhs)
void minlmsetcond(const minlmstate &state, const double epsg, const double epsf, const double epsx, const ae_int_t maxits)
struct alglib_impl::ae_state ae_state
void minbleicsetprecdefault(const minbleicstate &state)
ae_bool _mincgstate_init(void *_p, ae_state *_state, ae_bool make_automatic)
void mincgsetstpmax(mincgstate *state, double stpmax, ae_state *_state)
alglib_impl::minlbfgsstate * c_ptr()
void calculatestepbound(ae_vector *x, ae_vector *d, double alpha, ae_vector *bndl, ae_vector *havebndl, ae_vector *bndu, ae_vector *havebndu, ae_int_t nmain, ae_int_t nslack, ae_int_t *variabletofreeze, double *valuetofreeze, double *maxsteplen, ae_state *_state)
void minlbfgssetstpmax(minlbfgsstate *state, double stpmax, ae_state *_state)
ae_bool ae_fp_greater_eq(double v1, double v2)
Definition: ap.cpp:1351
void trimprepare(double f, double *threshold, ae_state *_state)
real_1d_array g
Definition: optimization.h:932
void minqpsetscale(const minqpstate &state, const real_1d_array &s)
real_1d_array g
Definition: optimization.h:620
void mincgsetxrep(mincgstate *state, ae_bool needxrep, ae_state *_state)
void rmatrixsyrk(const ae_int_t n, const ae_int_t k, const double alpha, const real_2d_array &a, const ae_int_t ia, const ae_int_t ja, const ae_int_t optypea, const double beta, const real_2d_array &c, const ae_int_t ic, const ae_int_t jc, const bool isupper)
Definition: linalg.cpp:518
minlbfgsreport & operator=(const minlbfgsreport &rhs)
ae_int_t & terminationtype
Definition: optimization.h:982
void mincgresultsbuf(const mincgstate &state, real_1d_array &x, mincgreport &rep)
void rmatrixmv(const ae_int_t m, const ae_int_t n, const real_2d_array &a, const ae_int_t ia, const ae_int_t ja, const ae_int_t opa, const real_1d_array &x, const ae_int_t ix, real_1d_array &y, const ae_int_t iy)
Definition: linalg.cpp:319
void minbleicsetprecdiag(const minbleicstate &state, const real_1d_array &d)
void ae_v_moved(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n, double alpha)
Definition: ap.cpp:4425
alglib_impl::mincgstate * c_ptr()
void minlbfgssetscale(minlbfgsstate *state, ae_vector *s, ae_state *_state)
ae_bool _minbleicreport_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
void minbleicsetgradientcheck(const minbleicstate &state, const double teststep)
void mincgsetprecdiag(const mincgstate &state, const real_1d_array &d)
void minlmcreatev(ae_int_t n, ae_int_t m, ae_vector *x, double diffstep, minlmstate *state, ae_state *_state)
void mincgsetprecdefault(mincgstate *state, ae_state *_state)
alglib_impl::minasareport * c_ptr()
void minlbfgssetgradientcheck(const minlbfgsstate &state, const double teststep)
void minbleiccreate(const ae_int_t n, const real_1d_array &x, minbleicstate &state)
real_2d_array j
Definition: optimization.h:934
ae_bool cqmconstrainedoptimum(convexquadraticmodel *s, ae_vector *x, ae_state *_state)
void minbleicresultsbuf(minbleicstate *state, ae_vector *x, minbleicreport *rep, ae_state *_state)
bool minasaiteration(const minasastate &state)
ae_bool ae_is_symmetric(ae_matrix *a)
Definition: ap.cpp:2248
ae_bool isfinitertrmatrix(ae_matrix *x, ae_int_t n, ae_bool isupper, ae_state *_state)
void ae_v_muld(double *vdst, ae_int_t stride_dst, ae_int_t n, double alpha)
Definition: ap.cpp:4538
void mincgcreatef(ae_int_t n, ae_vector *x, double diffstep, mincgstate *state, ae_state *_state)
void mincgsetprecdiag(mincgstate *state, ae_vector *d, ae_state *_state)
ae_bool _minlmreport_init(void *_p, ae_state *_state, ae_bool make_automatic)
double ae_fabs(double x, ae_state *state)
Definition: ap.cpp:1520
ae_int_t & ncholesky
Definition: optimization.h:893
void minbleicsetxrep(const minbleicstate &state, const bool needxrep)
ae_bool derivativecheck(double f0, double df0, double f1, double df1, double f, double df, double width, ae_state *_state)
ae_int_t numberofchangedconstraints(ae_vector *x, ae_vector *xprev, ae_vector *bndl, ae_vector *havebndl, ae_vector *bndu, ae_vector *havebndu, ae_int_t nmain, ae_int_t nslack, ae_state *_state)
ae_int_t & iterationscount
Definition: optimization.h:648
void minlbfgssetcholeskypreconditioner(minlbfgsstate *state, ae_matrix *p, ae_bool isupper, ae_state *_state)
void mincgsetxrep(const mincgstate &state, const bool needxrep)
doublereal * c
void cqmsetq(convexquadraticmodel *s, ae_matrix *q, ae_vector *r, ae_int_t k, double theta, ae_state *_state)
doublereal * g
double * bl
void minlmsetxrep(minlmstate *state, ae_bool needxrep, ae_state *_state)
#define ae_false
Definition: ap.h:196
void * ae_malloc(size_t size, ae_state *state)
Definition: ap.cpp:222
void minlbfgssetprecdefault(minlbfgsstate *state, ae_state *_state)
void mincgsetstpmax(const mincgstate &state, const double stpmax)
real_2d_array h
Definition: optimization.h:933
double cqmeval(convexquadraticmodel *s, ae_vector *x, ae_state *_state)
doublereal * grad
ae_bool _mincgstate_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
bool minbleiciteration(const minbleicstate &state)
void mincgresults(mincgstate *state, ae_vector *x, mincgreport *rep, ae_state *_state)
void minlmsetbc(minlmstate *state, ae_vector *bndl, ae_vector *bndu, ae_state *_state)
union alglib_impl::ae_matrix::@12 ptr
void minlbfgssetdefaultpreconditioner(minlbfgsstate *state, ae_state *_state)
void cqmsetactiveset(convexquadraticmodel *s, ae_vector *x, ae_vector *activeset, ae_state *_state)
void minasaresults(const minasastate &state, real_1d_array &x, minasareport &rep)
void mincgoptimize(mincgstate &state, void(*func)(const real_1d_array &x, double &func, void *ptr), void(*rep)(const real_1d_array &x, double func, void *ptr), void *ptr)
_mincgstate_owner & operator=(const _mincgstate_owner &rhs)
void ae_frame_make(ae_state *state, ae_frame *tmp)
Definition: ap.cpp:402
ae_bool _minlbfgsreport_init(void *_p, ae_state *_state, ae_bool make_automatic)
static double * y
void minqpsetbc(const minqpstate &state, const real_1d_array &bndl, const real_1d_array &bndu)
ae_int_t & ncholesky
Definition: optimization.h:989
bool mincgiteration(const mincgstate &state)
ae_int_t & debugfeasgpaits
Definition: optimization.h:748
minlmstate & operator=(const minlmstate &rhs)
ae_int_t & outeriterationscount
Definition: optimization.h:891
void minlbfgssetpreccholesky(const minlbfgsstate &state, const real_2d_array &p, const bool isupper)
void minlmcreatefgh(const ae_int_t n, const real_1d_array &x, minlmstate &state)
ae_bool _minlbfgsreport_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
void minasaoptimize(minasastate &state, void(*grad)(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr), void(*rep)(const real_1d_array &x, double func, void *ptr), void *ptr)
void _minbleicstate_clear(void *_p)
void minlbfgssetxrep(const minlbfgsstate &state, const bool needxrep)
void minqpsetalgobleic(const minqpstate &state, const double epsg, const double epsf, const double epsx, const ae_int_t maxits)
void minlbfgssetprecdiag(const minlbfgsstate &state, const real_1d_array &d)
void cqmadx(convexquadraticmodel *s, ae_vector *x, ae_vector *y, ae_state *_state)
ae_bool apservisfinitematrix(ae_matrix *x, ae_int_t m, ae_int_t n, ae_state *_state)
void mincgrestartfrom(const mincgstate &state, const real_1d_array &x)
void bvectorsetlengthatleast(ae_vector *x, ae_int_t n, ae_state *_state)
void minqpsetorigin(minqpstate *state, ae_vector *xorigin, ae_state *_state)
ae_bool _minqpstate_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
void minlbfgscreatef(const ae_int_t n, const ae_int_t m, const real_1d_array &x, const double diffstep, minlbfgsstate &state)
void cqmsetb(convexquadraticmodel *s, ae_vector *b, ae_state *_state)
void minqpsetquadraticterm(minqpstate *state, ae_matrix *a, ae_bool isupper, ae_state *_state)
void snnlsinit(ae_int_t nsmax, ae_int_t ndmax, ae_int_t nrmax, snnlssolver *s, ae_state *_state)
doublereal * w
void minbleicsetbarrierwidth(const minbleicstate &state, const double mu)
double * p_double
Definition: ap.h:437
void filterdirection(ae_vector *d, ae_vector *x, ae_vector *bndl, ae_vector *havebndl, ae_vector *bndu, ae_vector *havebndu, ae_vector *s, ae_int_t nmain, ae_int_t nslack, double droptol, ae_state *_state)
void mincgcreate(ae_int_t n, ae_vector *x, mincgstate *state, ae_state *_state)
ae_bool _minbleicstate_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
void minbleicsetbarrierdecay(minbleicstate *state, double mudecay, ae_state *_state)
void minlmresultsbuf(const minlmstate &state, real_1d_array &x, minlmreport &rep)
alglib_impl::mincgreport * p_struct
Definition: optimization.h:639
void mincgsetcgtype(const mincgstate &state, const ae_int_t cgtype)
ae_bool minlmiteration(minlmstate *state, ae_state *_state)
minasareport & operator=(const minasareport &rhs)
void cqmsetd(convexquadraticmodel *s, ae_vector *d, double tau, ae_state *_state)
_minqpreport_owner & operator=(const _minqpreport_owner &rhs)
ae_bool _minbleicreport_init(void *_p, ae_state *_state, ae_bool make_automatic)
ae_bool _minqpreport_init(void *_p, ae_state *_state, ae_bool make_automatic)
void minqpsetlc(minqpstate *state, ae_matrix *c, ae_vector *ct, ae_int_t k, ae_state *_state)
void minlbfgsrestartfrom(minlbfgsstate *state, ae_vector *x, ae_state *_state)
void ae_state_clear(ae_state *state)
Definition: ap.cpp:373
const alglib_impl::ae_matrix * c_ptr() const
Definition: ap.cpp:6463
void minlmoptimize(minlmstate &state, void(*fvec)(const real_1d_array &x, real_1d_array &fi, void *ptr), void(*rep)(const real_1d_array &x, double func, void *ptr), void *ptr)
ae_bool ae_fp_eq(double v1, double v2)
Definition: ap.cpp:1313
void cqmevalx(convexquadraticmodel *s, ae_vector *x, double *r, double *noise, ae_state *_state)
minlmreport & operator=(const minlmreport &rhs)
void minlmrestartfrom(minlmstate *state, ae_vector *x, ae_state *_state)
void _minlmstate_clear(void *_p)
cmache_1 eps
void minbleicresultsbuf(const minbleicstate &state, real_1d_array &x, minbleicreport &rep)
void minlbfgssetdefaultpreconditioner(const minlbfgsstate &state)
void minlbfgssetprecscale(const minlbfgsstate &state)
void minqpcreate(const ae_int_t n, minqpstate &state)
real_1d_array x
Definition: optimization.h:935
void minbleicsetgradientcheck(minbleicstate *state, double teststep, ae_state *_state)
ae_bool _minlmstate_init(void *_p, ae_state *_state, ae_bool make_automatic)
alglib_impl::mincgstate * p_struct
Definition: optimization.h:607
alglib_impl::minbleicreport * p_struct
Definition: optimization.h:730
void minasasetstpmax(minasastate *state, double stpmax, ae_state *_state)
ae_bool ae_matrix_init_copy(ae_matrix *dst, ae_matrix *src, ae_state *state, ae_bool make_automatic)
Definition: ap.cpp:801
ae_bool ae_matrix_init(ae_matrix *dst, ae_int_t rows, ae_int_t cols, ae_datatype datatype, ae_state *state, ae_bool make_automatic)
Definition: ap.cpp:756
void cqmdropa(convexquadraticmodel *s, ae_state *_state)
void _minasastate_clear(void *_p)
void minqpsetbc(minqpstate *state, ae_vector *bndl, ae_vector *bndu, ae_state *_state)
doublereal * x
void ae_matrix_destroy(ae_matrix *dst)
Definition: ap.cpp:909
double v_nan
Definition: ap.h:355
#define i
void minbleicsetcond(const minbleicstate &state, const double epsg, const double epsf, const double epsx, const ae_int_t maxits)
void minlmcreatefgj(const ae_int_t n, const ae_int_t m, const real_1d_array &x, minlmstate &state)
void minbleicrestartfrom(minbleicstate *state, ae_vector *x, ae_state *_state)
void _minqpreport_clear(void *_p)
ql0001_ & k(htemp+1),(cvec+1),(atemp+1),(bj+1),(bl+1),(bu+1),(x+1),(clamda+1), &iout, infoqp, &zero,(w+1), &lenw,(iw+1), &leniw, &glob_grd.epsmac
void ae_v_add(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n)
Definition: ap.cpp:4452
void mincgsetgradientcheck(const mincgstate &state, const double teststep)
ae_int_t & activeconstraints
doublereal * d
void cqmrewritedensediagonal(convexquadraticmodel *s, ae_vector *z, ae_state *_state)
void mincgsetscale(mincgstate *state, ae_vector *s, ae_state *_state)
void minlmcreatefgh(ae_int_t n, ae_vector *x, minlmstate *state, ae_state *_state)
double ** hess
ae_bool _minlmstate_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
double theta
void minqpsetalgocholesky(const minqpstate &state)
ae_bool _minqpstate_init(void *_p, ae_state *_state, ae_bool make_automatic)
ae_bool _minbleicstate_init(void *_p, ae_state *_state, ae_bool make_automatic)
ae_bool minbleiciteration(minbleicstate *state, ae_state *_state)
ae_bool minlbfgsiteration(minlbfgsstate *state, ae_state *_state)
_minlmstate_owner & operator=(const _minlmstate_owner &rhs)
void _minbleicreport_clear(void *_p)
ae_int_t & iterationscount
Definition: optimization.h:808
void minasarestartfrom(minasastate *state, ae_vector *x, ae_vector *bndl, ae_vector *bndu, ae_state *_state)
void _convexquadraticmodel_clear(void *_p)
void threshold(double *phi, unsigned long nvox, double limit)
Definition: lib_vwk.cpp:524
void minlbfgssetstpmax(const minlbfgsstate &state, const double stpmax)
double * bu
void mincgsuggeststep(const mincgstate &state, const double stp)
void minlmsetstpmax(minlmstate *state, double stpmax, ae_state *_state)
void minqpresultsbuf(minqpstate *state, ae_vector *x, minqpreport *rep, ae_state *_state)
void mincgresults(const mincgstate &state, real_1d_array &x, mincgreport &rep)
void minasaresults(minasastate *state, ae_vector *x, minasareport *rep, ae_state *_state)
void minbleicresults(minbleicstate *state, ae_vector *x, minbleicreport *rep, ae_state *_state)
void trimfunction(double *f, ae_vector *g, ae_int_t n, double threshold, ae_state *_state)
ae_int_t ae_v_len(ae_int_t a, ae_int_t b)
Definition: ap.cpp:4562
ae_int_t & iterationscount
Definition: optimization.h:981
void ae_vector_destroy(ae_vector *dst)
Definition: ap.cpp:707
void _minlbfgsreport_clear(void *_p)
doublereal * b
void minbleicoptimize(minbleicstate &state, void(*func)(const real_1d_array &x, double &func, void *ptr), void(*rep)(const real_1d_array &x, double func, void *ptr), void *ptr)
void minlbfgssetprecscale(minlbfgsstate *state, ae_state *_state)
void minlmsetacctype(minlmstate *state, ae_int_t acctype, ae_state *_state)
void minbleicsetprecdiag(minbleicstate *state, ae_vector *d, ae_state *_state)
ae_bool _convexquadraticmodel_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
ae_bool enforceboundaryconstraints(ae_vector *x, ae_vector *bl, ae_vector *havebl, ae_vector *bu, ae_vector *havebu, ae_int_t nmain, ae_int_t nslack, ae_state *_state)
minqpreport & operator=(const minqpreport &rhs)
void minqpresults(const minqpstate &state, real_1d_array &x, minqpreport &rep)
real_1d_array x
Definition: optimization.h:621
ae_int_t & inneriterationscount
Definition: optimization.h:749
double cqmxtadx2(convexquadraticmodel *s, ae_vector *x, ae_state *_state)
void minasasetxrep(const minasastate &state, const bool needxrep)
void _minlbfgsstate_clear(void *_p)
mincgreport & operator=(const mincgreport &rhs)
void minlbfgscreate(ae_int_t n, ae_int_t m, ae_vector *x, minlbfgsstate *state, ae_state *_state)
void minlbfgscreatef(ae_int_t n, ae_int_t m, ae_vector *x, double diffstep, minlbfgsstate *state, ae_state *_state)
void minbleicsetscale(const minbleicstate &state, const real_1d_array &s)
alglib_impl::minqpstate * c_ptr()
void ae_v_move(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n)
Definition: ap.cpp:4371
void minlmcreatefj(ae_int_t n, ae_int_t m, ae_vector *x, minlmstate *state, ae_state *_state)
ae_bool _minqpreport_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
_mincgreport_owner & operator=(const _mincgreport_owner &rhs)
void minlbfgssetscale(const minlbfgsstate &state, const real_1d_array &s)
void minlmcreatefgj(ae_int_t n, ae_int_t m, ae_vector *x, minlmstate *state, ae_state *_state)
void minlbfgsoptimize(minlbfgsstate &state, void(*func)(const real_1d_array &x, double &func, void *ptr), void(*rep)(const real_1d_array &x, double func, void *ptr), void *ptr)
alglib_impl::minlmstate * p_struct
Definition: optimization.h:915
void mincgcreatef(const ae_int_t n, const real_1d_array &x, const double diffstep, mincgstate &state)
void minlbfgsrestartfrom(const minlbfgsstate &state, const real_1d_array &x)
int in
double * f
alglib_impl::minlbfgsstate * p_struct
Definition: optimization.h:767
void ae_vector_clear(ae_vector *dst)
Definition: ap.cpp:692
void minlbfgssetpreccholesky(minlbfgsstate *state, ae_matrix *p, ae_bool isupper, ae_state *_state)
void mincgsetprecscale(const mincgstate &state)
ae_int_t length() const
Definition: ap.cpp:5882
void rmatrixcopy(const ae_int_t m, const ae_int_t n, const real_2d_array &a, const ae_int_t ia, const ae_int_t ja, real_2d_array &b, const ae_int_t ib, const ae_int_t jb)
Definition: linalg.cpp:166
void _convexquadraticmodel_destroy(void *_p)
_minasastate_owner & operator=(const _minasastate_owner &rhs)
ae_bool _mincgreport_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
ae_bool ae_fp_less(double v1, double v2)
Definition: ap.cpp:1327
alglib_impl::minlmreport * p_struct
Definition: optimization.h:972
alglib_impl::minqpreport * c_ptr()
void minbleicsetxrep(minbleicstate *state, ae_bool needxrep, ae_state *_state)
void mincgresultsbuf(mincgstate *state, ae_vector *x, mincgreport *rep, ae_state *_state)
void minqpsetstartingpoint(minqpstate *state, ae_vector *x, ae_state *_state)
void minqpoptimize(const minqpstate &state)
double safeminposrv(double x, double y, double v, ae_state *_state)
void _minasareport_clear(void *_p)
void minbleicsetprecscale(const minbleicstate &state)
ae_bool _minlmreport_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
ae_int_t & terminationtype
void minlbfgssetxrep(minlbfgsstate *state, ae_bool needxrep, ae_state *_state)
void minbleicsetlc(minbleicstate *state, ae_matrix *c, ae_vector *ct, ae_int_t k, ae_state *_state)
void minbleicsetbarrierwidth(minbleicstate *state, double mu, ae_state *_state)
void minbleicsetprecdefault(minbleicstate *state, ae_state *_state)
void minqpsetalgocholesky(minqpstate *state, ae_state *_state)
void minlbfgssetcond(minlbfgsstate *state, double epsg, double epsf, double epsx, ae_int_t maxits, ae_state *_state)
void mincgsetcond(const mincgstate &state, const double epsg, const double epsf, const double epsx, const ae_int_t maxits)
quaternion_type< T > normalize(quaternion_type< T > q)
Definition: point.cpp:278
#define ae_bool
Definition: ap.h:194
ae_bool ae_fp_neq(double v1, double v2)
Definition: ap.cpp:1321
ae_int_t & terminationtype
Definition: optimization.h:894
ae_bool isfinitevector(ae_vector *x, ae_int_t n, ae_state *_state)
void rvectorsetlengthatleast(ae_vector *x, ae_int_t n, ae_state *_state)
double z
void minbleicsetbc(minbleicstate *state, ae_vector *bndl, ae_vector *bndu, ae_state *_state)
alglib_impl::minlmreport * c_ptr()
__host__ __device__ float length(float2 v)
void minlbfgsresultsbuf(minlbfgsstate *state, ae_vector *x, minlbfgsreport *rep, ae_state *_state)
void mincgcreate(const ae_int_t n, const real_1d_array &x, mincgstate &state)
ae_bool _minasareport_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
void ae_touch_ptr(void *p)
Definition: ap.cpp:294
minbleicstate & operator=(const minbleicstate &rhs)
void minbleicresults(const minbleicstate &state, real_1d_array &x, minbleicreport &rep)
minlbfgsstate & operator=(const minlbfgsstate &rhs)
void minasarestartfrom(const minasastate &state, const real_1d_array &x, const real_1d_array &bndl, const real_1d_array &bndu)
double ae_maxreal(double m1, double m2, ae_state *state)
Definition: ap.cpp:1577
ae_error_type
Definition: ap.h:201
void direction(const MultidimArray< double > &orMap, MultidimArray< double > &qualityMap, double lambda, int size, MultidimArray< double > &dirMap, int x, int y)
void minlmcreatevj(ae_int_t n, ae_int_t m, ae_vector *x, minlmstate *state, ae_state *_state)
void minasacreate(const ae_int_t n, const real_1d_array &x, const real_1d_array &bndl, const real_1d_array &bndu, minasastate &state)
void minqpresults(minqpstate *state, ae_vector *x, minqpreport *rep, ae_state *_state)
void mode
ae_int_t & terminationtype
Definition: optimization.h:811
ae_bool ae_vector_set_length(ae_vector *dst, ae_int_t newsize, ae_state *state)
Definition: ap.cpp:658
void ae_v_sub(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n)
Definition: ap.cpp:4506
void mincgsuggeststep(mincgstate *state, double stp, ae_state *_state)
void minasasetalgorithm(minasastate *state, ae_int_t algotype, ae_state *_state)
bool rmatrixsvd(const real_2d_array &a, const ae_int_t m, const ae_int_t n, const ae_int_t uneeded, const ae_int_t vtneeded, const ae_int_t additionalmemory, real_1d_array &w, real_2d_array &u, real_2d_array &vt)
Definition: linalg.cpp:1851
void minbleicsetstpmax(const minbleicstate &state, const double stpmax)
alglib_impl::minqpreport * p_struct
Definition: optimization.h:881
_minlmreport_owner & operator=(const _minlmreport_owner &rhs)
void _minlmreport_clear(void *_p)
void minasasetcond(const minasastate &state, const double epsg, const double epsf, const double epsx, const ae_int_t maxits)
void minlmsetcond(minlmstate *state, double epsg, double epsf, double epsx, ae_int_t maxits, ae_state *_state)
ae_int_t postprocessboundedstep(ae_vector *x, ae_vector *xprev, ae_vector *bndl, ae_vector *havebndl, ae_vector *bndu, ae_vector *havebndu, ae_int_t nmain, ae_int_t nslack, ae_int_t variabletofreeze, double valuetofreeze, double steptaken, double maxsteplen, ae_state *_state)
_minbleicstate_owner & operator=(const _minbleicstate_owner &rhs)
struct alglib_impl::ae_vector ae_vector
ae_bool _apbuffers_init(void *_p, ae_state *_state, ae_bool make_automatic)
ae_bool _minasastate_init(void *_p, ae_state *_state, ae_bool make_automatic)
const alglib_impl::ae_vector * c_ptr() const
Definition: ap.cpp:5907
bool minlbfgsiteration(const minlbfgsstate &state)
void mincgsetcond(mincgstate *state, double epsg, double epsf, double epsx, ae_int_t maxits, ae_state *_state)
#define j
double ae_minreal(double m1, double m2, ae_state *state)
Definition: ap.cpp:1582
ae_bool _mincgreport_init(void *_p, ae_state *_state, ae_bool make_automatic)
alglib_impl::minlbfgsreport * p_struct
Definition: optimization.h:799
void minqpsetquadratictermsparse(const minqpstate &state, const sparsematrix &a, const bool isupper)
ae_bool _minasareport_init(void *_p, ae_state *_state, ae_bool make_automatic)
void cqmscalevector(convexquadraticmodel *s, ae_vector *x, ae_state *_state)
int m
void minlmsetgradientcheck(const minlmstate &state, const double teststep)
void minlmsetxrep(const minlmstate &state, const bool needxrep)
alglib_impl::minasastate * c_ptr()
void mincgsetprecdefault(const mincgstate &state)
alglib_impl::mincgreport * c_ptr()
void minlmcreatevgj(const ae_int_t n, const ae_int_t m, const real_1d_array &x, minlmstate &state)
void minlmsetscale(const minlmstate &state, const real_1d_array &s)
void minlmcreatevgj(ae_int_t n, ae_int_t m, ae_vector *x, minlmstate *state, ae_state *_state)
struct alglib_impl::ae_matrix ae_matrix
double cqmdebugconstrainedevale(convexquadraticmodel *s, ae_vector *x, ae_state *_state)
void minbleicsetstpmax(minbleicstate *state, double stpmax, ae_state *_state)
ae_int_t & iterationscount
ae_int_t & inneriterationscount
Definition: optimization.h:890
ae_int_t & terminationtype
Definition: optimization.h:742
alglib_impl::minlmstate * c_ptr()
double ** pp_double
Definition: ap.h:455
void error(char *s)
Definition: tools.cpp:107
void ae_state_init(ae_state *state)
Definition: ap.cpp:309
void minbleicsetscale(minbleicstate *state, ae_vector *s, ae_state *_state)
alglib_impl::minqpstate * p_struct
Definition: optimization.h:830
void rmatrixrighttrsm(const ae_int_t m, const ae_int_t n, const real_2d_array &a, const ae_int_t i1, const ae_int_t j1, const bool isupper, const bool isunit, const ae_int_t optype, const real_2d_array &x, const ae_int_t i2, const ae_int_t j2)
Definition: linalg.cpp:410
void rmatrixsetlengthatleast(ae_matrix *x, ae_int_t m, ae_int_t n, ae_state *_state)
double ae_sqrt(double x, ae_state *state)
Definition: ap.cpp:1535
void mincgsetprecscale(mincgstate *state, ae_state *_state)
void ae_assert(ae_bool cond, const char *msg, ae_state *state)
Definition: ap.cpp:1227
union alglib_impl::ae_vector::@11 ptr
ae_bool _minlbfgsstate_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
ae_int_t rows() const
Definition: ap.cpp:6419
void minlbfgssetgradientcheck(minlbfgsstate *state, double teststep, ae_state *_state)
void minqpsetquadraticterm(const minqpstate &state, const real_2d_array &a, const bool isupper)
ae_bool _minasastate_init_copy(void *_dst, void *_src, ae_state *_state, ae_bool make_automatic)
void cqmseta(convexquadraticmodel *s, ae_matrix *a, ae_bool isupper, double alpha, ae_state *_state)
real_1d_array fi
Definition: optimization.h:931
void ae_v_moveneg(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n)
Definition: ap.cpp:4398
void minqpsetlc(const minqpstate &state, const real_2d_array &c, const integer_1d_array &ct, const ae_int_t k)
_minqpstate_owner & operator=(const _minqpstate_owner &rhs)
ae_bool findfeasiblepoint(ae_vector *x, ae_vector *bndl, ae_vector *havebndl, ae_vector *bndu, ae_vector *havebndu, ae_int_t nmain, ae_int_t nslack, ae_matrix *ce, ae_int_t k, double epsi, ae_int_t *qpits, ae_int_t *gpaits, ae_state *_state)
alglib_impl::minbleicreport * c_ptr()
void mincgsetscale(const mincgstate &state, const real_1d_array &s)
const char *volatile error_msg
Definition: ap.h:389
_minlbfgsreport_owner & operator=(const _minlbfgsreport_owner &rhs)
ae_bool spdmatrixcholeskyrec(ae_matrix *a, ae_int_t offs, ae_int_t n, ae_bool isupper, ae_vector *tmp, ae_state *_state)
Definition: linalg.cpp:23199
void minlmrestartfrom(const minlmstate &state, const real_1d_array &x)
void minlbfgssetcholeskypreconditioner(const minlbfgsstate &state, const real_2d_array &p, const bool isupper)
void minlmcreatev(const ae_int_t n, const ae_int_t m, const real_1d_array &x, const double diffstep, minlmstate &state)
void minlmresults(minlmstate *state, ae_vector *x, minlmreport *rep, ae_state *_state)
void minbleicsetbarrierdecay(const minbleicstate &state, const double mudecay)
void minasasetstpmax(const minasastate &state, const double stpmax)
#define ae_machineepsilon
Definition: ap.h:825
void minasacreate(ae_int_t n, ae_vector *x, ae_vector *bndl, ae_vector *bndu, minasastate *state, ae_state *_state)
void minbleiccreatef(ae_int_t n, ae_vector *x, double diffstep, minbleicstate *state, ae_state *_state)
_minbleicreport_owner & operator=(const _minbleicreport_owner &rhs)
void minbleicsetbc(const minbleicstate &state, const real_1d_array &bndl, const real_1d_array &bndu)
void tagsortbuf(ae_vector *a, ae_int_t n, ae_vector *p1, ae_vector *p2, apbuffers *buf, ae_state *_state)
void minbleiccreate(ae_int_t n, ae_vector *x, minbleicstate *state, ae_state *_state)
_minlbfgsstate_owner & operator=(const _minlbfgsstate_owner &rhs)
int mu
void minbleicsetprecscale(minbleicstate *state, ae_state *_state)
void minlbfgsresultsbuf(const minlbfgsstate &state, real_1d_array &x, minlbfgsreport &rep)
minqpstate & operator=(const minqpstate &rhs)
ae_bool _convexquadraticmodel_init(void *_p, ae_state *_state, ae_bool make_automatic)
ptrdiff_t ae_int_t
Definition: ap.h:186
void minqpsetquadratictermsparse(minqpstate *state, sparsematrix *a, ae_bool isupper, ae_state *_state)
ae_int_t & iterationscount
Definition: optimization.h:739
ae_bool _minlbfgsstate_init(void *_p, ae_state *_state, ae_bool make_automatic)
doublereal * u
void minqpsetlinearterm(minqpstate *state, ae_vector *b, ae_state *_state)
void ae_v_subd(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n, double alpha)
Definition: ap.cpp:4533
ae_bool ae_vector_init(ae_vector *dst, ae_int_t size, ae_datatype datatype, ae_state *state, ae_bool make_automatic)
Definition: ap.cpp:580
void minasasetxrep(minasastate *state, ae_bool needxrep, ae_state *_state)
void minlmcreatefj(const ae_int_t n, const ae_int_t m, const real_1d_array &x, minlmstate &state)
ae_int_t ae_maxint(ae_int_t m1, ae_int_t m2, ae_state *state)
Definition: ap.cpp:1567
void minasasetcond(minasastate *state, double epsg, double epsf, double epsx, ae_int_t maxits, ae_state *_state)
alglib_impl::minasareport * p_struct
void cqmgradunconstrained(convexquadraticmodel *s, ae_vector *x, ae_vector *g, ae_state *_state)
ae_bool ae_isfinite(double x, ae_state *state)
Definition: ap.cpp:1495
double ae_sqr(double x, ae_state *state)
Definition: ap.cpp:1530
alglib_impl::minbleicstate * c_ptr()
void minasaresultsbuf(minasastate *state, ae_vector *x, minasareport *rep, ae_state *_state)
void minlmresults(const minlmstate &state, real_1d_array &x, minlmreport &rep)
#define INF
Definition: svm.cpp:43
void minqpsetalgobleic(minqpstate *state, double epsg, double epsf, double epsx, ae_int_t maxits, ae_state *_state)
constexpr int K
void minlbfgsresults(const minlbfgsstate &state, real_1d_array &x, minlbfgsreport &rep)
ae_bool minasaiteration(minasastate *state, ae_state *_state)
void minlmresultsbuf(minlmstate *state, ae_vector *x, minlmreport *rep, ae_state *_state)
void mincgsetcgtype(mincgstate *state, ae_int_t cgtype, ae_state *_state)
void minasasetalgorithm(const minasastate &state, const ae_int_t algotype)
ae_int_t * p_int
Definition: ap.h:436
void mincgsetgradientcheck(mincgstate *state, double teststep, ae_state *_state)
void ae_v_addd(double *vdst, ae_int_t stride_dst, const double *vsrc, ae_int_t stride_src, ae_int_t n, double alpha)
Definition: ap.cpp:4479
alglib_impl::minlbfgsreport * c_ptr()
ae_bool ae_vector_init_copy(ae_vector *dst, ae_vector *src, ae_state *state, ae_bool make_automatic)
Definition: ap.cpp:614
ae_int_t & outeriterationscount
Definition: optimization.h:750
#define FAIL()
Definition: gtest.h:1749
ae_bool ae_fp_less_eq(double v1, double v2)
Definition: ap.cpp:1335
void minqpcreate(ae_int_t n, minqpstate *state, ae_state *_state)
void minlbfgscreate(const ae_int_t n, const ae_int_t m, const real_1d_array &x, minlbfgsstate &state)
void minlmsetgradientcheck(minlmstate *state, double teststep, ae_state *_state)
bool minlmiteration(const minlmstate &state)
void minbleicsetlc(const minbleicstate &state, const real_2d_array &c, const integer_1d_array &ct, const ae_int_t k)
void minlbfgssetcond(const minlbfgsstate &state, const double epsg, const double epsf, const double epsx, const ae_int_t maxits)
ae_bool mincgiteration(mincgstate *state, ae_state *_state)
alglib_impl::ae_int_t ae_int_t
Definition: ap.h:889
void _mincgreport_clear(void *_p)
void cqminit(ae_int_t n, convexquadraticmodel *s, ae_state *_state)
alglib_impl::minasastate * p_struct
void minqpsetstartingpoint(const minqpstate &state, const real_1d_array &x)
double cqmdebugconstrainedevalt(convexquadraticmodel *s, ae_vector *x, ae_state *_state)
void minlmsetacctype(const minlmstate &state, const ae_int_t acctype)
void mincgrestartfrom(mincgstate *state, ae_vector *x, ae_state *_state)
void ae_frame_leave(ae_state *state)
Definition: ap.cpp:415
alglib_impl::sparsematrix * c_ptr()
Definition: linalg.cpp:4775
ae_bool * p_bool
Definition: ap.h:435
void minqpoptimize(minqpstate *state, ae_state *_state)
void minlmsetstpmax(const minlmstate &state, const double stpmax)
void ae_matrix_clear(ae_matrix *dst)
Definition: ap.cpp:891
#define ae_true
Definition: ap.h:195
int * n
void minbleiccreatef(const ae_int_t n, const real_1d_array &x, const double diffstep, minbleicstate &state)
ae_bool ae_fp_greater(double v1, double v2)
Definition: ap.cpp:1343
void minqpsetorigin(const minqpstate &state, const real_1d_array &xorigin)
_minasareport_owner & operator=(const _minasareport_owner &rhs)
void minlbfgsresults(minlbfgsstate *state, ae_vector *x, minlbfgsreport *rep, ae_state *_state)
ae_int_t cnt
Definition: ap.h:429
ae_bool ae_matrix_set_length(ae_matrix *dst, ae_int_t rows, ae_int_t cols, ae_state *state)
Definition: ap.cpp:854
doublereal * a
void fblscholeskysolve(ae_matrix *cha, double sqrtscalea, ae_int_t n, ae_bool isupper, ae_vector *xb, ae_vector *tmp, ae_state *_state)
Definition: linalg.cpp:31390
void minlmsetscale(minlmstate *state, ae_vector *s, ae_state *_state)
ql0001_ & zero(ctemp+1),(cvec+1),(a+1),(b+1),(bl+1),(bu+1),(x+1),(w+1), &iout, ifail, &zero,(w+3), &lwar2,(iw+1), &leniw, &glob_grd.epsmac
void minbleicsetcond(minbleicstate *state, double epsg, double epsf, double epsx, ae_int_t maxits, ae_state *_state)
void minqpresultsbuf(const minqpstate &state, real_1d_array &x, minqpreport &rep)
void minasaresultsbuf(const minasastate &state, real_1d_array &x, minasareport &rep)
void projectgradientintobc(ae_vector *x, ae_vector *g, ae_vector *bl, ae_vector *havebl, ae_vector *bu, ae_vector *havebu, ae_int_t nmain, ae_int_t nslack, ae_state *_state)
void minlbfgssetprecdefault(const minlbfgsstate &state)
ae_int_t ae_minint(ae_int_t m1, ae_int_t m2, ae_state *state)
Definition: ap.cpp:1572
void minqpsetscale(minqpstate *state, ae_vector *s, ae_state *_state)
void ae_free(void *p)
Definition: ap.cpp:237
alglib_impl::minbleicstate * p_struct
Definition: optimization.h:670
minasastate & operator=(const minasastate &rhs)
ae_int_t & terminationtype
Definition: optimization.h:651
double ae_v_dotproduct(const double *v0, ae_int_t stride0, const double *v1, ae_int_t stride1, ae_int_t n)
Definition: ap.cpp:4344
check(nparam, nf, nfsr, &Linfty, nineq, nineqn, neq, neqn, ncsrl, ncsrn, mode, &modem, eps, bgbnd, param)
void minlmsetbc(const minlmstate &state, const real_1d_array &bndl, const real_1d_array &bndu)
void minlbfgssetprecdiag(minlbfgsstate *state, ae_vector *d, ae_state *_state)
void minbleicrestartfrom(const minbleicstate &state, const real_1d_array &x)
mincgstate & operator=(const mincgstate &rhs)
void _mincgstate_clear(void *_p)
#define ae_maxrealnumber
Definition: ap.h:826
void snnlssetproblem(snnlssolver *s, ae_matrix *a, ae_vector *b, ae_int_t ns, ae_int_t nd, ae_int_t nr, ae_state *_state)
void minqpsetlinearterm(const minqpstate &state, const real_1d_array &b)
#define xc